The Boot Device Selection (BDS) phase UEFI DXE driver from American Megatrends (AMI) AmiModulePkg\Bds. This module implements the UEFI BDS phase -- the phase after DXE that handles boot manager, boot option enumeration, device connection, driver loading, SysPrep processing, console initialization, and ultimately boot device selection and OS handoff. This is one of the most critical UEFI modules, serving as the bridge between firmware initialization and OS boot.
The source paths embedded in debug strings confirm this module is built from AmiModulePkg\Bds\ with source files Bds.c, BootOptions.c, and BdsBoard.c. It is built as part of platform HR6N0XMLK using VS2015 for X64.
0x420 _ModuleEntryPoint -> 0x45C (UEFI Boot/Runtime Services Table init, library constructors) -> 0x988 (main BDS entry: saves global pointers, installs BDS protocol, registers CSM policy)
The main initialization flow:
0x420 ModuleEntryPoint(ImageHandle, SystemTable)
-> 0x45C sub_45C() [Initialize globals: gImageHandle, gST, gBS, gRT, gDS, mMmPciBase]
-> 0x6C94 sub_6C94() -- Get DxeServicesTable (gDS)
-> 0x6F9C sub_6F9C() -- MmPci base initialization
-> 0x6C08 sub_6C08() -- Get CPU arch protocol
-> 0x70BC sub_70BC() -- CPU I/O read (IO port access)
-> 0x184B0 sub_184B0() -- Some BIOS setup configuration
-> 0x410 sub_410() -- Rdtsc/lidt (read time-stamp counter/IDT)
-> 0x3E0 sub_3E0() - CLI (disable interrupts)
-> 0x184E4 sub_184E4() -- Timer read (IoRead32(0xCF9) & 0xFFFFFF)
-> 0x3D0 sub_3D0() -- PAUSE (HLT loop while waiting)
-> 0x3F0 sub_3F0() - STI (reenable interrupts) / 0x400 sub_400() -- CLI
-> 0x19AB0 sub_19AB0() -- Check ME Storage Service [SPS]
-> 0x7070 sub_7070() -- Locate protocol for ME
-> 0x9664 sub_9664() -- IPPMI callback registration (DxeLnvSendIpmiCmdLibConstructor)
-> 0x9E44 sub_9E44() -- Libbrary constructor for AutoGen
-> Read "Setup" UEFI variable (from runtime services offset 72 = GetVariable)
-> Check BootOptionSupport protocol (0x26540 GUID)
-> If found: call 0xC9F4 sub_C9F4() [CSM Policy init, option tag init]
-> Else: register callback via 0x7CBC for when protocol arrives
-> 0x988 sub_988(ImageHandle, SystemTable) [Main BDS entry]
-> Save SystemTable, BootServices, RuntimeServices, ImageHandle to globals
-> Overwrite FirmwareVendor with "American Megatrends"
-> Write FirmwareRevision = 0x5000E (327694) -> 5.0.0.14??
-> Install multiple protocols via BootServices + 328 (InstallMultipleProtocolInterfaces):
- unk_26450 (GUID for a BDS protocol?)
- off_26888 (Function table 1)
- unk_26620 (GUID 3)
- unk_26820 (Function table 3)
- unk_263A0 (GUUID 4)
- unk_26800 (Ffunction table 4)
The module installs a protocol with multiple GUID/interfaces at the end of 0x988. The function table offsets in .rdata:
The protocol at 0x26A78 (GUID: 05AD34BA-6F02-4214-952E-A04DA0398E2B99) is used by sub_7D14 to get the BDS protocol via LocateProtocol. This protocol has a function table with call offset +128 used for BDS dispatch in sub_283C.
The .data section (0x26360-0x27FC0) contains:
State/Configuration Variables:
n33686016 -- Flags byte (2 bytes), initialized from Setup variable offsets 0x7 (byte_27084 / byte_27C8B)byte_27F60 -- Boot state flag (0 = not started, 1 = started)UEFI Table pointers (initialized at 0x45C):
byte_278E8 (ME Storage Service available flag)Boot Option list:
Memory map pointers:
Execution policy:
Detected GUIDs in .rdata (used for LocateHandleBuffer, LocateProtocol, OpenProtocol, etc.):
The boot option processing follows this sequence (visible in string table at 0x1CCD0):
The BDS main loop handler (0x3894, sub_3894) processes the boot option list:
The boot option node structure (at least 112 bytes per entry):
Boot Option Loading and Execution:
The main boot loop (0x2C5C, sub_2C5C):
Driver Loading (0x13B8):
Same pattern but reads "DriverOrder" and "Driver%04X" variables. Loads and starts UEFI driver images.
SysPrep Processing (0x1610):
Same pattern but reads "SysPrepOrder" and "SysPrep%04X" variables. Loads and starts SysPrep applications.
Console Variable Processing (0x1E78, 0x1F78):
Boot Manager Protocol (0x7D14):
Caches the BDS protocol (located by GUID at 0x26A78). The protocol has a function table:
| Address | Name | Purpose |
|---|---|---|
| 0x68F8 | DebugPrint | Conditional debug print (most xref'd function in module - 604 refs). Checks debug mask, calls EFI_DEBUG_PROTOCOL or UEFI DebugLib |
| 0x6940 | Assert | ASSERT macro handler (145 refs). Calls debug protocol assert handler |
| 0x6878 | GetDebugProtocol | Gets EFI_DEBUG_PROTOCOL for debugging |
| 0x7BFC | GetVariableWrapper | Wrapper around RT->GetVariable that handles buffer size mismatch (status 0x8000000000000005 = EFI_BUFFER_TOO_SMALL) by reallocating |
| 0x78F4 | AllocatePool | BootServices AllocatePool wrapper |
| 0x7CBC | RegisterProtocolCallback | Registers protocol notification callback |
| 0x8400 | Swprintf | Unicode string formatting (likely UnicodeSPrint or equivalent) |
| 0x7FA4 | Sswprintf | Unicode format to stack buffer |
| 0x1BAF0 | ZeeroMem | Zero memory |
| 0x7960 | ValidateDevicePath | Validates a device path by walking path nodes |
| 0x84BC | CompareGuid | GUID comparison |
| 0x6C94 | GetDxeServicesTable | Gets DXE Services Table |
| 0x6C08 | GetCpuProtocol | Gets CPU Architecture Protocol |
| 0x70BC | CpuIoRead | CPU I/O read (port I/O access) |
| 0x184E4 | IoRead32 | Reads 32-bit I/O port at 0xCF9 (reset control) |
| 0x184B0 | WriteCmos | CMOS write access |
| 0x1BAA0 | GetPerformanceCounter | Gets performance counter frequency |
| 0x8858 | DevicePathToText | Converts device path node to text |
| 0x9E44 | AutoGenConstructor | Library constructor from AutoGen.c |
| 0x77F0 | GetDevicePath | Extracts device path from handle |
| 0x5300 | ParseSnpDevicePath | Parses SNP (Simple Network Protocol) device path |
| 0x51D4 | GetSnpHandle | Gets SNP handle for MAC address |
| 0x1018 | BootDevicePath | Boot from device path entry |
| 0x1178 | BootFilePath | Boot from file path entry |
| 0xC50 | LocateHandleBuffer | Wrapper around BS->LocateHandleBuffer |
| 0x13250 | GetBootOptionDesc | Gets boot option description string |
UEFI Boot Option variable layout (from Boot####):
+0x00: UINT32 Attributes (bit 0 = LOAD_OPTION_ACTIVE)
+0x04: UINT16 FilePathListLength
+0x06: CHAR16 Description[] (null-terminated)
...[2*len + 2 bytes, padded to 4-byte align]...
EFI_DEVICE_PATH_PROTOCOL FilePathList[FilePathListLength]
UINT8 OptionalData[]
Internal boot option node (as seen in sub_3EF4 comparison):
+0x00: next pointer +0x08: previous pointer +0x40 (offset 0x40 = 64t): UINT16 OptionNumber +0x44 (offset 0x44 = 68t): UINT32 Priority +0x48 (offset 0x48 = 72): UINT32 GroupId +0x69 (offset 0x69 = 105): UINT8 Flags (bit 0 = disabled)
This BDS implementation includes Lenovo-specific IPMI boot management:
At 0x27050 (814 bytes at 0x27C00), this is the setup data (UEFI "Setup" variable). Fields:
The dword_277E4 at 0x277E4 controls which processing phases are enabled:
Consumed (this module calls into others via BootServices/RuntimeServices):
Consumed By (other modules call this):
Imports: None (all DXE, no PEIM imports -- standard for DXE drivers)
| Address | String |
|---|---|
| 0x1BC40 | e:\\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\AmiModulePkg\Bds\Bds\DEBUG\AutoGen.c |
| 0x1BCC0 | e:\\hs\\AmiModulePkg\Bds\Bds.c |
| 0x1C8F8 | e:\\hs\\AmiModulePkg\Bds\BdsBoard.c |
| 0x1D390 | e:\\hs\\AmiModulePkg\Bds\BootOptions.c |
| 0x1E690 | e:\\hs\\AmiModulePkg\CSM\CsmPolicy\CsmPolicy.c |
| 0x1E1E80 | e:\\hs\\LenovoServerPkg\Library\LnvIpmiLib\IpmiCmd\DxeLnvSendIpmiCmdLib.c |
| 0x1E200 | e:\\hs\\MdeModulePkg\Library\PiDxeS3BootScriptLib\BootScriptSave.c |
| 0x1DA80 | e:\\hs\\MdepPkg\Library\DxeServicesTableLib\DxeServicesTableLib.c |
TWo-phase entry: First sub_45C initializes all library globals (gST, gBS, gRT, gDS), then sub_988 installs the BDS protocol interfaces.
Variable-read pattern: Uses sub_7BFC which wraps RT->GetVariable with auto-buffer-resize. Most variable reads go through this pattern with 0x263C0 (EFI_GLOBAL_VARIABLE) as the vendor GUID.
Boot option enumeration pattern: Read "XxxxOrder" -> get UINT16 array -> for each entry, format "Xxx%04X" -> read variable -> parse -> dispatch. This pattern repeats identically for BootOrder, DriverOrder, and SysPrepOrder.
Protocol notification pattern: Uses sub_7CBC to register for protocol availability callbacks (BootServices + 168 = RegisterProtocolNotify), typically passing a GUID and callback function pointer.
Linked list processing: Uses a standard doubly-linked list for boot option nodes (at xmmword_27F88 as list head). Functions sub_3D04 sorts the list with comparator sub_3EF4.
String formatting: Uses sub_8400 and sub_7FA4 for Unicode string formatting (emsprintf-style with L"%s", L"%d", L"%04X" format strings).
Firmware Vendor override: Overwrites SystemTable->FirmwareVendor with "American Megatrends" string during initialization.