Newer
Older
AMI-Aptio-BIOS-Reversed / Bds / Bds_analysis.md
@Ajax Dong Ajax Dong 2 days ago 18 KB Init

BDS Module Analysis

Overview

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.

File Information

  • PE File: Bds.efi
  • Index: 0222
  • Architecture: X64 (64-bit)
  • Image Size: 0x2a200 (172544 bytes)
  • MD5: 4a4f005f2c6a8ac440e89ac98aad94ad
  • SHA256: 0776eca53ce72b8c8ba830939fd36719062bc4868ea3debd6338a1eafaa0ca0a

Address Range

  • Entry Point: 0x420 (_ModuleEntryPoint)
  • .text: 0x2e0 - 0x1bc00 (0x1b920 bytes, rx)
  • .rdata: 0x1bc00 - 0x26360 (0xa760 bytes, r)
  • .data: 0x26360 - 0x27fc0 (0x1c60 bytes, rw)
  • Total functions: 408
  • Total strings: 809

Module Structure

Entry Point Flow

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)

BBS Protocol Interface

The module installs a protocol with multiple GUID/interfaces at the end of 0x988. The function table offsets in .rdata:

  • off_26888 at 0x26888 -- Function pointer table (likely the BDS protocol)
  • off_26820 at 0x26820 -- Another function table
  • off_26800 at 0x26800 -- Another function table

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.

Gllobal Data Layout (.data section)

The .data section (0x26360-0x27FC0) contains:

State/Configuration Variables:

  • 0x27050 -- "Setup" UEFI variable data (814 bytes, copied from 0x27C00)
  • 0x27080 -- n33686016 -- Flags byte (2 bytes), initialized from Setup variable offsets 0x7 (byte_27084 / byte_27C8B)
  • 0x27C00 -- Setup variable buffer (814 bytes)
  • 0x27F60 -- byte_27F60 -- Boot state flag (0 = not started, 1 = started)

UEFI Table pointers (initialized at 0x45C):

  • 0x27810 -- SystemTable_0 (gST)
  • 0x27818 -- qword_27818 (gBS = BootServices)
  • 0x27820 -- ImageHandle_0 (gImageHandle)
  • 0x27828 -- qword_27828 (gRT = RuntimeServices)
  • 0x27840 -- qword_27840 (gDS = DxeServicesTable)
  • 0x27848 -- qword_27848 (mPciUsra = MM PCI base protocol)
  • 0x27858 -- qword_27858 (CPPU protocol interface)
  • 0x27898 -- qword_27898 (BDS protocol interface, cached)
  • 0x278B0 -- qword_278B0 (FPDT performance data variable)
  • 0x278E8 -- byte_278E8 (ME Storage Service available flag)
  • 0x278F0 -- qword_278F0 (IPMI protocol)

Boot Option list:

  • 0x27930 -- qword_27930 (Boot option list head)
  • 0x27938 -- qword_27938 (Option tag list)
  • 0x27940 -- qword_27940 (Boot option support callback)
  • 0x279E0 -- qword_279E0 (Driver re-connect count)
  • 0x279E8 -- qword_279E8 (Driver re-connect handle array)

Memory map pointers:

  • 0x27800 -- qword_27800 (Memory map key/size)
  • 0x277F8 -- qword_277F8 (Memory map buffer)

Execution policy:

  • 0x277E4 -- dword_277E4 (BDS execution policy flags, bits [0:1] = type)

Keey Protocol GUIDs

Detected GUIDs in .rdata (used for LocateHandleBuffer, LocateProtocol, OpenProtocol, etc.):

  • 0x26360 -- LOaded image protocol
  • 0x263A0 -- UEFI BDS Architecture Protocol (installed by this driver)
  • 0x263C0 -- EFI_GLOBAL_VARIABLE_GUID
  • 0x26430 -- MM PCI base protocol (CpRcPkg)
  • 0x26450 -- BBS protocol
  • 0x264B0 -- SN Network Interface Identifier protocol
  • 0x26540 -- BootOptionSupport protocol
  • 0x26560 -- Block I/O protocol
  • 0x26580 -- Device Path protocol
  • 0x26590 -- Device Path To Text protocol
  • 0x265A0 -- Loaded Image Device Path protocol
  • 0x26650 -- SIMple File System protocol
  • 0x26660 -- IPPMI protocol (Lenovo)
  • 0x26690 -- ME Storage protocol
  • 0x26720 -- Option Tag protocol
  • 0x26780 -- UEFI HDD device path protocol
  • 0x267A0 -- CapsuleUpdateData GUID (runtime variable)
  • 0x267B0 -- ACPI table protocol
  • 0x267C0 -- DxeServicesTable GUID
  • 0x267D0 -- BBD phase dispatch protocol
  • 0x267E0 -- EFI_GLOBAL_VARIABLE (normal, not volatile)
  • 0x267F0 -- Timer arch protocol
  • 0x26888 -- BBS protocol function table
  • 0x26940 -- Boot option context

