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

Smbios

Function Table

Address Name Description
GetSmbiosStructureSize
GetSmbiosTotalTableSize
FindStructureByType
FindStructureByHandle
FindStringByNumber
ReplaceStringInStructure
ClearSmbiosFieldsByBitmap
UpdateEPSHeader
UpdateEPSHeader3
UpdateSmbiosTableHeader
UpdateSmbiosTable
DeleteStructureByHandle
AddStructureByHandle
AddStructureByIndex
ReadStructureByType
ReadStructureByHandle
SmbiosEndOfDxe
SmbiosDynamicUpdate
UpdateStructuresWithNvramData
SmbiosPiAddStructure
SmbiosPiUpdateString
SmbiosPiRemoveStructure
SmbiosPiGetNextStructure
SmbiosDriverEntryPoint
_ModuleEntryPoint
Global Data
EFI_SYSTEM_TABLE *gSystemTable = NULL; // qword_9208
qword_91F8 EFI_RUNTIME_SERVICES_TABLE *gRuntimeServices = NULL; // qword_9200
qword_9138 - SMBIOS table base
n0x2000 UINT8 *gSmbiosEntryPoint = NULL; // off_8A80 - "SM" EPS
word_958E / n0xFFFD
word_95A0 //
byte_8C1A (in rdata)
byte_9158 UINT8 gSmbiosFirstDynamicUpdateSeen = TRUE; // byte_8BA8
Protocol GUIDs (referenced via global data)
EFI_SMBIOS_PROTOCOL GUID: {0x0358B4B4, 0x4B47, 0x46B7, {0x9C, 0x6C, 0xD4, 0x8F, 0x8A, 0x56, 0x43, 0x55}}
AMI_SMBIOS_PROTOCOL GUID: {0x8C3D856A, 0x6D47, 0x4C1B, {0xA0, 0x49, 0x3C, 0x59, 0x0B, 0xD7, 0x0C, 0x28}}
extern EFI_GUID gEfiSmbiosProtocolGuid;
PCD Protocol handle
VOID *mPcdProtocol = NULL; // qword_9228
MM PCI Base Protocol handle
VOID *mPciUsra = NULL; // qword_9198
SMBIOS static table FV file GUID
extern EFI_GUID gSmbiosStaticTableFileGuid; // unk_8920
Debug helper: macro to call DebugPrint / sub_4F00
sub_4F00 is DebugPrint with error level as first arg
Forward declarations of static helpers
Start after the formatted area (the header-defined portion)
StringArea = (UINT8 *)Record + Record->Length;
Walk through the null-terminated strings area
while (*StringArea != 0) {
Skip the terminating null of the last string
Now StringArea points to the double-null terminator.
Include the final null.
Add the terminator structure size
TotalSize += GetSmbiosStructureSize ((SMBIOS_STRUCTURE_HEADER *)Cursor);
Advance to the Nth string (1-based), walking past null-terminated strings
for (Index = 1; Index < StringNum; Index++) {
Skip null terminator
Check if we are still within the structure
if ((UINTN)StrPos >= (UINTN)EndPos) {
For now, a placeholder that calls down to the internal implementation.
The actual decompiled logic (sub_1BEC) performs an in-place string swap
with compaction of the trailing content.
Full implementation from decompilation would:
ASSERT (FALSE); // Not yet fully reimplemented; see sub_1BEC decompilation.
Null out the specific byte offset (field clearing)
Each entry is 3 bytes (offset, skip, reserved)
SMBIOS v2.x EPS update
Calculate the intermediate checksum value
Set the SMBIOS table address (lower 32 bits)
Count the number of SMBIOS structures (excluding the terminator)
Cursor = gSmbiosTableBase;
Include the terminator in the count
Compute the maximum string size across all structures
Fill EPS fields
Compute EPS checksum (checksum of bytes 0..length-1 should be 0)
Clear checksum field first
Bytes 16-30 inclusive
Compute the intermediate EPS checksum (for the DMI area)
Reset EPS checksum
Write the EPS to the legacy region at the pre-allocated address
if (gSmbiosEntryPoint != NULL) {
SMBIOS v3.0 EPS update
Set the table maximum size and address
Compute EPS checksum (bytes 5..23 sum to zero)
Clear checksum
Write the v3 EPS to the pre-allocated region
if (gSmbiosV3EntryPoint != NULL) {
Update both EPS headers and re-program to legacy region
If a legacy region protocol is available, unprotect the E/F segment
Update v2.x EPS
UpdateEPSHeader ();
Update v3.0 EPS
DEBUG ((EFI_D_INFO, "::: SMBIOS - Exit UpdateSmbiosTableHeader :::\n"));
Core SMBIOS table update function
Debug trace
DEBUG ((EFI_D_INFO, "* SMBIOS - UpdateSmbiosTable *\n"));
If a LegacyRegionProtocol is available, unprotect
if (Operation == SMBIOS_DELETE_STRUCTURE) {
Delete the structure at the given pointer
DEBUG ((EFI_D_INFO, "Deleting structure\n"));
SmbiosCopyMem ((VOID )Structure, (UINT8 )Structure + StructSize, RemainingSize);
Fill vacated space with 0xFF
SmbiosSetMem ((UINT8 *)Structure + RemainingSize, -1, StructSize);
Unknown operation
return EFI_INVALID_PARAMETER;
DEBUG ((EFI_D_INFO, "Adding structure\n"));
Check if the handle already exists (for inserts requiring uniqueness)
if (HandleValue <= 0xFFFD) {
Validate structure integrity
if ((UINT16 )((UINT8 *)Structure + Size - 2) != 0) {
Handle special case: Type 4 (Processor) with Length 42 (0x2A)
that has empty type-specific fields - clip trailing zeros
if (Structure->Type == SMBIOS_TYPE_PROCESSOR_INFORMATION &&
Compact away the empty fields at offset 42
SmbiosCopyMem ((UINT8 )Structure + 42, (UINT8 )Structure + 48, Size - 48);
Allocate scratch buffer
ScratchBuffer = AllocatePool (gSmbiosTableSize + Size);
Copy existing table into scratch
SmbiosCopyMem (ScratchBuffer, gSmbiosTableBase, gSmbiosTableSize);
Calculate current used size
NewTableSize = GetSmbiosTotalTableSize (gSmbiosTableBase);
Check if there is enough free space in the table
if (Size <= gSmbiosTableSize - NewTableSize) {
if (gSmbiosTableSize - NewTableSize >= Size) {
Enough space - do in-place operation
Need to expand the table
if (!gSmbiosTableExpansionEnabled) {
Cannot allocate after EndOfDxe
DEBUG ((EFI_D_ERROR
Locate insertion point
Find structure by handle to insert before
while (*WriteCursor != SMBIOS_TERMINATOR_TYPE) {
Find insertion point by handle value ordering
while (*WriteCursor != SMBIOS_TERMINATOR_TYPE &&
Assign the handle
if (HandleValue > 0xFFFD) {
Insert the new structure
SmbiosCopyMem (WriteCursor, Structure, Size);
Copy the remaining structures after the insertion point
Walk original table from OldCursor to end to compute trail size
while (*TrailSrc != SMBIOS_TERMINATOR_TYPE) {
terminator SmbiosCopyMem (TrailDst, OldCursor, TrailSize);
Check for handle collision and fix up
if (HandleValue >= ((SMBIOS_STRUCTURE_HEADER *)CheckCursor)->Handle) {
Also update the global next handle tracker
if (HandleValue >= gNextSmbiosHandle) {
Free scratch and update EPS
if (ScratchBuffer != NULL) {
Restore legacy region protection
DEBUG ((EFI_D_INFO, "Status = %r\n", EFI_SUCCESS));
If the table was reallocated, free the old one and update the pointer
Delete a structure by handle
Specialized path for Processor type structures with specific flags
Status = EFI_UNSUPPORTED; // Placeholder for sub_26E0 path
Add a structure by index (insert before given handle)
Specialized path
Status = EFI_UNSUPPORTED;
Read a structure by type
Find the next available handle
Producer handle table management
If the first entry is unused, take it
if (Entry->Handle == SMBIOS_INVALID_HANDLE) {
Search for an existing entry with this handle, or an unused slot
for (Index = 0; Index < SMBIOS_PRODUCER_HANDLE_COUNT; Index++) {
Found existing entry for this handle (update in place)
Found an empty slot
Table full; silently fail (original behavior)
return NULL;
EndOfDxe Event Handler
Close the event (it is a one-shot notification)
Allocate a scratch buffer to work with the SMBIOS table
ScratchBuffer = AllocatePool (gSmbiosTableSize);
Locate LegacyRegionProtocol to unprotect E/F segment for EPS programming
Status = gBS->LocateProtocol (&gEfiLegacyRegionProtocolGuid, NULL, (VOID )&LegacyRegion);**
Continue without legacy region programming if protocol unavailable
LegacyRegion = NULL;
Copy the SMBIOS table to scratch for processing
Update both EPS headers and program to legacy region
Lock the table (no further expansion allowed)
gSmbiosTableExpansionEnabled = FALSE;
Close the event
Create onboard device data (type 41 structures)
Create onboard device extended info (type 42)
Populate runtime-configurable structures from NVRAM
Perform dynamic update of SMBIOS structures (types populated from data sources)
DEBUG ((EFI_D_INFO, "* SMBIOS - DynamicUpdateStructures *\n"));
First time through: populate from firmware data sources
After all dynamic updates, trigger memory type information update
Check if system is in S5/S6 state for memory data decisions
Signal the new table to listeners
Close and re-create the periodic event
Update entry points
Decompiled logic from sub_B70:
DEBUG ((EFI_D_INFO, "* SMBIOS - UpdateStructuresWithNvramData *\n"));
Placeholder for the full NVRAM update logic.
The decompiled function (sub_B70, ~800 instructions) performs:
PI SMBIOS Protocol implementation
if (!FindNextAvailableHandle (0) / check availability /) {
Use the provided handle (replace existing if applicable)
if (!AddStructureByHandle (Structure->Handle, (UINT8 *)Structure, StructSize)) {
Locate the structure by handle
if (!FindStructureByHandle (&Cursor, *Handle)) {
Validate string number
Compute new string length
NewStringLen = 0;
ScratchBuffer = AllocatePool (StructSize + NewStringLen + 1);
Copy structure to scratch
SmbiosCopyMem (ScratchBuffer, Cursor, StructSize);
Replace the string
ReplaceStringInStructure (ScratchBuffer, *StringNumber, String);
Delete old structure
DEBUG ((EFI_D_INFO, "Deleting structure with handle = %x\n", *Handle));
Add updated structure
DEBUG ((EFI_D_INFO, "Adding structure with handle = %x\n", *Handle));
Clean up
FreePool (ScratchBuffer);
Remove from producer handle table (compact entries)
EntryToRemove = SMBIOS_PRODUCER_HANDLE_COUNT;
Compact the table
SmbiosCopyMem (
Clear the last entry
No type filter - just advance past current handle
if (*Handle != SMBIOS_STARTING_HANDLE) {
Advance to next
if (*Cursor == SMBIOS_TERMINATOR_TYPE) {
Type filter active
Advance past current
Find next matching type
Found a structure
if (*Cursor != SMBIOS_TERMINATOR_TYPE) {
Look up producer handle
if (ProducerHandle != NULL) {
Search producer handle table
if (*Handle != SMBIOS_TERMINATOR_TYPE) {
No more structures
Driver Entry Point
Initialize global service pointers
if (gSystemTable == NULL) {
1 page = 4KB, more than enough for 31 bytes
Initialize the EPS memory with the "SM" signature
SmbiosCopyMem (gSmbiosEntryPoint, SMBIOS_ENTRY_POINT_SIG, 31);
Initialize the v3 EPS memory with the "SM3" signature
SmbiosCopyMem (gSmbiosV3EntryPoint, SMBIOS_V3_ENTRY_POINT_SIG, 24);
Read "Setup" variable
DataSize = sizeof (SetupVar);
Read "SecureBoot" variable
DataSize = sizeof (BOOLEAN);
Locate all handles that support FirmwareVolume2 protocol
Search each FV for the SMBIOS static table file
for (Index = 0; Index < NumberOfHandles; Index++) {
Read the raw section from the FV file
Found the static SMBIOS data section
StaticTableFound = TRUE;
Skip section header
Locate the last handle in the static table and fix up
Update the terminator handle to the next available
No static table; start with an empty table (just a terminator)
StaticTableSize = 0x2000; // Use default table size
Initialize to 0xFF
SmbiosSetMem (gSmbiosTableBase, -1, gSmbiosTableSize);
Copy the static table into the new buffer
SmbiosCopyMem (gSmbiosTableBase, StaticTableData, StaticTableSize);
Free the FV section data
DEBUG ((EFI_D_INFO, "Freeing Buffer\n"));
Create an empty terminator structure
Length = 4 bytes (Type, Length, Handle[2])
Read any NVRAM-based structures from Setup variable
Populate structures from the NVRAM data store
DEBUG ((EFI_D_INFO, "Before UpdateStructuresWithNvramData\n"));
Register the EndOfDxe event group notification
Status = gBS->CreateEventEx (
Initialize the producer handle table to invalid state
Walk the table and register each existing structure's handle
Update both EPS headers
the .data section (off_8A38). This is a reconstructed representation.
SmbiosProtocol = AllocateZeroPool (sizeof (SMBIOS_PROTOCOL));
Library constructors (ProcessLibraryConstructorList) are called
in the AutoGen before reaching the entry function body.
ProcessLibraryConstructorList (ImageHandle, SystemTable);
Call the real driver entry point
return SmbiosDriverEntryPoint (ImageHandle, SystemTable);

Generated by HR650X BIOS Decompilation Project