📜 ⬆️ ⬇️

Device file UEFI BIOS, part and a half: UEFI Platform Initialization

In the first part of this article, we learned about the UEFI Capsule and Intel Flash Image format. It remains to consider the structure and contents of EFI Firmware Volume, but to understand the differences between PEI modules and DXE drivers, we start with the UEFI boot process, and leave the structure of EFI Firmware Volume to the second part.

UEFI Platform Initialization


From a bird's eye view, the UEFI boot process looks like this:

Generally speaking, we are not interested in all this process, but in its part - Platform Initialization (PI), which is divided into 3 phases: SEC , PEI and DXE .
All PI documentation can be freely downloaded from the UEFI Forum website . The SEC and PEI phases are described in Volume 1, the DXE phase in Volume 2, common architectural elements, including the EFI FFS file and header formats that interest us in Volume 3, the SMM subphase (starts in the middle of DXE and runs parallel) in Volume 4, standards for equipment and software compatible with PI are in Volume 5. I will not write about equipment and software here, but the remaining phases should be mentioned, since without knowing them, it is difficult to understand why there is so much in the BIOS file and how it all differs from each other.

SEC Phase

The first phase of the download, the tasks of which are as follows:
  1. Process all types of platform restarts: power on after inactive state, rebooting from active state, exit from deep sleep mode, various exceptions
  2. Prepare a temporary memory
  3. Become a Root of Trust system: either trust the rest of the PI, or check their validity in some way
  4. Prepare the necessary data structures and transfer them and control to the PEI phase. At a minimum, the state of the platform, the address and size of the BFV , the address and size of the temporary RAM, the address and size of the stack are transmitted

In fact, on x86-64, the SEC phase goes like this:
  1. Reset Vector: reset the cache and go to the main initialization procedure in ROM
  2. Switch to protected mode: switch to a protected mode processor with flat memory without paging
  3. Initialize MTRRs for BSP: caching of known values ​​for different memory areas
  4. Microcode Patch Update: microcode update of all available processors
  5. Initialize NEM : the free cache is marked as non-resettable, after which it can be used as temporary RAM before initialization of the main one, and also allows you to write this initialization on ordinary PLs with a stack, in this case C
  6. Early BSP / AP interactions: sending all AP interrupts INIT IPI , then Start-up IPI, receiving BIST data from all APs
  7. Hand-off to PEI entry point: transfer of control and data to the PEI phase

It can be seen that participants in the SEC phase from the BIOS image will need at least patches for the CPU microcode stored there, as well as the address and size of the Boot Firmware Volume. Yes, and the SEC code itself is recorded in the same chip and is still running there.

PEI phase

The second phase, the main task of which is to initialize enough continuous RAM so that you can start the DXE phase, prepare and transfer the detected devices to the DXE phase so that the DXE drivers can correctly initialize them. The PEI executable code consists of a kernel called the PEI Foundation, which is common to processors with the same architecture and PEIM modules that perform initial initialization of specific devices and developed by the manufacturers of these devices. Chain of Trust support modules that perform validation checks on other modules may also be present. PEI allows independent development and debugging of modules, and no one bothers to write and integrate your own module, if necessary.
PEIM may have a list of dependencies on other modules, so the order of their launch is not random and is chosen by the PEI dispatcher. PEIM modules can fill in data-independent data structures — HOBs , which contain data for transmission to the DXE driver and GUID of this driver.
In fact, on x86-64, the PEI phase happens like this:
  1. Establish use of "memory": transfer data from ROM to early RAM (i.e., cache)
  2. PEI Dispatcher: Launching PEIM modules in order from non-dependencies to complex dependencies. This is a loop that ends at the moment when there are no remaining modules
  3. CPI PEIM: CPU initialization, MSR setup, etc. (We will return to this module when discussing the CPU PM patch)
  4. Platform PEIM: early initialization of MCH , ICH , embedded platform interfaces ( SMBus , Reset, etc.). Determination of the boot mode (normal, Recovery, S3 Resume), using data obtained in the SEC phase.
  5. Memory Initialization PEIM: initialize the main RAM and transfer cache data to it, which can now be used normally. the process depends on the state of the system defined at the previous step, for example, when S3 Resume memory testing is not performed, which reduces the load time
  6. If the system is not in S3 Resume, then HOBs and control are transferred to the DXE phase, and the PEI phase ends there.
  7. If it does, it is running the PEIM for S3 Boot Script CPU, which returns all processors to their saved state.
  8. S3 Boot Script Executor: restore the status of other devices
  9. OS Resume Vector: transition to OS

