SBL chooses EDK II build system to compile and build SBL image. EDK II build infrastructure provides a flexible framework supporting different platforms and extensive configuration capabilities.
It supports many tools chains including GCC on Linux and Visual Studio on Windows.
This choice also comes with two benefits:
EDK II build tool is familiar to many UEFI/BIOS developers
Open source EDK II libraries can be ported with smaller effort
SBL build process is implemented in top level build script
BuildLoader.py. The following diagram illustrates main steps:
The generated files are located in
The SBL image, configuration data, and (generated) helper scripts, are located in
To assist debugging, the build process also generates
SlimBootloader.txt file which contains flash layout details for each component in SBL image.
Pre Build Customization
SBL build system provides build time customization. Before the build, one can modify the configuration file
Platform/<Platform_Foo>/BoardConfig.py based on requirement, image footprint, or hardware features etc.
Prebuild process determines the build time configuration by generating multiple files, among those are:
Finalized platform configuration based on
C header file for configuration data structure based on
C file for Internal configuration data with default values
See Customize Build for more details.
SBL master build script
BuildLoader.py provides many options to compile images. To get help:
python BuildLoader.py build -h
Set env variable for SBL Key directory:
Build SBL for a supported platform:
python BuildLoader.py build <platform_name>
Clean up files generated during build process:
python BuildLoader.py clean
Final SBL image(s) should be generated under
See Build Tool for more details.
Build Details per Stage
Slim Bootloader is built in stages and more information on each stage is given below.
Packaged As: FD containing Stage1A FV, and FSP-T binary as a FILE
Stage 1A FV:
PEIPcdDataBase, and Stage1A PEIM
Stage 1A contains a module called VTF (Volume Top File) which is placed at the top within the Stage 1A FV. The VTF contains the reset vector code and hence the VTF needs to be placed at an appropriate address so that the reset vector code in the the Vtf0 file (Identified by the GUID
1BA0062E-C779-4582-8566-336AE8F78F09) aligns with the reset vector of Intel x86 architecture.
The entry point for the Stage1A module within the Stage1A FV (
_ModuleEntryPoint) is placed as the first DWORD of the built FV. The reset vector code from the Vtf0 jumps to this address and continues from the
Packaged As: FD containing Stage1B FV, and FSP-M binary as a FILE
Stage 1B FV: Contains
CfgDataInt.bin, and Stage1B PEIM
Packaged As: FD containing Stage2 FV, and FSP-S binary as a FILE
Stage 2 FV: Contains ACPI Table, Vbt, Logo, and Stage2 PEIM
Packaged As: FD containing OsLoader FV
Packaged As: FD containing Firmware Update FV
Note that FwUpdate is included only if
ENABLE_FWUis enabled in
In addition to the Slim Bootloader Stages and the payloads, the final SBL image may include some other components like Microcode binaries, ACM binary, SBL container binaries, etc.
Post Build Image Construction
Each stage and component of Slim Bootloader is individually built and then put together into one image at the end of the build process.
The final image layout for Slim Bootloader can be defined in
If firmware resiliency is enabled, the layout will typically contain redundant copies of the boot-critical code. Check Firmware Resiliency and Recovery for more details.
As discussed above, the final SBL image includes SBL stages and other components, examples of which are listed below:
These additional components included in the SBL image are placed in the non-redundant region of the image
The list of components in the final image in the final image is present in the
ACM.bin- Authenticated Code Module
MRCDATA.bin- Memory Reference Code Data, used to store Memory Reference Code training data
VARIABLE.bin- This region is used for
SetVariable()APIs provided by
UCODE.bin- CPU Microcode
The components listed above are generated by the
Payloads other than OsLoader and FW Update are built independently and the payload binary is packaged as
EPAYLOAD.binto be included in the final SBL image
EPAYLOAD.bin- Payload for SBL - used for extra payloads (UEFI Payload, Linux, u-boot, etc.). Refer to Integrate Multiple Payloads for more details.
Patching of stages
Patching of stages is done to allow for code simplicity and for faster booting. The addresses of certain elements like BFV, FIT, FlashMap, etc. are pre-loaded into the SBL binary at pre-defined locations.
The Boot Firmware Volume (BFV) address needs to be placed as the the last DWORD of memory. Thus, the BFV needs to be placed as the last DWORD of Stage 1A. And this BFV will be mapped to the memory address
0xFFFFFFFC(top of memory - 4).
Thus, in the image layout, BFV will be patched onto (top of Stage 1A -
When passing a negative offset to
patch_fv(), it is considered relative to 4GB (
Thus, the final offset will be equal to :
FileSize - (0xFFFFFFFF - offset + 1)
This can be seen in patching of BFV, FlashMap, and FIT.
Stage 1A Entry point is patched onto the Stage 1A
Stage 1A Module base is patched onto entry point + 4
Address of VerInfo file (GUID:
3473A022-C3C2-4964-B309-22B3DFB0B6CA) is patched onto
Address of PcdFileDataBase (GUID:
EFAC3859-B680-4232-A159-F886F2AE0B83) is patched onto
Address of FlashMap (GUID:
3CEA8EF3-95FC-476F-ABA5-7EC5DFA1D77B) is patched onto
0xFFFFFFF8(top of Stage 1A - 0x08)
Address of Firmware Interface Table (FIT) is patched onto memory address
0xFFFFFFC0(top of Stage 1A - 0x40)
FIT Signature Low, FIT Signature High, and FIT table max length are patched onto offsets 0, 4, and 8 respectively.
FIT entries are generated by
BuildLoader.py - update_fit_table()at build time.
Address of HashStore is patched onto
Stage 1B entry point address is patched into the Stage 1B
Stage 1B module based is patched onto entry point + 4
Address of Internal CfgDataBase (GUID:
016E6CD0-4834-4C7E-BCFE-41DFB88A6A6D) is patched onto
Stage 2 entry point address is patched into the Stage 2
Stage 2 module based is patched onto entry point + 4
Address of VBT (GUID:
E08CA6D5-8D02-43AE-ABB1-952CC787C933) is patched onto
Address of ACPI Table (GUID:
7E374E25-8E01-4FEE-87F2-390C23C606CD) address is patched onto
Address of Splash Logo (GUID:
5E2D3BE9-AD72-4D1D-AAD5-6B08AF921590) address is patched onto
Post Build Customization
SBL supports platform customizations by embedding configuration data in a dedicated region in the image. The configuration data region can be patched without recompiling the code. This feature is most useful in supporting multiple similar boards in a single SBL image.
Adding an SBL Container
It may be required to include additional binary components to the final SBL image.
The required components can be added to the image as SBL containers
GetContainerList()initially creates a blank list, and then adds each container entry into this list
The list of containers included in the final SBL image can be seen in the platform’s
BoardConfig.py - GetContainerList()function
GetContainerList()returns a list of containers. Each container entry is also a list consisting of several different fields shown in the example below
Make sure that the existing entries in the function are being put into
container_listas one list
To create a new container, you will need to create a list where the first entry lists the container, and the remaining list the components inside it
Adding files named
test3to a container named “SBLC” will be done as follows:
def GetContainerList (self): container_list =  ... ... container_list.append([ # Name | File | CompressAlg | AuthType | Key File | Region Align | Region Size | Svn Info ('SBLC', 'SBLC.bin', '', container_list_auth_type, 'KEY_ID_CONTAINER'+'_'+self._RSA_SIGN_TYPE, 0, 0 , 0), ('TST1', '/path/to/test1', '', container_list_auth_type, 'KEY_ID_CONTAINER_COMP'+'_'+self._RSA_SIGN_TYPE, 0, 0 , 0), ('TST2', '/path/to/test2', '', container_list_auth_type, 'KEY_ID_CONTAINER_COMP'+'_'+self._RSA_SIGN_TYPE, 0, 0 , 0), ('TST3', '/path/to/test3', '', container_list_auth_type, 'KEY_ID_CONTAINER_COMP'+'_'+self._RSA_SIGN_TYPE, 0, 0 , 0)3 ]) ... ...
This will create a container named
.binfile needs to be added to the SBL image layout so that it can be included in the final image
In the platform’s
BoardConfig.py, we need to add the size of the required component.
GetImageLayout(), add the component to the non-redundant section
class Board: ... ... self.SBLC_SIZE = 0x1000 ... def GetImageLayout(): ... ... img_list.extend ([ ('NON_REDUNDANT.bin', [ # File | Compression | Size | Stitch Mode | Stitch Position ('SBLC.bin' , '' , self.SBLC_SIZE, STITCH_OPS.MODE_FILE_PAD, STITCH_OPS.MODE_POS_TAIL), ... ... ] ) ]) ... ...
Release vs Debug Build
SBL build system provides building debug or release images. Debug build contains verbose log messages for debugging, while release build image is deployed in a production environment. It contains minimum log messages to the console, and in some cases, may be built with more secure configurations, compared to debug build image.
Build system builds debug SBL image by default. To build a release image:
python BuildLoader.py build <target> -r
When verified boot is enabled, SBL release build requires container image format to boot OS.
Developing on Windows
Typically, Windows C compiler generates smaller code size compared to GCC build. This needs to be considered when allocating image size in SBL build.