Newer
Older
AMI-Aptio-BIOS-Reversed / OpromUpdateDxeLightningRidgeEXECB2 / OpromUpdateDxeLightningRidgeEXECB2.md
@Ajax Dong Ajax Dong 2 days ago 12 KB Init

OpromUpdateDxeLightningRidgeEXECB2

Function Table

Address Name Description
ReadUnaligned64
ReportAssert
DebugPrint
CompareGuid
IsFunctionInPopulatedSlot
GetBoardInfo
GetSlotConfig1
GetSlotConfig2
SetPcieSlotNumber
_ModuleEntryPoint
GUID Instances
EFI_PCI_IO_PROTOCOL GUID - used to read PCI config space via LocateProtocol
Reference at .rdata:0xCE0
STATIC CONST EFI_GUID mEfiPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
UBA Debug Protocol GUID - used to locate the debug output protocol
Reference at .rdata:0xCF0
STATIC CONST EFI_GUID mUbaDebugProtocolGuid = UBA_DEBUG_PROTOCOL_GUID;
UBA Config Protocol GUID - main protocol for registering board config
Reference at .rdata:0xD00
STATIC CONST EFI_GUID mUbaConfigProtocolGuid = UBA_CONFIG_PROTOCOL_GUID;
EFI Guided Section Extraction Protocol GUID (unused by this driver)
Reference at .rdata:0xD10
STATIC CONST EFI_GUID mEfiGuidedSectionExtractionProtocolGuid =
be used by the UBA framework or by external consumers of the data section.
OpromUpdate LightningRidge EXEC B2 Board Registration GUID
Reference at .rdata:0xEF0
STATIC CONST EFI_GUID mOpromUpdateBoardGuid = OPROM_UPDATE_BOARD_GUID;
PCIe Root Port BDF Lookup Table (.data@0xED1)
PCIe Root Port BDF lookup table.
Maps 8 PCIe root port indices to Bus:Device:Function addresses.
Used by IsFunctionInPopulatedSlot() to locate root port config space.
byte 0 = Register offset (in the encoding: shifted to bits [15:8])
byte 1 = [2:0]=Function, [7:3]=Device (in the encoding: shifted to bits [23:16])
byte 2 = Bus number (in the encoding: shifted to bits [31:24])
The "in the encoding" means combined as:
Reg ** (Func << 8) (Dev << 11) (Bus << 16) BIT28 (extended cfg)**
Decoded entries (from 0xED1 data):
Entry 0: { 0x00, 0x03, 0x00 } -> B=0 D=0 F=3 Reg=0x00 (PCH internal)
Entry 1: { 0x00, 0x01, 0x80 } -> B=128 D=0 F=1 Reg=0x00 (PCIe domain)
Entry 2: { 0x00, 0x02, 0x80 } -> B=128 D=0 F=2 Reg=0x00 (PCIe domain)
Entry 3: { 0x02, 0x03, 0x80 } -> B=128 D=0 F=3 Reg=0x02 (PCIe domain)
Entry 4: { 0x00, 0x02, 0x00 } -> B=0 D=0 F=2 Reg=0x00 (PCH internal)
Entry 5: { 0x00, 0x01, 0x00 } -> B=0 D=0 F=1 Reg=0x00 (PCH internal)
Entry 6: { 0x05, 0x1c, 0x00 } -> B=0 D=3 F=4 Reg=0x05 (PCH internal)
Entry 7: { 0x00, 0x03, 0x80 } -> B=128 D=0 F=3 Reg=0x00 (PCIe domain, dup)
Bus 0x80 (128) entries are in the PCIe domain range (typically bus 128+).
Bus 0 entries are PCH-internal PCIe root ports in the legacy bus 0 range.
STATIC CONST UINT8 mPcieRootPortBdfTable[MAX_PCIE_ROOT_PORTS * 4] attribute((aligned(4))) = {
Each entry: { RegOffset, DevFunc, Bus, Pad } (4 bytes)
Entry 0
Entry 1
Entry 2
Entry 3
Entry 4
Entry 5
Entry 6
Entry 7
PCIe Slot Configuration Tables (.data section)
PCIe Slot Configuration Table 1 (at .data@0xD60).
Contains 6 entries describing PCIe slot-to-BDF mappings.
Each entry encodes slot port info, capability flags, and PCI address.
Used by GetSlotConfig1() callback.
STATIC CONST PCIE_SLOT_CONFIG_ENTRY mSlotConfigTable1[MAX_SLOT_CONFIG1_ENTRIES] = {
PCIe Slot Configuration Table 2 (at .data@0xE60).
Contains 10 entries describing additional PCIe slot-to-BDF mappings.
Used by GetSlotConfig2() callback.
STATIC CONST PCIE_SLOT_CONFIG_ENTRY mSlotConfigTable2[MAX_SLOT_CONFIG2_ENTRIES] = {
Empty Board Info Structure (.data@0xD20)
Empty board info structure. LightningRidge EXEC B2 does not provide
any additional board-specific data beyond the PCIe slot config tables.
STATIC CONST UINT64 mEmptyBoardInfo[8] = { 0 };
PBDS Board Config Registration Structure (.data@0xEF0)
PBDS board config registration structure.
Contains the board GUID and 4 callback function RVAs.
Registered with UBA Config Protocol at driver entry.
Layout (48 bytes):
offset 0: Board GUID (OPROM_UPDATE_BOARD_GUID, 16 bytes)
offset 16: PBDS_CONFIG_SIGNATURE ("PBDS", 4 bytes)
offset 20: Version (1, 4 bytes)
offset 24: Callback 0 - IsFunctionInPopulatedSlot (8 bytes, relocatable RVA)
offset 32: Callback 1 - GetBoardInfo (8 bytes, relocatable RVA)
offset 40: Callback 2 - GetSlotConfig1 (8 bytes, relocatable RVA)
offset 48 (= 0x30): Callback 3 - GetSlotConfig2 (8 bytes, relocatable RVA)
Total from start of GUID: 16 + 32 = 48 bytes
typedef struct {
Global Variables (.data section)
Cached pointer to the UEFI System Table.
Initialized in _ModuleEntryPoint().
EFI_SYSTEM_TABLE *gSystemTable = NULL;
Cached pointer to the UEFI Boot Services Table.
EFI_BOOT_SERVICES *gBootServices = NULL;
Cached pointer to the UEFI Runtime Services Table.
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;
Cached pointer to the UBA Debug Protocol interface.
Lazily initialized by LocateDebugProtocol().
VOID *gDebugProtocol = NULL;
Cached pointer to the HOB (Hand-Off Block) list.
Populated by GetHobList().
VOID *gHobList = NULL;
Debug output control flags.
Determines whether debug output is suppressed or displayed.
UINTN gDebugFlags = 0;
Trigger assertion using UBA Debug Protocol assert handler.
ReportAssert (
Lazily locate the UBA Debug Protocol if not yet cached.
DebugProtocol = LocateDebugProtocol ();
Call the ReportAssert function at interface offset +0.
The debug protocol interface has:
Status = ((EFI_STATUS (EFIAPI )(CONST CHAR8 , UINTN, CONST CHAR8 *))DebugProtocol)(
Check CMOS debug verbosity configuration.
CMOS index 0x4B (at I/O ports 0x70/0x71) stores board-specific
debug output control bits.
CMOS register 0x4B layout:
bit 7 = valid flag (if set, use configured level)
bits [6:0] = debug verbosity level
Read CMOS by writing index to 0x70, then reading data from 0x71.
The index byte preserves bit 7 of the CMOS index register
If the debug level is > 3 AND also 0... this is a hardware quirk
for this platform. Check an additional hardware register for
the override flag.
that provides debug override. This is specific to the C620
bit 1 = debug enable
This MMIO address is a virtual/physical address in the
the PCH root complex).
DataByte *= ((volatile UINT8 *)0xFDAF0490 & 2) 1;**
Determine if our error level matches the CMOS-configured level.
The CMOS level is 0-based (0=disable, 1=error, 2=warn, 3=info, 4+=verbose)
while ErrorLevel is a UEFI-style bitmask.
EffectiveErrorLevel = 0x80000000; // DEBUG_INFO = bit 31
DEBUG_ERROR = bit 2
The requested error level is not enabled in the current debug config.
return 0;
Call the UBA Debug Protocol's Report function at interface offset +8.
Takes (ErrorLevel, FormatString, VariableArgs) as parameters.
va_start (VaList, Format);
Already cached.
return gDebugProtocol;
Raise TPL to TPL_NOTIFY (31) to prevent any callbacks during
our critical section (protocol location can re-enter).
We save the old TPL and immediately restore it.
PagesAndMemory = gBS->RaiseTPL (TPL_NOTIFY);
If the old TPL was <= TPL_APPLICATION (16 = 0x10)
we are in a safe context to locate the protocol.
if (PagesAndMemory <= 0x10) {
Locate the UBA Debug Protocol.
Status = gBS->LocateProtocol (
Registration (not used)
Protocol not found; clear the cached pointer.
gDebugProtocol = NULL;
Trigger assertion via UBA Debug Protocol.
Compare as two 64-bit values. The GUID structure is:
For 64-bit comparison, first 8 bytes and last 8 bytes.
Use ReadUnaligned64 for safe access (GUID may not be aligned).
Guid1Data = (CONST UINT64 *)Guid1;
a full UINT64 from the given address. GUID comparison in the
original code is: ((UINT64 )Guid1)[0] == ((UINT64 )Guid2)[0] &&
if (ReadUnaligned64 (Guid1) == ReadUnaligned64 (Guid2) &&
return gHobList;
Get the configuration table pointer.
In the original binary's compiled code:
NumberOfTableEntries = (UINTN )(SystemTable + 0x68)
ConfigTable = *(VOID )(SystemTable + 0x70)**
NumberOfTableEntries = gSystemTable->NumberOfTableEntries;
Compare the GUID of each configuration table entry
against the HOB list GUID.
if (CompareGuid (&(gHobListGuid), &(ConfigTable[Index].VendorGuid))) {
Found the HOB list entry.
gHobList = ConfigTable[Index].VendorTable;
Failed to find the HOB list in the configuration table.
Report assert.
DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", 0x800000000000000EULL);
Cannot access PCI config space; assume function is not in a populated slot.
return FALSE;
Bit is set: this slot is NOT populated (or is excluded from check).
Build EFI_PCI_IO_PROTOCOL_PCI_ADDRESS from the root port entry.
Bits [7:0] = Register base (RootPortEntry->RegisterOffset)
Bits [10:8] = Function = RootPortEntry->DevFunc & 0x07
Bits [15:11] = Device = (RootPortEntry->DevFunc >> 3) & 0x1F
Bits [23:16] = Bus = RootPortEntry->Bus
Bit 28 = 1 (extended config space)
PciAddr **= (RootPortEntry[Index].RegisterOffset & 0xFF) **
Read PCI Express Device Capabilities function range.
Offset 0x19 relative to the capability base:
Offset 0x1A relative to the capability base:
These reads identify which function numbers the downstream
device (behind this root port) occupies.
Check if the given function number falls within the range.
if (FuncNum >= CapFuncMin && FuncNum <= CapFuncMax) {
6 return EFI_SUCCESS;
Driver Entry Point
Cache ImageHandle: This is required for driver unload and protocol operations.
gImageHandle = ImageHandle;
Cache SystemTable.
gSystemTable = SystemTable;
Cache BootServices from SystemTable.
gBootServices = SystemTable->BootServices;
gRuntimeServices = SystemTable->RuntimeServices;
Locate and cache the HOB list from SystemTable configuration table.
GetHobList ();
Register board configuration with UBA Config Protocol.
Locate the UBA Config Protocol.
The protocol GUID is e03e0d46-5263-4845-b0a4-58d57b3177e2.
Registration = (PBDS_REGISTRATION *)&mBoardRegistration;
The UBA Config Protocol interface provides:
Register the board:
Guid = OPROM_UPDATE_BOARD_GUID (371bd79c-...)
Data = PBDS_BOARD_CONFIG structure with callbacks
Size = sizeof(PBDS_REGISTRATION) (48 bytes)
Function at protocol+16 (index 2) takes:
Status = ((EFI_STATUS (EFIAPI )(VOID , EFI_GUID , VOID , UINTN))(
Skip GUID, point to PBDS data
32 bytes: sig + ver + 4 funcs

Generated by HR650X BIOS Decompilation Project