Thus, with S3 Resume, the launch of the DXE phase does not occur at all, which makes it possible to speed up the loading greatly. When you turn on FastBoot, loading can be accelerated even more by running the minimum set of tests and PEIM modules.
It can be seen that in the PEI phase from the BIOS image, at least the PEI Foundation and modules for all equipment that needs early initialization will be needed. It is also worth telling that the format of PEI modules may either coincide with the format of the DXE (PE32 +) drivers, or be different from it by the header, since The PE32 + header contains many fields that are not used in the PEI phase, and the place in the processor cache is not rubber. Therefore, a special TE format was developed for PEIM, the header of which contains only the required fields. TEs are executable-in-place ( XIP ), relocatable and position independent ( PIC ). There are also hybrid DXE / PEI modules with two entry points, but they must be in PE32 + format, because otherwise the DXE driver will not launch such a module.
')
DXE Phase

Here, the main and final initialization of everything is performed based on the HOBs received from PEI. The DXE code consists of the kernel, it is the DXE Foundation, the dispatcher, and the drivers. The kernel initializes and starts various UEFI services: Boot Services, Runtime Services, and DXE Services. The dispatcher is responsible for finding and running DXE drivers, which also have dependencies. Drivers perform final hardware initialization and provide hardware abstraction for services. All DXE code, except the Runtime parts of the Foundation and the Runtime DXE drivers, is unloaded from memory at the end of the BDS phase, which I will not discuss here.
There is no sense in describing the DXE startup process thoroughly either, it can be described in two words: the kernel is loaded, it creates the necessary data structures, then the dispatcher starts up and loads all available drivers from all available media, then the bootloader starts up and tries to find the OS bootloader on these media his management. If it is found, it is excellent; if not, we try further until we find it. If they didn’t find anything, we execute the code of the Platform Policy module, which the motherboard manufacturer wrote for us, giving us a message that “Operating System is missing”.
It can be seen that from the BIOS image for this phase you need DXE-drivers and everything that they may need. Most of the files in EFI FS are used here.

SMM subphase

During the DXE phase, the moment comes when the dispatcher loads the SMM Init driver, from which this subphase begins. SMM is a special mode of the processor, which it switches to when receiving a special interrupt - SMI , which can be both software and hardware. Most (or even all) SMI sources can be disabled if the transition to SMM is not required. The SMM code runs in SMRAM , which becomes inaccessible to the OS after the end of the DXE phase, because the SMM driver intentionally closes access to it. The SMM code is executed even after the end of the DXE phase, before the PC is turned off.
The SMM Init driver opens SMRAM, creates its map and data structures needed to run other SMM drivers, and before the end of the phase, DXE closes SMRAM access completely. SMM drivers are hardware dependent and do not have access to the bytecode interpreter, so writing SMM drivers on EBC is not supported. There are two kinds of these drivers: pure SMM, which are loaded by the Init directly into SMRAM, and SMM / DXE hybrids, which are first launched by the DXE controller and then copy a part of themselves into SMRAM. The SMM Init itself is just such a hybrid.
It can be seen that SMM drivers are needed for this subphase from a BIOS image.

Conclusion


Now you know how UEFI boots and what modules are needed for it.
I decided to divide the planned second part into two more in order to reduce the size of the post and reduce the cognitive load on the reader.
In the second part of the article, we will finally look at the structure of the EFI FV file, and the information from this one will be very useful for you there.
Thanks for attention.

Literature


  1. Unified Extensible Firmware Interface (UEFI), Paper by Jean-François Agneessens
  2. Reducing Platform, Michael Rothman, Genliu Xing, Yan Wang and Jiong Gong
  3. UEFI Platform Initialization Specification 1.2.1 Errata A, Documents by UEFI Forum

Source: https://habr.com/ru/post/185764/


All Articles