Booot Option Lifecycle

The boot option processing follows this sequence (visible in string table at 0x1CCD0):

  1. DefaultFixedBootOrder_Init -- Initialize fixed boot order defaults
  2. UpdateBootOptionVariables -- Update boot option variables
  3. ClearIPMIBootVariable -- Clear IPMI boot request variables
  4. RestoreBootorder -- Restore previous boot order
  5. AdjustEfiOsBootOrder -- Adjust EFI OS boot order based on discovered partitions
  6. ReadBootOptions -- Read existing Boot#### variables
  7. CollectBootDevices -- Enumerate bootable devices
  8. FilterBootDeviceList -- Filter out ineligible devices
  9. CreateEfiOsBootOption -- Create EFI OS boot options
  10. CreateShellBootOption -- Create UEFI Shell boot option
  11. MatchBootOptionsToDevices -- Match existing options to devices
  12. DeleteUnmatchedUefiHdBootDevices -- Remove orphan entries
  13. FboSyncBootOptionsFromDevOrder -- Sync options from device order
  14. CreateBootOptionsForNewBootDevices -- Create for new devices
  15. DeleteShellBootOptionOnSecureBoot -- Remove Shell if secure boot on
  16. SetBootOptionTags -- Assign option tags
  17. Default_SetBootOptionTags -- Default tag assignment
  18. EfiOsName_NormalizeBootOptions -- Normalize boot option names
  19. PreProcessBootOptions -- Pre-processing
  20. SetBootOptionPriorities -- Set option priorities
  21. SetIpmiBootOptionPriorities -- Set IPMI-based priorities
  22. ApplyIpmiBootRequest -- Apply IPMI boot override request
  23. FboIpmiBootTag -- FBO IPMI boot tag handling
  24. PostProcessBootOptions -- Post-processing
  25. FBO_UpdateBootListPriority -- Update boot list priority
  26. MaskOrphanDevices -- Mask orphan devices
  27. FboSetLegacyDeviceOrder -- Set legacy device order
  28. FBO_SetDefaultUefiBootOption -- Set default UEFI boot option
  29. FboAdjustDeviceOrder -- Adjust device order
  30. FBO_SCEBuildDefault -- SCE build defaults
  31. SaveBootOptions -- Save options to UEFI variables
  32. SaveIPMISetBootOrder -- Save IPMI boot order
  33. CreateOldBootOrder -- Create old boot order backup
  34. BeforeEnumerate -- Signal before enumerate event
  35. CallTheDispatcher -- Call BDS dispatcher
  36. PerrformCapsuleUpdate -- Capsule update processing
  37. UpdateESRTFmpEntry -- Update ESRT FMP entry
  38. RecoverTheMemory -- Memory recovery
  39. SignalLenoVoEndOfDxe -- Signal Lenovo-specific EndOfDxe
  40. HandoffToTSE -- Handoff to TSE (TSecurity?)

EDS Phase Flow (State Machine)

The BDS main loop handler (0x3894, sub_3894) processes the boot option list:

  1. sub_3894 - "Before Adding Group Headers" -- Process the boot option linked list, assign group header entries, set priorities
  2. sub_6348 - Validate/sort the list

The boot option node structure (at least 112 bytes per entry):

  • Offset +0x00: next pointer
  • Offet +0x08: previous pointer
  • Offset +0x20: Option number (WORD at +64, which is +0x40 from node base)
  • Ofset +0x44: Priority value (DWORD at offset +68)
  • Offset +0x48: Group ID (DWORD at offset +72)
  • Ofset +0x68: Disabled/hidden/detached flags (BYTE at offset +105)

Boot Option Loading and Execution:

The main boot loop (0x2C5C, sub_2C5C):

  1. Read "BootOrder" UEFI variable (list of UINT16 option numbers)
  2. For each boot option number:
    a. Read "Boot%04X" variable
    b. If Type == 5 (UEFI_DEVICE_PATH): Call sub_1018 (device path boot)
    c. Else: Call sub_1178 (file path / appliccation boot)
  3. Clean up and iterate

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.

Coonsole Initialization

Console Variable Processing (0x1E78, 0x1F78):

  • Reads "ConOut", "ConIn", "ErrOut", "ConOutDev", "ConInDev", "ErrOutDev" variables
  • Each contains a device path -- connects the console devices
  • Dispatches to sub_A98 to actually connect the console

