# OpromUpdateDxeLightningRidgeEXECB3

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **_ModuleEntryPoint** |  |
|  | **DebugPrint** |  |
|  | **DebugAssert** |  |
|  | **IsHobListGuid** |  |
|  | **ReadUnaligned64** |  |
|  | **IsPcieSlotConfigured** |  |
|  | **OpromGetConfigA** |  |
|  | **OpromGetConfigB** |  |
|  | **OpromGetConfigC** |  |
|  | **OpromSetSlotNumber** |  |
| UEFI | **standard protocol pointer caches (set by _ModuleEntryPoint)** |  |
| Image | **addr 0xF30: gST** |  |
| Image | **addr 0xF38: gBS** |  |
| Image | **addr 0xF40: gImageHandle** |  |
| Image | **addr 0xF48: gRT** |  |
| EFI_SYSTEM_TABLE | ***gST             = NULL;** |  |
| Cached | **protocol/hand-off block pointers (resolved lazily)** |  |
| Image | **addr 0xF50: gOpromProtocol  (UBA DebugLib protocol cache)** |  |
| Image | **addr 0xF58: gHobList        (HOB list pointer cache)** |  |
| UBA_DEBUG_LIB_PROTOCOL | ***gOpromProtocol  = NULL;** |  |
| Step | **1: Cache UEFI standard protocol pointers.** |  |
| These | **are also set by the library constructors in** |  |
| UefiBootServicesTableLib | **and UefiRuntimeServicesTableLib** |  |
| but | **we cache them explicitly here for robustness.** |  |
| gImageHandle | **= ImageHandle;** |  |
| Step | **2: Resolve the HOB (Hand-Off Block) list.** |  |
| This | **walks SystemTable->ConfigurationTable[] looking for the entry** |  |
| with | **VendorGuid == EFI_HOB_LIST_GUID ({7739F24C-...}).** |  |
| The | **associated VendorTable pointer is the HOB list header.** |  |
| Result | **is cached in gHobList (image addr 0xF58).** |  |
| GetHobList | **();** |  |
| Step | **3: Print the platform identification banner.** |  |
| ErrorLevel | **0x80000000 is the UBA-specific debug severity mask.** |  |
| DebugPrint | **(0x80000000, "UBA:OpromUpdate-TypeLightningRidgeEXECB3\n");** |  |
| Step | **4: Locate the UBA_CONFIG_PROTOCOL.** |  |
| GUID | **{E03E0D46-5263-4845-B0A4-58D57B3177E2} identifies the** |  |
| ConfigBuffer | **= 0;** |  |
| Step | **5: Call the protocol's RegisterConfig function.** |  |
| The | **function pointer is at vtable index 2 (offset 0x10).** |  |
| EFI_STATUS | **(*RegisterConfig)(** |  |
| VOID | ***This** |  |
| CONST | **EFI_GUID *ConfigGuid** |  |
| CONST | **VOID *ConfigData** |  |
| UINTN | **ConfigDataSize** |  |
| ConfigGuid | **= &gOpromUpdateConfigDataGuid** |  |
| ConfigData | **= &mOpromUpdateConfig (PBDS structure, 48 bytes)** |  |
| DataSize | **= 48 (sizeof(OPROM_UPDATE_CONFIG))** |  |
| UbaConfigProtocol | **= (VOID *)ConfigBuffer;** |  |
| Return | **cached pointer if already resolved.** |  |
| if | **(gOpromProtocol != NULL) {** |  |
| Check | **available pool size by allocating and immediately freeing.** |  |
| Type | **31 is EfiBootServicesData in this platform's memory map.** |  |
| If | **only <= 0x10 bytes available, return NULL.** |  |
| Resolve | **the UBA DebugLib protocol.** |  |
| Resolve | **the DebugLib protocol (lazy initialization).** |  |
| Protocol | **= GetDebugLibProtocol ();** |  |
| Read | **CMOS register 0x4B to determine the board platform type.** |  |
| CMOS | **access sequence:** |  |
| PlatformType | **= IoRead8 (0x70);                              /* Save NMI state */** |  |
| If | **CMOS returned > 3 and == 0, the register is uninitialized.** |  |
| Fall | **back to MMIO at 0xFDAF0490 (GPIO or strapping register).** |  |
| Extract | **bit 1, OR with 1 to get platform type 1 or 3.** |  |
| if | **(PlatformType > 3) {** |  |
| Select | **debug mask based on platform type.** |  |
| if | **(PlatformType == 1) {** |  |
| Check | **if the error level matches the platform debug mask.** |  |
| If | **no bits match, suppress the output.** |  |
| if | **((DebugMask & ErrorLevel) == 0) {** |  |
| Call | **the protocol's DebugPrint function at vtable offset 0x00.** |  |
| The | **protocol's DebugPrint uses VA_LIST, not variadic args.** |  |
| VA_START | **(VaList, Format);** |  |
| Call | **the protocol's assertion handler at vtable offset 0x08.** |  |
| if | **(gHobList != NULL) {** |  |
| Access | **the configuration table array from the system table.** |  |
| SystemTable | **+ 0x68 = NumberOfTableEntries (UINTN)** |  |
| SystemTable | **+ 0x70 = ConfigurationTable (EFI_CONFIGURATION_TABLE *)** |  |
| TableCount | **= gST->NumberOfTableEntries;** |  |
| Iterate | **through the configuration table entries to find the HOB list.** |  |
| Each | **entry is 24 bytes: 16-byte VendorGuid + 8-byte VendorTable pointer.** |  |
| We | **compare the first 8 bytes and next 8 bytes separately via** |  |
| ReadUnaligned64 | **against the reference GUID halves.** |  |
| if | **(ConfigTable != NULL) {** |  |
| Found | **the HOB list GUID. The associated VendorTable pointer** |  |
| is | **the HOB list (PHIT HOB header).** |  |
| gHobList | **= (VOID *)ConfigTable[Index].VendorTable;** |  |
| If | **we didn't find the GUID in any table entry, trigger an ASSERT.** |  |
| if | **(gHobList == NULL) {** |  |
| If | **the resolved pointer is NULL, trigger another ASSERT.** |  |
| Compare | **the GUID as two 64-bit halves.** |  |
| First | **half: Data1(4) + Data2(2) + Data3(2) = 8 bytes (little-endian)** |  |
| Second | **half: Data4(8) = 8 bytes** |  |
| return | **(ReadUnaligned64 (&gEfiHobListGuid) == ReadUnaligned64 (Guid))** |  |
| Assert | **if the pointer is NULL.** |  |
| if | **(Buffer == NULL) {** |  |
| Dereference | **the pointer directly.** |  |
| return | ***(CONST UINT64 *)Buffer;** |  |
| Initialize | **the table pointer to start BEFORE the first entry.** |  |
| The | **original code uses &unk_ED1 as the base, then reads 3 bytes** |  |
| at | **offsets [-1, 0, +1], advancing by 4 each iteration.** |  |
| Our | **implementation uses direct indexing into mPcieSlotRanges[]** |  |
| which | **avoids the +1 offset trick.** |  |
| SlotData | **= (CONST UINT8 *)&mPcieSlotRanges;** |  |
| Iterate | **each of the 8 PCIe slot range entries.** |  |
| for | **(SlotIndex = 0; SlotIndex < 8; SlotIndex++) {** |  |
| Check | **if this slot bit is clear in the mask.** |  |
| A | **clear bit (0) means the slot is NOT yet configured and** |  |
| should | **be checked for device presence.** |  |
| if | **(((CurrentMask >> SlotIndex) & 1) == 0) {** |  |
| Extract | **the 3 bytes from the slot entry.** |  |
| In | **the original assembly:** |  |
| v8 | **= byte[-1] (mPcieSlotRanges[SlotIndex].Bus)** |  |
| v9 | **= byte[0]  (mPcieSlotRanges[SlotIndex].Device)** |  |
| v10 | **= byte[+1] (mPcieSlotRanges[SlotIndex].Function)** |  |
| BusByte | **= mPcieSlotRanges[SlotIndex].Bus;** |  |
| Compute | **the BDF address from the 3-byte descriptor.** |  |
| This | **gives a PciLib-style address with register field = 0.** |  |
| SlotBdfAddr | **= (((DevByte | ((UINT64)FuncByte << 8)) << 8)** |  |
| Open | **EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL to access PCI config space.** |  |
| The | **protocol GUID is {2F707EBB-4A1A-11D4-9A38-0090273FC14D}.** |  |
| Read | **PCI config space register at offset 0x19.** |  |
| On | **PCIe root ports, this is typically the Secondary Bus Number** |  |
| Intel | **chipsets repurpose this register to encode the start of** |  |
| the | **secondary bus range for this slot.** |  |
| The | **Pci.Read function at vtable index 7 (offset 0x38) is used.** |  |
| Read | **PCI config space register at offset 0x1A.** |  |
| This | **is the Subordinate Bus Number register on PCIe root ports** |  |
| or | **Header Type on standard devices. Encodes the end of the** |  |
| secondary | **bus range for this slot.** |  |
| Check | **if the target BDF address falls within the slot's range.** |  |
| If | **reg_0x19 <= PcieBdfAddr <= reg_0x1A, the device at this** |  |
| BDF | **is in the slot's secondary bus range.** |  |
| if | **((PcieBdfAddr >= RegValue19) && (PcieBdfAddr <= RegValue1A)) {** |  |
| Always | **set slot number to 0 on this platform.** |  |
| Log | **the slot assignment: "[UBA]:SetPcieSlotNumber callback - 0\n"** |  |
| DebugPrint | **(0x80000000, "[UBA]:SetPcieSlotNumber callback - %d\n", 0);** |  |

---
*Generated by HR650X BIOS Decompilation Project*