/** @file
LegacyRegion2 DXE driver - Reconstructed C source.
Manages PAM (Programmable Attribute Map) registers to control
read/write/execute permissions on the legacy VGA/BIOS memory region
(0xC0000 - 0xFFFFF). Installs the EFI_LEGACY_REGION2_PROTOCOL.
Source file: e:\hs\PurleyPlatPkg\Legacy\Dxe\LegacyRegion\LegacyRegion.c
PDB: LegacyRegion2.pdb
Build: VS2015 DEBUG, PurleyPlatPkg
Copyright (C) 2026 Contributors. All rights reserved.
**/
#include "LegacyRegion2.h"
//
// ---------------------------------------------------------------------------
// Global data
// ---------------------------------------------------------------------------
//
//
// PAM region descriptor table.
// 13 entries of 9 bytes each = 117 bytes.
// Located at .data offset 0x1050 (unk_1050).
//
LEGACY_REGION_DESCRIPTOR mRegionDescriptorTable[LEGACY_REGION_DESCRIPTOR_COUNT] = {
{ 0xF0000, 0x10000, 0 }, // 0xF0000 - 0xFFFFF (BIOS segment F, 64 KB)
{ 0xC0000, 0x4000, 1 }, // 0xC0000 - 0xC3FFF (VGA BIOS segment 0, 16 KB)
{ 0xC4000, 0x4000, 2 }, // 0xC4000 - 0xC7FFF
{ 0xC8000, 0x4000, 3 }, // 0xC8000 - 0xCBFFF
{ 0xCC000, 0x4000, 4 }, // 0xCC000 - 0xCFFFF
{ 0xD0000, 0x4000, 5 }, // 0xD0000 - 0xD3FFF
{ 0xD4000, 0x4000, 6 }, // 0xD4000 - 0xD7FFF
{ 0xD8000, 0x4000, 7 }, // 0xD8000 - 0xDBFFF
{ 0xDC000, 0x4000, 8 }, // 0xDC000 - 0xDFFFF
{ 0xE0000, 0x4000, 9 }, // 0xE0000 - 0xE3FFF
{ 0xE4000, 0x4000, 10 }, // 0xE4000 - 0xE7FFF
{ 0xE8000, 0x4000, 11 }, // 0xE8000 - 0xEBFFF
{ 0xEC000, 0x4000, 12 }, // 0xEC000 - 0xEFFFF
};
//
// Global variable definitions.
// These are initialised in ModuleEntryPoint via library constructor code
// linked from MdePkg UefiBootServicesTableLib / UefiRuntimeServicesTableLib.
//
EFI_HANDLE gImageHandle = NULL; // 0x10F0
EFI_SYSTEM_TABLE *gST = NULL; // 0x10E0
EFI_BOOT_SERVICES *gBS = NULL; // 0x10E8
EFI_RUNTIME_SERVICES *gRT = NULL; // 0x10F8
//
// Located protocols.
//
EFI_LEGACY_REGION_PROTOCOL *gLegacyRegion = NULL; // 0x1170 (qword_1170)
EFI_LEGACY_REGION2_PROTOCOL *gLegacyRegion2 = NULL; // 0x1168 (qword_1168)
//
// PAM capabilities bitmask read from gLegacyRegion2->PamCapabilities.
// Lower 4 bits indicate which PAM attribute slots are active.
//
UINT32 gPamCapabilities = 0; // 0x1160 (dword_1160)
//
// Cached HOB list pointer, initially NULL. Populated by GetHobList().
//
VOID *gHobList = NULL; // 0x1108 (qword_1108)
//
// Signature / sentinel value. 'INIT' in little-endian = 0x4E495449.
//
UINT32 gLegacyRegion2Signature = 0x4E495449; // 0x1120 (n1313293650)
//
// Saved ImageHandle for protocol installation.
//
EFI_HANDLE gImageHandleSaved = NULL; // 0x1158 (ImageHandle_0)
//
// Protocol handle for the installed LegacyRegion2 protocol.
//
EFI_HANDLE gLegacyRegion2ProtocolHandle = NULL; // 0x1128 (qword_1128)
//
// EFI_LEGACY_REGION2_PROTOCOL function table (installed as protocol interface).
//
// Individual function pointers populated in WheaSupportEntry().
//
EFI_LEGACY_REGION2_PROTOCOL gLegacyRegion2Protocol; // 0x1130-0x1158
// Function pointer slots used for initialising above protocol:
// psub_898 at 0x1130 -> LegacyRegion2Decode
// psub_8BC at 0x1138 -> LegacyRegion2Program
// psub_8BC_0 at 0x1140 -> LegacyRegion2ProgramLock
// psub_930 at 0x1148 -> LegacyRegion2GetMaxSize
// psub_588 at 0x1150 -> LegacyRegion2GetMaxSize (fallback/unused)
// ImageHandle_0 at 0x1158 -> gImageHandleSaved
//
// ---------------------------------------------------------------------------
// Library helper functions (linked from MdePkg BaseLib / DebugLib)
// ---------------------------------------------------------------------------
//
/**
ASSERT and debug-log macro helper (library wrapper).
Writes the status string via the debug library's assertion handler,
which performs CMOS-based platform type detection and routes to the
appropriate serial/console output.
@param Status Error status.
@param FormatString Format string.
@param ... Variable arguments.
**/
VOID
DebugAssertPrint (
IN UINTN Status,
IN CONST CHAR8 *FormatString,
...
)
{
//
// This function is a thin wrapper around the platform's debug print
// (DebugLib). It checks the CMOS register 0x4B to determine the
// platform type, reads I/O port 0x70/0x71 to get the status bits,
// then calls into the registered debug handler obtained via the HOB.
//
__debugbreak (); // Placeholder -- implementation is in DebugLib
}
/**
ASSERT macro helper.
Invokes the assertion call-out with the file/line/condition text.
@param FileName Source file name.
@param LineNumber Line number.
@param Condition Condition string.
**/
VOID
DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Condition
)
{
//
// Calls the registered assertion handler (via HOB callback).
// Placeholder -- implementation is in DebugLib.
//
__debugbreak ();
}
/**
Read an unaligned 64-bit value from memory.
@param Buffer Pointer to the 8-byte value.
@return The 64-bit value read.
**/
UINT64
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
if (Buffer == NULL) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c", 192,
"Buffer != ((void *) 0)"
);
}
return *(const UINT64 *)Buffer;
}
//
// ---------------------------------------------------------------------------
// HOB list lookup (replacement for DxeHobLib)
// ---------------------------------------------------------------------------
//
/**
Check if a Configuration Table entry GUID matches the HOB list GUID.
Compares the full 16 bytes of the entry's VendorGuid against the
HOB list GUID at 0x1040 ({7739F24C-93D7-11D4-9A3A-0090273FC14D}),
using two 8-byte unaligned reads.
@param ConfigEntry Pointer to the EFI_CONFIGURATION_TABLE entry.
@retval TRUE The entry's GUID matches the HOB list GUID.
@retval FALSE No match.
**/
BOOLEAN
EFIAPI
IsHobListConfigEntry (
IN VOID *ConfigEntry
)
{
EFI_CONFIGURATION_TABLE *Entry = (EFI_CONFIGURATION_TABLE *)ConfigEntry;
EFI_GUID HobListGuid = HOB_LIST_GUID;
//
// Compare first 8 bytes and last 8 bytes of the GUID separately
// via unaligned reads (ReadUnaligned64 from BaseLib).
//
return (ReadUnaligned64 (&Entry->VendorGuid) == ReadUnaligned64 (&HobListGuid)) &&
(ReadUnaligned64 (&Entry->VendorGuid.Data4) == ReadUnaligned64 (&HobListGuid.Data4));
}
/**
Get the HOB list pointer from the System Table Configuration Table.
Scans gST->ConfigurationTable for an entry whose VendorGuid matches
the HOB List GUID ({7739F24C-93D7-11D4-9A3A-0090273FC14D}) and
returns the associated VendorTable pointer (which is the HOB list).
@return Pointer to the HOB list, or NULL if not found.
**/
VOID *
GetHobList (
VOID
)
{
UINTN Index;
if (gHobList != NULL) {
return gHobList;
}
gHobList = NULL;
//
// Iterate over the Configuration Table.
// gST->ConfigurationTable is an array of EFI_CONFIGURATION_TABLE entries,
// each 24 bytes (16-byte GUID + 8-byte pointer).
//
if (gST->NumberOfTableEntries > 0) {
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (IsHobListConfigEntry (
(VOID *)&gST->ConfigurationTable[Index]
)) {
gHobList = gST->ConfigurationTable[Index].VendorTable;
break;
}
}
}
//
// If not found, ASSERT via the debug library.
//
if (gHobList == NULL) {
DebugAssertPrint (
0x80000000LL,
"\nASSERT_EFI_ERROR (Status = %r)\n",
0x800000000000000EuLL
);
DebugAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 54,
"!EFI_ERROR (Status)"
);
DebugAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 55,
"mHobList != ((void *) 0)"
);
}
return gHobList;
}
/**
Return a cached version of the DXE HOB list pointer.
@return The cached HOB list pointer.
**/
VOID *
GetHobListCache (
VOID
)
{
return GetHobList ();
}
//
// ---------------------------------------------------------------------------
// PAM (Programmable Attribute Map) register helpers
// ---------------------------------------------------------------------------
//
/**
Read a PAM attribute register for a given region index.
Accesses the chipset PAM I/O registers via the LegacyRegion protocol's
ReadPamRegister function (offset +8 in the protocol vtable).
@param RegionIndex Index of the region (0-3, up to 4 per PAM register).
@return The 32-bit PAM register value.
**/
UINT32
ReadPamAttribute (
IN UINT8 RegionIndex
)
{
return gLegacyRegion->ReadPamRegister (RegionIndex, 0, PAM_READ_PORT);
}
/**
Write a PAM attribute register for a given region index.
@param RegionIndex Index of the region.
@param Value The 32-bit PAM register value to write.
**/
VOID
WritePamAttribute (
IN UINT8 RegionIndex,
IN UINT32 Value
)
{
gLegacyRegion->WritePamRegister (RegionIndex, 0, PAM_WRITE_PORT, Value);
}
//
// ---------------------------------------------------------------------------
// EFI_LEGACY_REGION2_PROTOCOL implementation
// ---------------------------------------------------------------------------
//
/**
Decode a region of legacy memory.
Validates that the requested range [StartAddress, StartAddress+Length)
is entirely within 0xC0000-0xFFFFF.
@param This Protocol instance.
@param StartAddress Start of region.
@param Length Length of region.
@retval EFI_SUCCESS Range is valid.
@retval EFI_INVALID_PARAMETER Range extends outside legacy region.
**/
EFI_STATUS
EFIAPI
LegacyRegion2Decode (
IN EFI_LEGACY_REGION2_PROTOCOL *This,
IN UINT32 StartAddress,
IN UINT32 Length
)
{
if ((StartAddress < LEGACY_REGION_BASE) ||
(StartAddress + Length - 1 > LEGACY_REGION_TOP)) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
LegacyRegion2Program - Program legacy region for read/write decode.
Calls LegacyRegion2Decode for validation, then programs the PAM registers.
@param This Protocol instance.
@param StartAddress Start of region.
@param Length Length of region.
@param LegacyDecode TRUE = enable decode (read/write).
@param RealReadSignal TRUE = assert read signal.
@retval EFI_SUCCESS Region programmed.
@retval EFI_INVALID_PARAMETER Region outside 0xC0000-0xFFFFF.
**/
EFI_STATUS
EFIAPI
LegacyRegion2Program (
IN EFI_LEGACY_REGION2_PROTOCOL *This,
IN UINT32 StartAddress,
IN UINT32 Length,
IN BOOLEAN LegacyDecode,
IN BOOLEAN RealReadSignal
)
{
EFI_STATUS Status;
Status = LegacyRegion2Decode (This, StartAddress, Length);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check platform write-disable policy via LegacyRegion2 protocol.
// If the platform has the write-lock active (Capabilities bit 0),
// force write-enable (RealReadSignal = 1).
//
// The original assembly checks:
// *(gLegacyRegion2->... + 0x06F4) byte != 0 -> write locked
// *(gLegacyRegion2->... + 0x06F1) byte >= 3 -> SMM version >= 3
//
if (RealReadSignal) {
if (*(UINT8 *)((UINTN)gLegacyRegion2 + 0x06F4) != 0 ||
*(UINT8 *)((UINTN)gLegacyRegion2 + 0x06F1) >= 3) {
RealReadSignal = 1;
}
}
return ProgramPamRegisters (
StartAddress,
Length,
LegacyDecode ? 1 : 0,
RealReadSignal ? 1 : 0,
NULL
);
}
/**
LegacyRegion2ProgramLock - Program with full locking semantics.
Forces LegacyDecode=2 (override) and uses RealReadSignal policy from
the LegacyRegion2 protocol's internal state.
@param This Protocol instance.
@param StartAddress Start of region.
@param Length Length of region.
@param LegacyDecode TRUE = enable decode.
@param RealReadSignal TRUE = assert read signal.
@retval EFI_SUCCESS Region programmed.
@retval EFI_INVALID_PARAMETER Region outside 0xC0000-0xFFFFF.
**/
EFI_STATUS
EFIAPI
LegacyRegion2ProgramLock (
IN EFI_LEGACY_REGION2_PROTOCOL *This,
IN UINT32 StartAddress,
IN UINT32 Length,
IN BOOLEAN LegacyDecode,
IN BOOLEAN RealReadSignal
)
{
EFI_STATUS Status;
Status = LegacyRegion2Decode (This, StartAddress, Length);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check platform write-disable via LegacyRegion2 protocol internal state.
//
if (RealReadSignal) {
if (*(UINT8 *)((UINTN)gLegacyRegion2 + 0x06F4) != 0 ||
*(UINT8 *)((UINTN)gLegacyRegion2 + 0x06F1) >= 3) {
RealReadSignal = 1;
}
}
//
// LegacyDecode=2 signals "override" in the PAM programming core.
//
return ProgramPamRegisters (
StartAddress,
Length,
2,
RealReadSignal ? 1 : 0,
NULL
);
}
/**
LegacyRegion2GetMaxSize - Return maximum decode size.
@param This Protocol instance.
@param MaxSize Receives the maximum size.
@retval EFI_SUCCESS MaxSize was set.
**/
EFI_STATUS
EFIAPI
LegacyRegion2GetMaxSize (
IN EFI_LEGACY_REGION2_PROTOCOL *This,
OUT UINT32 *MaxSize
)
{
*MaxSize = 0;
return EFI_SUCCESS;
}
//
// ---------------------------------------------------------------------------
// PAM register programming core
// ---------------------------------------------------------------------------
//
/**
Program PAM registers for the given range.
Iterates over all 13 entries in mRegionDescriptorTable and for every
entry that overlaps the requested [StartAddress, StartAddress+Length)
range:
- Determines the region's PAM attribute bit position (based on Type).
- Reads the current 32-bit PAM register value via LegacyRegion protocol.
- Modifies the 2-bit attribute field (read-enable, write-enable).
- Writes the updated register value back.
@param StartAddress Start of the range.
@param Length Length of the range.
@param LegacyDecode 0=read-only, 1=enable, 2=override (force enable).
@param RealReadSignal 0=force read-only (on overlap), 1=assert writes.
@param MaxSize Optional: receives the largest region size encountered.
@retval EFI_SUCCESS Always returned.
**/
EFI_STATUS
ProgramPamRegisters (
IN UINT32 StartAddress,
IN UINT32 Length,
IN UINT32 LegacyDecode,
IN UINT32 RealReadSignal,
OUT UINT32 *MaxSize OPTIONAL
)
{
UINT32 MaxRegionSize;
UINTN Index;
UINT8 RegionIndex;
UINT32 RequestEnd;
MaxRegionSize = 0;
RequestEnd = StartAddress + Length;
//
// Iterate over all 13 region descriptors.
//
for (Index = 0; Index < LEGACY_REGION_DESCRIPTOR_COUNT; Index++) {
LEGACY_REGION_DESCRIPTOR *Region = &mRegionDescriptorTable[Index];
UINT32 RegionBase = Region->Base;
UINT32 RegionLength = Region->Length;
UINT32 RegionType = Region->Type;
UINT32 RegionEnd = RegionBase + RegionLength;
UINT32 ReadValue;
UINT32 WriteValue;
UINT32 Attr;
BOOLEAN Overlap;
//
// Check for overlap between request and this region.
//
Overlap = (StartAddress < RegionEnd && RequestEnd > RegionBase);
if (!Overlap) {
continue;
}
//
// Track the largest region size for the optional MaxSize output.
//
if (RegionLength > MaxRegionSize) {
MaxRegionSize = RegionLength;
}
//
// Find the first active PAM attribute slot from the capabilities mask.
// gPamCapabilities lower 4 bits indicate which of the 4 slots per
// PAM register are active for this platform.
//
for (RegionIndex = 0; RegionIndex < 4; RegionIndex++) {
if ((gPamCapabilities >> RegionIndex) & 1) {
break;
}
}
//
// Read current PAM register values.
// Two reads: the "read port" register and the "write port" register.
// For types 0-6, attributes are in ReadValue; for types 7-12, in WriteValue.
//
ReadValue = ReadPamAttribute (RegionIndex);
WriteValue = ReadPamAttribute (RegionIndex);
//
// Extract the 2-bit attribute field based on region type.
// PAM registers pack 4 x 2-bit attributes into a 32-bit value.
// Type determines which 2-bit slot:
// Types 0-6: 8 bits per slot (bits 4-5 for type 0, 8-9 for type 1, ...)
// Types 7-12: same layout but in WriteValue (bits 0-1 for type 7, ...)
//
if (RegionType <= 6) {
//
// Attributes are in the low PAM register (ReadValue).
//
switch (RegionType) {
case 0: Attr = (ReadValue >> 4) & 3; break;
case 1: Attr = (ReadValue >> 8) & 3; break;
case 2: Attr = (ReadValue >> 12) & 3; break;
case 3: Attr = (ReadValue >> 16) & 3; break;
case 4: Attr = (ReadValue >> 20) & 3; break;
case 5: Attr = (ReadValue >> 24) & 3; break;
case 6: Attr = (ReadValue >> 28) & 3; break;
default: Attr = 0; break;
}
} else {
//
// Attributes are in the high PAM register (WriteValue).
//
switch (RegionType) {
case 7: Attr = WriteValue & 3; break;
case 8: Attr = (WriteValue >> 4) & 3; break;
case 9: Attr = (WriteValue >> 8) & 3; break;
case 10: Attr = (WriteValue >> 12) & 3; break;
case 11: Attr = (WriteValue >> 16) & 3; break;
case 12: Attr = (WriteValue >> 20) & 3; break;
default: Attr = 0; break;
}
}
//
// Modify the attribute bits.
// If LegacyDecode == 1: set bit 0 (read enable).
// If RealReadSignal == 1: set bit 1 (write enable).
// If RealReadSignal == 0 and overlap: clear bit 1.
//
if (LegacyDecode == 1) {
Attr |= 1;
}
if (RealReadSignal == 1) {
Attr |= 2;
} else if (Overlap) {
Attr &= ~2;
}
//
// Write the modified PAM register values back.
// For types 0-6: modify ReadValue.
// For types 7-12: modify WriteValue, then XOR attrs between
// the two registers (the LegacyRegion2 protocol expects the
// attribute bits to be toggled across both registers).
//
if (RegionType <= 6) {
//
// Apply to the low PAM register (ReadValue).
//
switch (RegionType) {
case 0: ReadValue = (ReadValue & ~0x30) | (Attr << 4); break;
case 1: ReadValue = (ReadValue & ~0x300) | (Attr << 8); break;
case 2: ReadValue = (ReadValue & ~0x3000) | (Attr << 12); break;
case 3: ReadValue = (ReadValue & ~0x30000) | (Attr << 16); break;
case 4: ReadValue = (ReadValue & ~0x300000) | (Attr << 20); break;
case 5: ReadValue = (ReadValue & ~0x3000000) | (Attr << 24); break;
case 6: ReadValue = (ReadValue & ~0x30000000) | (Attr << 28); break;
}
//
// Perform two writes: the PAM controller expects separate
// writes to the read-port and write-port registers.
//
WritePamAttribute (RegionIndex, ReadValue);
WritePamAttribute (RegionIndex, WriteValue);
} else {
//
// Apply to the high PAM register (WriteValue).
//
switch (RegionType) {
case 7: WriteValue = (WriteValue & ~3) | (Attr & 3); break;
case 8: WriteValue = (WriteValue & ~0x30) | ((Attr & 3) << 4); break;
case 9: WriteValue = (WriteValue & ~0x300) | ((Attr & 3) << 8); break;
case 10: WriteValue = (WriteValue & ~0x3000) | ((Attr & 3) << 12); break;
case 11: WriteValue = (WriteValue & ~0x30000) | ((Attr & 3) << 16); break;
case 12: WriteValue = (WriteValue & ~0x300000) | ((Attr & 3) << 20); break;
}
//
// XOR the attribute bits into ReadValue to synchronise both PAM registers.
//
ReadValue ^= (WriteValue & 0x300) ? 2 : 0;
WritePamAttribute (RegionIndex, ReadValue);
WritePamAttribute (RegionIndex, WriteValue);
}
}
if (MaxSize != NULL) {
*MaxSize = MaxRegionSize;
}
return EFI_SUCCESS;
}
//
// ---------------------------------------------------------------------------
// Entry Point
// ---------------------------------------------------------------------------
//
/**
Entry point for the LegacyRegion2 DXE driver.
Saves ImageHandle and SystemTable to globals (for library consumption),
initialises the HOB cache, and calls WheaSupportEntry.
@param ImageHandle The firmware-allocated handle for this image.
@param SystemTable The EFI system table.
@retval EFI_SUCCESS The driver initialised successfully.
@retval Others An error occurred.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Save globals for library use (UefiBootServicesTableLib /
// UefiRuntimeServicesTableLib constructors).
//
gImageHandle = ImageHandle;
gST = SystemTable;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
//
// Initialise the HOB list cache.
//
GetHobList ();
//
// Call the main driver initialisation.
//
return WheaSupportEntry (ImageHandle);
}
//
// ---------------------------------------------------------------------------
// Driver Initialisation
// ---------------------------------------------------------------------------
//
/**
Main driver initialisation routine (WheaSupportEntry style).
Locates the EFI_LEGACY_REGION_PROTOCOL and EFI_LEGACY_REGION2_PROTOCOL,
reads PAM capabilities, populates the LegacyRegion2 protocol function
table, and installs it on a new protocol handle.
@param ImageHandle The image handle.
@retval EFI_SUCCESS Protocol installed successfully.
@retval Others An error occurred locating protocols or installing.
**/
EFI_STATUS
WheaSupportEntry (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
//
// Save ImageHandle for the protocol installation.
//
gImageHandleSaved = ImageHandle;
//
// Locate the EFI_LEGACY_REGION_PROTOCOL (provided by CSM / platform driver).
//
Status = gBS->LocateProtocol (
&gEfiLegacyRegionProtocolGuid,
NULL,
(VOID **)&gLegacyRegion
);
if (EFI_ERROR (Status)) {
DebugAssertPrint (
0x80000000LL,
"\nASSERT_EFI_ERROR (Status = %r)\n",
Status
);
DebugAssert (
"e:\\hs\\PurleyPlatPkg\\Legacy\\Dxe\\LegacyRegion\\LegacyRegion.c",
573,
"!EFI_ERROR (Status)"
);
}
//
// Locate the EFI_LEGACY_REGION2_PROTOCOL (provided by SMM / other).
//
Status = gBS->LocateProtocol (
&gEfiLegacyRegion2ProtocolGuid,
NULL,
(VOID **)&gLegacyRegion2
);
if (EFI_ERROR (Status)) {
DebugAssertPrint (
0x80000000LL,
"\nASSERT_EFI_ERROR (Status = %r)\n",
Status
);
DebugAssert (
"e:\\hs\\PurleyPlatPkg\\Legacy\\Dxe\\LegacyRegion\\LegacyRegion.c",
575,
"!EFI_ERROR (Status)"
);
}
//
// Read the PAM capabilities from the LegacyRegion2 protocol.
//
gPamCapabilities = gLegacyRegion2->PamCapabilities;
gLegacyRegion2Signature = 0x4E495449; // 'INIT'
//
// Build the LegacyRegion2 protocol function table.
//
gLegacyRegion2Protocol.Decode = LegacyRegion2Decode;
gLegacyRegion2Protocol.Program = LegacyRegion2Program;
gLegacyRegion2Protocol.ProgramLock = LegacyRegion2ProgramLock;
gLegacyRegion2Protocol.GetMaxSize = LegacyRegion2GetMaxSize;
gLegacyRegion2Protocol.RegionCapabilities = gPamCapabilities;
//
// Install the protocol on a new handle.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&gLegacyRegion2ProtocolHandle,
&gEfiLegacyRegion2ProtocolGuid,
&gLegacyRegion2Protocol,
NULL
);
if (EFI_ERROR (Status)) {
DebugAssertPrint (
0x80000000LL,
"\nASSERT_EFI_ERROR (Status = %r)\n",
Status
);
DebugAssert (
"e:\\hs\\PurleyPlatPkg\\Legacy\\Dxe\\LegacyRegion\\LegacyRegion.c",
597,
"!EFI_ERROR (Status)"
);
}
return EFI_SUCCESS;
}