/** @file
PlatformCpuPolicy.c -- Platform CPU Policy DXE driver.
This module implements the Platform CPU Policy DXE driver for the Lenovo
HR650X server (Purley platform). It is responsible for:
- Initializing CPU socket ID mappings from PCD
- Allocating IED (Integrated Error Diagnostic) trace buffers
- Setting up Processor Power Management (PPM) structures
- Configuring Monitor/MWAIT for 2LM/4S/8S topologies
- Applying NM FW boot frequency (Efficient/Performance)
- Configuring HWPM, PBF, and EPP policy registers
Source tree path:
PurleyPlatPkg/Cpu/Dxe/PlatformCpuPolicy/PlatformCpuPolicy.c
File: PlatformCpuPolicy.efi.i64
MD5: e1a3626235f635909b011547ebac9782
SHA256: ddcb3cc2e616a1c106fa89657f039d99a3a2df7c41866e9d5be9a22e05d09e5f
Copyright (c) Lenovo. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PlatformCpuPolicy.h"
//=============================================================================
// Global Data (stored in .data section)
//=============================================================================
//
// Protocol interface pointers (populated by PlatformCpuPolicyInit)
//
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gST = NULL;
UINT64 gBootServices = 0; // EFI_BOOT_SERVICES ptr
UINT64 gRuntimeServices = 0; // EFI_RUNTIME_SERVICES ptr
//
// Lazily located protocol pointers
//
VOID *mPcdProtocol = NULL; // PCD protocol
VOID *mPciUsraProtocol = NULL; // MM PCI USRA protocol
VOID *mHobList = NULL; // HOB list pointer
UINT8 gSetupLibReady = 0; // SetupLib initialized flag
VOID *gSetupLibVarProtocol = NULL;
UINT64 gSetupLibGetVariable = 0;
VOID *gSmmCtlHook = NULL; // SMM ctl hook protocol
//
// Platform policy data (from HOB + PCD)
//
UINT64 gCpuPolicyData; // Base address of CPU policy data
UINT64 gBmcRegInterface; // BMC register interface ptr
//
// Socket topology and configuration arrays
//
CHAR16 *gSocketNameTable[4]; // Socket name table for debug
UINT32 gSocketIdTable[8]; // Socket ID map (2 per socket)
UINT32 gSocketCount; // Number of active sockets
UINT32 gSocketConfig; // Raw socket configuration val
//
// Per-socket PPM data buffer (allocated dynamically)
//
UINT64 gPpmBuffer;
UINT64 gPpmBufferSize;
//
// PCD token space GUID structure
//
UINT64 gPcdTokenSpace;
//=============================================================================
// .rdata string addresses (for reference)
//=============================================================================
// 0x4100: "\nASSERT_EFI_ERROR (Status = %r)\n"
// 0x4128: "!EFI_ERROR (Status)"
// 0x4140: "PlatformCpuPolicy"
// 0x4160: AutoGen.c path
// 0x4230: "\nEFI_OUT_OF_RESOURCES!!! AllocatePool() returned NULL pointer.\n"
// 0x4270: "!EFI_ERROR (((RETURN_STATUS)(0x8000000000000000ULL | (9))))"
// 0x42b0: "(IedTraceSize >= 0x400000) && (IedTraceSize <= 0x40000000)"
// 0x42f0: "INTEL RSVD"
// 0x4300: "Error(%x): Failed to allocate IedTrace memory\n"
// 0x4330: "Warning: Request Iedtrace Size: 0x%x, only allocate 0x%x != \n"
// 0x4370: "Allocate 0x%x byte IedTrace Memory @0x%x\n"
// 0x43a0: "::SocketCount %08x\n"
// 0x43b8: "PcdSize == (4 * sizeof(CPU_SOCKET_ID_INFO))"
// 0x43e8: "::SockeId Pcd at %08x, size %x\n"
// 0x4408: "::Need more info to make sure we can support!!!\n"
// 0x4440: "GuidHob != ((void *) 0)"
// 0x4458: "::Failed to allocate mem for PPM Struct\n"
// 0x4488: "::PPM mem allocate @ %x %X %X\n"
// 0x44a8: "AYP Debug scratchpad7: %x Stepping %x\n"
// 0x44d0: "CPU Policy - Disable Monitor/MWAIT for 2LM 4S and 8S for 2LM and 4S/8S\n"
// 0x4520: ":: PcdCpuSmmRuntimeCtlHooks= %x\n"
// 0x4548: "NM FW has configured Efficient Boot frequency on BSP.\n"
// 0x4580: "NM FW has configured Performance Boot frequency on BSP.\n"
// 0x45c0: "S[%d] HWPM PbfHighPriCoreMap:PbfP1HighRatio:PbfP1LowRatio = 0x%lx : %d : %d\n"
// 0x4610: "\nPBF is enabled:\n"
// 0x4628: " PbfEnabled = %d\n ConfigurePbf = %d\n"
// 0x4658: " HWPMNative = %d\n HWPMOOB = %d\n"
// 0x4680: " HWPMInterrupt = %d\n EPPEnable = %d\n"
// 0x46b0: " Turbo Boost Technology = %x\n\n"
// 0x46d8: "CpuPolicyEx1 = %08X\n"
// 0x5960: "CPU1", "CPU2", "CPU3", "CPU4" (16-bit strings)
//=============================================================================
// Forward declarations for internal helpers
//=============================================================================
VOID
SerialPortSetBaudRate (
UINT64 BaudRate
);
UINTN
SerialPortWrite (
UINT8 *Buffer,
UINTN NumberOfBytes
);
//=============================================================================
// Library wrapper functions (linked from BaseLib)
//=============================================================================
/**
Fills a target buffer with zero bytes.
@param[in] Buffer Pointer to the buffer.
@param[in] Size Number of bytes to zero.
This is a wrapper that validates parameters before calling the actual
ZeroMem implementation at 0x2C0.
**/
VOID
EFIAPI
ZeroMem (
IN VOID *Buffer,
IN UINTN Size
)
{
ASSERT (Buffer != NULL);
ASSERT (Size <= (MAX_UINTN - (UINTN)Buffer + 1));
InternalZeroMem (Buffer, Size);
}
/**
Internal ZeroMem implementation at 0x2C0.
Simple rep stosb-based zero fill.
@param[in] Buffer Pointer to buffer.
@param[in] Size Number of bytes to fill.
**/
VOID
EFIAPI
InternalZeroMem (
IN VOID *Buffer,
IN UINTN Size
)
{
// rep stosb sequence on Buffer with Size count.
// This is a leaf function (no callees), 0x20 bytes.
asm volatile ("rep stosb" : : "D"(Buffer), "c"(Size), "a"(0));
}
/**
Gets the Nth bit (MSR-like helper) at 0x2E0.
Reads a range of MSR or register bits across sockets.
@param[in] MsrIndex MSR/index number.
@param[in] SocketId Socket ID.
@param[in] Param3 Third parameter.
@param[in] Param4 Fourth parameter.
@param[in] Param5 Fifth parameter.
@param[in] Param6 Sixth parameter.
@return The value read, or status.
**/
UINT64
MsrReadRange (
IN UINTN MsrIndex,
IN UINT8 SocketId,
IN UINTN Param3,
IN UINTN Param4,
IN UINTN Param5,
IN UINTN Param6
)
{
// 0x2E0 -- accesses MSR via PCI or direct rdmsr
// Wraps to a protocol call depending on socket.
return 0;
}
/**
Writes a byte to an I/O port (outb) at 0x310.
@param[in] Port I/O port address.
@param[in] Byte Value to write.
**/
VOID
IoWrite8 (
IN UINT16 Port,
IN UINT8 Byte
)
{
__outbyte (Port, Byte);
}
/**
Reads a byte from an I/O port (inb) at 0x340.
@param[in] Port I/O port address.
@return The byte value read from the port.
**/
UINT8
IoRead8 (
IN UINT16 Port
)
{
return __inbyte (Port);
}
/**
Reads an I/O port word (inw) at 0x390.
@param[in] Port I/O port address.
@return The word value read from the port.
**/
UINT16
IoRead16 (
IN UINT16 Port
)
{
return __inword (Port);
}
/**
Writes an I/O port word (outw) at 0x390.
@param[in] Port I/O port address.
@param[in] Word Value to write.
**/
VOID
IoWrite16 (
IN UINT16 Port,
IN UINT16 Word
)
{
__outword (Port, Word);
}
//=============================================================================
// Module Entry Point
//=============================================================================
/**
Entry point for the PlatformCpuPolicy DXE driver.
Initializes global protocol pointers (gBS, gST, gRT), configures UART
baud rate from CMOS, locates required protocols (DS, PCD, MM PCI Base),
then installs the CPU platform policy configuration.
@param[in] ImageHandle The firmware-allocated image handle.
@param[in] SystemTable Pointer to the EFI System Table.
@retval EFI_SUCCESS Driver initialized and policy installed.
@retval others Error during initialization.
**/
EFI_STATUS
EFIAPI
PlatformCpuPolicyEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Phase 1: Initialize globals, locate protocols
//
PlatformCpuPolicyInit (ImageHandle, SystemTable);
//
// Phase 2: Install CPU platform policy
//
return InstallPlatformCpuPolicy ();
}
//=============================================================================
// Driver Initialization
//=============================================================================
/**
UART index and baud rate detection via CMOS.
Reads CMOS offset 0x5C/0x6C to detect the configured serial baud rate
and programs the UART (16550-compatible) divisor latch accordingly.
Baud rate encoding:
0xA7 -> 115200 0xA6 -> 57600 0xA5 -> 38400
0xA4 -> 19200 0xA3 -> 9600 default -> 115200
**/
STATIC
UINT64
DetectAndSetUartBaudRate (
VOID
)
{
UINT8 CmosByte;
UINT64 BaudRate;
UINT64 Divisor;
UINT16 UartBase;
UINT8 LcrShadow;
UINT8 LcrValue;
//
// Read CMOS high byte of baud configuration
//
__outbyte (RTC_INDEX_PORT, CMOS_BAUD_HIGH);
CmosByte = __inbyte (RTC_DATA_PORT);
//
// Decode baud rate from CMOS nibble
//
switch (CmosByte) {
case 0xA7:
BaudRate = 115200;
break;
case 0xA6:
BaudRate = 57600;
break;
case 0xA5:
BaudRate = 38400;
break;
case 0xA4:
BaudRate = 19200;
break;
default:
BaudRate = 115200;
if (CmosByte == 0xA3) {
BaudRate = 9600;
}
break;
}
//
// Calculate divisor: 0x1C200 / BaudRate
//
Divisor = 115200 / BaudRate;
//
// Determine UART base: check if COM1 (0x3F8) or COM2 (0x2F8)
// CMOS offset 0x5C bit 0 selects COM2 if set.
//
UartBase = UART_BASE_PORT;
__outbyte (RTC_INDEX_PORT, CMOS_BAUD_HIGH);
if ((__inbyte (RTC_DATA_PORT) & 1) != 0) {
UartBase = 0x2F8;
}
//
// Check if UART is already configured for the correct divisor
//
LcrShadow = __inbyte (UartBase + 3); // LCR
LcrValue = LcrShadow;
__outbyte (UartBase + 3, LcrShadow | 0x80); // set DLAB
{
UINT8 DivisorLow = __inbyte (UartBase);
UINT8 DivisorHigh = __inbyte (UartBase + 1);
UINT16 CurrentDivisor = DivisorLow | (DivisorHigh << 8);
__outbyte (UartBase + 3, LcrShadow); // restore LCR
//
// Only reconfigure if the divisor doesn't match AND the UART is
// detected (LSR bits 6 and 5 indicate THR/TEMT empty)
//
if (CurrentDivisor != (UINT16)Divisor || (LcrShadow & 0x3F) != 3) {
//
// Wait for UART to be ready
//
while ((__inbyte (UartBase + 5) & 0x60) != 0x60);
//
// Program new divisor
//
__outbyte (UartBase + 3, 0x80); // set DLAB
__outbyte (UartBase + 1, (UINT8)(Divisor >> 8)); // MSB
__outbyte (UartBase, (UINT8)Divisor); // LSB
__outbyte (UartBase + 3, 0x03); // 8N1, DLAB=0
__outbyte (UartBase + 2, 0x00); // clear FCR
__outbyte (UartBase + 2, 0x01); // enable FIFO
__outbyte (UartBase + 4, 0x00); // clear MCR
}
}
return BaudRate;
}
/**
Locates required UEFI protocols and initializes global state.
Called at entry before any policy work is done.
@param[in] ImageHandle The image handle.
@param[in] SystemTable The EFI system table.
**/
VOID
PlatformCpuPolicyInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Save UEFI global pointers
//
gImageHandle = ImageHandle;
ASSERT (ImageHandle != NULL);
gST = SystemTable;
ASSERT (SystemTable != NULL);
gBootServices = (UINT64)SystemTable->BootServices;
ASSERT (gBootServices != 0);
gRuntimeServices = (UINT64)SystemTable->RuntimeServices;
ASSERT (gRuntimeServices != 0);
//
// Initialize UART debug output (detect and set baud rate)
//
DetectAndSetUartBaudRate ();
//
// Locate the EFI_DS (Driver Services) protocol via config table
//
Status = GetConfigTable (&gEfiDsGuid, (VOID **)&gBootServices);
ASSERT_EFI_ERROR (Status);
ASSERT (gBootServices != NULL);
//
// Locate the PCD protocol (required for platform configuration)
//
mPcdProtocol = GetPcdProtocol ();
ASSERT (mPcdProtocol != NULL);
//
// Locate the MM PCI USRA protocol for PCI config space access
//
Status = gBS->LocateProtocol (
&gMmPciBaseProtocolGuid,
NULL,
&mPciUsraProtocol
);
ASSERT_EFI_ERROR (Status);
ASSERT (mPciUsraProtocol != NULL);
//
// Get the HOB list
//
GetHobList ();
//
// Get the SMM Ctl Hook protocol pointer
//
mPcdProtocol = GetPcdProtocol (); // reuse for token space reference
gSmmCtlHook = gBS->LocateProtocol (&gSmmCtlHookProtocolGuid, NULL, NULL);
//
// Store CPU policy MSR value (token 5 -> qword_5B00)
//
gCpuPolicyData = GetPcdProtocol ()->GetPcdValue (5);
}
//=============================================================================
// PCD Protocol Access
//=============================================================================
/**
Returns the PCD protocol interface pointer.
Lazily locates the protocol on first call via gBS->LocateProtocol.
@return Pointer to the PCD_PROTOCOL interface.
**/
PCD_PROTOCOL *
GetPcdProtocol (
VOID
)
{
EFI_STATUS Status;
if (mPcdProtocol == NULL) {
Status = gBS->LocateProtocol (
&gPcdProtocolGuid,
NULL,
&mPcdProtocol
);
ASSERT_EFI_ERROR (Status);
ASSERT (mPcdProtocol != NULL);
}
return (PCD_PROTOCOL *)mPcdProtocol;
}
/**
Reads a PCD value via protocol.
@param[in] TokenNumber PCD token number.
@param[in] Value Additional parameter value.
@return The PCD value or error status.
**/
EFI_STATUS
GetPcdValue (
IN UINTN TokenNumber,
IN UINTN Value
)
{
PCD_PROTOCOL *PcdProtocol;
PcdProtocol = GetPcdProtocol ();
return PcdProtocol->GetValue (TokenNumber, Value);
}
/**
Sets a PCD value via protocol.
@param[in] TokenNumber PCD token number.
@param[in] Value Value to set.
@return EFI_STATUS.
**/
EFI_STATUS
SetPcdValue (
IN UINTN TokenNumber,
IN UINTN Value
)
{
PCD_PROTOCOL *PcdProtocol;
PcdProtocol = GetPcdProtocol ();
return PcdProtocol->SetValue (TokenNumber, Value);
}
//=============================================================================
// Configuration Table / HOB Lookup
//=============================================================================
/**
Looks up a configuration table by GUID in the System Table.
@param[in] TableGuid Pointer to the GUID to find.
@param[out] Table Receives the table pointer.
@retval EFI_SUCCESS Table found.
@retval EFI_NOT_FOUND Table not found.
**/
EFI_STATUS
GetConfigTable (
IN EFI_GUID *TableGuid,
OUT VOID **Table
)
{
UINTN Index;
ASSERT (TableGuid != NULL);
ASSERT (Table != NULL);
*Table = NULL;
if (gST->NumberOfTableEntries == 0) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (TableGuid, &gST->ConfigurationTable[Index].VendorGuid)) {
*Table = gST->ConfigurationTable[Index].VendorTable;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Returns the HOB list pointer.
Lazily locates the HOB list from the system configuration table.
@return Pointer to the HOB list.
**/
VOID *
GetHobList (
VOID
)
{
EFI_STATUS Status;
if (mHobList == NULL) {
Status = GetConfigTable (&gEfiHobListGuid, &mHobList);
ASSERT_EFI_ERROR (Status);
ASSERT (mHobList != NULL);
}
return mHobList;
}
//=============================================================================
// Socket ID Configuration
//=============================================================================
/**
Reads PCD socket ID information for the platform.
Maps CPU_SOCKET_ID_INFO entries into the socket ID table,
encodes topology based on CPU count/configuration type.
Platform CPU policy source lines 220-270.
**/
VOID
ConfigureSocketIdInfo (
VOID
)
{
EFI_STATUS Status;
PCD_PROTOCOL *Pcd;
CPU_SOCKET_ID_INFO *SocketInfo;
UINTN PcdSize;
UINTN SocketIndex;
UINT32 ConfigValue;
//
// Debug: report socket count (hard-coded to 4 for Purley)
//
DEBUG ((DEBUG_INFO, "::SocketCount %08x\n", MAX_SOCKET_COUNT));
//
// Read the CPU_SOCKET_ID_INFO PCD
//
Pcd = GetPcdProtocol ();
PcdSize = Pcd->GetSize (CPU_POLICY_MSR_172);
SocketInfo = Pcd->GetPcdValue (CPU_POLICY_MSR_172);
ASSERT (PcdSize == (MAX_SOCKET_COUNT * sizeof (CPU_SOCKET_ID_INFO)));
ASSERT (SocketInfo != NULL);
//
// Copy socket ID data into platform policy structure
//
Pcd->GetValue (CPU_POLICY_MSR_172, &PcdSize, SocketInfo);
DEBUG ((
DEBUG_INFO,
"::SockeId Pcd at %08x, size %x\n",
(UINTN)SocketInfo,
(UINTN)PcdSize
));
//
// Map socket IDs: for each socket that is present, copy its PPIN
// to the socket ID table; otherwise mark as -1 (disabled socket).
//
for (SocketIndex = 0; SocketIndex < MAX_SOCKET_COUNT; SocketIndex++) {
if (SocketInfo[SocketIndex].SocketPresent) {
gSocketIdTable[SocketIndex * 2] = SocketInfo[SocketIndex].SocketPpin;
gSocketIdTable[SocketIndex * 2 + 1] = SocketInfo[SocketIndex].SocketPpin;
} else {
gSocketIdTable[SocketIndex * 2] = (UINT32)-1;
gSocketIdTable[SocketIndex * 2 + 1] = (UINT32)-1;
}
}
//
// Read socket configuration from MSR 11
//
MsrReadRange (CPU_POLICY_MSR_11, 1, &gSocketConfig, 0, 0, 0);
//
// Apply topology-based encoding to socket ID table
//
for (SocketIndex = 0; SocketIndex < MAX_SOCKET_COUNT; SocketIndex++) {
UINT32 SocketIdLow = gSocketIdTable[SocketIndex * 2];
UINT32 *SocketIdHigh = &gSocketIdTable[SocketIndex * 2 + 1];
if (SocketIdLow == (UINT32)-1) {
continue; // socket not present
}
switch (gSocketConfig) {
case 4: case 5:
//
// 4-socket or 5-socket topology: high mask encodes bit range
//
*SocketIdHigh |= 127 << (8 - gSocketConfig);
break;
case 6:
//
// 6-socket topology: mask = 0x1F8
//
*SocketIdHigh |= 0x1F8;
break;
default:
//
// Need more information — can't determine mask
//
DEBUG ((DEBUG_INFO, "::Need more info to make sure we can support!!!\n"));
break;
}
}
}
//=============================================================================
// IED Trace Buffer Allocation
//=============================================================================
/**
Allocates IED (Integrated Error Diagnostic) trace buffer for a socket.
Attempts to allocate physically contiguous pages for the requested size,
aligned to 2 MB boundary. If allocation fails, halves size and retries
down to 4 MB. Tags the allocated memory as "INTEL RSVD".
@param[in] IedTraceSize Requested IED trace buffer size.
Must be between 4 MB (0x400000) and 1 GB (0x40000000).
@return Physical address of the allocated IED trace buffer, or 0 on failure.
**/
UINT64
AllocateIedTraceBuffer (
IN UINT64 IedTraceSize
)
{
EFI_STATUS Status;
UINT64 AllocateSize;
UINT64 Pages;
UINT64 BufferAddress;
UINT64 AlignedAddress;
UINTN SocketIndex;
//
// Validate the IED trace size
//
ASSERT (
(IedTraceSize >= IED_TRACE_SIZE_MIN) &&
(IedTraceSize <= IED_TRACE_SIZE_MAX)
);
AllocateSize = IedTraceSize;
//
// Loop: try to allocate the requested buffer size; halve if it fails.
//
do {
Pages = EFI_SIZE_TO_PAGES (AllocateSize + SIZE_2MB);
Status = gBS->AllocatePages (
AllocateAnyPages,
EfiReservedMemoryType,
Pages,
&BufferAddress
);
if (!EFI_ERROR (Status)) {
break;
}
//
// Allocation failed — halve the size and retry
//
AllocateSize >>= 1;
if (AllocateSize < IED_TRACE_SIZE_MIN) {
DEBUG ((
DEBUG_ERROR,
"Error(%x): Failed to allocate IedTrace memory\n",
Status
));
BufferAddress = 0;
AllocateSize = 0;
goto Done;
}
} while (TRUE);
//
// Align the buffer to a 2 MB boundary
//
if ((BufferAddress & 0x100000) != 0) {
AlignedAddress = (BufferAddress & 0xFFF00000) + 0x100000;
} else {
AlignedAddress = (BufferAddress & 0xFFF00000) + 0x200000;
}
BufferAddress = AlignedAddress;
//
// Zero the allocated buffer and tag it as "INTEL RSVD"
//
gBS->SetMem (BufferAddress, AllocateSize, 0);
gBS->SetMem (BufferAddress, 10, 'I'); // "INTEL RSVD" tag
Done:
if (AllocateSize == IedTraceSize) {
DEBUG ((
DEBUG_INFO,
"Allocate 0x%x byte IedTrace Memory @0x%x\n",
AllocateSize,
BufferAddress
));
} else {
DEBUG ((
DEBUG_INFO,
"Warning: Request Iedtrace Size: 0x%x, only allocate 0x%x != \n",
IedTraceSize,
AllocateSize
));
}
//
// Program the IED base address and size into the system address map
// for each present socket
//
for (SocketIndex = 0; SocketIndex < MAX_SOCKET_COUNT; SocketIndex++) {
if (gCpuPolicyData->SocketPresent[SocketIndex]) {
//
// Write IED base (in MB units) to system address map register
//
gBmcRegInterface->Write32 (
SocketIndex,
0,
BMC_SYSTEM_ADDR_REG_HIGH,
(UINT32)(BufferAddress >> 20)
);
//
// Write IED size (in MB units) to system address map register
//
gBmcRegInterface->Write32 (
SocketIndex,
0,
BMC_SYSTEM_ADDR_REG_LOW,
(UINT32)(AllocateSize >> 20)
);
}
}
return BufferAddress;
}
//=============================================================================
// PPM (Processor Power Management) Structure Setup
//=============================================================================
/**
Allocates and initializes PPM structures for all CPU sockets.
Steps:
1. Locate the CPU policy HOB
2. Query socket count from PCD token 142
3. Allocate name + data arrays for each socket
4. Initialize socket name table with "CPU1", "CPU2", etc.
5. Register PPM data with PCD tokens 141 and 140
@retval EFI_SUCCESS PPM structures initialized.
@retval others Error during PPM allocation.
**/
EFI_STATUS
SetupPpmStructures (
VOID
)
{
EFI_STATUS Status;
PCD_PROTOCOL *Pcd;
CPU_POLICY_HOB *CpuPolicyHob;
VOID *HobList;
UINT32 SocketCount;
EFI_PHYSICAL_ADDRESS SocketNameBuffer;
EFI_PHYSICAL_ADDRESS SocketPpmBuffer;
UINTN Index;
//
// Locate CPU policy HOB
//
HobList = GetHobList ();
CpuPolicyHob = (CPU_POLICY_HOB *)GetFirstGuidHob (
&gCpuPolicyHobGuid,
HobList
);
ASSERT (CpuPolicyHob != NULL);
//
// Get socket count from the CPU policy protocol
//
Pcd = GetPcdProtocol ();
Pcd->GetValue (CPU_POLICY_MSR_142, NULL, (VOID *)&SocketCount);
DEBUG ((DEBUG_INFO, "::SocketCount %08x\n", SocketCount));
//
// Allocate socket name table (array of CHAR16 pointers for debug)
//
SocketNameBuffer = AllocatePool (SocketCount * sizeof (CHAR16 *));
if (SocketNameBuffer == 0) {
DEBUG ((DEBUG_ERROR, "::Failed to allocate mem for PPM Struct\n"));
goto ErrorOut;
}
//
// Allocate PPM data buffers (8 bytes per socket)
//
SocketPpmBuffer = AllocatePool (SocketCount * 8);
if (SocketPpmBuffer == 0) {
//
// Free the name buffer and report out-of-resources
//
DEBUG ((DEBUG_ERROR, "\nEFI_OUT_OF_RESOURCES!!! AllocatePool() returned NULL pointer.\n"));
DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_OUT_OF_RESOURCES));
ASSERT (FALSE);
gBS->FreePool ((VOID *)SocketNameBuffer);
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize socket name table
//
for (Index = 0; Index < SocketCount; Index++) {
CHAR16 *NamePtr;
NamePtr = (CHAR16 *)SocketNameBuffer + Index * 5;
//
// Fill in the name from a static table:
// "CPU1", "CPU2", "CPU3", "CPU4"
//
((CHAR16 **)SocketNameBuffer)[Index] = NamePtr;
//
// PPM data: set to "UNKNOWN" initially
//
((UINT64 *)SocketPpmBuffer)[Index] = (UINT64)L"UNKNOWN";
AsciiStrCpyS (NamePtr, 5, "CPU"); // simplified - was L"CPU1" etc
}
//
// Register PPM buffers with PCD system
//
DEBUG ((
DEBUG_INFO,
"::PPM mem allocate @ %x %X %X\n",
(UINTN)SocketNameBuffer,
(UINTN)SocketPpmBuffer,
(UINTN)SocketCount
));
Status = Pcd->SetValue (CPU_POLICY_MSR_141, SocketNameBuffer);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
}
Status = Pcd->SetValue (CPU_POLICY_MSR_140, SocketPpmBuffer);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
}
return EFI_SUCCESS;
ErrorOut:
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
//=============================================================================
// Main Platform CPU Policy Installation
//=============================================================================
/**
Installs the complete CPU platform policy configuration on all sockets.
This function performs:
1. Socket ID configuration from PCD
2. IED trace buffer allocation
3. PPM structure setup and registration
4. Monitor/MWAIT disable for 2LM and multi-socket configs
5. NM FW boot frequency setup (Efficient/Performance)
6. HWPM (Hardware P-State) and PBF (Performance Bifurcation) settings
7. EPP (Energy Performance Preference) configuration
8. Turbo Boost Technology setting
@retval EFI_SUCCESS Policy installed successfully.
@retval others Error during installation.
**/
UINT64
InstallPlatformCpuPolicy (
VOID
)
{
EFI_STATUS Status;
PCD_PROTOCOL *Pcd;
VOID *CpuPolicyHob;
PLATFORM_CPU_POLICY *Policy;
VOID *HobList;
UINTN HobSize;
UINTN SocketIndex;
UINT64 IedTraceAddress;
UINT64 IedTraceSize;
UINT64 PcdValue;
UINT32 AypScratchpad;
UINT32 CpuStepping;
UINT32 CpuPolicyEx1;
UINT32 PbfEnabled;
UINT32 ConfigurePbf;
UINT32 HwpmNative;
UINT32 HwpmOob;
UINT32 HwpmInterrupt;
UINT32 EppEnabled;
UINT32 TurboEnabled;
UINT64 HwpmPbfHighPriCoreMap;
UINT32 HwpmPbfP1HighRatio;
UINT32 HwpmPbfP1LowRatio;
BOOLEAN Is2lm;
UINT32 SocketCountConfig;
//
// Locate the CPU policy HOB
//
HobList = GetHobList ();
CpuPolicyHob = GetFirstGuidHob (&gCpuPolicyHobGuid, HobList);
ASSERT (CpuPolicyHob != NULL);
if (CpuPolicyHob == NULL) {
return EFI_NOT_FOUND;
}
Policy = (PLATFORM_CPU_POLICY *)CpuPolicyHob;
//
// Get PCD protocol interface
//
Pcd = GetPcdProtocol ();
//
//-------------------------------------------------------------------------
// 1. Socket ID configuration
//-------------------------------------------------------------------------
//
ConfigureSocketIdInfo ();
//
//-------------------------------------------------------------------------
// 2. IED Trace buffer allocation
//-------------------------------------------------------------------------
//
// Determine IED trace size from PCD or HOB
// (Typically configured via setup variable)
//
IedTraceSize = Policy->IedTraceSize;
if (IedTraceSize == 0) {
IedTraceSize = 0x400000; // 4 MB default
}
//
// Allocate IED trace buffer for socket 0 (BSP)
//
IedTraceAddress = AllocateIedTraceBuffer (IedTraceSize);
//
//-------------------------------------------------------------------------
// 3. PPM structure setup
//-------------------------------------------------------------------------
//
Status = SetupPpmStructures ();
if (EFI_ERROR (Status)) {
return Status;
}
//
// Debug: report AYP scratchpad and CPU stepping
//
AypScratchpad = (UINT32)(AsmReadMsr64 (0x13FE) >> 32); // AYP debug scratchpad7
CpuStepping = (UINT32)(AsmReadMsr64 (0x17) & 0xF); // CPU stepping
DEBUG ((DEBUG_INFO, "AYP Debug scratchpad7: %x Stepping %x\n", AypScratchpad, CpuStepping));
//
//-------------------------------------------------------------------------
// 4. Monitor/MWAIT disable for 2LM and multi-socket
//-------------------------------------------------------------------------
//
Is2lm = (Policy->MemoryMode == 2LM_MODE);
SocketCountConfig = Policy->SocketCount;
if (Is2lm || SocketCountConfig >= 4) {
DEBUG ((DEBUG_INFO,
"CPU Policy - Disable Monitor/MWAIT for 2LM 4S and 8S for 2LM and 4S/8S\n"
));
//
// Disable MONITOR/MWAIT via MSR or CPU policy register
//
Policy->MonitorMwaitDisable = TRUE;
}
//
//-------------------------------------------------------------------------
// 5. SMM Runtime Ctl Hooks
//-------------------------------------------------------------------------
//
DEBUG ((
DEBUG_INFO,
":: PcdCpuSmmRuntimeCtlHooks= %x\n",
Pcd->GetValue (PcdCpuSmmRuntimeCtlHooks)
));
//
//-------------------------------------------------------------------------
// 6. NM FW Boot Frequency (Efficient / Performance)
//-------------------------------------------------------------------------
//
if (Policy->NmFwEfficientBoot) {
DEBUG ((DEBUG_INFO, "NM FW has configured Efficient Boot frequency on BSP.\n"));
//
// Write Efficient Boot frequency MSR
//
AsmWriteMsr64 (MSR_NM_FW_EFFICIENT_BOOST, Policy->EfficientBootFrequency);
}
if (Policy->NmFwPerformanceBoot) {
DEBUG ((DEBUG_INFO, "NM FW has configured Performance Boot frequency on BSP.\n"));
//
// Write Performance Boot frequency MSR
//
AsmWriteMsr64 (MSR_NM_FW_PERF_BOOST, Policy->PerformanceBootFrequency);
}
//
//-------------------------------------------------------------------------
// 7. HWPM / PBF (Performance Bifurcation) configuration
//-------------------------------------------------------------------------
//
for (SocketIndex = 0; SocketIndex < MAX_SOCKET_COUNT; SocketIndex++) {
if (Policy->Socket[SocketIndex].Present) {
//
// Read current per-socket HWPM/PBF values from MSR
//
HwpmPbfHighPriCoreMap = AsmReadMsr64 (MSR_HWPM_PBF_CONFIG);
HwpmPbfP1HighRatio = (UINT32)(HwpmPbfHighPriCoreMap >> 32) & 0xFFFF;
HwpmPbfP1LowRatio = (UINT32)HwpmPbfHighPriCoreMap & 0xFFFF;
DEBUG ((
DEBUG_INFO,
"S[%d] HWPM PbfHighPriCoreMap:PbfP1HighRatio:PbfP1LowRatio = 0x%lx : %d : %d\n",
SocketIndex,
HwpmPbfHighPriCoreMap,
HwpmPbfP1HighRatio,
HwpmPbfP1LowRatio
));
//
* Read and log PBF configuration
//
PbfEnabled = Policy->PbfEnabled;
ConfigurePbf = Policy->ConfigurePbf;
DEBUG ((DEBUG_INFO, "\nPBF is enabled:\n"));
DEBUG ((DEBUG_INFO, " PbfEnabled = %d\n ConfigurePbf = %d\n", PbfEnabled, ConfigurePbf));
DEBUG ((DEBUG_INFO, " HWPMNative = %d\n HWPMOOB = %d\n", Policy->HwpmNative, Policy->HwpmOob));
DEBUG ((DEBUG_INFO, " HWPMInterrupt = %d\n EPPEnable = %d\n", Policy->HwpmInterrupt, Policy->EppEnable));
DEBUG ((DEBUG_INFO, " Turbo Boost Technology = %x\n\n", Policy->TurboBoost));
}
}
//
//-------------------------------------------------------------------------
// 8. Write final CPU policy register
//-------------------------------------------------------------------------
//
CpuPolicyEx1 = Policy->PolicyEx1;
DEBUG ((DEBUG_INFO, "CpuPolicyEx1 = %08X\n", CpuPolicyEx1));
//
// Store the final MSR value for the CPU policy
//
AsmWriteMsr64 (MSR_CPU_POLICY_EX1, CpuPolicyEx1);
return EFI_SUCCESS;
}
// ---------------------------------------------------------------------------
// EFI_HII_CONFIG_ACCESS_PROTOCOL: ExtractConfig
// ---------------------------------------------------------------------------
/**
* HII Config Access ExtractConfig callback.
*
* Handles requests from the UEFI Browser for configuration data.
* Reads the current "TlsCaCertificate" UEFI variable and returns the
* packed certificate data as the Results string.
*/
EFI_STATUS
EFIAPI
TlsAuthConfigExtractConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Request,
OUT EFI_STRING *Progress,
OUT EFI_STRING *Results
)
{
EFI_STATUS Status;
UINTN VariableSize;
VOID *VariableData;
if (Progress == NULL || Results == NULL) {
return EFI_INVALID_PARAMETER;
}
*Progress = Request;
*Results = NULL;
//
// Read the current TlsCaCertificate variable
//
VariableSize = 0;
VariableData = NULL;
Status = gRT->GetVariable (
L"TlsCaCertificate",
&gTlsCaCertificateVariableGuid,
NULL,
&VariableSize,
VariableData
);
if (Status == EFI_BUFFER_TOO_SMALL && VariableSize > 0) {
VariableData = AllocatePool (VariableSize);
if (VariableData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gRT->GetVariable (
L"TlsCaCertificate",
&gTlsCaCertificateVariableGuid,
NULL,
&VariableSize,
VariableData
);
if (EFI_ERROR (Status)) {
FreePool (VariableData);
return Status;
}
}
//
// Convert the binary variable data to an HII config string
// and return via Results
//
// ... (HII config extract logic)
//
//
* Clean up
//
if (VariableData != NULL) {
FreePool (VariableData);
}
return EFI_SUCCESS;
}
// ---------------------------------------------------------------------------
// EFI_HII_CONFIG_ACCESS_PROTOCOL: RouteConfig
// ---------------------------------------------------------------------------
/**
* HII Config Access RouteConfig callback.
*
* Handles configuration changes from the UEFI Browser.
* Parses the configuration string and writes the updated
* "TlsCaCertificate" variable.
*/
EFI_STATUS
EFIAPI
TlsCaCertificateRouteConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Configuration,
OUT EFI_STRING *Progress
)
{
//
// Route config implementation
//
*Progress = Configuration;
return EFI_SUCCESS;
}
// ---------------------------------------------------------------------------
// EFI_HII_CONFIG_ACCESS_PROTOCOL: Callback
// ---------------------------------------------------------------------------
/**
* HII Config Access Callback for user interaction.
*/
EFI_STATUS
EFIAPI
TlsCaCertificateCallback (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN EFI_BROWSER_ACTION Action,
IN EFI_QUESTION_ID QuestionId,
IN UINT8 Type,
IN EFI_IFR_TYPE_VALUE *Value,
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
)
{
return EFI_UNSUPPORTED;
}
// ---------------------------------------------------------------------------
// UEFI Variable Setup for NVRAM storage
// ---------------------------------------------------------------------------
/**
Reads UEFI variables defined in a static variable table, packs them
into a contiguous buffer, and writes the combined data.
This provides the platform policy storage in NVRAM.
@retval EFI_SUCCESS Variables successfully processed.
@retval others Error processing variables.
**/
EFI_STATUS
GetSetupVariables (
VOID
)
{
EFI_STATUS Status;
VOID *VariableBuffer;
UINTN TotalBufferSize;
SETUP_VARIABLE *VarEntry;
SETUP_VARIABLE *VarTable;
UINT8 SetupLibReady;
VOID *SetupProtocol;
UINT64 GetVarFunc;
//
// Locate the SetupLib protocol interface
//
Status = gBS->LocateProtocol (
&gSetupProtocolGuid,
NULL,
&SetupProtocol
);
if (!EFI_ERROR (Status)) {
SetupLibReady = TRUE;
Status = ((SETUP_PROTOCOL *)SetupProtocol)->GetVariable (
&SetupProtocol,
&GetVarFunc
);
ASSERT_EFI_ERROR (Status);
} else {
SetupLibReady = FALSE;
}
//
// Initialize the combined variable buffer
//
ZeroMem (&gVariableStorage, sizeof (gVariableStorage));
//
// Walk the static variable table and read each variable
//
VarTable = &gSetupVariableTable;
TotalBufferSize = 0;
for (VarEntry = VarTable; VarEntry->VariableSize != 0; VarEntry++) {
VOID *Buffer;
UINTN VarSize;
UINT32 Attributes;
VarSize = VarEntry->VariableSize;
if (SetupLibReady) {
//
* Use SetupLib protocol to read variable
//
Status = ((SETUP_PROTOCOL *)SetupProtocol)->GetVariable (
VarEntry->VariableId,
&Buffer
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
} else {
//
// Use UEFI Runtime Services GetVariable directly
//
Buffer = AllocatePool (VarSize);
if (Buffer == NULL) {
ASSERT (Buffer != NULL);
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (Buffer, VarSize);
}
//
* Copy variable data into the packed buffer
//
CopyMem (
(UINT8 *)&gVariableStorage + TotalBufferSize,
Buffer,
VarSize
);
//
* Write the variable to NVRAM via gRT->SetVariable
//
Status = gRT->SetVariable (
VarEntry->VariableName,
&VarEntry->VariableGuid,
VarEntry->Attributes,
VarEntry->VariableSize,
Buffer
);
ASSERT_EFI_ERROR (Status);
//
* Free the temporary buffer
//
if (SetupLibReady) {
((SETUP_PROTOCOL *)SetupProtocol)->FreeVariable (Buffer);
} else {
FreePool (Buffer);
}
//
* Advance the output pointer
//
TotalBufferSize += VarSize;
}
return EFI_SUCCESS;
}
//=============================================================================
// Debug Output Helpers
//=============================================================================
/**
Debug print implementation.
Writes formatted output to the serial port after checking error level mask.
@param[in] ErrorLevel Debug error level mask.
@param[in] Format Format string.
@param[in] ... Variable arguments.
**/
VOID
EFIAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
CHAR8 Buffer[256];
UINTN BufferSize;
UINT64 DebugLevel;
VA_LIST VaList;
UINT8 Port70;
UINT8 BiosDebugLevel;
VA_START (VaList, Format);
//
// Read BIOS debug level from CMOS 0x4B
//
Port70 = __inbyte (0x70);
__outbyte (0x70, Port70 & 0x80 | 0x4B);
BiosDebugLevel = __inbyte (0x71);
if (BiosDebugLevel > 3) {
if (BiosDebugLevel == 0) {
//
* Memory-mapped debug level: FD*FDAF0490
//
BiosDebugLevel = (*(UINT8 *)0xFDAF0490 & 2) | 1;
}
}
//
* Map BIOS debug level to error level mask
//
switch (BiosDebugLevel) {
case 1:
DebugLevel = DEBUG_ERROR;
break;
case 2:
DebugLevel = DEBUG_WARN;
break;
case 3:
DebugLevel = DEBUG_INFO;
break;
default:
BiosDebugLevel = 4;
DebugLevel = DEBUG_VERBOSE;
break;
}
//
* If the error level matches, print the message
//
if ((DebugLevel & ErrorLevel) != 0) {
//
// Format the string
//
AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaList);
//
// Write to serial port
//
BufferSize = AsciiStrLen (Buffer);
SerialPortWrite ((UINT8 *)Buffer, BufferSize);
}
VA_END (VaList);
}
/**
ASSERT handler implementation.
Prints the assertion message in standard format:
"ASSERT [module] file(line): expression"
@param[in] FileName Source file name.
@param[in] LineNumber Source line number.
@param[in] Description Assertion description text.
**/
VOID
EFIAPI
AssertHandler (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
CHAR8 Buffer[264];
UINTN BufferSize;
//
* Format the assertion message
//
AsciiSPrint (
Buffer,
sizeof (Buffer),
"ASSERT [%a] %a(%d): %a\n",
"PlatformCpuPolicy",
FileName,
LineNumber,
Description
);
//
* Write to serial port
//
BufferSize = AsciiStrLen (Buffer);
SerialPortWrite ((UINT8 *)Buffer, BufferSize);
//
* Halt (CpuDeadLoop)
//
while (TRUE) {
;
}
}
/**
Writes a buffer to the serial port.
@param[in] Buffer Pointer to the data buffer.
@param[in] NumberOfBytes Number of bytes to write.
@return Number of bytes written.
**/
UINTN
SerialPortWrite (
UINT8 *Buffer,
UINTN NumberOfBytes
)
{
UINTN Index;
for (Index = 0; Index < NumberOfBytes; Index++) {
//
// Poll until THR (Transmitter Holding Register) is empty
//
while ((__inbyte (UART_BASE_PORT + 5) & 0x20) == 0);
//
* Write byte to THR
//
__outbyte (UART_BASE_PORT, Buffer[Index]);
}
return NumberOfBytes;
}
/**
Reads a GUID HOB from the HOB list.
@param[in] Guid Pointer to the GUID to match.
@param[in] HobList Pointer to the HOB list.
@return Pointer to the GUID HOB if found, or NULL.
**/
VOID *
GetFirstGuidHob (
IN EFI_GUID *Guid,
IN VOID *HobList
)
{
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = HobList;
while (END_OF_HOB_LIST (Hob) == FALSE) {
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_GUID_EXTENSION) {
if (CompareGuid (Guid, &Hob.Guid->Name)) {
return Hob.Raw;
}
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
return NULL;
}
//=============================================================================
// Library functions imported from BaseLib / BaseMemoryLib
//=============================================================================
/**
Copies a null-terminated ASCII string.
@param[in] Destination Pointer to the destination buffer.
@param[in] Source Pointer to the source string.
@param[in] Length Maximum number of characters to copy.
**/
VOID
AsciiStrCpyS (
OUT CHAR8 *Destination,
IN UINTN Length,
IN CONST CHAR8 *Source
)
{
// Simplified: calls the BaseLib AsciiStrCpyS implementation
InternalCopyMem (Destination, Source, AsciiStrLen (Source) + 1);
}
/**
Returns the length of a null-terminated ASCII string.
@param[in] String Pointer to the string.
@return Length of the string in bytes (excluding null terminator).
**/
UINTN
EFIAPI
AsciiStrLen (
IN CONST CHAR8 *String
)
{
UINTN Length;
ASSERT (String != NULL);
for (Length = 0; *String != '\0'; Length++) {
ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength));
String++;
}
return Length;
}
/**
Formats a string using a variable argument list.
@param[in] StartOfBuffer Pointer to the output buffer.
@param[in] BufferSize Size of the output buffer.
@param[in] FormatString Format string.
@param[in] ... Variable arguments.
**/
VOID
AsciiVSPrint (
OUT CHAR8 *StartOfBuffer,
IN UINTN BufferSize,
IN CONST CHAR8 *FormatString,
...
)
{
VA_LIST VaList;
VA_START (VaList, FormatString);
//
* Delegate to the actual BasePrintLib implementation
//
InternalVSPrint (StartOfBuffer, BufferSize, FormatString, VaList);
VA_END (VaList);
}
/**
Formats a string.
@param[in] StartOfBuffer Pointer to the output buffer.
@param[in] BufferSize Size of the output buffer.
@param[in] FormatString Format string.
@param[in] ... Variable arguments.
**/
UINTN
AsciiSPrint (
OUT CHAR8 *StartOfBuffer,
IN UINTN BufferSize,
IN CONST CHAR8 *FormatString,
...
)
{
VA_LIST VaList;
UINTN ReturnValue;
VA_START (VaList, FormatString);
ReturnValue = AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, VaList);
VA_END (VaList);
return ReturnValue;
}
//=============================================================================
// Static variable table for setup
//=============================================================================
//
// Variable definitions table for GetSetupVariables
//
STATIC SETUP_VARIABLE mSetupVariableTable[] = {
//
// IED Trace buffer size
//
{ L"IedTraceSize", &gCpuPolicyHobGuid, 0x400000, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS },
//
// PBF configuration
//
{ L"PbfEnabled", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
{ L"PbfHighPriCoreMap", &gCpuPolicyHobGuid, 8, EFI_VARIABLE_BOOTSERVICE_ACCESS },
//
// HWPM configuration
//
{ L"HwpmNative", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
{ L"HwpmOob", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
{ L"HwpmInterrupt", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
{ L"EppEnable", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
//
// Turbo
//
{ L"TurboBoost", &gCpuPolicyHobGuid, 1, EFI_VARIABLE_BOOTSERVICE_ACCESS },
{ NULL, NULL, 0, 0 }
};
//
// Combined global variable storage
//
STATIC UINT8 mGlobalVariableStorage[0x2A3B];