背景知识还是参考:[我所认识的BIOS]系列 -- CPU的第一条指令。工作的缘故,我能接触到Intel Comet Lake RVP board,同时也有IBV提供的Reference Code,所以本文不过是基于原作者的文章实操一遍。
Step 0:
Reference Code生成的Master Rom大小为32MB,下图是Master Rom布局(用UEFITool打开Master ROM),其中BIOS块位于Master Rom的尾部:
展开BIOS region,其尾部显示为Sec Core,包含4块Section一个TE Image section和3个Raw section
这4个Section都可以被提取(选中Item--右键--"Extract body"--save),特别的TE image被提取后可以被IDA识别(因为TE image是精简版的PE文件,至于从源文件生成BIOS binary的过程,我会另起一篇文章分析):
IDA部分输出如下:
它和SecEntry.asm文件开头部份的代码几乎一致(内容不便贴出)。
UEFI启动的第一阶段是SEC阶段,SecEntry.asm文件名中虽然含有"SecEntry"字眼,但是它并不是开机执行的第一个Section,更谈不上开机时执行的第一条指令。另外,Master Rom最后16字节(即物理地址0xFFFFFFF0)的OPCode形如"0x90 0x90 0xE9",然而前面截图中OpCode不具备这样的特征:
所以可以断定SecEntry.asm所在的Section不包含开机执行的第一条指令,所以我们要将目光转移到同属同一个FFS的其他Section。看看最后一个Raw Section,提取并用IDA加载试试:
然而,IDA并不能识别其中的指令流,没办法只能用16进制编辑器打开:
看看嘛,偏移0x30处有"0x90 0x90 0xE9"这样的OPCode。其实raw.bin偏移0x30处正好对应物理地址0xFFFFFFF0。还没完,Raw.bin虽然小,但仔细挖掘一下内容不少,先参考UDK中UefiCpuPkg\ResetVector\FixupVtf\Vtf.nasmb文件,这是UDK的ResetVector:
BITS 16
ALIGN 16 ; 0xffffffd0
applicationProcessorEntryPoint:
;
; Application Processors entry point
;
; GenFv generates code aligned on a 4k boundary which will jump to this
; location. (0xffffffd0) This allows the Local APIC Startup IPI to be
; used to wake up the application processors.
;
jmp short resetVector
ALIGN 16 ; 0xffffffe0
peiCoreEntryPoint:
;
; PEI Core entry point
;
; GenFv fills the address of the PEI Core into this location
;
DD 0x12345678
ALIGN 16 ; 0xfffffff0
resetVector:
;
; Reset Vector
;
; This is where the processor will begin execution
;
nop
nop
jmp near $
ALIGN 8
ApStartupSegment:
DD 0x12345678
BootFvBaseAddress:
DD 0x12345678
ALIGN 16 ; 0x100000000
这份文件是Raw.bin的源文件,根据注释,在0xFFFFFFD0-0xFFFFFFFF之间为下列(伪)结构体:
struct
{
BYTE jmpReset[8];
DWORD pad0;
DWORD peiCoreEntryPoint;
DWORD pad1;
BYTE resetVector[8] = {0x90,0x90,0xe9,0x??,0x??};
DWORD ApStartupSegment;
DWORD BootFvBaseAddress;
};
其中peiCoreEntryPoint,ApStartupSegment,BootFvBaseAddress是在Build Master ROM阶段确定。(peiCoreEntryPoint/BootFvBaseAddress是两个地址值,是不是能inline-hook一把?)。resetVector的jmp指令使得BIOS跳去执行(IBV)FSP初始化相关的代码,也就是前面提到的SecEntry.asm中的代码。