UEFI BIOS file device, one and a half part: UEFI Platform Initialization

  • Tutorial
In the first part of this article, we introduced the UEFI Capsule format and Intel Flash Image. It remains to consider the structure and contents of the EFI Firmware Volume, but to understand the differences between PEI modules and DXE drivers, we start with the UEFI boot process, and set the EFI Firmware Volume structure 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 the whole process, but its part - Platform Initialization (PI), which is divided into 3 phases: SEC , PEI and DXE .
All PI documentation is free to download from the UEFI Forum website . SEC and PEI phases are described in Volume 1, DXE phase in Volume 2, common architectural elements, including EFI FFS file and header formats of interest to us , in Volume 3, SMM subphase(starts in the middle of DXE and runs in parallel) - in Volume 4, standards for PI-compatible hardware and software - in Volume 5. I won’t write about hardware and software here, but the rest of the phases need to be mentioned, because Without knowing them, it is difficult to understand why there are so many things 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: powering on after an inactive state, rebooting from an active state, exiting deep sleep mode, various kinds of exceptional situations
  2. Prepare temporary memory
  3. Become a Root of Trust system: either trust the rest of the PI parts, 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, platform status, address and BFV size , address and size of temporary RAM, address and stack size are transmitted

In fact, on x86-64, the SEC phase goes like this:
  1. Reset Vector: reset the cache and switch to the main initialization procedure in ROM
  2. Switch to protected mode: switch to protected mode of the processor with flat memory without swapping
  3. Initialize MTRRs for BSP: Cache Known Values ​​for Different Memory Areas
  4. Microcode Patch Update: Updates the microcode of all available processors.
  5. Initialize NEM : a free cache is marked as non-flushable, after which it can be used as temporary RAM until the main one is initialized, and it also allows you to write this very initialization in ordinary PL with a stack, in this case in C
  6. Early BSP / AP interactions: sending all APs an INIT IPI interrupt , then Start-up IPI, receiving BIST data from all APs
  7. Hand-off to PEI entry point: transfer control and data to the PEI phase

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

PEI phase

The second phase, the main task of which is to initialize a sufficient amount of continuous RAM so that you can start the DXE phase, prepare and transfer data about the detected devices to the DXE phase so that the DXE drivers can correctly initialize them. 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 check the validity of other modules may also be present. The PEI architecture allows independent development and debugging of modules, and no one bothers to write and integrate their 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 selected by the PEI manager. PEIMs can populate position-independent data structures — HOBs , which contain data to pass to the DXE driver and the GUID of that driver.
In fact, on x86-64, the PEI phase happens like this:
  1. Establish use of “memory": transferring data from ROM to early RAM (ie to cache)
  2. PEI Dispatcher: Run PEIM modules in order from no dependencies to complex dependencies. This is a cycle that ends when there are no running modules.
  3. CPI PEIM: initialize the CPU, configure the MSR, etc. (We will return to this module when discussing the CPU PM patch)
  4. Platform PEIM: early initialization of MCH , ICH , platform built-in interfaces ( SMBus , Reset, etc.). Determining the boot mode (normal, Recovery, S3 Resume) using the data obtained in the SEC phase.
  5. Memory Initialization PEIM: initializing the main RAM and transferring data from the cache to it, which can now be used normally. the process depends on the state of the system defined in the previous step, for example, when S3 Resume memory testing is not performed, which reduces boot time
  6. If the system is not in the S3 Resume, then the transfer of HOBs and control to the DXE phase occurs, and the PEI phase ends
  7. If it is still located, the CPU PEIM for S3 Boot Script is executed, which returns all processors to their saved state
  8. S3 Boot Script Executor: restoring the state of other devices
  9. OS Resume Vector: Transition to OS

Thus, with S3 Resume, the start of the DXE phase does not occur at all, which can greatly accelerate the download. When you enable FastBoot, you can accelerate the download even more by performing a minimal 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 requiring early initialization will be needed. It is also worth mentioning that the format of PEI modules can both coincide with the format of DXE drivers (PE32 +), and may differ from it in a header, because the PE32 + header contains many unused fields in the PEI phase, and the processor’s cache is not rubbery. Therefore, a special TE format was developed for PEIM , the header of which contains only the necessary fields. TE 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, since otherwise such a module does not start the DXE driver.

DXE Phase

Here, the main and final initialization of everything is performed based on the received from PEI HOBs. DXE code consists of a kernel, aka DXE Foundation, dispatcher, and 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 finalize hardware initialization and provide hardware abstraction for services. All DXE code, except the Foundation Runtime parts and the Runtime DXE drivers, is unloaded from memory at the end of the BDS phase , which I will not discuss here.
It doesn't make sense to describe thoroughly the DXE startup process, you can describe it in a nutshell: the kernel boots up, creates the necessary data structures, then the dispatcher starts and loads all available drivers from all available media, then the bootloader starts and tries to find the OS loader on these media and transfer him control. If found - excellent, if not - try on until we find it. If you haven’t found anything yet, we’ll execute the code for the Platform Policy module, which was written for us by the motherboard manufacturer, which displays a message that says “Operating System is missing”.
It can be seen that from the BIOS image for this phase, DXE drivers are needed and all that they may need. Most of the files in EFI FS are used here.

Subphase SMM

During the DXE phase, the moment comes when the dispatcher loads the SMM Init driver, from which this subphase begins. SMM is a special processor mode that it switches to when it receives a special interrupt - SMI , which can be either software or hardware. Most (or even all) of the SMI sources can be disabled if you do not need to switch to SMM. SMM code runs in SMRAM , which becomes unavailable 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 DXE phase ends, until the PC shuts down.
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 completely blocks access to SMRAM. 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 types of these drivers: pure SMMs that are loaded directly by the Init into SMRAM, and SMM / DXE hybrids that are first launched by the DXE manager and then copy part of themselves to SMRAM. The SMM Init itself is just such a hybrid.
It can be seen that SMM drivers are needed for this subphase from the BIOS image.

Conclusion


Now you know how UEFI loads 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 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. Analysis of the building blocks and attack vectors associated with the Unified Extensible Firmware Interface (UEFI), Paper by Jean-François Agneessens
  2. Reducing Platform Boot Time, Paper by Michael Rothman, Genliu Xing, Yan Wang and Jiong Gong
  3. UEFI Platform Initialization Specification 1.2.1 Errata A, Documents by UEFI Forum

Also popular now: