# POSTDataTransfer

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **GetDebugInterface** |  |
|  | **DebugPrint** |  |
|  | **DebugAssert** |  |
|  | **UnalignedRead64** |  |
|  | **GuidCompare** |  |
|  | **HobLocate** |  |
|  | **MmioPciExpressRead32** |  |
|  | **PciExpressBaseAddr** |  |
|  | **PcdLocate** |  |
|  | **sub_39C** |  |
|  | **ProcessPci** |  |
|  | **ProcessSADTAD** |  |
|  | **CollectPOSTData** |  |
|  | **sub_1148** |  |
|  | **ModuleEntryPoint** |  |
| Global | **variables** |  |
| UINT64 | **gImageHandle;** |  |
| qword_2708 | **UINT64             gIioUdsProtocol;               // qword_2710** |  |
| qword_2740 | **UINT64             gMtrrSettings;                 // qword_2748** |  |
| qword_2750 | **UINT64             gPort80DebugValue;             // qword_2758** |  |
| GUID | **definitions (from UEFI spec / platform headers)** |  |
| EFI_GUID | **gEfiPciRootBridgeIoProtocolGuid = { 0x2F707EBB, 0x4A1A, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } };** |  |
| Each | **entry: { Bus, Device, Function, Register offset, Value mask }** |  |
| 696 | **entries (0x2B8 bytes), 5 bytes each** |  |
| STATIC | **CONST UINT8  mSadAdTopologyTable[696 * 5] = { 0 };** |  |
| Check | **if we have enough buffer space (>= 16 bytes)** |  |
| if | **(gBS >= 0x10) {** |  |
| GUID | **not found: ASSERT and fall through** |  |
| DebugPrint | **(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", 0x800000000000000E);** |  |
| Validate | **that the address fits within PCIe config space range** |  |
| if | **((Address & ~0xFFFFFFF) != 0) {** |  |
| Locate | **all handles that support gEfiPciRootBridgeIoProtocolGuid** |  |
| NumHandles | **= 0;** |  |
| Iterate | **over all PCI root bridge handles** |  |
| for | **(HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {** |  |
| Get | **the PCI Root Bridge IO protocol for this handle** |  |
| PciRootBridgeIo | **= NULL;** |  |
| Get | **resource list to determine bus range** |  |
| Status | **= (*(UINT64 (__fastcall **)(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *, UINT64 *))(** |  |
| If | **no resource list, do a full bus scan (0-255)** |  |
| if | **(ResourceList == 0) {** |  |
| Set | **initial bus range from resource list** |  |
| Bus | **= StartBus;** |  |
| Scan | **all buses, devices, functions** |  |
| while | **(Bus <= EndBus) {** |  |
| Retry | **up to 8 times on failure** |  |
| Status | **= PciRootBridgeIo->Pci.Read (** |  |
| Check | **if device is present (VendorId != 0xFFFF)** |  |
| if | **(VendorId == 0xFFFF) {** |  |
| Read | **PCI header type** |  |
| Read | **full config space (64 bytes)** |  |
| PciAddress | **= PCI_EXPRESS_ADDRESS (Bus, Function, Device, 0);** |  |
| Valid | **PCI device (non-multifunction or function 0)** |  |
| IpmiMsgType | **= ConfigSpace[0x11];  // Subsystem Vendor ID (or similar)** |  |
| DebugPrint | **(0x80000000, "[%X/%X/%X]  ", Bus, Device, Function);** |  |
| if | **((ConfigSpace[BarIndex * 4] & 2) != 0 ||** |  |
| BarValue | **= *(UINT32 *)&ConfigSpace[BarIndex * 4];** |  |
| Command | **register backup** |  |
| Disable | **decoding by clearing command register bits** |  |
| Calculate | **PCI config space offset for the BAR** |  |
| if | **(IpmiDataReady) {** |  |
| BarValueMask | **= ~0ULL;** |  |
| Restore | **command register** |  |
| Send | **via IPMI** |  |
| IpmiMsgType | **= 4865;** |  |
| Handle | **multi-function devices** |  |
| Process | **resource list to find acpi (0x79) and pnp (0x02) descriptors** |  |
| while | **(ResourceList != 0) {** |  |
| End | **tag** |  |
| Status | **= 1;** |  |
| Type | **2 descriptor (DWORD address space): extract bus range** |  |
| StartBus | **= *(UINT16 *)(ResourceList + 14);** |  |
| Free | **the handle buffer** |  |
| if | **(HandleBuffer != NULL) {** |  |
| Locate | **gEfiIioUdsProtocolGuid** |  |
| Status | **= (*(UINT64 (__fastcall **)(VOID *, UINT64, UINT64 *))(gBootServices + 320))(** |  |
| Locate | **gEfiCpuCsrAccessGuid** |  |
| Iterate | **over 4 possible sockets** |  |
| for | **(Socket = 0; Socket < 4; Socket++) {** |  |
| Socket | **is present** |  |
| Process | **SAD/AD topology table (696 entries)** |  |
| TableIndex | **= 9 * Socket;** |  |
| First | **pass: read CPUBUSNO and CPUBUSNO1 for this socket** |  |
| CpuBusNo | **= (*(UINT32 (__fastcall **)(UINT8, UINT32, UINT32))(gGpioCsrAccessProtocol + 8))(** |  |
| CPUBUSNO | **CSR** |  |
| Check | **CPUBUSNO_VALID** |  |
| Bus | **information valid: store it** |  |
| No | **bus information for this socket; use default** |  |
| DebugPrint | **(0x80000000, "No Bus Information in Socket %x.", Socket);** |  |
| Calculate | **the full PCI address using the socket's bus number** |  |
| BusNum | **= gSocketBusInfo[Socket][1 + SadAdEntry[4]];** |  |
| Now | **process CSR-based DIMM/DDRIO data for the 24 VCU/MC channels** |  |
| for | **(Index = 0; Index < 24; Index++) {** |  |
| Write | **selector register** |  |
| Some | **CSR selector** |  |
| Read | **the data register** |  |
| Temp | **= (*(UINT32 (__fastcall **)(UINT8, UINT8, UINT32))(gGpioCsrAccessProtocol + 40))(** |  |
| Register | **the boot services timer event** |  |
| Ensure | **IPMI transport protocol is available** |  |
| if | **(gIpmiTransport == 0) {** |  |
| Collect | **PCI data and SAD/AD data** |  |
| ProcessPci | **();** |  |
| Initialize | **global variables (BootServices, SystemTable, etc.)** |  |
| sub_39C | **(ImageHandle, SystemTable);** |  |
| Create | **a timer event to collect POST data** |  |
| Status | **= (*(EFI_STATUS (__fastcall **)(UINT64, UINT64, EFI_EVENT *))(gBootServices + 80))(** |  |
| TimerPeriodic | **16,            // NotifyTpl** |  |

---
*Generated by HR650X BIOS Decompilation Project*