/**
* MemRas.c - Memory RAS (Reliability, Availability, Serviceability) Driver
* PurleySktPkg/Dxe/MemRas/MemRas
*
* Entry point and protocol installation for the Purley platform memory RAS
* subsystem. This driver handles memory error correction, sparing,
* address translation, patrol scrubbing, and S3 boot script save/restore.
*
* ============================================================================
* Initialization Sequence
* ============================================================================
*
* ModuleEntryPoint() [0x5CC]
* |
* +-> MemRasInitGlobals() [sub_AF90, 0xAF90]
* | Allocates global context, calls ~23 sub-initializers in sequence
* |
* +-> MemRasDriverEntry() [sub_B724, 0xB724]
* | Allocates protocol structures, populates function table,
* | reads platform config, installs protocol, registers events
* | Calls: sub_10E20() (S3 save events) + sub_17BCC() (VLS init)
* |
* +-> MemRasSecondaryInit() [sub_B6AC, 0xB6AC]
* Calls sub_B724() if context not already initialized
* Sets global status to 0x8000000000000001 if failed
*
* On failure (entry point):
* +-> MemRasFallbackInit() [0xB56C]
* Calls sub_39BC() + sub_2290() + sub_1220()
*
* ============================================================================
* Memory Layout
* ============================================================================
*
* All allocations use BootServices->AllocatePool (PoolType=6=EfiBootServicesData):
* 1. Context structure: 24 bytes (qword_CD8B0)
* 2. Protocol structure: 568 bytes (qword_27818)
* 3. Socket config buffer: 32768 bytes (qword_CD740) in .data
* 4. Scratch/work buffer: 25037 bytes (allocated at runtime)
* 5. Error log buffer: 1643 bytes (qword_CD748)
*
* ============================================================================
* Protocol Function Table (at qword_27818, populated at offsets 160-424)
* ============================================================================
*
* Offset Function Description
* ------ ----------- -----------------------------------------------
* 0x0A0 sub_DB54 Init - per-socket initialization
* 0x0A8 sub_1430 Init2 - stub (returns success)
* 0x0B0 sub_1A4CC SpareRank - start sparing on rank
* 0x0B8 sub_19DA4 Alternate spare rank path
* 0x0C0 sub_1A610 SpareCopy - handle spare copy done
* 0x0E0 sub_CCC4 GetFailedDimmErrorInfo
* 0x108 sub_1B1D0 CheckAndHandleNewRankSparingEvent
* 0x110 sub_F800 HandlePatrolCompleteEventForNode
* 0x118 sub_F694 HandleSpareRankUCEvent
* 0x120 sub_1BB28 SpareCopyDone handler
* 0x130 sub_E730 S3BootScriptSave
* 0x138 sub_1AB5C Compare GUID / HOB lookup
* 0x140 sub_1B6AC Check rank state
* 0x148 sub_C47C ForEachChannel - iterate channels
* 0x150 sub_CA34 Check rank state per MC
* 0x158 sub_CA28 Check rank state per channel (stub)
* 0x160 sub_DAA4 GetSystemAddress (channel addr -> sys addr)
* 0x168 sub_C39C GetChannelAddress (rank addr -> channel addr)
* 0x170 sub_D6C0 Address translation
* 0x178 sub_DC34 GetRankAddress
* 0x180 sub_DE7C ReverseAddressTranslate
* 0x0F0 sub_15010 DisableMemoryMigration
* 0x0F8 sub_122A8 SetupMemoryMigration
* 0x190 sub_D9E8 TranslateRIR (Rank Interleave Registers)
* 0x198 sub_F4B4 GetErrorLogSysAddr
* 0x0E8 sub_1430 StubInit (same as Init2)
* 0x0C8 sub_DBFC ForwardAddrTranslate
* 0x0D0 sub_E060 McChToLogChId (MC channel to logical channel)
* 0x0D8 sub_C570 TadId2SadId (TAD to SAD index translation)
* 0x100 sub_DA6C GetDDRTSystemAddress
* 0x188 sub_CD04 ForEachSocket - iterate sockets
* 0x1A0 sub_D758 TranslateSAD (System Address Decoder)
* 0x1A8 sub_CD44 TranslateDDRTTad (DDRT TAD translation)
*
* ============================================================================
* Address Translation Pipeline
* ============================================================================
*
* Forward (System Address -> Physical):
* 1. TranslateSAD (sub_D758) - System Address Decoder routing
* SAD maps system address -> socket/MC/channel via interleave rules
* 2. TadId2SadId (sub_C570) - Find SAD entry from TAD index
* 3. TranslateTAD (in sub_D6C0) - Target Address Decoder
* TAD provides per-channel offset/limit translations
* 4. GetChannelAddress (sub_C39C) - Channel address calculation
* 5. TranslateRIR (sub_D9E8) - Rank Interleave Register
* RIR maps channel address -> physical rank via interleave registers
* 6. ADDDCSupportForAddrTrans - ADDDC lockstep rank handling
* 7. RankSpareSupportForAddrTrans - Rank spare mapping
* 8. TranslateRankAddress - Row/Column/Bank/BankGroup extraction
* 9. TranslateDDRTTad (sub_CD44) - DDRT-specific translation (2LM/PMEM)
*
* Reverse (Physical -> System Address):
* 1. ReverseAddressTranslate (sub_DE7C)
* 2. GetDDRTSystemAddress (sub_DA6C) - DDRT-specific reverse
* 3. GetSystemAddress (sub_DAA4) - channel addr -> system addr
*
* ============================================================================
* Error Handling / Sparing State Machine
* ============================================================================
*
* Global bitmaps (dword_23680, dword_23684):
* - mEventProgressBitmap[dword_23680]: Bit per NodeId, set when error
* handling is in progress
* - mEventPendingBitmap[dword_23684]: Bit per NodeId, set when error
* handling is pending (deferred)
*
* Rank states (per rank state machine):
* available -> scrubbing -> do_spare_copying -> spare_copy_done -> try_do_tag
*
* ============================================================================
* Key Global Variables (.data section, 0x22AC0-0xEE920)
* ============================================================================
*
* qword_23658 (0x23658): RAS status code
* dword_23680 (0x23680): mEventProgressBitmap
* dword_23684 (0x23684): mEventPendingBitmap
* word_2367C (0x2367C): Error threshold
* qword_23670 (0x23670): Scratch buffer pointer
* byte_63AEC (0x63AEC): Platform config byte 1
* byte_65ED2 (0x65ED2): Platform config byte 2
* dword_63B24 (0x63B24): Platform config (number of sockets)
* dword_63C4C (0x63C4C): Platform config (memory base address)
* qword_26650 (0x26650): S3 save context
* qword_27828 (0x27828): System memory size
* qword_27830 (0x27830): Memory type / node info
* qword_27838 (0x27838): Number of sockets config
* qword_27840 (0x27840): Number of channels config
* qword_27848 (0x27848): Memory range end
* qword_27850 (0x27850): Memory range start
* byte_27858 (0x27858): Channel mode (lockstep/non-lockstep)
*/
// Include auto-generated UEFI header from AutoGen.c
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
// Protocol GUIDs (referenced in .rdata section as unk_22B*)
// unk_22BB0: gEfiMemRasProtocolGuid - Memory RAS protocol
// unk_22B20: Platform RAS policy protocol
// unk_22B40: CPU CSR access protocol
// unk_22B90: Additional platform protocol
// unk_22BA0: Additional platform protocol
// unk_22B30: Protocol interface GUID for InstallProtocolInterface
// unk_22B60: Event protocol for S3 boot script
// unk_22B80: SMM communication protocol
// unk_22BC0: Variable access protocol
#include "MemRas.h"
//
// ============================================================================
// Module-Level Global Variables
// ============================================================================
//
// These are populated from HOBs and platform policy protocols at init time.
//
// Configuration read from HOB at offset 1677
UINT8 ChannelMode; // byte_27858 - 0=non-lockstep, 1=lockstep
// Configuration from platform policy protocol
UINT8 VlsEnabled; // byte_63AEC
UINT8 SpareMode; // byte_65ED2
UINT32 NumSockets; // dword_63B24
UINT32 MemoryBase; // dword_63C4C
// Memory configuration from HOB
UINT64 MemoryRangeStart; // qword_27850
UINT64 MemoryRangeEnd; // qword_27848
UINT32 SystemMemorySize; // qword_27840
UINT32 NumChannels; // qword_27838
UINT32 MemoryType; // qword_27830
UINT32 MemoryGranularity; // qword_27828
//
// ============================================================================
// _ModuleEntryPoint [0x5CC]
// ============================================================================
//
// UEFI DXE driver entry point. Called by DXE dispatcher.
//
// Flow:
// 1. MemRasInitGlobals() - Allocate and initialize global state
// 2. MemRasDriverEntry() - Protocol installation (primary path)
// 3. On failure, MemRasFallbackInit() tries secondary path
//
EFI_STATUS
EFIAPI
ModuleEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Phase 1: Allocate and initialize global context.
// Allocates socket configuration buffer, protocol structure,
// scratch buffers, and error log buffer.
//
MemRasInitGlobals();
//
// Phase 2: Primary driver entry - allocate protocol, populate
// function table, read platform config from HOB and policy protocols,
// install protocol interface, register S3 save events,
// initialize VLS (Virtual Lockstep) info.
//
Status = MemRasDriverEntry(ImageHandle, SystemTable);
if (EFI_ERROR(Status)) {
//
// Phase 3 (fallback): On failure, attempt secondary initialization.
// Calls memory initialization, event registration, S3 boot script.
//
Status = MemRasFallbackInit(ImageHandle, SystemTable);
}
return Status;
}
//
// ============================================================================
// MemRasInitGlobals() [sub_AF90, 0xAF90]
// ============================================================================
//
// Called first from ModuleEntryPoint. Allocates and initializes all
// module-level buffers and structures.
//
// Init sequence (23 sub-initializers):
// 1. sub_6BC - Global lock/state initialization
// 2. sub_758 - BaseLib setjmp/longjmp context init
// 3. sub_794 - UEFI boot/runtime service table init
// 4. sub_10AC - Driver binding/entry point library init
// 5. sub_1430 - [stub] returns success
// 6. sub_163C - Memory allocation library init
// 7. sub_1928 - HOB list library init
// 8. sub_1AB8 - PCI Express library init
// 9. sub_1BC8 - [stub] returns success
// 10. sub_1C7C - SMM LockBox / S3 boot script library init
// 11. sub_1FB4 - Timer library init
// 12. sub_20CC - ACPI timer lib / decompress lib / services table
// 13. sub_35D4 - EMCA platform hooks / MP sync data lib init
// 14. sub_43A0 - [stub] returns success
// 15. sub_51A8 - SMM communication / variable protocol init
// 16. sub_552C - IPMI / error reporting library init
// 17. sub_5FB4 - OemRasLib init
// 18. sub_6C00 - Platform-specific RAS init
//
EFI_STATUS
MemRasInitGlobals(
VOID
)
{
//
// Each sub-initializer is a library constructor from the
// linked static libraries. They are called sequentially.
// On debug builds, each failure triggers ASSERT via
// _ASSERT(!EFI_ERROR(Status)) pattern.
//
// The pattern for each call is:
//
// Status = LibraryConstructor();
// ASSERT_EFI_ERROR(Status);
//
// Phase 1: Core library initialization
// 0x6BC - BaseLib / lock init
// 0x758 - UefiBootServicesTableLib constructor
// 0x794 - UefiRuntimeServicesTableLib constructor
//
// Phase 2: Driver support libraries
// 0x10AC - UefiDriverEntryPoint / UefiLib constructors
// 0x1430 - [stub, returns success]
// 0x163C - Memory allocation library
// 0x1928 - HOB library (mHobList initialization)
// 0x1AB8 - SmmMmPciBaseLib constructor
// 0x1BC8 - [stub, returns success]
// 0x1C7C - S3BootScriptLib / SmmLockBoxSmmLib constructor
// 0x1FB4 - AcpiTimerLib constructor
// 0x20CC - DxeServicesTableLib + TianoCustomDecompressLib
//
// Phase 3: Platform-specific RAS libraries
// 0x35D4 - mpsyncdatalib + emcaplatformhookslib init
// 0x43A0 - [stub, returns success]
// 0x51A8 - SmmLnvSendIpmiCmdLib / SmmVariable protocol
// 0x552C - AmiErrReportingLib init
// 0x5FB4 - OemRasLib init
// 0x6C00 - Platform-specific RAS init
//
return EFI_SUCCESS;
}
//
// ============================================================================
// MemRasDriverEntry() [sub_B724, 0xB724]
// ============================================================================
//
// Core driver entry. Allocates protocol structure, reads HOB data,
// populates function pointer table, installs protocol interface,
// and sets up event handlers.
//
EFI_STATUS
EFIAPI
MemRasDriverEntry(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
MEM_RAS_PROTOCOL *Protocol;
VOID *ContextBuffer;
VOID *PlatformPolicy;
VOID *CpuCsrAccess;
VOID *PlatformProtocol;
UINT8 *HobData;
//
// Step 1: Allocate context structure (24 bytes) and zero it.
// qword_CD8B0 -> ContextBuffer (sizeof=24)
//
Status = gBS->AllocatePool(EfiBootServicesData, 24, &ContextBuffer);
ASSERT_EFI_ERROR(Status);
ZeroMem(ContextBuffer, 24);
//
// Step 2: Allocate protocol structure (568 bytes) and zero it.
// qword_27818 -> Protocol (MEM_RAS_PROTOCOL)
//
Status = gBS->AllocatePool(EfiBootServicesData, 568, &Protocol);
ASSERT_EFI_ERROR(Status);
ZeroMem(Protocol, 568);
// Link protocol to context
*(MEM_RAS_PROTOCOL **)((UINT8 *)ContextBuffer + 16) = Protocol;
//
// Step 3: Allocate socket configuration buffer (32768 bytes).
// qword_CD740 -> SocketConfig
// Stored in .data section (global variable)
//
Status = gBS->AllocatePool(EfiBootServicesData, 0x8000, &gSocketConfig);
ASSERT_EFI_ERROR(Status);
ZeroMem(gSocketConfig, 0x8000);
// Initialize scratch buffer tracking
gScratchBuffer = gSocketConfig + 32760;
//
// Step 4: Allocate scratch buffer (25037 bytes).
// First 8 bytes of protocol structure stores pointer to this.
//
Status = gBS->AllocatePool(EfiBootServicesData, 25037, &Protocol[0]);
ASSERT_EFI_ERROR(Status);
ZeroMem(Protocol, 25037);
//
// Step 5: Allocate error log buffer (1643 bytes).
// qword_CD748 -> gErrorLogBuffer
//
Status = gBS->AllocatePool(EfiBootServicesData, 1643, &gErrorLogBuffer);
ASSERT_EFI_ERROR(Status);
ZeroMem(gErrorLogBuffer, 1643);
//
// Step 6: Locate PlatformRasPolicy protocol (unk_22BB0).
// This provides platform RAS configuration data.
//
Status = gBS->LocateProtocol(&gPlatformRasPolicyGuid, NULL, &PlatformPolicy);
ASSERT_EFI_ERROR(Status);
//
// Step 7: Initialize protocol signature.
// Initial: 0x12345678 (temporary)
// Final: 0x4D495053 ("MIPS")
//
*(UINT32 *)ContextBuffer = 0x12345678;
MemRasSocketInit(Protocol);
*(UINT32 *)ContextBuffer = 0x4D495053;
*(MEM_RAS_PROTOCOL **)ContextBuffer = &gProtocolContext;
//
// Step 8: Populate function pointer table.
// All function pointers are installed at their respective
// offsets within the protocol structure.
//
Protocol->Init = sub_DB54;
Protocol->Init2 = sub_1430; // stub
Protocol->SpareRank = sub_1A4CC;
Protocol->SpareRank2 = sub_19DA4;
Protocol->SpareCopy = sub_1A610;
Protocol->GetFailedDimmErrorInfo = sub_CCC4;
Protocol->CheckAndHandleNewRankSparingEvent = sub_1B1D0;
Protocol->HandlePatrolCompleteEventForNode = sub_F800;
Protocol->HandleSpareRankUCEvent = sub_F694;
Protocol->SpareCopyDone = sub_1BB28;
Protocol->S3BootScriptSave = sub_E730;
Protocol->CompareGuidOrSimilar = sub_1AB5C;
Protocol->CheckRankState = sub_1B6AC;
Protocol->ForEachChannel = sub_C47C;
Protocol->CheckRankStatePerMC = sub_CA34;
Protocol->CheckRankStatePerCh = sub_CA28;
Protocol->GetSystemAddress = sub_DAA4;
Protocol->GetChannelAddress = sub_C39C;
Protocol->AddressTranslation = sub_D6C0;
Protocol->GetRankAddress = sub_DC34;
Protocol->ReverseAddressTranslate = sub_DE7C;
Protocol->DisableMemoryMigration = sub_15010;
Protocol->SetupMemoryMigration = sub_122A8;
Protocol->TranslateRIR = sub_D9E8;
Protocol->GetErrorLogSysAddr = sub_F4B4;
Protocol->StubInit = sub_1430; // stub
Protocol->ForwardAddrTranslate = sub_DBFC;
Protocol->McChToLogChId = sub_E060;
Protocol->TadId2SadId = sub_C570;
Protocol->GetDDRTSystemAddress = sub_DA6C;
Protocol->ForEachSocket = sub_CD04;
Protocol->TranslateSAD = sub_D758;
Protocol->TranslateDDRTTad = sub_CD44;
//
// Step 9: Locate platform RAS policy protocol (unk_22B20).
// Returns the HOB list pointer with system configuration.
//
Status = gBS->LocateProtocol(&gPlatformRasHobGuid, NULL, (VOID **)&PlatformPolicy);
ASSERT_EFI_ERROR(Status);
//
// Step 10: Locate CPU CSR access and additional protocol.
//
Status = gBS->LocateProtocol(&gCpuCsrAccessGuid, NULL, (VOID **)&CpuCsrAccess);
ASSERT_EFI_ERROR(Status);
Status = gBS->LocateProtocol(&gPlatformProtocolGuid, NULL, &PlatformProtocol);
ASSERT_EFI_ERROR(Status);
//
// Step 11: Read platform configuration from policy protocol.
// Offset 1677: Channel mode (lockstep bit)
// Offset 1780: VLS enable flag
// Offset 1782: Spare mode
// Offset 1777: RAS mode (0=SDDC, 1=ADDDC, etc.)
// Offset 2067: Number of sockets
// Offset 280: Memory base address / range
// Offset 4: System memory size
// Offset 8: Number of channels
// Offset 12: Memory type
// Offset 20: Memory granularity
//
HobData = (UINT8 *)*(UINTN *)PlatformPolicy;
ChannelMode = HobData[1677];
VlsEnabled = HobData[1780];
SpareMode = HobData[1782];
NumSockets = *(UINT32 *)(HobData + 2067);
MemoryBase = *(UINT32 *)(HobData + 280);
MemoryRangeStart = *(UINT64 *)(HobData + 280);
MemoryRangeEnd = MemoryRangeStart + *(UINT32 *)(HobData + 288);
SystemMemorySize = *(UINT32 *)(HobData + 4);
NumChannels = *(UINT32 *)(HobData + 8);
MemoryType = *(UINT32 *)(HobData + 12);
MemoryGranularity = *(UINT32 *)(HobData + 20);
//
// Step 12: Initialize 4 socket entries in scratch buffer.
// Sets byte at offset 1606 to 1 for each socket.
//
for (UINT32 Socket = 0; Socket < 4; Socket++) {
HobData[1606 + 119 * Socket] = 1;
}
//
// Step 13: Install MemRas protocol interface.
// GUID: gEfiMemRasProtocolGuid (unk_22B30)
// Context data: Protocol structure (MEM_RAS_PROTOCOL *)
//
*(UINT64 *)((UINT8 *)ContextBuffer + 8) = 0; // Protocol handle init
Status = gBS->InstallProtocolInterface(
(EFI_HANDLE *)((UINT8 *)ContextBuffer + 8),
&gEfiMemRasProtocolGuid,
EFI_NATIVE_INTERFACE,
ContextBuffer + 16 // points to MEM_RAS_PROTOCOL *
);
ASSERT_EFI_ERROR(Status);
gMemRasProtocolHandle = *(EFI_HANDLE *)((UINT8 *)ContextBuffer + 8);
//
// Step 14: Register S3 boot script save handler.
// sub_10E20() - Allocates context, sets event type=3,
// registers sub_10F38 as callback for gEfiEventReadyToBootGuid,
// installs protocol for gEfiMemRasS3SaveProtocolGuid.
//
MemRasS3SaveRegister();
//
// Step 15: Initialize VLS (Virtual Lockstep) state.
// sub_17BCC() - Sets VLS variable "VLSEstablished" to known GUID.
// If variable doesn't exist, creates it. Locates VariableArchProtocol
// and reads back "VLSEstablished" to verify.
//
InitializeVLSInfo();
//
// Step 16: Initialize spare copy done handler.
// sub_1BB28()
//
Protocol->SpareCopyDone();
//
// Step 17: Initialize rank sparing event handler.
// sub_1B1D0()
//
Protocol->CheckAndHandleNewRankSparingEvent();
//
// Step 18: Conditionally initialize patrol scrub.
// If NumSockets >= 3 or NumSockets <= 1, start patrol scrub.
// sub_F800()
//
if (NumSockets >= 3 || NumSockets <= 1) {
Protocol->HandlePatrolCompleteEventForNode();
}
//
// Step 19: Initialize alternate spare rank path.
// sub_1A47C()
//
sub_1A47C();
//
// Step 20: Register per-socket MCE events (if configured).
// If platform config byte (offset 35) has bits 2 and 4 set,
// register sub_1A0D4 as callback for event groups at
// unk_22C40 and unk_22C50.
//
if ((HobData[35] & 0x14) == 0x14) {
gBS->CreateEventEx(
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
sub_1A0D4,
NULL,
&gEventGroupGuid1,
&Event1
);
gBS->CreateEventEx(
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
sub_1A0D4,
NULL,
&gEventGroupGuid2,
&Event2
);
}
return EFI_SUCCESS;
}
//
// ============================================================================
// MemRasSecondaryInit() [sub_B6AC, 0xB6AC]
// ============================================================================
//
// Called from ModuleEntryPoint when MemRasInitGlobals() succeeds.
// If unk_23560 context is valid, calls MemRasDriverEntry().
// Otherwise sets global status to indicate failure.
//
EFI_STATUS
EFIAPI
MemRasSecondaryInit(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Global status initialized to error (0x8000000000000001)
//
gRasStatus = 0x8000000000000001uLL;
//
// Check if context (unk_23560) has setjmp/longjmp already set up.
// sub_2C0() performs a setjmp(context) - returns 0 on success.
//
if (!sub_2C0(&unk_23560)) {
//
// Context was not initialized, so this is first entry.
// Call the full driver entry.
//
EFI_STATUS Status;
Status = MemRasDriverEntry(ImageHandle, SystemTable);
MemRasStatusUpdate(Status);
//
// Should never reach here - ASSERT failure.
//
ASSERT(FALSE);
}
return gRasStatus;
}
//
// ============================================================================
// MemRasFallbackInit() [sub_B56C, 0xB56C]
// ============================================================================
//
// Called when MemRasDriverEntry() returns an error.
// Provides alternative initialization path for error recovery.
//
// Initialization steps:
// 1. sub_39BC - Platform-specific RAS initialization (925 bytes)
// 2. sub_2290 - Memory error event registration
// 3. sub_1220 - S3 boot script save (23 bytes, stub)
//
EFI_STATUS
EFIAPI
MemRasFallbackInit(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = PlatformRasInit();
ASSERT_EFI_ERROR(Status);
Status = RegisterMemoryErrorEvents(ImageHandle, SystemTable);
ASSERT_EFI_ERROR(Status);
Status = S3BootScriptSaveInit(ImageHandle, SystemTable);
ASSERT_EFI_ERROR(Status);
return Status;
}
//
// ============================================================================
// GetOrSetErrorHandlingStatus() [sub_D7A0, 0xD7A0]
// ============================================================================
//
// Manages the per-node error handling progress and pending bitmaps.
//
// Operations:
// 0 (RAS_ERROR_PROGRESS):
// 0 = Clear Progress bit for NodeId
// 1 = Set Progress bit for NodeId (must have Pending bit set)
// 2 = Get Progress status
//
// 1 (RAS_ERROR_PENDING):
// 0 = Clear Pending bit for NodeId
// 1 = Set Pending bit for NodeId (must have Pending bit clear)
// 2 = Get Pending status
//
// 2 (RAS_ERROR_GET_STATUS):
// 2 = Get Progress status (via dword_23680)
// 3 = Get Pending status (via dword_23684)
//
//EFI_STATUS
//GetOrSetErrorHandlingStatus(
// IN UINT8 NodeId,
// IN UINT32 Operation,
// OUT UINT32 *Status OPTIONAL
// )
//{
// switch (Operation) {
// case 0: // Progress
// switch (*Status) {
// case 0: // Clear
// mEventProgressBitmap &= ~(1 << NodeId);
// DEBUG((DEBUG_INFO, "Clear Event Progress Node%d\n", NodeId));
// return EFI_SUCCESS;
// case 1: // Set
// ASSERT((mEventPendingBitmap & (1 << NodeId)) != 0);
// mEventProgressBitmap |= (1 << NodeId);
// DEBUG((DEBUG_INFO, "Set Event Progress Node%d\n", NodeId));
// return EFI_SUCCESS;
// default:
// ASSERT(FALSE);
// return EFI_INVALID_PARAMETER;
// }
//
// case 1: // Pending
// switch (*Status) {
// case 0: // Clear
// mEventPendingBitmap &= ~(1 << NodeId);
// DEBUG((DEBUG_INFO, "Clear Event Pending Node%d\n", NodeId));
// return EFI_SUCCESS;
// case 1: // Set
// ASSERT((mEventPendingBitmap & (1 << NodeId)) == 0);
// mEventPendingBitmap |= (1 << NodeId);
// DEBUG((DEBUG_INFO, "Set Event Pending Node%d\n", NodeId));
// return EFI_SUCCESS;
// default:
// ASSERT(FALSE);
// return EFI_INVALID_PARAMETER;
// }
//
// case 2: // Get - return Progress bitmap
// *Status = (mEventProgressBitmap >> NodeId) & 1;
// DEBUG((DEBUG_INFO, "Get Progress Node%d = %d\n", NodeId, *Status));
// return EFI_SUCCESS;
//
// case 3: // Get - return Pending bitmap
// *Status = (mEventPendingBitmap >> NodeId) & 1;
// DEBUG((DEBUG_INFO, "Get Pending Node%d = %d\n", NodeId, *Status));
// return EFI_SUCCESS;
//
// default:
// ASSERT(FALSE);
// return EFI_INVALID_PARAMETER;
// }
//}