# BmcElog

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **DebugAssert** |  |
|  | **IpmiDetectInterface** |  |
|  | **IpmiSendCommand** |  |
|  | **IpmiGetResponse** |  |
|  | **BmcElogRead** |  |
|  | **BmcElogClear** |  |
|  | **BmcElogSetStatus** |  |
|  | **BmcElogWrite** |  |
|  | **CompareGuid** |  |
|  | **OnExitBootServices** |  |
|  | **OnVirtualAddressChange** |  |
|  | **FreeBmcElogProtocolBuffer** |  |
|  | **BmcElogEntryPoint** |  |
| Module | **globals** |  |
| EFI_HANDLE | **gImageHandle  = NULL;** |  |
| IPMI | **transport protocol handle (opaque)** |  |
| VOID | ***mIpmiTransport   = NULL;** |  |
| ASSERT | **reporting function** |  |
| result | **= sub_1A60();** |  |
| if | **(result)** |  |
| return | **(*(UINT64 (__fastcall **)(UINT64, UINT64, UINT64))(result + 8))** |  |
| This | **is the DebugAssert() routine from DebugLib.** |  |
| if | **(mBootServices != 0) {** |  |
| Internal | **memory operations** |  |
| if | **((UINTN)Source < (UINTN)Destination &&** |  |
| Src8 | **= &Src8[Length - 1];** |  |
| No | **overlap: copy 8 bytes at a time** |  |
| Count | **= Length >> 3;** |  |
| if | **(Length >= 8) {** |  |
| IPMI | **transport helper** |  |
| If | **mIpmiTransport cached, return it.** |  |
| If | **mBootServices exists:** |  |
| Check | **if buffer size needed <= 0x10** |  |
| Allocate | **pool** |  |
| Locate | **protocol handle for the IPMI transport GUID (unk_3000)** |  |
| Cache | **in mIpmiTransport** |  |
| if | **(mIpmiTransport != NULL) {** |  |
| Get | **transport via GetIpmiTransport()** |  |
| Read | **CMOS 0x70/0x71 register 0x4B to get BMC interface type** |  |
| Map | **to transport interface ID:** |  |
| 1 | **-> 0x80000004 (KCS)** |  |
| 2 | **-> 0x80000006 (SMBUS)  [value 3 would be BT]** |  |
| 3 | **-> BT** |  |
| If | **IoOperation matches the interface, call transport.** |  |
| VA_LIST | **Args;** |  |
| Read | **CMOS register 0x4B** |  |
| BmcIfType | **= IoRead8 (0x70);** |  |
| Call | **the transport function through the protocol** |  |
| return | **((EFI_STATUS (__fastcall *)(** |  |
| Loop | **up to 512 iterations sending the IPMI command via** |  |
| the | **transport protocol (qword_3040).** |  |
| If | **transport returns CC_CANNOT_RETRY (0xC5), retry with** |  |
| a | **"Write" sub-command (0x42 / 0x42 = Write).** |  |
| Otherwise | **return success or timeout.** |  |
| VOID | ***Transport;** |  |
| IPMI | **transport protocol** |  |
| Prepare | **command packet** |  |
| Send | **command via transport->SendCommand (offset +16)** |  |
| Status | **= ((EFI_STATUS (__fastcall *)(** |  |
| NetFunction | **0,           // Lun** |  |
| Command | **WriteData** |  |
| Check | **for retryable error (0xC5 = CC_CANNOT_RETRY)** |  |
| if | **(*(UINT8 *)((UINT8 *)Transport + 8) == 0xC5) {** |  |
| NetFunction | **0** |  |
| Write | **sub-command** |  |
| Opens | **GetResponse command to the IPMI transport.** |  |
| Uses | **the BMC_ELOG_REFROTOCOL signature validation.** |  |
| Copies | **data from transport buffer to output.** |  |
| UINT8 | **Buffer[16];** |  |
| Validates | **REFROTOCOL signature at This-113** |  |
| checks | **revision, builds read request via transport.** |  |
| Copies | **16 bytes of event data to output.** |  |
| BMC_ELOG_REFROTOCOL | ***Ref;** |  |
| Validate | **signature** |  |
| Ref | **= (BMC_ELOG_REFROTOCOL *)((UINT8 *)This - 113);** |  |
| Build | **the IPMI Get SEL Entry command** |  |
| Reserved | **ReadData[2] = 0xFF00;                         // Record type mask / last entry** |  |
| Starting | **record ID** |  |
| Get | **SEL Entry** |  |
| Validates | **signature, performs clear/reserve SEL operation.** |  |
| If | **a3 (Data) is non-NULL, does a full SEL erase with record ID reservation.** |  |
| If | **a3 is NULL, does a "Get SEL Info" then "Clear SEL" via sub_138C.** |  |
| Get | **SEL Info** |  |
| ResponseSize | **= 14;** |  |
| Reserved | **);** |  |
| Erase | **is not supported** |  |
| return | **EFI_UNSUPPORTED;** |  |
| Reserve | **SEL first** |  |
| EFI_STATUS | **ReserveStatus;** |  |
| Reserve | **SEL** |  |
| Erase | **SEL with reservation (full clear)** |  |
| UINT8 | **EraseData[4];** |  |
| Reservation | **byte 1** |  |
| Reservation | **byte 0** |  |
| Check | **completion code** |  |
| if | **(*(UINT8 *)((UINT8 *)(*(VOID **)((UINT8 *)mHobList + 0x3040)) + 8) == 0x80) {** |  |
| Clear | **via Set SEL Time / erase mechanism using sub_138C** |  |
| UINT8 | **ClearBuf[6];** |  |
| Set | **SEL Time** |  |
| Validates | **signature and revision.** |  |
| Sends | **or gets SEL info to read/write bit 3 of the SEL operation** |  |
| support | **flags (bit 3 = SEL enable/disable).** |  |
| Get | **SEL Info parameter** |  |
| IPMI | **Get SEL Info command (NetFn=6, Cmd=0x47)** |  |
| Storage | **NetFn** |  |
| Set | **the enable/disable bit** |  |
| UINT8 | **NewResponse = Response;** |  |
| Set | **SEL Time (to change enable)** |  |
| Validates | **REFROTOCOL signature, checks revision** |  |
| opens | **an IPMI session, sends command data** |  |
| and | **returns the record ID.** |  |
| Prepare | **buffer and open IPMI session** |  |
| ZeroMem | **(Buffer, sizeof (Buffer));** |  |
| Check | **overflow bit; if set return EFI_OUT_OF_RESOURCES** |  |
| return | **EFI_OUT_OF_RESOURCES;** |  |
| DataSize | **must be <= 0x10 (max SEL record size)** |  |
| if | **(DataSize > 16) {** |  |
| Send | **the Add SEL Entry command** |  |
| HOB | **library support** |  |
| sub_1D94 | **/ sub_1E04:** |  |
| Compare | **two GUIDs as two 64-bit values.** |  |
| sub_1E04 | **reads a UINT64 from a potentially unaligned address.** |  |
| UINT64 | ***Data1 = (UINT64 *)Guid1;** |  |
| Scans | **the HOB list (from SystemTable + 104/112) looking for** |  |
| a | **HOB with a specific GUID (unk_3020, unk_3028).** |  |
| Caches | **result in mHobList.** |  |
| If | **no matching HOB, asserts.** |  |
| EFI_PEI_HOB_POINTERS | **Hob;** |  |
| HOB | **list not found - assertion** |  |
| DebugAssert | **(** |  |
| Event | **notification handlers** |  |
| Clears | **the cached BootServices pointer.** |  |
| mBootServices | **= 0;** |  |
| If | **mIpmiTransport is set, calls RuntimeServices->ConvertPointer** |  |
| to | **convert the pointer for the new virtual address mapping.** |  |
| Memory | **allocation helpers** |  |
| AllocatePool | **and ZeroMem for the BmcElog protocol structure.** |  |
| VOID | ***Buffer;** |  |
| Frees | **the BmcElog protocol buffer allocated during initialization.** |  |
| EFI_STATUS | **Status;** |  |
| Initialize | **module globals** |  |
| gST | **= SystemTable;** |  |
| Validate | **pointers** |  |
| if | **(ImageHandle == NULL) {** |  |
| Cache | **boot services pointer (used in sub_1BA8-style notification cleanups)** |  |
| mBootServices | **= (UINT64)gBS;** |  |
| Register | **ExitBootServices event to clear BS pointer** |  |
| Register | **VirtualAddressChange event** |  |
| Get | **the HOB list** |  |
| GetFirstHob | **();** |  |
| Get | **the cached transport pointer** |  |
| Locate | **IPMI transport protocol handle** |  |
| Status | **= gBS->LocateProtocol (** |  |
| Reserve | **SEL (for subsequent clear operations)** |  |
| ZeroMem | **(InitData, sizeof (InitData));** |  |
| Reserve | **SEL command data** |  |
| Check | **response for SEL support** |  |
| if | **(InitData[1] & 0x04) {** |  |
| Allocate | **and initialize the REFROTOCOL structure** |  |
| RefProtocol | **= (BMC_ELOG_REFROTOCOL *)AllocateZeroedRefProtocol (EfiBootServicesData);** |  |
| Initialize | **the protocol structure** |  |
| Register | **function pointers into the REFROTOCOL at known offsets** |  |
| Install | **the protocol** |  |
| Status | **= gBS->InstallProtocolInterface (** |  |
| Enable | **SEL logging (if already enabled, ensure it stays)** |  |
| EnableStatus | **= 1;** |  |

---
*Generated by HR650X BIOS Decompilation Project*