/** @file
StaticSkuDataDxeLightningRidgeEXECB3 -- Static SKU/Platform Data DXE Driver
This UEFI DXE driver provides static SKU and platform configuration data
for Lightning Ridge EXEC B3 platforms. It installs the following static
data tables via a custom protocol:
- UMPT (UEFI Memory Population Table):
Socket-to-memory-channel topology describing DIMM population for
multi-socket configurations (up to 8 sockets, 3 channels per socket).
- PIRQ (Platform IRQ Routing) / CCT (Core Configuration Table):
Processor core-to-APIC-interrupt routing maps for up to 8 logical
processors per cluster, covering 4 interrupt vectors per core.
- CFH (Core Family Hierarchy):
Extended core topology data describing per-core capabilities
(type 0x1F entries indicating core count per cluster).
- ACPF (ACPI Processor Info):
ACPI _SB CPU device mapping associating processor GUIDs with
their ACPI namespace identifiers.
The driver entry point:
1. Initializes UEFI globals (gImageHandle, gST, gBS, gRT).
2. Locates the Platform Protocol (GUID E03E0D46-...).
3. Walks the HOB list to discover the platform database.
4. Registers static data tables via the protocol's install interface.
NOTE: This driver has zero IAT imports (no DLL/PE dependencies). All
functionality is provided by the UEFI boot and runtime services tables.
Image base 0x0, image size 0xFB60.
Copyright (C) 2025, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "StaticSkuDataDxeLightningRidgeEXECB3.h"
//
// -------------------------------------------------------------------------
// Protocol GUIDs
// -------------------------------------------------------------------------
//
STATIC CONST EFI_GUID mPlatformProtocolGuid =
STATIC_SKU_DATA_PLATFORM_PROTOCOL_GUID;
STATIC CONST EFI_GUID mStaticSkuDataProtocolGuid =
STATIC_SKU_DATA_PROTOCOL_GUID;
STATIC CONST EFI_GUID mPirqProtocolGuid =
{ 0x0FF8A1CF, 0xA0AB, 0x4AC0,
{ 0xBF, 0xC9, 0x34, 0xA7, 0x8F, 0x68, 0xDD, 0x8A } };
STATIC CONST EFI_GUID mAcpiProcessorInfoGuid =
{ 0x4C1F48A5, 0xC976, 0x4D90,
{ 0x9F, 0x03, 0x8E, 0x9B, 0x1C, 0x32, 0x7F, 0xCF } };
STATIC CONST EFI_GUID mAcpiProcessorDataGuid =
{ 0x81129EF8, 0x391D, 0x4F63,
{ 0xAE, 0x99, 0x58, 0x51, 0x7E, 0xC0, 0x77, 0xE3 } };
STATIC CONST EFI_GUID mHobMemoryAllocModuleGuid =
{ 0x7739F24C, 0x93D7, 0x11D4,
{ 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } };
//
// -------------------------------------------------------------------------
// Globals
// -------------------------------------------------------------------------
//
EFI_HANDLE gImageHandle = NULL; ///< Offset 0xF550
EFI_SYSTEM_TABLE *gST = NULL; ///< Offset 0xF540
EFI_BOOT_SERVICES *gBS = NULL; ///< Offset 0xF548
EFI_RUNTIME_SERVICES *gRT = NULL; ///< Offset 0xF558
VOID *gPlatformProtocol = NULL; ///< Offset 0xF560
VOID *gHobList = NULL; ///< Offset 0xF568
UINT8 gCmosIndex = 0; ///< Offset 0xF570
//
// -------------------------------------------------------------------------
// Debug Assertion Strings (offset 0x780 - 0x3F00)
// -------------------------------------------------------------------------
//
STATIC CONST CHAR8 mAssertEfiError[] = "\nASSERT_EFI_ERROR (Status = %r)\n";
STATIC CONST CHAR8 mAssertNotEfiError[] = "!EFI_ERROR (Status)";
STATIC CONST CHAR8 mAssertImageHandle[] = "gImageHandle != ((void *) 0)";
STATIC CONST CHAR8 mAssertSystemTable[] = "gST != ((void *) 0)";
STATIC CONST CHAR8 mAssertBootServices[] = "gBS != ((void *) 0)";
STATIC CONST CHAR8 mAssertRuntimeServices[]= "gRT != ((void *) 0)";
STATIC CONST CHAR8 mAssertHobList[] = "mHobList != ((void *) 0)";
STATIC CONST CHAR8 mAssertBuffer[] = "Buffer != ((void *) 0)";
STATIC CONST CHAR8 mFilePathBootServices[] =
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c";
STATIC CONST CHAR8 mFilePathHobLib[] =
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c";
STATIC CONST CHAR8 mFilePathRuntimeServices[] =
"e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c";
STATIC CONST CHAR8 mFilePathUnaligned[] =
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c";
//
// ACPI namespace method names for SKU data access
//
STATIC CONST CHAR8 mAcpiNameCCT0[] = "_SB_.CCT0";
STATIC CONST CHAR8 mAcpiNameCCT1[] = "_SB_.CCT1";
STATIC CONST CHAR8 mAcpiNameCCT2[] = "_SB_.CCT2";
STATIC CONST CHAR8 mAcpiNameCCT3[] = "_SB_.CCT3";
STATIC CONST CHAR8 mAcpiNameCCT4[] = "_SB_.CCT4";
STATIC CONST CHAR8 mAcpiNameCCT5[] = "_SB_.CCT5";
STATIC CONST CHAR8 mAcpiNameCCT6[] = "_SB_.CCT6";
STATIC CONST CHAR8 mAcpiNameCCT7[] = "_SB_.CCT7";
STATIC CONST CHAR8 mAcpiNameCCT8[] = "_SB_.CCT8";
STATIC CONST CHAR8 mAcpiNameCFH0[] = "_SB_.CFH0";
//
// -------------------------------------------------------------------------
// Static Data Section Layout (0x4080 - 0xF580)
// -------------------------------------------------------------------------
// The .data section contains the platform HOB descriptor block followed
// by the UMPT config table, UMPT data entries, PIRQ routing, core family
// hierarchy, ACPI processor info, and memory topology tables.
//
//
// Platform HOB descriptor at 0x40A0.
// Structure: HOB GUID, tag 'UMPT', version, data ptr, config ptr,
// PIRQ protocol GUID, tag 'PIRQ', version, PIRQ data ptr,
// ACPI processor GUID, NULL sentinel, size.
//
STATIC CONST struct {
EFI_GUID HobGuid; ///< gEfiHobMemoryAllocModuleGuid
UINT32 UmptTag; ///< 'UMPT' = 0x54504D55
UINT32 UmptVersion; ///< 1
VOID *UmptDataPtr; ///< -> 0x9060 (UMPT data entries)
VOID *UmptConfigPtr; ///< -> 0x9040 (UMPT config descriptors)
EFI_GUID PirqProtocolGuid; ///< STATIC_SKU_DATA_PROTOCOL_GUID
UINT32 PirqTag; ///< 'PIRQ' = 0x51524950
UINT32 PirqVersion; ///< 1
VOID *PirqDataPtr; ///< -> 0x90D8 (PIRQ data entries)
EFI_GUID AcpiProcGuid; ///< ACPI_PROCESSOR_INFO_PROTOCOL_GUID
UINT64 NullSentinel; ///< NULL terminator
UINT64 AcpiDataSize; ///< 1984 = 0x7C0
} mPlatformHobBlock = {
{ 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } },
0x54504D55, // 'UMPT'
1,
(VOID *)0x9060,
(VOID *)0x9040,
{ 0x0FF8A1CF, 0xA0AB, 0x4AC0, { 0xBF, 0xC9, 0x34, 0xA7, 0x8F, 0x68, 0xDD, 0x8A } },
0x51524950, // 'PIRQ'
1,
(VOID *)0x90D8,
{ 0x4C1F48A5, 0xC976, 0x4D90, { 0x9F, 0x03, 0x8E, 0x9B, 0x1C, 0x32, 0x7F, 0xCF } },
0,
1984
};
//
// UMPT configuration table at 0x9040.
// Each entry: { UINT64 DataOffset, UINT64 DataSize }
//
STATIC CONST TABLE_DESCRIPTOR mUmptConfigTable[] = {
{ 0xD690, 59 }, // Socket memory topology (59 bytes)
{ 0xC2C0, 211 }, // IOAPIC interrupt routing (211 bytes)
{ 0x9110, 25 }, // Socket core/thread map (25 bytes)
{ 0xDB30, 2 }, // Config sentinel (2 bytes)
};
//
// UMPT data entries at 0x9060.
// Each entry: { UINT64 DataOffset, UINT64 DataSize }
//
STATIC CONST TABLE_DESCRIPTOR mUmptDataTable[] = {
{ 0x9110, 25 }, // Socket core topology map
{ 0xDB30, 2 }, // Config sentinel
{ 0xDB60, 275 }, // Core Family Hierarchy (CFH)
{ 0xBD80, 67 }, // Core Configuration Table (CCT)
};
//
// ACPI Processor Data block at 0x9020.
//
STATIC CONST struct {
UINT32 Tag; ///< 'ACPF' = 0x46504341
UINT32 Version; ///< 1
UINT32 ProcessorType; ///< 0x4100
UINT32 Reserved1;
EFI_GUID ProcessorGuid; ///< {81129EF8-391D-4F63-AE99-58517EC077E3}
UINT64 DataOffset; ///< 0xD690
UINT32 ProcessorCount; ///< 59 = 0x3B
UINT32 Reserved2;
} mAcpiProcessorBlock = {
0x46504341, // 'ACPF'
1,
0x4100,
0,
{ 0x81129EF8, 0x391D, 0x4F63, { 0xAE, 0x99, 0x58, 0x51, 0x7E, 0xC0, 0x77, 0xE3 } },
0xD690,
0x3B,
0
};
//
// PIRQ data table header at 0x40D8.
//
STATIC CONST struct {
UINT32 Tag; ///< 'PIRQ' = 0x51524950
UINT32 Flags; ///< 1
VOID *DataPtr; ///< -> 0x90D8 (PIRQ routing entries)
EFI_GUID Guid; ///< ACPI_PROCESSOR_INFO_PROTOCOL_GUID
} mPirqDataTable = {
0x51524950, // 'PIRQ'
1,
(VOID *)0x90D8,
{ 0x4C1F48A5, 0xC976, 0x4D90, { 0x9F, 0x03, 0x8E, 0x9B, 0x1C, 0x32, 0x7F, 0xCF } },
};
//
// Memory socket topology data at 0xD690 (59+ bytes).
// 20-byte entries: { UINT32 Socket; UINT8 Reserved[7]; UINT8 Type;
// UINT8 SubType; UINT8 ChannelMap[3]; UINT8 Reserved2[3] }
//
STATIC CONST UINT8 mSocketMemoryTopology[] = {
// Socket 0, DDR5 (Type=0x0A), channels [4,5,6] (A/B/C)
0x01,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0A,0x00,0x04, 0x05,0x06,0x00,0x00,
0x01,0x00,0x00,0x00, 0x01,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0A,0x01,0x06, 0x04,0x05,0x00,0x00,
0x01,0x00,0x00,0x00, 0x02,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0A,0x02,0x05, 0x06,0x04,0x00,0x00,
0x01,0x00,0x00,0x00, 0x03,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0A,0x03,0x06, 0x04,0x05,0x00,0x00,
// Socket 1, Type=0x0B, channels rotated
0x02,0x00,0x00,0x00, 0x01,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0B,0x01,0x06, 0x04,0x05,0x00,0x00,
0x02,0x00,0x00,0x00, 0x02,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0B,0x02,0x05, 0x06,0x04,0x00,0x00,
0x02,0x00,0x00,0x00, 0x03,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0B,0x03,0x06, 0x04,0x05,0x00,0x00,
// Socket 2, Type=0x0C
0x03,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0C,0x00,0x04, 0x05,0x06,0x00,0x00,
0x03,0x00,0x00,0x00, 0x01,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0C,0x01,0x06, 0x04,0x05,0x00,0x00,
0x03,0x00,0x00,0x00, 0x02,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0C,0x02,0x05, 0x06,0x04,0x00,0x00,
0x03,0x00,0x00,0x00, 0x03,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0C,0x03,0x06, 0x04,0x05,0x00,0x00,
// Socket 3, Type=0x0D
0x04,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0D,0x00,0x04, 0x05,0x06,0x00,0x00,
// Socket 4, Type=0x0E
0x05,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0E,0x00,0x04, 0x05,0x06,0x00,0x00,
// Socket 5, Type=0x0F
0x06,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x0F,0x00,0x04, 0x05,0x06,0x00,0x00,
// Socket 6, Type=0x10
0x07,0x00,0x00,0x00, 0x00,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x10,0x00,0x04, 0x05,0x06,0x00,0x00,
0x07,0x00,0x00,0x00, 0x01,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x10,0x01,0x06, 0x04,0x05,0x00,0x00,
};
//
// Socket core/thread topology at 0x9110 (25 bytes).
//
STATIC CONST UINT8 mSocketCoreTopology[] = {
0x01,0x00,0x00,0x00, 0x00,0x10,0xC0,0xFE, // Socket 0, APIC base 0xFEC00000
0x09,0x20,0x00,0x00, 0x01,0x00,0x00,0x00, // Type 0x20, count=9
0x00,0x80,0xC0,0xFE, 0x0A,0x20 // Socket 1, APIC base 0xFEC08000,...
};
//
// IOAPIC interrupt routing data at 0xC2C0 (211 bytes).
// 12-byte entries: mapping from PCIe slot/device to IOAPIC input pins.
//
STATIC CONST UINT8 mIoApicRoutingData[] = {
// Entry 0: flags=0xFF, ioapic=0x00, intin=0x09, dev=0x07
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x00,0x09,0x07, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x00,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x01,0x09,0x03, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x02,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x03,0x09,0x03, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x00,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x01,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x02,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0xFF,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x04,0x03,0x09,0x02, 0x00,0x00,0x03,0x00, 0x03,0x00,0x00,0x00,
};
//
// Core Family Hierarchy at 0xDB60 (275 bytes).
// 16-byte entries: {UINT16 Type(0x001F), UINT8 Cluster, UINT8 Reserved[2],
// UINT8 Flags, UINT8 ApicId, UINT16 Reserved2, UINT32 Caps}
//
STATIC CONST UINT8 mCoreFamilyHierarchy[] = {
// Clusters 0-10, each with type 0x1F (standard core)
// Type(2)=0x1F, Cluster=0, Caps=8
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 1: ApicId=1
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 2: ApicId=2
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x02, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 3: ApicId=3
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x03, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 4: ApicId=4
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x04, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 5: ApicId=5
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x05, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 6: ApicId=6
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x06, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 7: ApicId=7
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x07, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 8: ApicId=8, caps=1
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x08, 0x00,0x00,0x01,0x00, 0x01,0x00,0x00,0x00,
// Cluster 9: ApicId=9
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x09, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster A: ApicId=0xA
0x00,0x00,0x00,0x00, 0x1F,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0xFF,0x00,0x08,0x0A, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
};
//
// Core Configuration Table (CCT) at 0xBD80 (67 bytes).
// 16-byte entries: {UINT16 Type(0x001C), UINT8 Index, UINT8 Reserved[3],
// UINT8 Flags, UINT8 ApicCluster, UINT8 CoreMap[4],
// UINT32 Reserved2}
//
STATIC CONST UINT8 mCoreConfigTable[] = {
// Cluster 0, 4-way interleave: cores [16,17,18,19]
0x00,0x00,0x00,0x00, 0x1C,0x00,0xFF,0x00, 0xFF,0x00,0xFF,0x00,
0x00,0x08,0x10,0x11, 0x12,0x13,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 1, rotated: [17,18,19,16]
0x1C,0x01,0xFF,0x00, 0xFF,0x00,0xFF,0x00, 0x00,0x08,0x11,0x12,
0x13,0x10,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 2, rotated: [18,19,16,17]
0x1C,0x02,0xFF,0x00, 0xFF,0x00,0xFF,0x00, 0x00,0x08,0x12,0x13,
0x10,0x11,0x00,0x00, 0x00,0x00,0x00,0x00,
// Cluster 3, rotated: [19,16,17,18]
0x1C,0x03,0xFF,
};
//
// UMPT entry 1 sentinel (2 bytes) at 0xDB30.
//
STATIC CONST UINT8 mConfigSentinel[] = { 0x00, 0x00 };
//
// PIRQ routing entries header at 0x90D8.
// Entries: {UINT64 DataPtr, UINT64 Size, ...}
//
STATIC CONST TABLE_DESCRIPTOR mPirqDataEntries[] = {
{ 0xBD70, 7 }, // PIRQ entry 0: 7 bytes header
{ 0x9660, 1 }, // PIRQ entry 1
{ 0x9240, 0x20E}, // PIRQ entry 2: large routing table
{ 0, 1 }, // Terminator
};
//
// PIRQ routing entry at 0xBD70 (7 bytes header).
//
STATIC CONST UINT8 mPirqRoutingHeader[] = {
0x0B, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x05,
};
//
// -------------------------------------------------------------------------
// Helper Functions
// -------------------------------------------------------------------------
//
/**
Retrieves the platform protocol interface.
Singleton accessor. On first call it locates the protocol via
gBS->LocateProtocol. Subsequent calls return the cached pointer.
@return Pointer to the platform protocol interface, or NULL.
**/
VOID *
GetPlatformProtocol (
VOID
)
{
EFI_STATUS Status;
if (gPlatformProtocol == NULL) {
Status = gBS->LocateProtocol (
(EFI_GUID *)&mPlatformProtocolGuid,
NULL,
&gPlatformProtocol
);
if (EFI_ERROR (Status)) {
gPlatformProtocol = NULL;
}
}
return gPlatformProtocol;
}
/**
Reports an assertion/debug message through the platform protocol.
@param[in] FileName Source file name string.
@param[in] LineNumber Line number in the source file.
@param[in] Description Assert/error description.
**/
VOID
DebugReport (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
VOID *PlatformProtocol;
UINT64 (*DebugFunc)(CONST CHAR8 *, UINTN, CONST CHAR8 *);
PlatformProtocol = GetPlatformProtocol ();
if (PlatformProtocol != NULL) {
//
// Protocol function at offset +8: DebugReport(file, line, desc)
//
DebugFunc = *(UINT64 (**)(CONST CHAR8 *, UINTN, CONST CHAR8 *))(
(UINT8 *)PlatformProtocol + 8
);
if (DebugFunc != NULL) {
DebugFunc (FileName, LineNumber, Description);
}
}
}
/**
Reads an unaligned 64-bit value from memory.
Equivalent to ReadUnaligned64 from BaseLib.
@param[in] Buffer Pointer to the buffer to read from.
@return The 64-bit value read from the buffer.
**/
UINT64
EFIAPI
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
if (Buffer == NULL) {
DebugReport (mFilePathUnaligned, 192, mAssertBuffer);
return 0;
}
return *(const UINT64 *)Buffer;
}
/**
Retrieves and caches the HOB list pointer.
Walks the system configuration table entries to find the HOB list
matching gEfiHobMemoryAllocModuleGuid. Caches the result in gHobList.
@param[in] ImageHandle The image handle (unused in this implementation).
@return Pointer to the HOB list, or NULL.
**/
VOID *
GetHobList (
IN EFI_HANDLE ImageHandle
)
{
UINTN HobCount;
UINTN Index;
VOID *TableEntry;
if (gHobList != NULL) {
return gHobList;
}
//
// Walk the system configuration table.
// gST + 104 = NumberOfTableEntries (offset 0x68 in EFI_SYSTEM_TABLE)
// gST + 112 = ConfigurationTable (offset 0x70)
//
HobCount = *(UINTN *)((UINT8 *)gST + 104);
if (HobCount > 0) {
for (Index = 0; Index < HobCount; Index++) {
TableEntry = (VOID *)(*(UINTN *)((UINT8 *)gST + 112) + (Index * 24));
if (CompareHobGuid (
(EFI_GUID *)&mHobMemoryAllocModuleGuid,
(EFI_GUID *)TableEntry
)) {
//
// Found -- the data pointer is at offset +16 in the table entry.
//
gHobList = *(VOID **)((UINT8 *)TableEntry + 16);
break;
}
}
}
if (gHobList == NULL) {
DebugWrite (0x8000000000000000ULL, mAssertEfiError, 0x800000000000000EULL);
DebugReport (mFilePathHobLib, 54, mAssertNotEfiError);
DebugReport (mFilePathHobLib, 55, mAssertHobList);
}
return gHobList;
}
/**
Compares two GUIDs for equality.
@param[in] Guid1 Pointer to the first GUID.
@param[in] Guid2 Pointer to the second GUID.
@retval TRUE The GUIDs are identical.
@retval FALSE The GUIDs differ or a pointer is NULL.
**/
BOOLEAN
EFIAPI
CompareHobGuid (
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
)
{
UINT64 FirstHalf;
UINT64 SecondHalf;
if ((Guid1 == NULL) || (Guid2 == NULL)) {
return FALSE;
}
FirstHalf = ReadUnaligned64 (Guid1);
SecondHalf = ReadUnaligned64 ((UINT8 *)Guid1 + 8);
return (FirstHalf == ReadUnaligned64 (Guid2)) &&
(SecondHalf == ReadUnaligned64 ((UINT8 *)Guid2 + 8));
}
/**
Writes debug output via the platform protocol's debug function.
Reads CMOS index register to determine the debug verbosity level.
@param[in] ErrorCode EFI error code or status value.
@param[in] FormatString Format string to output.
@param[in] ... Variable argument list.
@return The result code from the debug output function.
**/
UINT8
DebugWrite (
IN UINT64 ErrorCode,
IN CONST CHAR8 *FormatString,
...
)
{
VOID *PlatformProtocol;
UINT8 (*DebugFunc)(UINT64, CONST CHAR8 *, ...);
UINT8 Result;
UINT8 CmosIndex;
UINT8 CmosValue;
PlatformProtocol = GetPlatformProtocol ();
if (PlatformProtocol == NULL) {
return 0;
}
//
// Read CMOS register to determine debug verbosity.
// Index register 0x70, data register 0x71.
//
CmosValue = __inbyte (0x70);
__outbyte (0x70, (CmosValue & 0x80) | 0x4B);
CmosIndex = __inbyte (0x71);
gCmosIndex = CmosIndex;
if (CmosIndex > 3) {
if (CmosIndex == 0) {
//
// Read debug level from platform-specific memory location.
//
CmosIndex = (*(volatile UINT8 *)0xFDAF0490 & 2) | 1;
}
}
Result = CmosIndex - 1;
if (Result <= 0xFD) {
if (CmosIndex == 1) {
ErrorCode = 0x80000004ULL; // DEBUG_INFO
} else {
ErrorCode = 0x80000006ULL; // DEBUG_VERBOSE
}
if ((ErrorCode & ErrorCode) != 0) {
DebugFunc = *(UINT8 (**)(UINT64, CONST CHAR8 *, ...))PlatformProtocol;
if (DebugFunc != NULL) {
return DebugFunc (ErrorCode, FormatString, &FormatString + 1);
}
}
}
return Result;
}
//
// -------------------------------------------------------------------------
// Entry Point
// -------------------------------------------------------------------------
//
/**
Main entry point for the Static Sku Data DXE driver.
Initializes UEFI globals, locates the platform protocol, retrieves
the HOB list, and installs static SKU data tables.
Table installation calls the protocol's function at offset +16,
passing protocol GUID, data pointer, and size.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The driver initialized successfully.
@retval EFI_INVALID_PARAMETER ImageHandle or SystemTable was NULL.
@retval EFI_NOT_FOUND The platform protocol was not found.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *PlatformProtocol;
UINT64 (*InstallTableFunc)(VOID *, VOID *, VOID *, UINT64);
//
// Store global UEFI handles for library-style access.
//
gImageHandle = ImageHandle;
if (ImageHandle == NULL) {
DebugReport (mFilePathBootServices, 51, mAssertImageHandle);
return EFI_INVALID_PARAMETER;
}
gST = SystemTable;
if (SystemTable == NULL) {
DebugReport (mFilePathBootServices, 57, mAssertSystemTable);
return EFI_INVALID_PARAMETER;
}
gBS = SystemTable->BootServices;
if (gBS == NULL) {
DebugReport (mFilePathBootServices, 63, mAssertBootServices);
return EFI_INVALID_PARAMETER;
}
gRT = SystemTable->RuntimeServices;
if (gRT == NULL) {
DebugReport (mFilePathRuntimeServices, 47, mAssertRuntimeServices);
return EFI_INVALID_PARAMETER;
}
//
// Initialize the platform protocol and HOB list.
//
GetHobList (ImageHandle);
//
// Locate the platform protocol interface.
//
Status = gBS->LocateProtocol (
(EFI_GUID *)&mPlatformProtocolGuid,
NULL,
&PlatformProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
gPlatformProtocol = PlatformProtocol;
//
// Install static SKU data protocol.
// Protocol GUID: 0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A
// Install function at offset +16 in the protocol interface.
//
InstallTableFunc = (UINT64 (*)(VOID *, VOID *, VOID *, UINT64))(
(UINT8 *)PlatformProtocol + 16
);
if (InstallTableFunc == NULL) {
return EFI_UNSUPPORTED;
}
//
// Install the Static SKU Data protocol with PIRQ routing info.
//
Status = (EFI_STATUS)InstallTableFunc (
PlatformProtocol,
(VOID *)&mStaticSkuDataProtocolGuid,
(VOID *)&mPlatformHobBlock.PirqProtocolGuid,
24
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Install the PIRQ routing data table.
//
Status = (EFI_STATUS)InstallTableFunc (
PlatformProtocol,
(VOID *)&mPirqProtocolGuid,
(VOID *)&mPirqDataTable,
16
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Install the ACPI processor info table.
//
Status = (EFI_STATUS)InstallTableFunc (
PlatformProtocol,
(VOID *)&mAcpiProcessorInfoGuid,
(VOID *)&mAcpiProcessorBlock.AcpiProcGuid,
16
);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}