/**
* @file OpromUpdateDxeLightningRidgeEXECB3.h
*
* @brief Header for OpromUpdateDxeLightningRidgeEXECB3 UEFI DXE driver.
*
* This module is a UBA (Unified Board Architecture) board-type DXE driver
* for the LightningRidge EXEC B3 platform (index 31 of 427 PE files in the
* HR650X BIOS). It registers PCIe Option ROM (OpROM) update configuration
* tables via the UBA framework, providing callback functions that the
* platform uses to determine which PCIe slots and devices should receive
* OpROM updates.
*
* == UBA Registration Pattern ==
* 1. _ModuleEntryPoint caches UEFI globals (gImageHandle, gST, gBS, gRT)
* 2. GetHobList() resolves the HOB list via SystemTable->ConfigurationTable
* 3. DebugPrint() emits the platform banner using the UBA DebugLib protocol
* 4. gBS->LocateProtocol() resolves the UBA_CONFIG_PROTOCOL by GUID
* {E03E0D46-5263-4845-B0A4-58D57B3177E2}
* 5. The protocol's RegisterConfig function (vtable offset 0x10) is called
* with an OPROM_UPDATE_CONFIG structure (PBDS) containing 5 callbacks
*
* Source paths reference "e:\hs\MdePkg\Library\" (internal build server).
* PDB: OpromUpdateDxeLightningRidgeEXECB3.pdb
* SHA256: d58f84d1adb92017d59b450e242cac64939aadc6e24a35da7573064e7b531022
*/
#ifndef __OPROM_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__
#define __OPROM_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__
#include "../uefi_headers/Uefi.h"
/*==============================================================================
* GUID Definitions (stored in .rdata section at compile-time addresses)
*============================================================================*/
/**
* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID
* {2F707EBB-4A1A-11D4-9A38-0090273FC14D}
*
* Standard UEFI protocol for PCI Root Bridge IO operations (config space access).
* Stored at image address 0xCE0.
* Used by IsPcieSlotConfigured() to read PCI config space registers.
*
* In the original binary, this GUID is at offset 0xCE0 (16 bytes).
* Sub_48C calls gBS->LocateProtocol() with this GUID inside its loop.
*/
#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \
{ 0x2F707EBB, 0x4A1A, 0x11D4, \
{ 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
/**
* UBA_DEBUG_LIB_PROTOCOL_GUID
* {36232936-0E76-31C8-A13A-3AF2FC1C3932}
*
* UBA DebugLib protocol GUID. Used for debug output and assertions.
* Resolved lazily via gBS->LocateProtocol() by GetDebugLibProtocol().
*
* Protocol interface layout (vtable):
* - Offset 0x00: DebugPrint function pointer
* - Offset 0x08: DebugAssert function pointer
*
* Stored at image address 0xCF0.
* The result is cached in gOpromProtocol (image addr 0xF50).
*/
#define UBA_DEBUG_LIB_PROTOCOL_GUID \
{ 0x36232936, 0x0E76, 0x31C8, \
{ 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }
/**
* UBA_CONFIG_PROTOCOL_GUID
* {E03E0D46-5263-4845-B0A4-58D57B3177E2}
*
* UBA board-type configuration protocol GUID for LightningRidge EXEC B3.
* This protocol is registered by the platform-specific UBA board driver
* and provides a RegisterConfig function at vtable offset 0x10 (function
* index 2). The entry point calls this function to register the OpROM
* update configuration (PBDS structure and config GUID).
*
* Stored at image address 0xD00.
*
* Protocol interface layout (vtable):
* - Offset 0x00: Reserved / QueryInterface?
* - Offset 0x08: Reserved / Unknown function
* - Offset 0x10: RegisterConfig(configGuid, configData, dataSize)
*/
#define UBA_CONFIG_PROTOCOL_GUID \
{ 0xE03E0D46, 0x5263, 0x4845, \
{ 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }
/**
* EFI_HOB_LIST_GUID
* {7739F24C-93D7-11D4-9A3A-0090273FC14D}
*
* Standard UEFI HOB (Hand-Off Block) list GUID.
* GetHobList() walks the SystemTable->ConfigurationTable[] searching for
* this GUID to locate the HOB list pointer.
*
* Stored as two 8-byte halves at image addresses 0xD10 and 0xD18.
* The comparison in IsHobListGuid() reads these as unaligned 64-bit values.
*/
#define EFI_HOB_LIST_GUID \
{ 0x7739F24C, 0x93D7, 0x11D4, \
{ 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
/**
* OPROM_UPDATE_CONFIG_DATA_GUID
* {371BD79C-DE79-4C5F-AA2B-BC9EBEFA988F}
*
* Configuration data identifier GUID for the OpROM update config structure.
* Passed to the UBA_CONFIG_PROTOCOL.RegisterConfig() call as the
* ConfigGuid parameter identifying the type of configuration being registered.
* Stored at image address 0xEF0.
*/
#define OPROM_UPDATE_CONFIG_DATA_GUID \
{ 0x371BD79C, 0xDE79, 0x4C5F, \
{ 0xAA, 0x2B, 0xBC, 0x9E, 0xBE, 0xFA, 0x98, 0x8F } }
/*==============================================================================
* Type Definitions
*============================================================================*/
/**
* OPROM_UPDATE_CONFIG - PBDS protocol interface structure (48 bytes total)
*
* This structure is registered with the UBA_CONFIG_PROTOCOL.RegisterConfig().
* It contains the signature/version header and five callback function pointers.
* The callbacks are resolved to absolute function addresses at runtime via
* relocation (the .reloc section has entries for this structure).
*
* Layout at image address 0xF00:
* Offset Size Field Description
* ------ ---- ------------------- ----------------------------
* 0x00 4 'PBDS' Signature (0x53444250)
* 0x04 4 Version Structure version (always 1)
* 0x08 8 IsPcieSlotConfigured Ptr to IsPcieSlotConfigured()
* 0x10 8 OpromGetConfigA Ptr to OpromGetConfigA()
* 0x18 8 OpromGetConfigB Ptr to OpromGetConfigB()
* 0x20 8 OpromGetConfigC Ptr to OpromGetConfigC()
* 0x28 8 OpromSetSlotNumber Ptr to OpromSetSlotNumber()
* ------ ---- -----
* Total 48 bytes (0x30)
*/
typedef struct {
UINT32 Signature; ///< 'PBDS' = 0x53444250
UINT32 Version; ///< Structure version (must be 1)
UINT64 IsPcieSlotConfigured; ///< Function pointer: IsPcieSlotConfigured()
UINT64 OpromGetConfigA; ///< Function pointer: OpromGetConfigA()
UINT64 OpromGetConfigB; ///< Function pointer: OpromGetConfigB()
UINT64 OpromGetConfigC; ///< Function pointer: OpromGetConfigC()
UINT64 OpromSetSlotNumber; ///< Function pointer: OpromSetSlotNumber()
} OPROM_UPDATE_CONFIG;
/**
* UBA_DEBUG_LIB_PROTOCOL - Debug output protocol interface
*
* Resolved by GetDebugLibProtocol() via gBS->LocateProtocol() with
* UBA_DEBUG_LIB_PROTOCOL_GUID. Cached in gOpromProtocol.
*
* The protocol provides two functions at its vtable base:
* - Offset 0x00: DebugPrint - debug output with format string and VA_LIST
* - Offset 0x08: DebugAssert - assertion failure handler
*/
typedef struct {
UINT64 DebugPrint; ///< Function pointer: DebugPrint(ErrorLevel, Format, VaList)
UINT64 DebugAssert; ///< Function pointer: DebugAssert(FileName, LineNumber, Desc)
} UBA_DEBUG_LIB_PROTOCOL;
/**
* UBA_CONFIG_PROTOCOL - Board-type configuration protocol
*
* Located via gBS->LocateProtocol() using UBA_CONFIG_PROTOCOL_GUID.
* Provides a RegisterConfig function at vtable offset 0x10 that accepts
* a configuration type GUID, data structure pointer, and data size.
*
* Vtable layout:
* [0] @+0x00: Unknown (QueryInterface?)
* [1] @+0x08: Unknown
* [2] @+0x10: RegisterConfig(Protocol*, ConfigGuid*, ConfigData*, DataSize)
*/
typedef struct {
UINT64 Unknown0; ///< Reserved / QueryInterface?
UINT64 Unknown1; ///< Reserved / Unknown function
UINT64 RegisterConfig; ///< RegisterConfig(ConfigGuid, ConfigData, DataSize)
} UBA_CONFIG_PROTOCOL;
/**
* PCIE_SLOT_RANGE - PCIe slot BDF descriptor (4 bytes)
*
* Describes a single PCIe slot's Bus/Device/Function range for slot
* validation. Each entry is 4 bytes but only the first 3 bytes are used
* by IsPcieSlotConfigured().
*
* The function reads these with a byte-level stride of 4 bytes and
* accesses them at offsets [-1, 0, +1] relative to a pointer that starts
* at image address 0xED1, advancing by 4 each iteration.
*
* Stored at image address 0xED0 (8 entries).
*/
typedef struct {
UINT8 Bus; ///< PCI Bus number (byte at offset -1)
UINT8 Device; ///< PCI Device number (byte at offset 0)
UINT8 Function; ///< PCI Function number (byte at offset +1)
UINT8 Reserved; ///< Not used (byte at offset +3, stride padding)
} PCIE_SLOT_RANGE;
/*==============================================================================
* Global Variable Declarations
*
* These globals are at fixed addresses in the .data segment:
* gST at 0xF30 EFI System Table
* gBS at 0xF38 EFI Boot Services
* gImageHandle at 0xF40 EFI Image Handle
* gRT at 0xF48 EFI Runtime Services
* gOpromProtocol at 0xF50 UBA DebugLib protocol cache (lazy init)
* gHobList at 0xF58 HOB list pointer cache (lazy init)
*============================================================================*/
extern EFI_SYSTEM_TABLE *gST;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_HANDLE gImageHandle;
extern EFI_RUNTIME_SERVICES *gRT;
extern UBA_DEBUG_LIB_PROTOCOL *gOpromProtocol;
extern VOID *gHobList;
/*==============================================================================
* Function Prototypes
*
* All functions are module-internal (STATIC in the .c file, or called via
* function pointers registered with the UBA framework). There is no public
* API exposed by this driver beyond _ModuleEntryPoint.
*============================================================================*/
/**
* _ModuleEntryPoint - UEFI DXE driver entry point.
*
* Called by the DXE Dispatcher. Performs the following initialization:
* 1. Caches ImageHandle, SystemTable, BootServices, RuntimeServices globals
* 2. Resolves the HOB list via GetHobList()
* 3. Emits platform banner "UBA:OpromUpdate-TypeLightningRidgeEXECB3"
* 4. Locates UBA_CONFIG_PROTOCOL by GUID {E03E0D46-5263-4845-B0A4-58D57B3177E2}
* 5. Calls RegisterConfig(vtable[2]) with:
* - Config GUID: {371BD79C-DE79-4C5F-AA2B-BC9EBEFA988F}
* - Config data: PBDS structure (48 bytes)
* - Data size: 48
*
* @param[in] ImageHandle Handle for this driver image.
* @param[in] SystemTable Pointer to the UEFI system table.
*
* @return EFI_SUCCESS Configuration registered successfully.
* @return Other LocateProtocol or RegisterConfig failure.
*/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
/**
* IsPcieSlotConfigured - Check if a PCIe BDF is in a configured slot range.
*
* UBA framework callback (registered via PBDS at offset +0x08).
* Iterates 8 PCIE_SLOT_RANGE entries at 0xED0. For each slot where the
* corresponding bit in SlotMask is clear (slot not yet configured):
* 1. Opens EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL via gBS->LocateProtocol()
* 2. Reads PCI config register 0x19 (Secondary Bus Number / BIST)
* 3. Reads PCI config register 0x1A (Subordinate Bus Number / Header Type)
* 4. Checks if PcieBdfAddr falls within [reg_0x19, reg_0x1A]
*
* The BDF address for each slot is computed from the 3-byte descriptor:
* combined = (Bus | ((Device | (Function << 8)) << 8)) << 8
* Then ORed with 0x19 or 0x1A as the config space register offset.
*
* @param[in] PcieBdfAddr PCIe BDF address to test (bus:device:function).
* @param[in] SlotMask Bitmask of slots (bits 0-7). Clear bit means
* the slot should be checked for presence.
*
* @return TRUE The BDF is within a configured slot range.
* @return FALSE The BDF is not within any configured slot range.
*/
BOOLEAN
IsPcieSlotConfigured (
IN UINT64 PcieBdfAddr,
IN UINT32 SlotMask
);
/**
* OpromGetConfigA - Get pointer to Config Table A (primary PCIe topology).
*
* UBA framework callback (registered via PBDS at offset +0x10).
* Returns a pointer to the zero-initialized primary configuration table
* at image address 0xD20. On the LightningRidge EXEC B3 platform, this
* table is unused (all zeros) - it acts as a terminator/sentinel.
*
* @param[out] ConfigTable Receives pointer to the configuration table.
*
* @return EFI_SUCCESS Always.
*/
EFI_STATUS
OpromGetConfigA (
OUT VOID **ConfigTable
);
/**
* OpromGetConfigB - Get pointer to Config Table B and entry count.
*
* UBA framework callback (registered via PBDS at offset +0x18).
* Returns pointer to the 6-entry configuration table at image address
* 0xD60, describing PCIe root port topology for OpROM updates.
*
* The table entries encode bus/device/function ranges, vendor/device IDs,
* and slot information. See the .c file for the raw data layout.
*
* @param[out] ConfigTable Receives pointer to the configuration table.
* @param[out] EntryCount Receives the number of entries (6).
*
* @return EFI_SUCCESS Always.
*/
EFI_STATUS
OpromGetConfigB (
OUT VOID **ConfigTable,
OUT UINTN *EntryCount
);
/**
* OpromGetConfigC - Get pointer to Config Table C and entry count.
*
* UBA framework callback (registered via PBDS at offset +0x20).
* Returns pointer to the 10-entry configuration table at image address
* 0xE60, describing extended PCIe device topology for OpROM updates.
*
* The entries include Intel I350 Gigabit Ethernet and 82599ES 10GbE
* device configurations. See the .c file for the raw data layout.
*
* @param[out] ConfigTable Receives pointer to the configuration table.
* @param[out] EntryCount Receives the number of entries (10).
*
* @return EFI_SUCCESS Always.
*/
EFI_STATUS
OpromGetConfigC (
OUT VOID **ConfigTable,
OUT UINTN *EntryCount
);
/**
* OpromSetSlotNumber - Set PCIe slot number callback.
*
* UBA framework callback (registered via PBDS at offset +0x28).
* Always sets slot number to 0 on this platform and logs:
* "[UBA]:SetPcieSlotNumber callback - %d\n"
* with %d=0, indicating slot enumeration starts from slot 0.
*
* @param[out] SlotNumber Receives the slot number (always 0).
*
* @return EFI_SUCCESS Always.
*/
EFI_STATUS
OpromSetSlotNumber (
OUT UINT8 *SlotNumber
);
/**
* GetDebugLibProtocol - Resolve and cache the UBA DebugLib protocol.
*
* Called lazily on first use from DebugPrint() or DebugAssert().
* Performs a UEFI pool allocation of type 31 to check minimum pool size
* (must be > 0x10 bytes), then calls gBS->LocateProtocol() with
* UBA_DEBUG_LIB_PROTOCOL_GUID {36232936-0E76-31C8-A13A-3AF2FC1C3932}.
*
* The result is cached in gOpromProtocol (image addr 0xF50), so
* subsequent calls return immediately.
*
* @return Pointer to UBA_DEBUG_LIB_PROTOCOL, or NULL if:
* - Pool allocation fails (< 0x10 bytes available)
* - LocateProtocol fails
*/
UBA_DEBUG_LIB_PROTOCOL *
GetDebugLibProtocol (
VOID
);
/**
* DebugPrint - Platform-aware debug output.
*
* Reads CMOS register 0x4B via port 0x70/0x71 to determine platform type:
* Type 1 = LightningRidge -> debug mask = 0x80000004
* Type 2/3 = other -> debug mask = 0x80000006
* Falls back to MMIO read at 0xFDAF0490 bit | 1 when CMOS returns 0.
*
* The output is only emitted when (ErrorLevel & DebugMask) != 0.
* If the DebugLib protocol is not yet resolved, GetDebugLibProtocol()
* is called to initialize it.
*
* @param[in] ErrorLevel Debug message severity level mask.
* @param[in] Format Printf-compatible format string.
* @param[in] ... Variable arguments for format string.
*
* @return Non-zero if output succeeded, 0 if suppressed or protocol missing.
*/
UINTN
EFIAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
);
/**
* DebugAssert - ASSERT failure handler.
*
* Calls the DebugLib protocol's assertion handler at protocol offset 0x08.
* This is the runtime ASSERT() macro implementation for this module.
* If the protocol is not yet resolved, GetDebugLibProtocol() is called.
*
* @param[in] FileName Source file name string.
* @param[in] LineNumber Line number of the assertion.
* @param[in] Description Assertion description string.
*/
VOID
DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
);
/**
* GetHobList - Locate the HOB (Hand-Off Block) list.
*
* Walks gST->ConfigurationTable[] entries looking for the entry whose
* VendorGuid matches EFI_HOB_LIST_GUID
* ({7739F24C-93D7-11D4-9A3A-0090273FC14D}). The associated VendorTable
* pointer is the HOB list. Result is cached in gHobList (image addr 0xF58).
*
* If the GUID is not found in any ConfigTable entry, triggers ASSERT
* with status 0x800000000000000E (EFI_NOT_FOUND).
* If the resolved pointer is NULL, another ASSERT is triggered.
*
* Source file paths (from ASSERT strings):
* e:\hs\MdePkg\Library\DxeHobLib\HobLib.c (lines 54-55)
*
* @return Pointer to the HOB list, or NULL on failure.
*/
VOID *
GetHobList (
VOID
);
/**
* IsHobListGuid - Compare a GUID against EFI_HOB_LIST_GUID.
*
* Compares two GUIDs by splitting each into two 64-bit halves using
* ReadUnaligned64(). The reference EFI_HOB_LIST_GUID halves are stored
* at image addresses 0xD10 (first 8 bytes) and 0xD18 (second 8 bytes).
*
* @param[in] Guid Pointer to the GUID to compare.
*
* @return TRUE The GUID matches EFI_HOB_LIST_GUID.
* @return FALSE The GUID does not match.
*/
BOOLEAN
IsHobListGuid (
IN EFI_GUID *Guid
);
/**
* ReadUnaligned64 - Read a 64-bit value from an unaligned pointer.
*
* Direct 8-byte read with NULL pointer assertion check via DebugAssert().
* Source: e:\hs\MdePkg\Library\BaseLib\Unaligned.c, line 192.
*
* @param[in] Buffer Pointer to read from (must not be NULL).
*
* @return The 64-bit value at the address.
*/
UINT64
ReadUnaligned64 (
IN CONST VOID *Buffer
);
#endif /* __OPROM_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__ */