/*++
StaticSkuDataDxeLightningRidgeEXECB1.c
UEFI DXE driver for static SKU data on the Intel Purley platform
(Lightning Ridge EXEC B1 revision).
This driver's purpose is to read platform SKU information from the
UEFI HOB list (handoff data from PEI phase) and register it as
multiple UBA (Universal BIOS Agent) sub-protocols. The registered
protocols expose ACPI method outputs (_SB_.CCT0-CCT8, _SB_.CFH0,
FIX0, FIXX, FIXV, FIXY, FIXW etc.) to other DXE drivers and the
ACPI subsystem.
Build:
PurleyRpPkg/Uba/UbaMain/Dxe/TypeLightningRidgeEXECB1/
StaticSkuDataDxe/StaticSkuDataDxe/
DEBUG_VS2015\StaticSkuDataDxeLightningRidgeEXECB1.pdb
References:
- MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c
- MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c
- MdePkg/Library/DxeHobLib/HobLib.c
- MdePkg/Library/BaseLib/Unaligned.c
--*/
#include "../uefi_headers/Uefi.h"
#include "StaticSkuDataDxeLightningRidgeEXECB1.h"
//
// GUID Definitions (instantiation)
//
EFI_GUID gSkuDataProtocolGuid = SKU_DATA_PROTOCOL_GUID;
EFI_GUID gUbaProtocolGuid = UBA_PROTOCOL_GUID;
EFI_GUID gSkuHobGuid = SKU_HOB_GUID;
EFI_GUID gUmptProtocolGuid = UMPT_PROTOCOL_GUID;
EFI_GUID gPirqProtocolGuid = PIRQ_PROTOCOL_GUID;
EFI_GUID gAcpfProtocolGuid = ACPF_PROTOCOL_GUID;
//
// Global Variables
//
//
// gImageHandle -- EFI_HANDLE for this driver image, set by
// ModuleEntryPoint (sub_390). Used primarily for assertions.
//
EFI_HANDLE gImageHandle = NULL;
//
// gST -- Pointer to the UEFI System Table.
// Set by ModuleEntryPoint (sub_390) at 0x396.
//
EFI_SYSTEM_TABLE *gST = NULL;
//
// gBS -- Pointer to BootServices from the System Table.
// Set by ModuleEntryPoint at 0x3E1.
// Used for AllocatePool (offset 24) and LocateProtocol (offset 320).
//
EFI_BOOT_SERVICES *gBS = NULL;
//
// gRT -- Pointer to RuntimeServices from the System Table.
// Set by ModuleEntryPoint at 0x407.
//
EFI_RUNTIME_SERVICES *gRT = NULL;
//
// gUbaProtocol -- Cached pointer to the UBA protocol interface.
// Initialized by GetUbaProtocol() (sub_4C0).
//
UBA_PROTOCOL *gUbaProtocol = NULL;
//
// gHobList -- Cached pointer to the start of the UEFI HOB list.
// Initialized by GetHobList() (sub_608).
//
VOID *gHobList = NULL;
//
// Data used for CMOS SKU check in UbaCheckCmosSku().
//
UINT8 gCmosSkuValue; // Cached CMOS register 0x4B value
//
// External data tables (defined in the .data section of the binary).
//
extern volatile UINT8 gSkuDataProtocolGuidData[16]; // at 0x4080
extern volatile UINT8 gSkuHobGuidData[16]; // at 0x40A0
// SKU data protocol interfaces installed via UBA protocol:
extern SKU_DATA_INTERFACE_EXTENDED gUmptProtocolData; // at 0x40B0
extern SKU_DATA_INTERFACE gPirqProtocolData; // at 0x40D8
extern SKU_DATA_INTERFACE gAcpfProtocolData; // at 0x9020
// SKU configuration table (HOB data-derived entries):
extern SKU_CONFIG_TABLE gSkuConfigTable; // at 0x40F0
//
// CMOS/NVRAM Register Definitions
//
//
// CMOS register index 0x4B (decimal 75).
// On Intel Purley platforms, this register encodes the board SKU
// type:
// < 4 -> Standard values (1 = type A, 2 = type B, 3 = type C)
// >= 4 -> Must check memory-mapped I/O at 0xFDAF0490 bit 1.
// 0 -> Board uses MMIO-based SKU detection.
//
#define CMOS_INDEX_SKU_TYPE 0x4B
//
// RTC/CMOS I/O ports for indexed access.
//
#define RTC_INDEX_PORT 0x70
#define RTC_DATA_PORT 0x71
//
// RTC index port bits.
// Bit 7 is the NMI (Non-Maskable Interrupt) enable bit.
// When set, NMI is disabled; when clear, NMI is enabled.
//
#define RTC_INDEX_NMI_DISABLE 0x80
//
// Memory-mapped I/O address used for SKU type detection fallback.
// This is in the MMIO configuration space, typically an Intel
// platform register at:
// ((Bus 0xFE, Dev 0xAF, Func 0x04) << 12) + register offset
// = (0xFDAF << 12) + 0x490 = 0xFDAF0490
//
#define SKU_MMIO_DETECT_ADDR 0xFDAF0490
// Bit 1 of the MMIO register indicates the board variant.
#define SKU_MMIO_DETECT_BIT 2
//
// ACPI method name strings used in the SKU table.
// These are ASL method paths in the _SB_ (System Bus) scope.
//
#define ACPI_PATH_CCT(_N_) "_SB_.CCT" // Core Count Throttle (0-8)
#define ACPI_PATH_CFH "_SB_.CFH0" // CPU Family/Health
#define ACPI_PATH_FIX(_N_) "FIX" // Platform SKU info (0, X, V, Y, W)
//
// ModuleEntryPoint (sub_390)
//
/**
Entry point for the StaticSkuDataDxe Lightning Ridge EXECB1 driver.
This is the standard UEFI DXE driver entry point. It:
1. Saves ImageHandle, SystemTable, BootServices, RuntimeServices
to global variables (with NULL checks).
2. Initializes the HOB list via GetHobList().
3. Locates the UBA protocol handle using
BootServices->LocateProtocol(UBA_PROTOCOL_GUID, NULL, &Handle).
4. Registers three sub-protocols on the returned handle:
a. UMPT_PROTOCOL_GUID (24-byte interface at 0x40B0)
b. PIRQ_PROTOCOL_GUID (16-byte interface at 0x40D8)
c. ACPF_PROTOCOL_GUID (16-byte interface at 0x9020)
The UBA protocol's method at offset 0x10 (UBA_PROTOCOL.RegisterProtocol)
is used for each registration call.
@param[in] ImageHandle The firmware allocated handle for this driver.
@param[in] SystemTable A pointer to the EFI System Table.
@return EFI_SUCCESS The driver initialized and registered all SKU
data sub-protocols successfully.
@return Other Status from LocateProtocol or RegisterProtocol.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE UbaHandle;
//
// Step 1: Save UEFI core pointers to globals.
// These are used by the UBA ASSERT macros and protocol lookups.
//
gImageHandle = ImageHandle;
if (gImageHandle == NULL) {
//
// ASSERT: gImageHandle != NULL.
// File: MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c
// Line: 51
//
UbaAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
51,
"gImageHandle != ((void *) 0)"
);
}
gST = SystemTable;
if (gST == NULL) {
//
// ASSERT: gST != NULL.
// Line: 57
//
UbaAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
57,
"gST != ((void *) 0)"
);
}
gBS = SystemTable->BootServices;
if (gBS == NULL) {
//
// ASSERT: gBS != NULL.
// Line: 63
//
UbaAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
63,
"gBS != ((void *) 0)"
);
}
gRT = SystemTable->RuntimeServices;
if (gRT == NULL) {
//
// ASSERT: gRT != NULL.
// File: UefiRuntimeServicesTableLib.c, line 47
//
UbaAssert (
"e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
47,
"gRT != ((void *) 0)"
);
}
//
// Step 2: Initialize the HOB list.
// This scans SystemTable->ConfigurationTable for the HOB list GUID.
//
GetHobList ();
//
// Step 3: Locate the UBA protocol handle.
// BootServices->LocateProtocol (at BootServices offset 0x140 = 320
// in the function table). Returns a handle through which we
// register sub-protocols.
//
UbaHandle = NULL;
Status = gBS->LocateProtocol (
&gUbaProtocolGuid,
NULL, // Registration (none)
&UbaHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Step 4a: Register UMPT protocol.
// Method at offset 0x10 of the UBA_PROTOCOL.
//
Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
&gUmptProtocolGuid,
&gUmptProtocolData,
sizeof (SKU_DATA_INTERFACE_EXTENDED)
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Step 4b: Register PIRQ protocol.
//
Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
&gPirqProtocolGuid,
&gPirqProtocolData,
sizeof (SKU_DATA_INTERFACE)
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Step 4c: Register ACPF protocol.
//
Status = ((UBA_PROTOCOL *)UbaHandle)->RegisterProtocol (
&gAcpfProtocolGuid,
&gAcpfProtocolData,
sizeof (SKU_DATA_INTERFACE)
);
return Status;
}
//
// GetUbaProtocol (sub_4C0 at 0x4C0)
//
/**
Retrieves the UBA (Universal BIOS Agent) protocol interface pointer.
Uses BootServices->AllocatePool (offset 24 = slot 3) with pool type
EfiBootServicesData (value 31) to allocate a pool buffer. If the
allocation succeeds with buffer size <= 0x10 (16 bytes), the function
attempts to locate the UBA protocol via BootServices->LocateProtocol
(offset 320 = slot 40).
On success, the protocol pointer is cached in the global gUbaProtocol
and returned. On failure (protocol not found, or pool too small),
returns NULL.
The pool allocation size of 31 (0x1F) is a probing allocation used
to check whether the BootServices pointer is valid before performing
the LocateProtocol call.
NOTE: The "<= 16" check on the allocated pool size is unusual.
It may indicate that:
- The AllocatePool function returns a buffer with metadata, and
the effective data size must be >= 0x10 for the protocol header.
- Or this is a debugging/validation check.
@return Pointer to the UBA_PROTOCOL interface, or NULL if not found.
**/
UBA_PROTOCOL *
GetUbaProtocol (
VOID
)
{
UBA_PROTOCOL *Protocol;
VOID *PoolBuffer;
EFI_STATUS Status;
//
// Return cached pointer if already located.
//
if (gUbaProtocol != NULL) {
return gUbaProtocol;
}
//
// Attempt a probing pool allocation.
// Pool type 31 = EfiBootServicesData.
//
PoolBuffer = gBS->AllocatePool (31);
gBS->FreePool (PoolBuffer);
if (PoolBuffer != NULL && (UINTN)PoolBuffer <= 0x10) {
//
// Pool allocation succeeded and resulted in a low address
// (indicating the Boot Services table is functional).
// Now try to locate the UBA protocol.
//
Status = gBS->LocateProtocol (
&gUbaProtocolGuid,
NULL,
(VOID **)&Protocol
);
if (!EFI_ERROR (Status)) {
gUbaProtocol = Protocol;
return Protocol;
}
//
// LocateProtocol failed; clear the cached pointer.
//
gUbaProtocol = NULL;
return NULL;
}
return NULL;
}
//
// UbaAssert (sub_5C8 at 0x5C8)
//
/**
UBA assertion/debug helper function.
If the UBA protocol is available (via GetUbaProtocol), this function
calls the protocol's method at offset 0x08 (UBA_PROTOCOL->Method8),
which takes three arguments: FileName, LineNumber, and Expression.
The purpose of this method is to log/display an ASSERT failure
message via the UBA protocol's debug infrastructure, rather than
using the standard UEFI ASSERT macro.
@param[in] FileName Source file name string (e.g., path to .c file).
@param[in] LineNumber Line number in the source file where the ASSERT
condition failed.
@param[in] Expression The failed ASSERT expression as a string.
**/
VOID
UbaAssert (
IN CHAR8 *FileName,
IN UINTN LineNumber,
IN CHAR8 *Expression
)
{
UBA_PROTOCOL *Protocol;
Protocol = GetUbaProtocol ();
if (Protocol != NULL) {
//
// Call the ASSERT/debug method at protocol offset 0x08.
// This is not the same as RegisterProtocol (offset 0x10).
// The offset 0x08 method signature is:
// (CHAR8 *FileName, UINTN LineNumber, CHAR8 *Expression)
//
((EFI_STATUS (EFIAPI *)(CHAR8 *, UINTN, CHAR8 *))
(((UINT64 *)Protocol)[1])) (
FileName,
LineNumber,
Expression
);
}
}
//
// UbaCheckCmosSku (sub_540 at 0x540)
//
/**
Checks CMOS register 0x4B to determine the board SKU type, then
tests whether a given assertion flag is set for this SKU.
This function implements platform-specific SKU detection:
1. Reads the current RTC index register (saving NMI bit).
2. Selects CMOS index 0x4B.
3. Reads the data byte from CMOS register 0x4B.
4. Interprets the SKU type:
- n3 > 3: Use memory-mapped I/O at 0xFDAF0490
(bit 1 determines type: (value & 2) | 1)
- n3 == 0: (handled by the >3 check: both fall through
to MMIO path if n3 > 3 is true but 0 is not > 3;
only >3 and n3==0 cases lead to MMIO -- wait,
the logic is:
if (n3 > 3) {
if (!n3) // impossible since n3>3 here, so
n3 = (MEMORY[0xFDAF0490] & 2) | 1;
}
Actually this means: if n3 > 3, we still keep
n3 as-is, AND if n3 were 0 (dead path) we'd
go MMIO. The MMIO path is effectively dead
code in this '>3' branch.
REAL interpretation: the compiler generated
this structure from conditionals; the true
MMIO fallback happens for n3 > 3 || n3 == 0,
which is always true for n3 > 3.
In practice, n3 > 3 is rare.
- n3 == 1: Board type A, flags = 0x80000004
- n3 == 2 or 3: Board type B/C, flags = 0x80000006
- default: Returns 4 (no assertion, do nothing)
5. If (Flags & AssertFlag) is non-zero, calls the UBA protocol's
RegisterProtocol (offset 0x10) to register a data protocol.
6. Returns the method result.
Actually (re-analyzed from decompilation):
n3 = ReadCmos(0x4B)
v4 = 0
if (n3 != 0) {
// Check if n3 > 3 -> special case
if (n3 > 3 || n3 == 0) {
n3 = (ReadMmio(SKU_MMIO_DETECT_ADDR) & 2) | 1;
}
v3 = n3 - 1 // normalize to 0-based
if (v3 <= 253) { // i.e. n3 >= 1 and n3 <= 254
v3 = 4; // default result
v4 = 0x80000006; // flags for SKU type B/C
if (n3 == 1) {
v4 = 0x80000004; // flags for SKU type A
}
}
}
if (v4 & a1) {
// Call UBA protocol RegisterProtocol with ASSERT info
return (*v5)(a1, _nASSERT..., va);
}
@param[in] AssertFlag Bitmask to check against the platform flags.
Typically 0x80000000LL (EFI_ERROR check) or
0x80000004LL (type A) / 0x80000006LL (type
B/C).
@return The result of the UBA protocol call, or 4 if no action needed.
**/
UINT8
UbaCheckCmosSku (
IN UINT64 AssertFlag
)
{
UBA_PROTOCOL *Protocol;
UINT64 Flags;
UINT8 CmosValue;
UINT8 Result;
UINT8 RegIndex;
Protocol = GetUbaProtocol ();
Flags = 0;
Result = 0;
if (Protocol != NULL) {
//
// Read the current RTC index register to preserve NMI state.
//
RegIndex = IoRead8 (RTC_INDEX_PORT);
//
// Set RTC index to CMOS register 0x4B, preserving NMI bit.
//
IoWrite8 (RTC_INDEX_PORT, (RegIndex & RTC_INDEX_NMI_DISABLE) | CMOS_INDEX_SKU_TYPE);
//
// Read CMOS data byte.
//
CmosValue = IoRead8 (RTC_DATA_PORT);
//
// Apply SKU detection logic.
//
if ((UINT8)CmosValue > 3) {
//
// SKU value > 3 is unexpected. Fall back to MMIO detection.
// (In practice, this branch is rare for well-defined SKUs.)
//
if (CmosValue == 0) {
CmosValue = (MmioRead8 (SKU_MMIO_DETECT_ADDR) & SKU_MMIO_DETECT_BIT) | 1;
}
}
//
// Normalize: result = n3 - 1
// If n3 >= 1 and n3 <= 254, set default flags.
//
Result = CmosValue - 1;
if ((UINT8)Result <= 0xFD) {
//
// Default result when no assertion fires.
//
Result = 4;
Flags = 0x80000006; // SKU type B/C flags
if (CmosValue == 1) {
Flags = 0x80000004; // SKU type A flags
}
}
//
// If the required assertion flag is set in the platform flags,
// invoke the UBA protocol's RegisterProtocol (method @ +0x10)
// to register an assert-like protocol entry.
//
if ((Flags & AssertFlag) != 0) {
Result = (UINT8)Protocol->RegisterProtocol (
(EFI_GUID *)AssertFlag,
(VOID *)&CmosValue,
(UINTN *)&Flags
);
}
}
return Result;
}
//
// GetHobList (sub_608 at 0x608)
//
/**
Scans the UEFI configuration tables to find the HOB (Hand-Off Block)
list pointer.
The HOB list is produced in the PEI phase and passed to DXE via the
UEFI System Table's configuration table array. The configuration
table entries have the format:
struct {
EFI_GUID VendorGuid; // +0: 16-byte GUID
VOID *VendorTable; // +16: pointer to the table data
};
This function iterates through all entries in the array
(SystemTable->ConfigurationTable) looking for a specific
vendor table GUID.
The GUID used for matching is EFI_HOB_LIST_GUID:
{ 0x7739F24C, 0x93D7, 0x11D4,
{ 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
Actually it matches the GUID stored at 0x40A0 (gSkuHobGuid).
@param[in] a1 The GUID to match against (used in CompareGuidQwords).
In the actual implementation the GUID is from a fixed
location in the data section.
@return Pointer to the HOB list base, or 0 if not found.
Cached in gHobList.
**/
VOID *
GetHobList (
VOID
)
{
UINTN Index;
UINTN EntryCount;
VOID *ConfigTable;
VOID *HobList;
//
// Return cached pointer if already initialized.
//
if (gHobList != NULL) {
return gHobList;
}
//
// Assume no HOB list found initially.
//
gHobList = NULL;
HobList = NULL;
EntryCount = gST->NumberOfTableEntries;
if (EntryCount != 0) {
//
// Iterate through configuration table entries.
// Each entry is 24 bytes: 16-byte GUID + 8-byte pointer.
//
for (Index = 0; Index < EntryCount; Index++) {
ConfigTable = (VOID *)((UINTN)gST->ConfigurationTable + (Index * 24));
//
// Compare GUIDs: check if the table entry's GUID matches.
// The match checks two QWORDs (16 bytes):
// CompareGuidQwords reads 8 bytes from each GUID.
// If first 8 bytes AND second 8 bytes both match, we found it.
//
if (CompareGuidQwords (&gSkuHobGuid, ConfigTable)) {
//
// Found matching entry; extract the table pointer.
// The pointer is at offset 16 = 0x10 within the entry.
//
HobList = *(VOID **)((UINTN)ConfigTable + 16);
gHobList = HobList;
break;
}
}
//
// If HOB list was not found, fire assertion.
//
if (HobList == NULL) {
//
// Print the EFI_ERROR status first.
//
UbaCheckCmosSku (
0x80000000LL,
"\nASSERT_EFI_ERROR (Status = %r)\n",
0x800000000000000ELL
);
//
// ASSERT: EFI_ERROR(Status) -- Status is EFI_NOT_FOUND.
//
UbaAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
54,
"!EFI_ERROR (Status)"
);
}
//
// Verify the HOB list pointer is not NULL.
//
if (HobList == NULL) {
UbaAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
55,
"mHobList != ((void *) 0)"
);
}
}
return gHobList;
}
//
// CompareGuidQwords (sub_6E0 at 0x6E0)
//
/**
Compares two GUIDs by comparing their first 8 bytes and second
8 bytes independently as 64-bit values.
This is a fast non-standard GUID comparison used by GetHobList.
Instead of calling CompareGuid() from the UEFI spec, it compares
two UINT64 halves of the GUID structure. Because EFI_GUID is
defined as:
typedef struct {
UINT32 Data1; // 4 bytes at offset 0
UINT16 Data2; // 2 bytes at offset 4
UINT16 Data3; // 2 bytes at offset 6
UINT8 Data4[8]; // 8 bytes at offset 8
} EFI_GUID;
The first QWORD (offset 0) contains Data1+Data2+Data3.
The second QWORD (offset 8) contains Data4[0..7].
Comparing these as two UINT64 values is equivalent to a full
GUID comparison.
@param[in] Guid1 Pointer to the first GUID to compare.
@param[in] Guid2 Pointer to the second GUID (e.g., from the
SystemTable configuration table entry).
@retval TRUE All bytes of the two GUIDs match.
@retval FALSE The GUIDs differ.
**/
BOOLEAN
EFIAPI
CompareGuidQwords (
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
)
{
UINT64 FirstHalf1;
UINT64 FirstHalf2;
UINT64 SecondHalf1;
UINT64 SecondHalf2;
//
// Read the first 8 bytes of each GUID as a UINT64.
//
FirstHalf1 = ReadUnaligned64 ((VOID *)Guid1);
FirstHalf2 = ReadUnaligned64 ((VOID *)Guid2);
//
// Read the second 8 bytes of each GUID.
//
SecondHalf1 = ReadUnaligned64 ((VOID *)((UINTN)Guid1 + 8));
SecondHalf2 = ReadUnaligned64 ((VOID *)((UINTN)Guid2 + 8));
//
// Both halves must match for the GUID to be equal.
//
return (FirstHalf1 == FirstHalf2) && (SecondHalf1 == SecondHalf2);
}
//
// ReadUnaligned64 (sub_750 at 0x750)
//
/**
Reads a 64-bit value from an unaligned buffer pointer.
This is a simple dereference of a UINT64*. The function is named
after the BaseLib UEFI library function ReadUnaligned64(), which is
defined in MdePkg/Library/BaseLib/Unaligned.c.
The function asserts if the Buffer pointer is NULL.
@param[in] Buffer Pointer to the buffer to read (may be unaligned).
Must not be NULL.
@return The UINT64 value at the given address.
**/
UINT64
EFIAPI
ReadUnaligned64 (
IN VOID *Buffer
)
{
//
// Assert if Buffer is NULL.
//
if (Buffer == NULL) {
UbaAssert (
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
192,
"Buffer != ((void *) 0)"
);
}
return *(UINT64 *)Buffer;
}
//
// ReadUnaligned32 (helper wrapper, not in this binary but in standard BaseLib)
//
/**
Reads a 32-bit value from an unaligned buffer pointer.
@param[in] Buffer Pointer to the buffer to read.
@return The UINT32 value at the given address.
**/
UINT32
EFIAPI
ReadUnaligned32 (
IN UINT32 *Buffer
)
{
if (Buffer == NULL) {
UbaAssert (
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
192,
"Buffer != ((void *) 0)"
);
}
return *Buffer;
}
///
/// SKU Configuration Table
///
/// Starting at offset 0x40F0 from the image base, the SKU configuration
/// table is embedded in the .data section. Its content is HOB-derived
/// platform configuration data organized as an array of 32-byte entries.
///
/// The table header is:
/// 16 bytes: SKU table identifier (GUID-like, partially zero)
///
/// Each entry (32 bytes) describes a specific platform configuration
/// value. The names referenced by the table include:
///
/// Entry 0: "FIX0" - FIX method 0
/// Entries 1-9: "FIXX" (with sub-id 01-08) - Extended FIX methods
/// Entries 10-18: "FIXV" (with sub-id 02-08) - Vendor FIX methods
/// Entries 19-25: unnamed (data_type=0x0A, ASCII strings)
/// Entries 26-27: "FIXY"/"FIXW" - More FIX variants
/// ... repeating pattern of FIXY/FIXW pairs ...
///
/// The data_type field determines interpretation:
/// 0x0A: The data payload is an ASCII string.
/// 0x0C: The data payload contains an ACPI method name (like "FIX0").
/// 0x0E: The data payload contains 16-bit values / numeric data.
///
/// The ACPI method references _SB_.CCT0 through _SB_.CCT8 and _SB_.CFH0
/// are stored as ASCII strings in .rdata at 0x7C8-0x858 and referenced
/// by the SKU table entries via their offset fields.
///
/// The actual SKU data (the payloads for FIX0, FIXX, etc.) begins at
/// offset 0x5B80 in the image (0x5B80 + 0x4080 = 0x9C00 area), though
/// the precise layout depends on how the HOB data was produced by the
/// PEI phase via the PCD (Platform Configuration Database).
///
/*++
Notes on the UBA Protocol Registration:
The UBA protocol found via LocateProtocol at offset 0x140 in
BootServices (slot 40) is:
Protocol GUID: {E03E0D46-5263-4845-B0A4-58D57B3177E2}
Its interface has three known methods at offsets 0x00, 0x08, 0x10:
[0x00]: Some initialization/query method.
[0x08]: Debug/assert handler. Called by UbaAssert() with
(FileName, LineNumber, Expression).
[0x10]: RegisterProtocol. Called with
(ProtocolGuid, InterfaceData, InterfaceSize).
This registers a sub-protocol on the UBA handle so that
other DXE drivers can locate it via their own GUID.
The three sub-protocols registered by this driver are:
1. UMPT ({0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A})
Interface (24 bytes, at 0x40B0):
Tag = 'UMPT' (0x54504D55)
Version = 1
Data1 = 0x9060 (pointer to additional UMPT data)
Data2 = 0x9040 (pointer to resource descriptors)
2. PIRQ ({4C1F48A5-C976-4D90-9F03-8E9B1C327FCF})
Interface (16 bytes, at 0x40D8):
Tag = 'PIRQ' (0x51524950)
Version = 1
Data = 0x90D8 (pointer to PIRQ data table)
3. ACPF ({46504341-0001-0000-0041-000000000000})
Interface (16 bytes, at 0x9020):
Tag = 'ACPF' (0x46504341)
Version = 1
Data = 0x4100 (ACPI platform flags/version)
The data tables at 0x9040, 0x9060, and 0x90D8 contain pairs of
(Offset, Size) entries describing ACPI resource descriptors or
ACPI _CRS (Current Resource Settings) for the platform.
CMOS Register 0x4B Encoding:
0x01 = Board revision A (flags = 0x80000004)
0x02 = Board revision B (flags = 0x80000006)
0x03 = Board revision C (flags = 0x80000006)
>3 = Fall back to MMIO detection
0x00 = (invalid for production, MMIO fallback)
++*/