Newer
Older
AMI-Aptio-BIOS-Reversed / PurleyPlatPkg / Ras / Memory / MemRas / MemRas.md
@Ajax Dong Ajax Dong 2 days ago 9 KB Full restructure

MemRas

Function Table

Address Name Description
ModuleEntryPoint
MemRasInitGlobals
MemRasDriverEntry
MemRasSecondaryInit
MemRasFallbackInit
Include auto-generated UEFI header from AutoGen.c
Protocol GUIDs (referenced in .rdata section as unk_22B*)
These are populated from HOBs and platform policy protocols at init time.
Configuration read from HOB at offset 1677
byte_27858 - 0=non-lockstep, 1=lockstep
Configuration from platform policy protocol
byte_63AEC UINT8 SpareMode; // byte_65ED2
dword_63B24 UINT32 MemoryBase; // dword_63C4C
Memory configuration from HOB
qword_27850 UINT64 MemoryRangeEnd; // qword_27848
qword_27840 UINT32 NumChannels; // qword_27838
qword_27830 UINT32 MemoryGranularity; // qword_27828
_ModuleEntryPoint [0x5CC]
UEFI DXE driver entry point. Called by DXE dispatcher.
EFI_STATUS EFIAPI
Phase 1: Allocate and initialize global context.
Allocates socket configuration buffer, protocol structure
scratch buffers, and error log buffer.
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);
Phase 3 (fallback): On failure, attempt secondary initialization.
Calls memory initialization, event registration, S3 boot script.
Status = MemRasFallbackInit(ImageHandle, SystemTable);
Called first from ModuleEntryPoint. Allocates and initializes all
Init sequence (23 sub-initializers):
EFI_STATUS MemRasInitGlobals(
Each sub-initializer is a library constructor from the
linked static libraries. They are called sequentially.
On debug builds, each failure triggers ASSERT via
The pattern for each call is:
Status = LibraryConstructor();
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
0x1C7C - S3BootScriptLib / SmmLockBoxSmmLib constructor
0x1FB4 - AcpiTimerLib constructor
0x20CC - DxeServicesTableLib + TianoCustomDecompressLib
Phase 3: Platform-specific RAS libraries
0x35D4 - mpsyncdatalib + emcaplatformhookslib init
0x51A8 - SmmLnvSendIpmiCmdLib / SmmVariable protocol
0x552C - AmiErrReportingLib init
0x5FB4 - OemRasLib init
0x6C00 - Platform-specific RAS init
return EFI_SUCCESS;
Core driver entry. Allocates protocol structure, reads HOB data
populates function pointer table, installs protocol interface
and sets up event handlers.
Step 1: Allocate context structure (24 bytes) and zero it.
qword_CD8B0 -> ContextBuffer (sizeof=24)
Status = gBS->AllocatePool(EfiBootServicesData, 24, &ContextBuffer);
Step 2: Allocate protocol structure (568 bytes) and zero it.
qword_27818 -> Protocol (MEM_RAS_PROTOCOL)
Status = gBS->AllocatePool(EfiBootServicesData, 568, &Protocol);
Link protocol to context
Step 3: Allocate socket configuration buffer (32768 bytes).
qword_CD740 -> SocketConfig
Stored in .data section (global variable)
Status = gBS->AllocatePool(EfiBootServicesData, 0x8000, &gSocketConfig);
Initialize scratch buffer tracking
Step 4: Allocate scratch buffer (25037 bytes).
First 8 bytes of protocol structure stores pointer to this.
Status = gBS->AllocatePool(EfiBootServicesData, 25037, &Protocol[0]);
Step 5: Allocate error log buffer (1643 bytes).
qword_CD748 -> gErrorLogBuffer
Status = gBS->AllocatePool(EfiBootServicesData, 1643, &gErrorLogBuffer);
Step 6: Locate PlatformRasPolicy protocol (unk_22BB0).
This provides platform RAS configuration data.
Status = gBS->LocateProtocol(&gPlatformRasPolicyGuid, NULL, &PlatformPolicy);
Step 7: Initialize protocol signature.
Step 8: Populate function pointer table.
All function pointers are installed at their respective
offsets within the protocol structure.
stub Protocol->SpareRank = sub_1A4CC;
stub Protocol->ForwardAddrTranslate = sub_DBFC;
Step 9: Locate platform RAS policy protocol (unk_22B20).
Returns the HOB list pointer with system configuration.
Status = gBS->LocateProtocol(&gPlatformRasHobGuid, NULL, (VOID )&PlatformPolicy);**
Step 10: Locate CPU CSR access and additional protocol.
Status = gBS->LocateProtocol(&gCpuCsrAccessGuid, NULL, (VOID )&CpuCsrAccess);**
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;
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++) {
Step 13: Install MemRas protocol interface.
Context data: Protocol structure (MEM_RAS_PROTOCOL *)
Protocol handle init
points to MEM_RAS_PROTOCOL *
Step 14: Register S3 boot script save handler.
registers sub_10F38 as callback for gEfiEventReadyToBootGuid
installs protocol for gEfiMemRasS3SaveProtocolGuid.
Step 15: Initialize VLS (Virtual Lockstep) state.
If variable doesn't exist, creates it. Locates VariableArchProtocol
and reads back "VLSEstablished" to verify.
Step 16: Initialize spare copy done handler.
Step 17: Initialize rank sparing event handler.
Step 18: Conditionally initialize patrol scrub.
If NumSockets >= 3 or NumSockets <= 1, start patrol scrub.
if **(NumSockets >= 3 NumSockets <= 1) {**
Step 19: Initialize alternate spare rank path.
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) {
Called from ModuleEntryPoint when MemRasInitGlobals() succeeds.
If unk_23560 context is valid, calls MemRasDriverEntry().
Otherwise sets global status to indicate failure.
Global status initialized to error (0x8000000000000001)
gRasStatus = 0x8000000000000001uLL;
Check if context (unk_23560) has setjmp/longjmp already set up.
if (!sub_2C0(&unk_23560)) {
Context was not initialized, so this is first entry.
Call the full driver entry.
EFI_STATUS Status;
Should never reach here - ASSERT failure.
Called when MemRasDriverEntry() returns an error.
Provides alternative initialization path for error recovery.
Initialization steps:
Manages the per-node error handling progress and pending bitmaps.
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)
IN UINT8 NodeId
IN UINT32 Operation
OUT UINT32 *Status OPTIONAL
switch (Operation) {
case 0: // Progress
switch (*Status) {
case 0: // Clear
mEventProgressBitmap &= ~(1 << NodeId);
case 1: // Set
mEventProgressBitmap ** = (1 << NodeId);**
return EFI_INVALID_PARAMETER;
case 1: // Pending
case 2: // Get - return Progress bitmap
case 3: // Get - return Pending bitmap

Generated by HR650X BIOS Decompilation Project