| Address | Name | Description | |
|---|---|---|---|
| __inbyte | |||
| __outbyte | |||
| OpromGetConfigA | |||
| OpromGetConfigB | |||
| OpromGetConfigC | |||
| OpromSetSlotNumber | |||
| DebugPrint | |||
| DebugAssert | |||
| IsHobListGuid | |||
| IsPcieSlotConfigured | |||
| ReadUnaligned64 | |||
| _ModuleEntryPoint | |||
| NULL | // ============================================================================ | ||
| Platform | I/O Intrinsics (MSVC inbyte / outbyte replacements) | ||
| Embedded | Binary Data (PCIe Configuration Tables and GUIDs) | ||
| GUID | storage block at 0xCE0 in .rdata. | ||
| Contains | four GUIDs used by the driver. | ||
| static | CONST UINT8 GuidBlock[0x80] = { | ||
| OpROM | update protocol interface data block (at 0xF00 in original image). | ||
| This | structure serves as the registered protocol interface. | ||
| It | starts with a signature/header ("PBDS") followed by callbacks. | ||
| static | CONST UINT8 OpromUpdateProtocolData[0x38] = { | ||
| Version | = 1 | ||
| Size | = 0x048C | ||
| Function | pointers (offsets 0x10-0x28) - set to 0 in data section; | ||
| in | the actual binary these are relocation entries that get fixed up | ||
| by | the DXE dispatcher to point to the actual function addresses. | ||
| Null | terminator | ||
| PCIe | configuration table A (at address 0xD20 in original image). | ||
| Contains | PCIe root port and device configuration entries. | ||
| static | CONST UINT8 PcieConfigTableA[0xE6]; // Content documented below | ||
| PCIe | configuration table B (at address 0xD60 in original image). | ||
| 6 | entries of OpROM update PCIe config data. | ||
| static | CONST UINT8 PcieConfigTableB[0x150]; // Content documented below | ||
| PCIe | configuration table C (at address 0xE60 in original image). | ||
| static | CONST UINT8 PcieConfigTableC[0x70]; // Content documented below | ||
| Slot | configuration table (at address 0xED1 in original image). | ||
| 8 | entries, each 4 bytes, defining PCIe slot BDF addresses. | ||
| static | CONST UINT8 PcieSlotConfigTable[0x20] = { | ||
| Slot | 0: B=0x03 D=0x00 F=0x00 | ||
| Slot | 1: B=0x01 D=0x80 F=0x00 (Dev=16, Func=0) | ||
| Slot | 2: B=0x02 D=0x80 F=0x00 extra=0x02 | ||
| Slot | 3: B=0x03 D=0x80 F=0x00 | ||
| Slot | 4: B=0x02 D=0x00 F=0x00 | ||
| Slot | 5: B=0x01 D=0x00 F=0x00 extra=0x05 | ||
| Slot | 6: B=0x1C D=0x00 F=0x00 (extended) | ||
| Slot | 7: B=0x03 D=0x80 F=0x00 extra=0x9C | ||
| Global | Variables (.data segment) | ||
| Cached | pointer to the OpROM update protocol interface. | ||
| Resolved | once by GetDebugLibProtocol() and reused thereafter. | ||
| static | VOID *gOpromUpdateProtocol = NULL; | ||
| Cached | pointer to the HOB (Hand-Off Block) list. | ||
| Resolved | once by GetHobList() and reused thereafter. | ||
| VOID | *gHobList = NULL; | ||
| Callback | Implementations | ||
| Log | debug message: "[UBA]:SetPcieSlotNumber callback - %d\n" | ||
| with | the slot number value (always 0 on this platform). | ||
| DebugPrint | (DEBUG_INFO, "[UBA]:SetPcieSlotNumber callback - %d\n", 0); | ||
| Protocol | Resolution | ||
| Check | if protocol was already resolved. | ||
| if | (gOpromUpdateProtocol != NULL) { | ||
| Allocate | pool for the protocol interface. | ||
| The | pool type used corresponds to memory type 31 (implementation-specific | ||
| allocation | type for UBA protocol interfaces). | ||
| AllocatePool | signature: (PoolType, Size, Buffer). | ||
| Initialize | the protocol interface with callback pointers. | ||
| The | interface is initialized by setting up the internal callback table | ||
| with | the four platform-specific functions. | ||
| Locate | the DebugLib protocol using gBS->LocateProtocol(). | ||
| If | the protocol cannot be located (e.g., not yet installed), set the | ||
| cached | pointer to NULL so the caller can handle gracefully. | ||
| LocateProtocol | signature: (Protocol, Registration, Interface). | ||
| if | (EFI_ERROR((*gBS->LocateProtocol)(&GuidBlock[0x20], NULL, &gOpromUpdateProtocol))) { | ||
| Debug | Output | ||
| Resolve | the DebugLib/OpROM protocol interface. | ||
| Protocol | = GetDebugLibProtocol (); | ||
| Determine | platform type from CMOS register 0x4B. | ||
| Read | the CMOS register using port I/O instructions. | ||
| CmosValue | = __inbyte (RTC_INDEX_PORT); | ||
| Validate | platform type. If > 3, use as-is. | ||
| If | == 0, fall back to MMIO register at 0xFDAF0490. | ||
| if | (PlatformType > 3) { | ||
| PlatformType | is valid as-is | ||
| Platform | type 1..3 = valid | ||
| Check | if the platform type matches the Lightning Ridge EXEC B1 type. | ||
| if | ((PlatformType - 1) <= 0xFD) { | ||
| Build | the error mask for this platform: | ||
| if | (PlatformType == OPROM_PLATFORM_TYPE_LIGHTNING_RIDGE) { | ||
| If | the requested ErrorLevel matches the platform's error mask | ||
| call | the DebugLib protocol's output function (at offset 0x00). | ||
| if | ((ErrorMask & ErrorLevel) != 0) { | ||
| Invoke | the debug output function. | ||
| directly | pointing to the stack location after Format. In the actual | ||
| UEFI | DebugLib implementation, this is the DebugVPrint function. | ||
| Assertion | Handler | ||
| Resolve | the DebugLib protocol interface. | ||
| Call | the assertion handler function at offset 0x08 in the | ||
| protocol | interface. The assertion handler is accessed via pointer | ||
| arithmetic | on the raw protocol interface. | ||
| HOB | List Management | ||
| Return | cached value if already resolved. | ||
| if | (gHobList != NULL) { | ||
| Initialize | and iterate through configuration tables. | ||
| gHobList | = NULL; | ||
| Walk | the configuration table array. | ||
| Each | entry is 24 bytes (sizeof(EFI_CONFIGURATION_TABLE)). | ||
| for | (Index = 0; Index < TableCount; Index++) { | ||
| Check | if this table's VendorGuid matches EFI_HOB_LIST_GUID. | ||
| if | (IsHobListGuid (NULL, &ConfigTable[Index].VendorGuid)) { | ||
| If | no HOB list was found, trigger assertion failure. | ||
| if | (gHobList == NULL) { | ||
| Read | the expected GUID halves from the GUID storage block. | ||
| The | EFI_HOB_LIST_GUID is stored at GuidBlock + 0x10. | ||
| ExpectedFirstHalf | = ReadUnaligned64 (&GuidBlock[0x10]); | ||
| Read | the target GUID as two 64-bit halves. | ||
| GuidFirstHalf | = ReadUnaligned64 (GuidPtr); | ||
| Both | halves must match. | ||
| return | (GuidFirstHalf == ExpectedFirstHalf) && (GuidSecondHalf == ExpectedSecondHalf); | ||
| Slot | Population Detection | ||
| Locate | the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. | ||
| The | protocol GUID is stored at GuidBlock + 0x00. | ||
| Status | = (*gBS->LocateProtocol) (&GuidBlock[0x00], NULL, (VOID )&RootBridgeIo);** | ||
| Iterate | through 8 slot entries in the slot configuration table. | ||
| Each | entry is 4 bytes. | ||
| SlotEntry | = PcieSlotConfigTable; | ||
| Extract | slot PCI address from the configuration table: | ||
| SlotPrevExtra | = byte3 of PREVIOUS entry (or 0 for first entry | ||
| since | the byte before the table is 0) | ||
| SlotBus | = byte0 of CURRENT entry | ||
| SlotDevice | = byte1 of CURRENT entry | ||
| If | Index == 0, SlotPrevExtra is read from the byte preceding | ||
| the | slot configuration table (which is 0x00). | ||
| if | (Index == 0) { | ||
| byte3 | of previous entry | ||
| byte0 | SlotDevice = SlotEntry[1]; // byte1 | ||
| Check | if this slot's BDF matches the target BDF address. | ||
| If | the slot's bit in 'flags' is not set, skip this slot. | ||
| if | ((Reserved & (1 << Index)) == 0) { | ||
| Build | the PCI config space address for this slot: | ||
| SlotBdfAddress | **= (SlotPrevExtra << 8) | (SlotBus << 16) | (SlotDevice << 24)** |
| SlotBdfAddress | = ((UINT64)SlotPrevExtra << 8) | ||
| Read | registers at offsets 0x19 (BIST) and 0x1A (Header Type) | ||
| via | the PciRootBridgeIo protocol. The PCI Read function is at | ||
| offset | 0x38 (56) within the protocol interface structure. | ||
| EfiPciWidthUint8 | **SlotBdfAddress | PCI_REG_BIST** | |
| EfiPciWidthUint8 | **SlotBdfAddress | PCI_REG_HEADER_TYPE** | |
| Check | if the target BDF address falls within the range defined by | ||
| this | slot. The BIST value is the lower bound and Header Type is | ||
| the | upper bound. | ||
| if | (BdfAddress >= BistValue && BdfAddress <= HeaderTypeValue) { | ||
| Advance | to the next slot entry (4 bytes per entry). | ||
| SlotEntry | += 4; | ||
| Utility | Functions | ||
| Validate | Buffer is not NULL. | ||
| if | (Buffer == NULL) { | ||
| Read | 8 bytes from the buffer as a 64-bit value. | ||
| Cast | to volatile to prevent compiler optimizations from re-ordering | ||
| or | combining the access. | ||
| return | (CONST UINT64 )Buffer; | ||
| Module | Entry Point | ||
| Validate | input parameters. | ||
| if | (ImageHandle == NULL) { | ||
| Cache | global pointers. | ||
| gImageHandle | = ImageHandle; | ||
| Locate | HOB list (ensures PCI enumeration data is available). | ||
| Initializes | gHobList for use by the UBA framework. | ||
| GetHobList | (ImageHandle); | ||
| Log | debug banner indicating this is the OpROM Update driver for | ||
| the | Lightning Ridge EXEC B1 platform. | ||
| DebugPrint | (DEBUG_INFO, "UBA:OpromUpdate-TypeLightningRidgeEXECB1\n"); | ||
| Locate | the UBA Lightning Ridge EXEC B1 board-type protocol. | ||
| The | protocol GUID is stored at GuidBlock + 0x40. | ||
| If | the UBA protocol was found, register the OpROM update configuration. | ||
| The | registration function is at offset 0x10 in the protocol interface. | ||
| if | (!EFI_ERROR (Status)) { | ||
| Same | GUID as protocol | ||
| 0x30 | bytes |
Generated by HR650X BIOS Decompilation Project