Boot Manager Protocol (0x7D14):
Caches the BDS protocol (located by GUID at 0x26A78). The protocol has a function table:

  • +0x00: Reserved
  • +0x08: Reserved
  • +0x18: SetNextBootOption (3 args)
  • +0x30: GetBootOptionList (2 args)
  • +0x48: StartBootOption (2 args)
  • +0x78: AddBootOption (2 args)
  • +0x80: (at +128) Main BDS Entry -- calls the main BDS processing function

Internal Helper Functions

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

BBT Option Data Structures

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)

Lennovo/IPMI Integration

This BDS implementation includes Lenovo-specific IPMI boot management:

  • 0x9664 sub_9664() -- DxeLnvSendIpmiCmdLibConstructor -- Initializes IPMI command sending library
  • [SPS] ME Storage Service -- Checks if ME storage service is available
  • 0x19AB0 -- Query ME storage service availability
  • IPMI Boot Control -- Multiple functions handle IPMI boot commands:
    • ClearIPMIBootVariable
    • SetIpmiBootOptionPriorities
    • ApplyIpmiBootRequest
    • FboIpmiBootTag
    • SaveIPMISetBootOrder
  • FBO (Fied Boot Order) -- .string prefix "FBO" suggests Lenovo's "Fixed Boot Order" management (FboSyncBootOptionsFromDevOrder, FBOSetBootOptionTags, FBO_UpdateBootListPriority, etc.)

Address 0x27050 -- "Setup" Variable

At 0x27050 (814 bytes at 0x27C00), this is the setup data (UEFI "Setup" variable). Fields:

  • 0x7 (offset 7): Flags byte (byte_27084) -- bit 7 is used for some feature enable
  • 814 bytes total (sizeof EFI setup variable)

BDS Execution Policy

The dword_277E4 at 0x277E4 controls which processing phases are enabled:

  • Bits [0:1]:
    • 0 = Process all
    • 1 = Conditional (depends on sub_1350() check)
    • 3 = Disable all
  • Used for DriverXXXX, SysPrepXXXX processing gating

Dependencies

Consumed (this module calls into others via BootServices/RuntimeServices):

  • EFI_BOOT_SERVICES -- Seeected BS protocol
  • EFI_RUNTIME_SERVICES -- GetVariable, SetVariable
  • EFI_DXE_SERVICES_TABLE -- GS
  • CPU Architecture Protocol
  • MM PCI Base Protocol (CpRcPkg)
  • SNP (Simple Network Protocol)
  • Block I/O Protocol
  • Simple File System Protocol
  • Device Path To Text Protocol
  • Timer Arch Protocol
  • Lenovo IPMI Protocol
  • ME Storage Protocol
  • ACPI Table Protocol

Consumed By (other modules call this):

  • UEFI Boot Manager/Scheduler calls the BDS protocol Entry point (sub_283C)
  • Various drivers register boot option notification callbacks

Imports: None (all DXE, no PEIM imports -- standard for DXE drivers)

Noootable Strings

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

Function Count Summary

  • Total: 408 functions
  • Most-referenced: sub_68F8 (DebugPrint, 604 xrefs), sub_6940 (Assert, 145 xrefs)
  • Root functions: 96 (including multiple BDS sub-systems)
  • Call graph edges: 1635

Key Observed Patterns

  1. TWo-phase entry: First sub_45C initializes all library globals (gST, gBS, gRT, gDS), then sub_988 installs the BDS protocol interfaces.

  2. 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.

  3. 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.

  4. Protocol notification pattern: Uses sub_7CBC to register for protocol availability callbacks (BootServices + 168 = RegisterProtocolNotify), typically passing a GUID and callback function pointer.

  5. 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.

  6. String formatting: Uses sub_8400 and sub_7FA4 for Unicode string formatting (emsprintf-style with L"%s", L"%d", L"%04X" format strings).

  7. Firmware Vendor override: Overwrites SystemTable->FirmwareVendor with "American Megatrends" string during initialization.

Notes

  • The module explicitly overrides the firmware vendor to "American Megatrends" and sets firmware revision to 0x50000E.
  • This is a CSM-enabled BDS (CSM Policy integration in sub_C9F4).
  • Contains separate handling for UEFI, legacy, and IPMI boot options.
  • FBO (Fixed Boot Order) stringsuggest Lenovo-specific boot order management overlayed on standard UEFI BDS.
  • Capsule update support (CapsuleUpdateData variable) is handled in sub_2EA4.
  • Performance data (FPDT_Volatile variable) read and timer-converted in sub_1ACC.
  • S3 boot script support is referenced at the BootScriptSave.c path.
  • The memory type information strings (BsCode, BsData, RsCode, etc.) suggest memory type info logging functionality.
  • BDS execution policy gating (dword_277E4) controls whether Driver and SysPrep processing runs.