Newer
Older
AMI-Aptio-BIOS-Reversed / BmcElog / BmcElog.md
@Ajax Dong Ajax Dong 2 days ago 7 KB Init

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