| Address | Name | Description | |
|---|---|---|---|
| ReadUnaligned64 | |||
| WriteUnaligned64 | |||
| AsciiStrLen | |||
| StrLen | |||
| AsciiStrnLenS | |||
| UnicodeStrnToAsciiStrS | |||
| ReadUnaligned32 | |||
| CompareGuid | |||
| FreePool | |||
| GetConfigTable | |||
| GetPlatformLang | |||
| DebugPrint | |||
| AssertHandler | |||
| AddSmbiosString | |||
| FindFirstSmbiosString | |||
| RemoveAndAddSmbiosString | |||
| RemoveAllSmbiosStringsOfType | |||
| GetSmbiosStructuresAfterField | |||
| UpdateSmbiosStringField | |||
| BuildSmbiosStringRecord | |||
| BuildSmbiosType9Record | |||
| BuildSmbiosType41Record | |||
| MmPciWriteConfig | |||
| SmbiosDataUpdateDispatch | |||
| SmbiosDataUpdateEntry | |||
| SmbiosDataUpdateInit | |||
| ModuleEntryPoint | |||
| Global | UEFI system table pointers (initialized by SmbiosDataUpdateInit) | ||
| EFI_HANDLE | gImageHandle = NULL; ///< 0x3928 - EFI image handle | ||
| Cached | protocol/state pointers | ||
| VOID | *mDebugProtocol = NULL; ///< 0x3938 - Cached DebugLib protocol | ||
| Global | state | ||
| EFI_GUID | mSmbiosConfigGuid; ///< 0x38F0 - Board-specific SMBIOS config GUID | ||
| GUID | Definitions (protocol and config identifiers) | ||
| GUID | for the UBA config protocol opened from ImageHandle. | ||
| Contains | board-specific SMBIOS configuration data. | ||
| static | EFI_GUID mUbaConfigProtocolGuid = { | ||
| GUID | for "en-US" default language (RFC 4646). | ||
| Used | as default platform language when PlatformLang variable is not set. | ||
| static | UINT16 mDefaultLanguage[] = L"en-US"; | ||
| HOB | list GUID for configuration table lookup. | ||
| static | EFI_GUID mHobListGuid = { | ||
| DXE | Services Table GUID. | ||
| static | EFI_GUID mDxeServicesTableGuid = { | ||
| Global | Variable GUID for UEFI standard variables (PlatformLang). | ||
| static | EFI_GUID mGlobalVariableGuid = { | ||
| DebugLib | protocol GUID. | ||
| static | EFI_GUID mDebugLibProtocolGuid = { | ||
| HII | Font protocol GUID. | ||
| static | EFI_GUID mHiiFontProtocolGuid = { | ||
| HII | Database protocol GUID. | ||
| static | EFI_GUID mHiiDatabaseProtocolGuid = { | ||
| HII | Package List protocol GUID. | ||
| static | EFI_GUID mHiiPackageListProtocolGuid = { | ||
| HII | String protocol GUID. | ||
| static | EFI_GUID mHiiStringProtocolGuid = { | ||
| static | EFI_GUID mSmbiosProtocolGuid = { | ||
| MM | PCIe Base protocol GUID. | ||
| static | EFI_GUID mMmPciBaseProtocolGuid = { | ||
| UBA | SMBIOS Data protocol GUID. | ||
| This | protocol is used to register SMBIOS data update configuration. | ||
| static | EFI_GUID mUbaSmbiosDataProtocolGuid = { | ||
| SMBIOS | string package GUID for HII registration. | ||
| Identifies | this driver's HII string package for SMBIOS strings. | ||
| static | EFI_GUID mSmbiosStringPackageGuid = { | ||
| SMBIOS | String Descriptor Table | ||
| SMBIOS | Type 2 (Baseboard) string descriptor table (30 entries). | ||
| Each | entry is 10 bytes: {Type, FieldNum, StringId(16), Encoding, Offset, MaxLen, Flags, Reserved(16)} | ||
| These | descriptors define which SMBIOS Type 2 string fields to update and | ||
| which | HII string tokens to use for localized string lookup. | ||
| SMBIOS | Type 2 fields: Manufacturer, ProductName, Version, SerialNumber | ||
| static | CONST SMBIOS_STRING_DESC mSmbiosType2Descriptors[30] = { | ||
| Entry | 0: Type=8 (Type2), Field=3, StrId=0x0002, Enc=0x08, Off=8, Max=3, Flag=0x08000000 | ||
| Entry | 1: Type=8 (Type2), Field=4, StrId=0x04, Enc=0x10, Off=8, Max=16, Flag=5 | ||
| Entries | 2-29 follow the same pattern with different field numbers | ||
| string | IDs, encodings, offsets, max lengths, and flags. | ||
| Full | descriptor table details available in the disassembly at sub_77C. | ||
| The | table is a 300-byte (30 * 10) embedded constant array. | ||
| Key | field numbers: 5 (Manufacturer), 6 (ProductName), 7 (Version) | ||
| 8 | (SerialNumber), 9 (AssetTag), 10-29 (additional board strings). | ||
| Forward | Declarations of Internal Functions | ||
| Zero | 8-byte aligned chunks first. | ||
| SetMem | (Buf, Length & ~7, 0); | ||
| Zero | remaining bytes (0-7). | ||
| SetMem | (&Buf[Length & ~7], Length & 7, 0); | ||
| Copy | backwards from the end to avoid corruption. | ||
| Src | = &Src[Length - 1]; | ||
| Copy | remaining 8-byte chunks backward | ||
| No | overlap or destination before source: copy forward. | ||
| CountQwords | = Length >> 3; | ||
| Copy | 8-byte aligned chunks. | ||
| CopyMem | (Dst, Src, CountQwords * 8); | ||
| Copy | remaining bytes. | ||
| CopyMem | (Dst, Src, CountRemaining); | ||
| Memory | and String Library Functions | ||
| Check | for overlap between source and destination buffers. | ||
| Overlap | = FALSE; | ||
| Overlap | error, treated as buffer error | ||
| Convert | each UCS-2 character to ASCII. | ||
| while | (*Src != 0) { | ||
| GUID | Manipulation | ||
| Memory | Allocation | ||
| Status | = gBootServices->AllocatePool ( | ||
| Status | = gBootServices->FreePool (Buffer); | ||
| Configuration | Table Access | ||
| Compare | GUIDs using 128-bit comparison. | ||
| if | (CompareGuid (&ConfigTable[Index].VendorGuid, TableGuid)) { | ||
| HOB | List Access | ||
| Return | cached pointer if already initialized. | ||
| HobList | = mHobList; | ||
| Find | the HOB list in the configuration table. | ||
| Status | = GetConfigTable (&mHobListGuid, &mHobList); | ||
| Verify | the HOB list was found. | ||
| if | (mHobList == NULL) { | ||
| Language | and Variable Services | ||
| Call | GetVariable with zero size first to get required buffer size. | ||
| Status | = gRuntimeServices->GetVariable ( | ||
| Allocate | buffer of required size. | ||
| LangBuffer | = AllocatePool (BufferSize); | ||
| Read | the variable data. | ||
| Determine | the length of the language to check. | ||
| If | full match mode (LanguageMatch != 0) is disabled (0) | ||
| use | the full string; otherwise truncate to 3 characters. | ||
| if | (LanguageMatch == 0) { | ||
| Full | match: use the complete string length, but truncated | ||
| to | 3 chars if zero mode is off and string is long. | ||
| SupportedLen | = 0; | ||
| Scan | the supported languages string for a match. | ||
| if | (LanguageMatch != 0) { | ||
| Full | match mode: iterate through each language list entry. | ||
| Supported | = SupportedLanguages; | ||
| Skip | ';' separators. | ||
| while | (*Supported == ';') { | ||
| Get | the length of this supported language entry. | ||
| Match | found - allocate buffer and copy the language. | ||
| ResultLen | = SupportedLen + 1; | ||
| Short | match mode: truncate language to 3 characters, compare. | ||
| if | (CheckLen <= 3) { | ||
| Scan | supported languages. | ||
| If | full check fails, try truncating to 3 chars. | ||
| if | (CheckLen > 3 && 3 <= SupportedLen) { | ||
| Handle | RFC 4646 language tags with '-' separator. | ||
| while | (Supported[SupportedLen] == '-') { | ||
| Move | to next language string in varargs. | ||
| LangToCheck | = VA_ARG (Args, CONST CHAR8 *); | ||
| Debug | Output | ||
| DebugProtocol | = mDebugProtocol; | ||
| Allocate | pool as a probe. The allocation size is 31 bytes | ||
| PoolSize | = MEMORY_TYPE_BOOT_SERVICES_DATA; | ||
| This | is a non-standard check unique to this implementation. | ||
| if | ((UINTN)mDebugProtocol > 0x10) { | ||
| Status | = gBootServices->LocateProtocol ( | ||
| Suspicious | allocation pointer - treat as failure. | ||
| mDebugProtocol | = NULL; | ||
| Get | the DebugLib protocol; if not available, skip the print. | ||
| DebugProtocol | = GetDebugLibProtocol (); | ||
| Read | the platform SKU from RTC CMOS register 0x4B. | ||
| The | NMI-disable bit (0x80) is preserved in the index write. | ||
| IoWrite8 | **(RTC_CMOS_INDEX_PORT, (IoRead8 (RTC_CMOS_INDEX_PORT) & 0x80) | RTC_CMOS_INDEX_SKU);** | |
| Determine | effective SKU: | ||
| EffectiveSku | = CmosSku; | ||
| Read | platform info register for IIO mode detection. | ||
| Bit | 1 of 0xFDAF0490 indicates IIO configuration mode. | ||
| EffectiveSku | *= ((volatile UINT8 *)PLATFORM_INFO_REGISTER & 0x02) | 0x01;** | |
| Map | platform SKU to debug level filter mask. | ||
| Valid | SKU range (1-4 maps to 0-3). | ||
| FilterMask | = UBA_DEBUG_ERROR; // Default: only errors | ||
| If | the requested debug level passes the filter, call DebugPrint. | ||
| if | ((FilterMask & DebugLevel) != 0) { | ||
| DebugProtocol | layout: | ||
| Call | DebugProtocol->Assert (at offset +8). | ||
| HII | Protocol Services | ||
| Call | with NULL buffer to get required size. | ||
| Now | get the actual string. | ||
| Status | = ((EFI_HII_GET_STRING_INFO)((VOID )mHiiFont)[3])(** | ||
| Validate | parameters. | ||
| if | (HiiHandle == NULL) { | ||
| Get | the supported languages for this HII string package. | ||
| SupportedLanguages | = GetHiiSupportedLanguages (HiiHandle, StringId, Type, MaxLen); | ||
| Get | the current platform language. | ||
| Match | the platform language against supported languages. | ||
| Use | "en-US" as default language for matching. | ||
| Fall | back to the first supported language. | ||
| MatchedLanguage | = GetSupportedLanguage ( | ||
| Get | the localized string size by calling HiiFont->StringToImage (offset +8) | ||
| with | NULL buffer to get required size. | ||
| Allocate | buffer for the string. | ||
| ResultString | = AllocatePool (StringSize); | ||
| Get | the actual string. | ||
| Status | = ((EFI_HII_STRING_TO_IMAGE)((VOID )mHiiFont)[1])(** | ||
| Clean | up temporary allocations. | ||
| FreePool | (SupportedLanguages); | ||
| ResultString | was allocated separately, keep it | ||
| Call | StringToImage with NULL buffer to get required size. | ||
| Allocate | buffer. | ||
| String | = AllocatePool (Size); | ||
| if | (Guid == NULL) { | ||
| If | no string entries, return NULL handle. | ||
| if | (StringPackage == NULL) { | ||
| Calculate | total package size. | ||
| Each | entry header has size-4 in the first 4 bytes. | ||
| We | need to sum all entry sizes (excluding the 4-byte header | ||
| contribution | counted as size-4 per entry). | ||
| Entry | = StringPackage; | ||
| Allocate | buffer for the entire package list (header + data). | ||
| The | HII package list header is sizeof(EFI_HII_PACKAGE_LIST_HEADER) | ||
| which | includes a GUID (16 bytes) and package length (24 bytes total). | ||
| DataSize | = TotalSize + sizeof (EFI_HII_PACKAGE_LIST_HEADER); | ||
| Fill | in the package list header. | ||
| Copy | the GUID to the beginning of the package list. | ||
| CopyGuid | ((EFI_GUID *)PackageData, Guid); | ||
| Copy | all package entries. | ||
| Add | the terminating 4-byte zero entry. | ||
| CopyMem | (Dst, &mZeroGuid, 4); | ||
| Call | HiiDatabase->NewPackageList (at offset +0 of qword_3968). | ||
| Get | or locate the SMBIOS protocol. | ||
| SmbiosProto | = mSmbiosProtocol3; | ||
| Initialize | handle to "uninitialized" (0xFFFE). | ||
| The | SMBIOS AddString function at protocol offset 0 uses: | ||
| Handle | = SMBIOS_HANDLE_UNINITIALIZED; | ||
| SmbiosProto | = mSmbiosProtocol1; | ||
| Search | for the first matching string. | ||
| The | SMBIOS protocol GetNext function at offset +24 enumerates strings: | ||
| SearchType | = TypeId; | ||
| Find | and remove the current string, then add the replacement. | ||
| Status | = FindFirstSmbiosString (TypeId, &Handle); | ||
| Remove | the old string at protocol offset +16. | ||
| Add | the new string at protocol offset 0. | ||
| SmbiosProto | = mSmbiosProtocol2; | ||
| Locate | the SMBIOS protocol. | ||
| if | (gBootServices->LocateProtocol ( | ||
| Enumerate | and remove all strings of the given type. | ||
| Remove | each string of this type. | ||
| for | (; Count > 0; Count--) { | ||
| FieldCount | *TotalLength = Length; | ||
| Scan | through the string data to find the end. | ||
| Strings | are terminated by a double-null (one after each string | ||
| plus | a final null to mark end of all strings). | ||
| while | (TRUE) { | ||
| Found | a null terminator. Check if it's the end of strings | ||
| if | (*++Scan == '\0') { | ||
| Count | characters until next null. | ||
| for | (Index = 0; Index < 64; Index++) { | ||
| No | null found in 64 chars - likely an error. | ||
| Get | the source string length. | ||
| StringLen | = AsciiStrLen (NewString); | ||
| Get | the SMBIOS structure length. | ||
| GetSmbiosStructuresAfterField | (RecordBuffer, &TotalLen); | ||
| Calculate | the field position within the record. | ||
| FieldPos | = Buf[1]; // FieldCount (offset to first string) | ||
| Scan | through fields to find the target field position. | ||
| if | (FieldIndex > 1) { | ||
| Check | if the new string length matches the field's existing length. | ||
| If | AsciiStrLen of FieldPtr's region matches StringLen, we can do an | ||
| FieldLen | = AsciiStrLen (FieldPtr); | ||
| Same | length - in-place replacement. | ||
| if | (FieldPtr != NULL) { | ||
| if | *(FieldPtr >= (UINT8 )NewString | ** | |
| No | overlap, direct copy. | ||
| if | (FieldPtr == (UINT8 *)NewString) { | ||
| Same | pointer, nothing to do. | ||
| return | EFI_SUCCESS; | ||
| Recalculate | the structure after the field. | ||
| Overlap | detected - use auxiliary buffer for safe copy. | ||
| SMBIOS_STRING_RECORD_SIZE | if (RecordBuffer2 == NULL) { | ||
| Copy | the record to auxiliary buffer, modify, and copy back. | ||
| CopyMem | (RecordBuffer2, RecordBuffer, FieldPos + v13 + Buf[1]); | ||
| Write | new string. | ||
| AsciiStrCpyS | ( | ||
| Copy | back and recalculate. | ||
| GetSmbiosStructuresAfterField | (RecordBuffer2, &TotalLen); | ||
| Copy | the updated record back. | ||
| CopyMem | (&Buf[FieldPos + v13 + Buf[1]], &FieldPtr[FieldLen - StringLen + 1], StringLen + 1); | ||
| Final | size update. | ||
| Null | field pointer - append? This is a complex path. | ||
| Different | length - need to insert/remove space. | ||
| Allocate | auxiliary buffer for safe manipulation. | ||
| AuxBuffer | = (UINTN)AllocateZeroPool (SMBIOS_STRING_RECORD_SIZE); | ||
| Copy | the part before the new string. | ||
| Copy | the part after the old string, skipping it. | ||
| Calculate | new total length. | ||
| AuxTotalLen | = TotalLen - FieldLen + StringLen; | ||
| Copy | back to original buffer. | ||
| GetSmbiosStructuresAfterField | ((VOID *)AuxBuffer, &TotalLen); | ||
| Clean | up. | ||
| FreePool | ((VOID *)AuxBuffer); | ||
| Get | the descriptor entry for this index. | ||
| Desc | = &mSmbiosType2Descriptors[DescriptorIndex]; | ||
| Initialize | the SMBIOS string record header. | ||
| Byte | 0: Type (8 = Type 2 Baseboard) | ||
| Byte | 1: FieldCount (29 = total fields -1) | ||
| Word | 2-3: Handle (0xFFFE = uninitialized) | ||
| SMBIOS | type 2 | ||
| 30 | fields, index 0-29 | ||
| Copy | the descriptor field metadata into the record header at offsets 4-7. | ||
| From | the original binary (sub_77C, 0x77C): | ||
| If | StringId is non-zero, look up the localized string. | ||
| A | zero StringId means this descriptor has no associated string. | ||
| if | (StringId != 0) { | ||
| Get | the localized string from HII font protocol. | ||
| LocalizedString | = GetHiiString ( | ||
| Write | the string into the SMBIOS record buffer. | ||
| The | function handles buffer manipulation, overlap-safe | ||
| No | explicit FreePool needed here. | ||
| The | function at address 0xA20 constructs Type 9 SMBIOS records. | ||
| It | follows a similar pattern to BuildSmbiosStringRecord but for | ||
| SMBIOS | Type 9 (System Slots) fields. | ||
| From | the dispatch function (SmbiosDataUpdateDispatch), this function | ||
| is | called for 8 iterations (0-7). It takes a working buffer and index | ||
| builds | the record, and the caller then writes it to SMBIOS. | ||
| return | EFI_UNSUPPORTED; | ||
| The | function at address 0xD98 constructs Type 41 SMBIOS records. | ||
| SMBIOS | Type 41 (Onboard Devices Extended Information) fields. | ||
| is | called for 4 iterations (0-3). It takes a working buffer and index | ||
| MM | PCI Configuration | ||
| Encode | the PCI address. | ||
| Address | **format: ((Func & 7) | (8 * ((Dev & 0x1F) | (32 Bus)))) << 12* |
| UINT32 | Address; | ||
| Prepare | address structure for MmPciBase->Write. | ||
| Encode | the PCI address: Bits [14:12] = Func, [19:15] = Dev, [24:20] = Bus. | ||
| Call | MmPciUsra->Write (at offset +24) with the address structure. | ||
| if | (mMmPciUsra == NULL) { | ||
| SMBIOS | Data Update Dispatch | ||
| Allocate | working buffer for SMBIOS string record construction. | ||
| WorkBuffer | = AllocateZeroPool (SMBIOS_STRING_RECORD_SIZE); | ||
| Phase | 1: Process 30 SMBIOS Type 2 (Baseboard) string fields. | ||
| Remove | all existing Type 2 strings first. | ||
| RemoveAllSmbiosStringsOfType | (SMBIOS_TYPE_BASEBOARD); | ||
| Process | each Type 2 string field. | ||
| for | (i = 0; i < SMBIOS_TYPE2_COUNT; i++) { | ||
| Phase | 2: Process 8 SMBIOS Type 9 (System Slot) string fields. | ||
| RemoveAllSmbiosStringsOfType | (SMBIOS_TYPE_SYSTEM_SLOTS); | ||
| Phase | 3: Process 4 SMBIOS Type 41 (Onboard Device) string fields. | ||
| RemoveAllSmbiosStringsOfType | (SMBIOS_TYPE_ONBOARD_DEVICES); | ||
| FreePool | (WorkBuffer); | ||
| Main | Entry Point (SmbiosDataUpdateEntry) | ||
| Open | the UBA config protocol installed on ImageHandle. | ||
| Status | = gBootServices->OpenProtocol ( | ||
| module identification string. | |||
| Copy | the board-specific SMBIOS config GUID from UBA config data. | ||
| The | config data is at UbaConfig + 4 bytes (first 4 bytes are header). | ||
| CopyGuid | (&mSmbiosConfigGuid, (EFI_GUID )((UINT8 )UbaConfig + 4)); | ||
| Register | the HII string package. | ||
| gSmbiosStringPackHandle | = RegisterHiiPackageList ( | ||
| String | data from HII table | ||
| Prepare | the dispatch configuration buffer. | ||
| ZeroMem | (ConfigBuffer, sizeof (ConfigBuffer)); | ||
| Version | ConfigBuffer[2] = 9; // Dispatch function index | ||
| Locate | the UBA SMBIOS Data protocol. | ||
| if | (mUbaSmbiosDataProtocol == NULL) { | ||
| Register | the SMBIOS config with the UBA protocol. | ||
| This | call triggers the SmbiosDataUpdateDispatch callback. | ||
| return | ((UBA_SMBIOS_DATA_PROTOCOL *)mUbaSmbiosDataProtocol)->SetSmbiosData ( | ||
| Initialization | Function (SmbiosDataUpdateInit) | ||
| The | initialization logic from the original sub_38C (address 0x38C) | ||
| has | been inlined into ModuleEntryPoint() below. | ||
| This | function is kept as a stub for documentation purposes since the | ||
| original | binary had this as a separate function called from the entry | ||
| MM | PCIe base protocol) is now performed directly in ModuleEntryPoint(). | ||
| Module | Entry Point | ||
| Step | 1: Initialize global UEFI service table pointers. | ||
| gImageHandle | = ImageHandle; | ||
| Step | 2: Locate HII services protocols. | ||
| Locate | HII Font protocol. | ||
| Locate | HII String protocol. | ||
| Locate | HII Database protocol. | ||
| Locate | HII Package List protocol. | ||
| Locate | HII Package List protocol interface. | ||
| Step | 3: Find DXE Services Table from SystemTable->ConfigurationTable. | ||
| Status | = GetConfigTable (&mDxeServicesTableGuid, &mHobList); | ||
| Step | 4: Optionally locate MM PCIe base protocol. | ||
| This | may already be cached from a previous lookup. | ||
| Step | 5: Initialize HOB list. | ||
| HobLibInit | (); | ||
| Step | 6: Perform SMBIOS data update. | ||
| Status | = SmbiosDataUpdateEntry (ImageHandle); |
Generated by HR650X BIOS Decompilation Project