首页
社区
课程
招聘
分享一下UEFI固件的启动流程-SEC阶段
发表于: 2021-11-10 22:50 9626

分享一下UEFI固件的启动流程-SEC阶段

2021-11-10 22:50
9626

UEFI从上电到操作系统接管大致启动流程:
图片描述

 

本文主要涉及固件代码,不涉及TLS阶段及之后,因为这个阶段以后跟操作系统有关了。注意的是Uefi shell就是在TLS阶段,所以在写uefi应用模块的时候应该知道当前内存环境。

 

TLS阶段之前的代码,都是提前烧录到芯片中的,想调试前面的代码是有点困难的。我试了一下,IDA+gdb+vmware最早能接手的时候cpu已经进入ia32e模式了,内存也初始化完了,估摸着应该是DXE阶段。

 

本文基于intel开发的edk2,edk2是一个uefi框架,只是提供了一些代码可以参考,跟实际主板芯片上能用的代码还是有很大差距的,vmware的EFI64.ROM引导文件是基于edk2的,vbox也是。我去下了几个主流主板上新的bios,发现都是国外一个叫ami公司写的,而且并不依赖edk2,或许可能是把里面关于edk2的信息都删了,我也不清楚。

 

#
#

正文

首先cpu上电一定是实模式,走ResetVector,也就是复位后的第一行代码
UefiCpuPkg\ResetVector\Vtf0\Ia16\ResetVectorVtf0.asm

1
2
3
nop
nop
jmp     EarlyBspInitReal16

UefiCpuPkg\ResetVector\Vtf0\Ia16\Init16.asm

1
2
3
4
EarlyInit16:
    EarlyBspInitReal16:
    mov     di, 'BP'
    jmp     short Main16

UefiCpuPkg\ResetVector\Vtf0\Main.asm
图片描述
图片描述

 

这里有个问题,实模式下使用32位的寄存器。
参考
https://stackoverflow.com/questions/6917503/is-it-possible-to-use-32-bits-registers-instructions-in-real-mode

 

接下来就是16位实模式转32位,
UefiCpuPkg\ResetVector\Vtf0\Ia16\Real16ToFlat32.asm
主要是根据手册,设置一些控制寄存器的标志位。

 

图片描述
这里涉及到寻找BFV,BFV其实就是uefi image的起点。就相当于windows pe文件的dos头。

 

图片描述
这里就是BFV,结构可以参考uefi手册3.2.1章节
图片描述

 

本来自动解析uefi结构是有几个ida插件的,但是估计更新太慢了,在ida7.6上都用不了。就选择手动解析了。

 

找到BFV之后就找SEC entry point,把控制权交给SEC
图片描述

 

[ebp+0x30]又指向一个叫EFI_FFS_FILE_HEADER的结构,

 

图片描述
上图是第一个FFS,他会一直遍历每一个,直到遇到一个类型为EFI_FV_FILETYPE_SECURITY_CORE的节区。

 

图片描述
然后加上0x18,每个子节区的头大小都是固定的24字节。后面的字节就是每个类型不同的信息了。像SEC区的话就是一个PE32格式的映像。
然后就这样获得SEC的代码入口点
图片描述

 

到这里,正式进入UEFI内核的启动,也就是SEC阶段的开始。
OvmfPkg\Sec\X64\SecEntry.nasm

 

图片描述
这样子看不大懂,直接编译一下把宏去掉,就非常清楚了。
图片描述
所以代码中的FixedPcdGet(x)其实就相当于一个编译期确定的整数。

 

这部分代码就是选一段临时内存,并且填充一些数字。一部分当作堆,一部分当作栈。网上很多说设置MTRRs来把缓存当临时内存的,我没找到具体代码在哪。现在的bios都是16M大小,容纳810000h地址也是可以的,这部分不太清楚,有会的希望指点一下。

 

然后控制转到SecCoreStartupWithStack,

 

图片描述
这里的注释说了,我们目前是运行在flash芯片里的,内存此时还用不了。
InitializeCpuExceptioInHandlers就是把idt entry里的所有handler赋值为CommonInterruptEntry,定义在UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\ExceptionHandlerAsm.nasm。

 

紧接着调用ProcessLibraryConstructorList。这个函数在很多阶段会调用,只是完成不同的任务。

 

sec阶段主要是
图片描述
这部分代码存在于build/x64/OvmfPkg/AutoGen.c目录,build过之后才有,我也不知道咋回事。

 

然后调用InitializeFloatingPointUnits初始化浮点单元,
图片描述

 

然后存储一些信息,进入SEC二阶段,
图片描述
图片描述
,上面基本等于SecStartupPhase2(SecCoreData)

 

图片描述
然后SEC将控制转到PEI

 

......


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (1)
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2022-8-19 19:23
0
游客
登录 | 注册 方可回帖
返回
//