[小技巧]快速地知道BIOS跑了哪些DXE Module和顺序(AMI EFI)

        做EFI案子的朋友都碰到过这样的情况,有时候因为某些原因想知道BIOS各个Module执行的顺序或者到底有没有执行到,最笨的办法是用80 port一个点一个点的丢出来,不过我相信应该没有这么笨的人用这么笨的办法了吧;通常的方法是用串口或者USB debug cable,这个也可以实现,但是要有设备,比如板子上要有串口或者外接LPC转串口,USB debug cable, 甚至有可能再需要一个USB转串口的设备, 有点麻烦。
         我最近就遇到了这样的情况,板子上没有LPC接口和串口,也没有可用的USB debug cable, 那怎么办?我就想,DXE阶段memory已经可用了,何不把DXE module执行的信息保存到memory中呢。
        想到了就做!
        要保存到memory,那就要先申请一块么memory空间,这里暂定64KB吧,应该完全够了,申请memory空间的时间当然就应该在DXE dispateher之前。然后就可以在每个DXE Module执行之前把这个Module的信息保存到这块memory里面,最后可以在OS下把这段memory的数据读出来,就可以知道执行了哪些Module和这些Module的执行顺序了。如果需要执行了哪些checkpoint和执行顺序,也可以用类似的方法。

        具体实现上,在DxeMain.c里面先定义一个全局指针变量DebugMemory,在DxeMain函数中申请memory,然后写一个函数专门用来将信息(数据/字符串)存储到memory:

UINT8 *DebugMemory=0;

void ReportMsgToDebugMemory(UINT8 *Msg)
{
        UINT16 MsgOft=*(UINT16*)DebugMemory;
        if(DebugMemory)
        {
                Strcpy((DebugMemory+MsgOft), Msg);
                *(UINT16*)DebugMemory = MsgOft + (UINT16)Strlen(Msg);    //调整总共数据长度
        }
}


//Dxemain(), before invoke CoreDispatcher()
  CoreAllocatePool(EfiACPIReclaimMemory , 0x10000, &DebugMemory);
  *(UINT32*)0x4e0 = (UINT32)DebugMemory;   //save the memory address in BDA
  if(DebugMemory)
  {
        *(UINT16*)(DebugMemory)=0x02;      //用头两个字节表示已经存在的数据的长度
  }
        申请memory完成,接下来就可以使用了, 在Image.c里面的CoreStartImage函数里面做些改动:
//注释掉#ifdef EFI_DEBUG
{
//Debug message: name/entry point of the module being started
BOOLEAN GetImageName(EFI_HANDLE ImageHandle, CHAR8 *sName);
VOID Trace(UINTN Level, CHAR8 *sFormat,...);
CHAR8 sName[0x100];
CHAR8 crlf[]="\r\n\0";
    GetImageName(ImageHandle,sName);
    ReportMsgToDebugMemory(sName);    //保存DXE module的GUID到memory
    ReportMsgToDebugMemory(crlf);     //结尾处加上换行符,方便读出来以后显示用
    if(DebugMemory)
    {
        *(UINT32*)0x4e0=(UINT32)DebugMemory;    //CSM可能会初始化BDA数据,所以这里就暴力一点,每次执行一个module之前把memory地址重新保存到BDA
    }
    Trace(-1, "%s.Entry(%X)\n", sName, Image->EntryPoint);
//注释掉#endif

OK,至此为止, BIOS所需要修改的地方都修改完成了,接下来就可以进DOS,在BDA 0x4e0的地方读出debugmemory的地址,数据长度在DebugMemory的头两个字节,眼力好的人就直接去这个地址看吧,像我这样眼力不好的,就动手写个小程序,把DebugMemory里面的数据读出来保存到文件里面然后再看,以下是这个小程序的实现(需要进Big real mode),程序简单,不解释,你懂的!
#include "common.h"
#include "cpumode.h"
#include <stdio.h>
#include <stdlib.h>

#define MY_DEBUG 0

#if MY_DEBUG
#define DEBUG(Msg) printf Msg
#else
#define DEBUG(Msg)
#endif

#define BUFFER_SIZE 0x100
void main()
{
    UINT32  Tmpi;
    UINT32 DebugMemory=0;
    FILE *fp;
    CHAR8 *Buffer=0;
    UINT16 DebugLogSize=0, SizeToRead=0;
    char *sFile="BIOSLOG.txt";

    SetCpuMode(CpuModeBigReal);
    DebugMemory = MemRead32(0x4e0);
    if(DebugMemory)
    {
        if((fp=fopen(sFile,"wb"))==NULL)
        {
            printf("Error, failed to open the file for save!\r\n");
        }
        else
        {
            Buffer = malloc(BUFFER_SIZE);
            if(!Buffer)
            {
                printf("Error, failed to allocate the memory!\r\n");
            }
            else
            {
                DebugLogSize = MemRead16(DebugMemory);
                printf("DebugMemory = %04X%04X, Size = %04X\r\n",(UINT16)(DebugMemory >> 16), (UINT16)DebugMemory, DebugLogSize);
                printf("Save to file...\r\n");
                for(Tmpi=0; Tmpi<DebugLogSize;)
                {
                    SizeToRead = DebugLogSize-Tmpi;
                    if(SizeToRead > BUFFER_SIZE)
                    {
                        SizeToRead=BUFFER_SIZE;
                    }
                    /*DEBUG("Read Address = %04X%04X, Size = %04X\r\n", (UINT16)((DebugMemory+Tmpi) >> 16), (UINT16)(DebugMemory+Tmpi), SizeToRead);*/
                    MemReadBlock(DebugMemory + Tmpi, Buffer, SizeToRead);
                    /*DEBUG("Save memory block to file...\r\n");*/
                    fwrite(Buffer, SizeToRead, 1, fp);
                    /*DEBUG("ok\r\n");*/
                    Tmpi += SizeToRead;
                    
                }
                printf("End\r\n");
                
                
            }
            fclose(fp);
        }
    }
    else
    {
        printf("Error, DebugMemory not found!\r\n");
    }
    SetCpuMode(CpuModeReal);
}
        得到的文件内容是类似这样的:
[CBC59C4A-383A-41EB-A8EE-4498AEA567E4]      runtime
[9F3A0016-AE55-4288-829D-D22FD344C347]      AmiBoardInfo
[13AC6DD0-73D0-11D4-B06B-00AA00BD6DE7]      EBC
[16271FCA-55D9-4A33-93FC-5A3EB128DE21]      MiscSubclassDxe
[E23F86E1-056E-4888-B685-CFCD67C179D4]      SBRun
[67AC0B1E-54C2-41A6-B57E-C2A321416ABC]      ActiveBios
[1A2B4139-0DA4-416C-ADE3-85877B318266]      SmmControl
[D57C852E-809F-45CF-A377-D77BC0CB78EE]      IdeSmart
[1314216C-CB8D-421C-B854-06231386E642]      PlatformInfoDxe
[DED7956D-7E20-4F20-91A1-190439B04D5B]      SmbiosGetFlashData
[2F72309E-D5B0-4A9D-84A9-1AB38C698F78]      EcPs2Kbd
[26A2481E-4424-46A2-9943-CC4039EAD8F8]      S3Save
...
GUID后面的名称是我自己在source里面查到后加上去的。

        至于把一些checkpoint或者Trace的信息保存到DebugMemory,方法也是类似的, 这里不再赘述!


猜你喜欢

转载自blog.csdn.net/oddxyz/article/details/6715811