WeHack BBS
[转] UEFI启动过程 - 可打印的版本

+- WeHack BBS (https://bbs.wehack.space)
+-- 版块: 计算机技术 (https://bbs.wehack.space/forum-5.html)
+--- 版块: 固件技术讨论区 (https://bbs.wehack.space/forum-8.html)
+--- 主题: [转] UEFI启动过程 (/thread-49.html)



[转] UEFI启动过程 - vimacs - 08-01-2018

https://lists.01.org/pipermail/edk2-devel/2018-July/027684.html

Rafael,

Since it is useful to also understand this when you are bringing up a platform....

SEC generally contains the hardware reset vector. SEC hands off to the PEI Core. Generally there is some build magic to help SEC find the PEI Core. Worst case you can walk the BFV (Boot Firmware Volume) and find it.

SEC hands the PEI Core the EFI_SEC_PEI_HAND_OFF structure. This is how the PEI Core knows about stack, heap, and the location of the BFV to find PEIMs
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Pi/PiPeiCis.h#L967

The PEI Core has a PPI Notify Callback for gEfiPeiFirmwareVolumeInfoPpiGuid, and  gEfiPeiFirmwareVolumeInfo2PpiGuid to discover new FVs.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Pei/FwVol/FwVol.c#L547

PEI Code writes hobs, EFI_HOB_TYPE_FV and EFI_HOB_TYPE_FV3, to help DXE discover FVs.

When the DXE Core is started it will call FwVolBlockDriverInit() and  all the EFI_HOB_TYPE_FV, and optionally pick up the authentication status from EFI_HOB_TYPE_FV3, will get processed.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c#L625

via calling ProduceFVBProtocolOnBuffer(). ProduceFVBProtocolOnBuffer() can also be called gBS->ProcessFirmwareVolume().
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c#L452
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c#L687

Loading drivers from the FV is the job of the DXE Dispatcher. The DXE Dispatcher has protocol notify event on gEfiFirmwareVolume2ProtocolGuid that will get the executables in the Dispatch list, mDiscoveredList.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c#L1193

So adding a gEfiFirmwareVolume2ProtocolGuid driver, or calling gBS->ProcessFirmwareVolume() is how you would make an FV show up that was not listed in the HOBs.

In the DXE Phase security is handle by gBS->LoadImage() and it uses gEfiSecurity2ArchProtocolGuid and gEfiSecurityArchProtocolGuid to validate the image. This makes sense as a signed EFI PE/COFF image has the signature in the PE/COFF image, so you have to start the PE/COFF loading process to verify that signature.  gEfiSecurity2ArchProtocolGuid lets you build security policy based on the location of the driver.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Image/Image.c#L1041

When the Dispatcher runs of things to Dispatch it returns and the DXE Core calls the BDS to process platform Boot Device Selection.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c#L550

After BDS starts the only way to run code from an FV would be to call gDS->Dispatcher(). Likely you would call gDS->ProcessFirmwareVolume() and then  gDS->Dispatcher(). To speed boot it is not uncommon to have multiple FVs. For example you could have an FV that contained all the setup resources and only call gDS->ProcessFirmwareVolume() on that FV if the user hit the Setup hot key.

Thanks,

Andrew Fish

PS For x86 (0xFFFFFFF0 reset vector) and any other architectures that have the reset vector at the end there is a special file name in the FV called gEfiFirmwareVolumeTopFileGuid that tells the FV creation tools to put that file at the very end of the FV, so the end of that file would end up at the reset vector location.