/**
* @file RamDiskDxe.c
* @brief UEFI RAM Disk Driver - Decompiled C
*
* Modules decomposed:
* - RamDiskDriver.c (0x464-0x87E): Entry point, binding, ACPI check
* - RamDiskImpl.c (0x884-0x1C28): Register/unregister, HII population
* - RamDiskBlockIo.c (0x1C2C-0x2628): Block I/O protocol implementation
* - RamDiskProtocol.c (0x884-0x1610): NFIT ACPI table management
*
* Binary: HR650X_3647_AJAX_BIOS PE 0268_RamDiskDxe
* SHA256: 522d2f3558a28a1d1274c2c4a42a7b0abce1d2b9cf702b1f93517fd8a2c2ed17
* Image size: 0xa540
*/
/*============================================================================
* This is a reconstructed decompilation of RamDiskDxe.efi from the
* Lenovo HR650X BIOS. The original source is EDK2 MdeModulePkg
* Universal/Disk/RamDiskDxe.
*
* The binary contains 117 functions, of which 116 are compiler-generated
* sub_* helpers and 1 is _ModuleEntryPoint (renamed). Key entry points:
*
* 0x464 _ModuleEntryPoint - UEFI DXE entry point
* 0x4DC EfiDriverEntry - saves ImageHandle/SystemTable/BS/RT,
* locates HII protocols
* 0x3C4 DriverBindingStop - uninstalls RAM disks on driver stop
* 0x6A4 DriverBindingStart - installs driver, allocates private data
* 0x798 RamDiskAcpiCheck - locates ACPI protocols, publishes NFIT
* 0x884 RamDiskPublishNfit - adds NVDIMM region mapping to ACPI NFIT
* 0xC88 RamDiskDepublishNfit - removes region mapping from NFIT
* 0xEF8 RamDiskRegister - allocates private data, installs BlockIo
* 0x11EC RamDiskUnregister - uninstalls BlockIo, removes from list
* 0x13A4 RamInstallConfigAccess - installs HII Config Access
* 0x146C RamDestroyPrivate - frees private data
* 0x1510 RamDiskUnregisterAll - unregisters all RAM disks
* 0x1654 RamDiskCreateFromFile - creates RAM disk from file content
* 0x1890 RamDiskImplPopulateHii - populates HII form entries
* 0x1C2C RamDiskConfigAccess - HII Config Access Callback
* 0x1FBC RamDiskBlkIoReadBlocks - EFI_BLOCK_IO.ReadBlocks
* 0x20A0 RamDiskBlkIoWriteBlocks - EFI_BLOCK_IO.WriteBlocks
* 0x2194 RamDiskBlkIo2ReadBlocksEx - EFI_BLOCK_IO2.ReadBlocksEx
* 0x2230 RamDiskBlkIo2WriteBlocksEx - EFI_BLOCK_IO2.WriteBlocksEx
* 0x22CC RamDiskBlkIoFlushBlocks - flush (no-op for RAM)
* 0x23F4 RamDiskExtractConfig - HII ExtractConfig handler
* 0x5158 RamDiskRegisterProtocol - registers with HII database
*============================================================================*/
#include "RamDiskDxe.h"
/*============================================================================
* SECTION 1: UEFI Library Helper Functions
* These are compiler-generated wrappers found in the UEFI tree.
*============================================================================*/
/* sub_390: ZeroMem - zero a buffer via aligned memset */
VOID *
ZeroMem (
VOID *Buffer,
UINTN Length
)
{
memset (Buffer, 0, 8 * (Length >> 3));
memset ((UINT8 *)Buffer + 8 * (Length >> 3), 0, Length & 7);
return Buffer;
}
/* sub_25AC: GetDebugProtocol - retrieve and cache EFI_DEBUG_MASK_PROTOCOL */
EFI_DEBUG_MASK_PROTOCOL *
GetDebugProtocol (
VOID
)
{
EFI_STATUS Status;
UINTN MapKey;
if (gDebugMask != NULL) return gDebugMask;
MapKey = gBS->GetMemoryMap (&gMemoryMapSize, NULL, NULL, NULL, NULL);
gBS->ExitBootServices (gImageHandle, MapKey);
if (MapKey <= 0x10) {
Status = gBS->LocateProtocol (&gEfiDebugMaskProtocolGuid, NULL,
(VOID **)&gDebugMask);
if (EFI_ERROR (Status)) gDebugMask = NULL;
} else {
gDebugMask = NULL;
}
return gDebugMask;
}
/* sub_262C: DebugPrint - DEBUG_ERROR severity print */
VOID
DebugPrint (
UINT64 ErrorLevel,
CONST CHAR8 *Format,
...
)
{
EFI_DEBUG_MASK_PROTOCOL *Proto;
VA_LIST Marker;
VA_START (Marker, Format);
Proto = GetDebugProtocol ();
if (Proto != NULL) Proto->DebugPrint (ErrorLevel, Format, Marker);
VA_END (Marker);
}
/* sub_26B4: DebugAssert */
VOID
DebugAssert (
CONST CHAR8 *FileName,
UINTN LineNumber,
CONST CHAR8 *Description
)
{
EFI_DEBUG_MASK_PROTOCOL *Proto;
Proto = GetDebugProtocol ();
if (Proto != NULL) Proto->DebugAssert (FileName, LineNumber, Description);
}
/* sub_27A4: CopyMem */
VOID *
CopyMem (
VOID *Dest,
CONST VOID *Src,
UINTN Length
)
{
return memmove (Dest, Src, Length);
}
/* sub_3BD8: AllocatePool */
VOID *
AllocatePool (
UINTN Size
)
{
VOID *Buf = NULL;
EFI_STATUS Status;
Status = gBS->AllocatePool (EfiBootServicesData, Size, &Buf);
return EFI_ERROR (Status) ? NULL : Buf;
}
/* sub_3C08: AllocateZeroPool */
VOID *
AllocateZeroPool (
UINTN Size
)
{
VOID *Buf;
Buf = AllocatePool (Size);
if (Buf != NULL && Size > 0) ZeroMem (Buf, Size);
return Buf;
}
/* sub_3C34: AllocateCopyPool */
VOID *
AllocateCopyPool (
UINTN Size,
CONST VOID *Buf
)
{
VOID *New;
ASSERT (Buf != NULL);
ASSERT (Size <= (MAX_ADDRESS - (UINTN)Buf + 1));
New = AllocatePool (Size);
if (New != NULL) CopyMem (New, Buf, Size);
return New;
}
/* sub_3D2C: FreePool */
VOID
FreePool (
VOID *Buf
)
{
EFI_STATUS Status;
Status = gBS->FreePool (Buf);
if (EFI_ERROR (Status)) {
DebugPrint (EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT (FALSE);
}
}
/* sub_660C: ZeroMem wrapper */
VOID *
ZeroMem (
VOID *Buffer,
UINTN Length
)
{
ASSERT (Buffer != NULL);
ASSERT (Length <= (MAX_ADDRESS - (UINTN)Buffer + 1));
return ZeroMemAligned (Buffer, Length);
}
/* sub_2984: InitializeListHead */
LIST_ENTRY *
InitializeListHead (
LIST_ENTRY *Head
)
{
ASSERT (Head != NULL);
Head->ForwardLink = Head;
Head->BackLink = Head;
return Head;
}
/* sub_2A10: IsListEmpty */
BOOLEAN
IsListEmpty (
LIST_ENTRY *Head
)
{
ASSERT (InternalBaseLibIsListValid (Head));
return Head->ForwardLink == Head;
}
/* sub_2A48: RemoveEntryList */
LIST_ENTRY *
RemoveEntryList (
LIST_ENTRY *Entry
)
{
ASSERT (!IsListEmpty (Entry));
Entry->ForwardLink->BackLink = Entry->BackLink;
Entry->BackLink->ForwardLink = Entry->ForwardLink;
return Entry;
}
/* sub_29BC: InsertTailList */
VOID
InsertTailList (
LIST_ENTRY *Head,
LIST_ENTRY *Entry
)
{
Entry->ForwardLink = Head;
Entry->BackLink = Head->BackLink;
Head->BackLink->ForwardLink = Entry;
Head->BackLink = Entry;
}
/* sub_2918: InternalBaseLibIsListValid */
BOOLEAN
InternalBaseLibIsListValid (
LIST_ENTRY *Head
)
{
ASSERT (Head != NULL);
ASSERT (Head->ForwardLink != NULL);
ASSERT (Head->BackLink != NULL);
return TRUE;
}
/* sub_2B3C: ReadUnaligned64 */
UINT64
ReadUnaligned64 (
VOID *Buf
)
{
ASSERT (Buf != NULL);
return *(UINT64 *)Buf;
}
/* sub_2B0C: ReadUnaligned16 */
UINT16
ReadUnaligned16 (
VOID *Buf
)
{
ASSERT (Buf != NULL);
return *(UINT16 *)Buf;
}
/* sub_2CB4: UnicodeSPrint */
UINTN
UnicodeSPrint (
CHAR16 *Buf,
UINTN BufSize,
CONST CHAR16 *Fmt,
...
)
{
VA_LIST Marker;
VA_START (Marker, Fmt);
ASSERT (((UINTN)Buf & 1) == 0);
return UnicodeVSPrint (Buf, BufSize >> 1, 64, Fmt, Marker);
}
/* sub_6B58: StrLen */
UINTN
StrLen (
CONST CHAR16 *Str
)
{
CONST CHAR16 *Ptr;
ASSERT (Str != NULL);
ASSERT (((UINTN)Str & 1) == 0);
for (Ptr = Str; *Ptr != 0; Ptr++) {
if ((UINTN)(Ptr - Str) >= MAX_STRING_LENGTH) ASSERT (FALSE);
}
return Ptr - Str;
}
/* sub_6CB8: AsciiStrLen */
UINTN
AsciiStrLen (
CONST CHAR8 *Str
)
{
CONST CHAR8 *Ptr;
ASSERT (Str != NULL);
for (Ptr = Str; *Ptr != 0; Ptr++) {
if ((UINTN)(Ptr - Str) >= MAX_ASCII_STRING_LENGTH) ASSERT (FALSE);
}
return Ptr - Str;
}
/* sub_6D24: AsciiStrCmp */
INTN
AsciiStrCmp (
CONST CHAR8 *First,
CONST CHAR8 *Second
)
{
ASSERT (AsciiStrSize (First) != 0);
ASSERT (AsciiStrSize (Second) != 0);
ASSERT (AsciiStrLen (First) <= MAX_ASCII_STRING_LENGTH);
ASSERT (AsciiStrLen (Second) <= MAX_ASCII_STRING_LENGTH);
while (*First && *Second && *First == *Second) {
First++;
Second++;
}
return *First - *Second;
}
/* sub_273C: CompareGuid */
BOOLEAN
CompareGuid (
EFI_GUID *G1,
EFI_GUID *G2
)
{
UINT64 Front1, Front2;
UINT64 Back1, Back2;
Front1 = ReadUnaligned64 (G1);
Front2 = ReadUnaligned64 (G2);
Back1 = ReadUnaligned64 ((UINT8 *)G1 + 8);
Back2 = ReadUnaligned64 ((UINT8 *)G2 + 8);
return (BOOLEAN)(Front1 == Front2 && Back1 == Back2);
}
/* sub_26F4: CopyGuid */
VOID *
CopyGuid (
VOID *Dst,
CONST VOID *Src
)
{
return CopyMem (Dst, Src, sizeof (EFI_GUID));
}
/* DevicePath utilities */
UINT8
DevPathNodeType (
VOID *Node
)
{
ASSERT (Node != NULL);
return *(UINT8 *)Node;
}
UINT8
DevPathNodeSubType (
VOID *Node
)
{
ASSERT (Node != NULL);
return *((UINT8 *)Node + 1);
}
UINTN
DevPathNodeLength (
VOID *Node
)
{
ASSERT (Node != NULL);
return ReadUnaligned16 ((UINT16 *)((UINT8 *)Node + 2));
}
VOID *
DevPathNextNode (
VOID *Node
)
{
ASSERT (Node != NULL);
return (VOID *)((UINT8 *)Node + DevPathNodeLength (Node));
}
BOOLEAN
DevPathIsEnd (
VOID *Node
)
{
ASSERT (Node != NULL);
return (DevPathNodeType (Node) == END_DEVICE_PATH_TYPE &&
DevPathNodeSubType (Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
}
BOOLEAN
DevPathIsValid (
VOID *Path
)
{
VOID *Node;
UINTN Size;
ASSERT (Path != NULL);
Size = 0;
Node = Path;
for (;;) {
if (DevPathIsEnd (Node)) return DevPathNodeLength (Path) == 4;
if (DevPathNodeLength (Node) < 4) return FALSE;
if (DevPathNodeLength (Node) > (MAX_ADDRESS - Size)) return FALSE;
Size += DevPathNodeLength (Node);
if (Size > MAX_ADDRESS - 4) return FALSE;
Node = DevPathNextNode (Node);
}
}
UINTN
DevPathInstanceSize (
VOID *Path
)
{
VOID *Node;
VOID *Next;
UINTN Size;
Size = 0;
if (Path == NULL || !DevPathIsValid (Path)) return Size;
for (Next = Path; !DevPathIsEnd (Next); Next = Node) {
Node = DevPathNextNode (Next);
}
return DevPathNodeLength (Next) + (UINTN)Next - (UINTN)Path;
}
/* sub_3F5C: GetDevicePathSize wrapper */
UINTN
GetDevicePathSize (
VOID *Path
)
{
VOID *Node;
UINTN Size;
ASSERT (Path != NULL);
Size = 0;
Node = Path;
for (;;) {
if (DevPathIsEnd (Node)) return DevPathNodeLength (Path);
if (DevPathNodeLength (Node) < 4) return 0;
if (DevPathNodeLength (Node) > (MAX_ADDRESS - Size)) return 0;
Size += DevPathNodeLength (Node);
if (Size > MAX_ADDRESS - 4) return 0;
Node = DevPathNextNode (Node);
}
}
/* sub_3D70: GetDevicePathInstanceSize */
UINTN
GetDevicePathInstanceSize (
VOID *Path
)
{
VOID *Node, *Next;
UINTN Size;
Size = 0;
Node = Path;
if (Path == NULL || !DevPathIsValid (Path)) return Size;
for (Next = Node; !DevPathIsEnd (Next); Next = Node) {
Node = DevPathNextNode (Next);
}
return DevPathNodeLength (Next) + (UINTN)Next - (UINTN)Path;
}
/* sub_3FE4: GetDevPathNodeType */
UINT8
GetDevPathNodeType (
VOID *Node
)
{
ASSERT (Node != NULL);
return *(UINT8 *)Node;
}
/* sub_4010: GetDevPathNodeSubType */
UINT8
GetDevPathNodeSubType (
VOID *Node
)
{
ASSERT (Node != NULL);
return *((UINT8 *)Node + 1);
}
/* sub_4040: GetDevPathNodeLength */
UINTN
GetDevPathNodeLength (
VOID *Node
)
{
ASSERT (Node != NULL);
return ReadUnaligned16 ((UINT16 *)((UINT8 *)Node + 2));
}
/* sub_408C: GetNextDevPathNode */
VOID *
GetNextDevPathNode (
VOID *Node
)
{
ASSERT (Node != NULL);
return (VOID *)((UINT8 *)Node + GetDevPathNodeLength (Node));
}
/* sub_40C4: IsDevicePathEndType */
BOOLEAN
IsDevicePathEndType (
VOID *Node
)
{
return (GetDevPathNodeType (Node) == END_DEVICE_PATH_TYPE);
}
/* sub_4100: IsDevicePathEnd */
BOOLEAN
IsDevicePathEnd (
VOID *Node
)
{
ASSERT (Node != NULL);
return (BOOLEAN)(IsDevicePathEndType (Node) &&
GetDevPathNodeSubType (Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE);
}
/*============================================================================
* SECTION 2: Driver Entry Point and Binding
*============================================================================*/
/* _ModuleEntryPoint at 0x464 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT64 Registration;
/* sub_4DC: EfiDriverEntry */
gImageHandle = ImageHandle;
ASSERT (ImageHandle != NULL);
gST = SystemTable;
ASSERT (SystemTable != NULL);
gBS = SystemTable->BootServices;
ASSERT (gBS != NULL);
gRT = SystemTable->RuntimeServices;
ASSERT (gRT != NULL);
/* sub_46B4: Locate HII protocols */
gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, 0, &gHiiString);
gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, 0, &gHiiDatabase);
gBS->LocateProtocol (&gEfiHiiConfigRoutingGuid, 0, &gHiiConfigRouting);
gBS->LocateProtocol (&gEfiHiiConfigAccessGuid, 0, &gHiiConfigAccess);
/* Install driver binding + component name protocols */
Status = gBS->InstallMultipleProtocolInterfaces (
&gRamDiskDriverHandle,
&gEfiDriverBindingProtocolGuid, &gDriverBinding,
&gEfiComponentName2ProtocolGuid, &gComponentName2,
NULL
);
/* Set Stop function in ImageHandle's unload */
/* *Registration + 88 = DriverBindingStop sub_3C4 */
return RamDiskDxeDriverBindingStart (NULL, NULL);
}
/* sub_3C4: DriverBindingStop */
EFI_STATUS
RamDiskDxeDriverBindingStop (
EFI_DRIVER_BINDING_PROTOCOL *This,
EFI_HANDLE Controller,
UINTN NumberOfChildren,
EFI_HANDLE *ChildBuffer
)
{
RAM_DISK_PRIVATE_DATA *Private;
EFI_STATUS Status;
Status = gBS->OpenProtocol (
Controller,
&gEfiRamDiskProtocolGuid,
(VOID **)&Private,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
if (EFI_ERROR (Status)) return Status;
ASSERT (Private->Signature == RAM_DISK_SIGNATURE);
RamDiskUnregisterAll ();
gBS->ReinstallProtocolInterface (
Controller,
&gEfiRamDiskProtocolGuid,
&gDriverBinding,
&gEfiRamDiskProtocolGuid,
Private,
NULL
);
RamDestroyPrivate (Private);
return EFI_SUCCESS;
}
/* sub_6A4: DriverBindingStart */
EFI_STATUS
RamDiskDxeDriverBindingStart (
EFI_DRIVER_BINDING_PROTOCOL *This,
EFI_HANDLE Controller,
EFI_DEVICE_PATH_PROTOCOL *RemainingPath
)
{
RAM_DISK_PRIVATE_DATA *Private;
EFI_STATUS Status;
VOID *Registration;
Status = gBS->OpenProtocol (
Controller,
&gEfiRamDiskProtocolGuid,
&Registration,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
if (!EFI_ERROR (Status)) {
DebugPrint (EFI_D_WARN, "Driver already started!\n");
return EFI_ALREADY_STARTED;
}
Private = AllocateCopyPool (sizeof (RAM_DISK_PRIVATE_DATA),
&gRcfgGuid);
if (Private == NULL) return EFI_OUT_OF_RESOURCES;
Status = RamInstallConfigAccess (Private);
if (EFI_ERROR (Status) ||
EFI_ERROR (gBS->InstallProtocolInterface (
&gRamDiskDriverHandle,
&gEfiRamDiskProtocolGuid,
EFI_NATIVE_INTERFACE,
Private,
NULL
)))
{
RamDestroyPrivate (Private);
return Status;
}
InitializeListHead (&gRamDiskList);
RamDiskAcpiCheck ();
return EFI_SUCCESS;
}
/* sub_798: RamDiskAcpiCheck */
EFI_STATUS
RamDiskAcpiCheck (
VOID
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
gBS->RaiseTPL (TPL_CALLBACK);
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, 0,
(VOID **)&gAcpiTable);
if (EFI_ERROR (Status)) {
DebugPrint (EFI_D_ERROR,
"RamDiskAcpiCheck: Cannot locate the EFI ACPI Table Protocol,"
"unable to publish RAM disks to NFIT.\n");
}
Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, 0,
(VOID **)&gAcpiSdt);
if (EFI_ERROR (Status)) {
DebugPrint (EFI_D_ERROR,
"RamDiskAcpiCheck: Cannot locate the EFI ACPI Sdt Protocol,"
"unable to publish RAM disks to NFIT.\n");
gAcpiTable = NULL;
}
/* Publish each registered RAM disk to NFIT */
for (Link = gRamDiskList.ForwardLink;
Link != &gRamDiskList;
Link = Link->ForwardLink)
{
RAM_DISK_PRIVATE_DATA *Priv;
Priv = CR (Link, RAM_DISK_PRIVATE_DATA, ListEntry, RAM_DISK_SIGNATURE);
RamDiskPublishNfit (Priv);
}
return EFI_SUCCESS;
}
/*============================================================================
* SECTION 3: RAM Disk Registration/Unregistration
*============================================================================*/
/* sub_EF8: RamDiskRegister */
EFI_STATUS
RamDiskRegister (
EFI_PHYSICAL_ADDRESS BaseAddress,
UINT64 Size,
EFI_GUID *DevicePathGuid,
EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT EFI_HANDLE *RamDiskHandle
)
{
RAM_DISK_PRIVATE_DATA *Private;
LIST_ENTRY *Link;
EFI_STATUS Status;
if (Size == 0 || DevicePath == NULL || RamDiskHandle == NULL ||
BaseAddress >= ~Size + 1)
return EFI_INVALID_PARAMETER;
Private = AllocateCopyPool (sizeof (RAM_DISK_PRIVATE_DATA), &gRdskGuid);
if (Private == NULL) return EFI_OUT_OF_RESOURCES;
ZeroMem (Private, sizeof (RAM_DISK_PRIVATE_DATA));
Private->Signature = RAM_DISK_SIGNATURE;
Private->BaseAddress = BaseAddress;
Private->Size = Size;
CopyGuid (&Private->DevicePathGuid, DevicePathGuid);
InitializeListHead (&Private->ListEntry);
/* Build device path node with address range */
/* (MEDIA_FILEPATH_DP node containing base/end) */
Private->Media.BlockSize = RAM_DISK_DEFAULT_BLOCK_SIZE;
Private->Media.LastBlock = (Size / RAM_DISK_DEFAULT_BLOCK_SIZE) - 1;
Private->Media.MediaPresent = TRUE;
/* Initialize function pointers */
Private->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
Private->BlkIo.Media = &Private->Media;
Private->BlkIo.Reset = RamDiskBlkIoNoop;
Private->BlkIo.ReadBlocks = RamDiskBlkIoReadBlocks;
Private->BlkIo.WriteBlocks = RamDiskBlkIoWriteBlocks;
Private->BlkIo.FlushBlocks = RamDiskBlkIoFlushBlocks;
/* Install protocols */
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiBlockIoProtocolGuid, &Private->BlkIo,
&gEfiBlockIo2ProtocolGuid, &Private->BlkIo2,
&gEfiDevicePathProtocolGuid, Private->DevPath,
NULL
);
if (EFI_ERROR (Status)) {
FreePool (Private->DevPath);
FreePool (Private);
return Status;
}
InsertTailList (&gRamDiskList, &Private->ListEntry);
/* Publish to NFIT if ACPI is available */
if (gAcpiTable != NULL && gAcpiSdt != NULL)
RamDiskPublishNfit (Private);
return EFI_SUCCESS;
}
/* sub_11EC: RamDiskUnregister */
EFI_STATUS
RamDiskUnregister (
EFI_HANDLE Handle
)
{
VOID *Node;
UINT64 BaseAddress;
UINT64 EndAddress;
LIST_ENTRY *Link;
RAM_DISK_PRIVATE_DATA *Private;
Node = Handle;
if (Node == NULL) return EFI_INVALID_PARAMETER;
/* Walk to MEDIA_FILEPATH_DP node (type=4, subtype=9) */
while (GetDevPathNodeType (Node) != MEDIA_DEVICE_PATH ||
GetDevPathNodeSubType (Node) != MEDIA_FILEPATH_DP)
{
Node = GetNextDevPathNode (Node);
if (GetDevPathNodeType (Node) == END_DEVICE_PATH_TYPE)
return EFI_UNSUPPORTED;
}
BaseAddress = ReadUnaligned64 ((UINT8 *)Node + 4);
EndAddress = ReadUnaligned64 ((UINT8 *)Node + 12);
if (IsListEmpty (&gRamDiskList)) return EFI_UNSUPPORTED;
for (Link = gRamDiskList.ForwardLink;
Link != &gRamDiskList;
Link = Link->ForwardLink)
{
Private = CR (Link, RAM_DISK_PRIVATE_DATA, ListEntry, RAM_DISK_SIGNATURE);
if (Private->BaseAddress == BaseAddress &&
Private->BaseAddress + Private->Size - 1 == EndAddress &&
CompareGuid ((UINT8 *)Node + 20, &Private->DevicePathGuid))
{
if (Private->NfitPublished)
RamDiskDepublishNfit (Private);
gBS->UninstallMultipleProtocolInterfaces (
Private->Handle,
&gEfiBlockIoProtocolGuid, &Private->BlkIo,
&gEfiBlockIo2ProtocolGuid, &Private->BlkIo2,
&gEfiDevicePathProtocolGuid, Private->DevPath,
NULL
);
RemoveEntryList (&Private->ListEntry);
if (Private->FromFile)
FreePool ((VOID *)(UINTN)Private->BaseAddress);
FreePool (Private->DevPath);
FreePool (Private);
return EFI_SUCCESS;
}
}
return EFI_UNSUPPORTED;
}
/* sub_1510: RamDiskUnregisterAll */
VOID
RamDiskUnregisterAll (
VOID
)
{
LIST_ENTRY *Link;
LIST_ENTRY *Next;
RAM_DISK_PRIVATE_DATA *Private;
if (IsListEmpty (&gRamDiskList)) return;
Link = gRamDiskList.ForwardLink;
Next = Link->ForwardLink;
while (Link != &gRamDiskList) {
Private = CR (Link, RAM_DISK_PRIVATE_DATA, ListEntry, RAM_DISK_SIGNATURE);
gBS->UninstallMultipleProtocolInterfaces (
Private->Handle,
&gEfiBlockIoProtocolGuid, &Private->BlkIo,
&gEfiBlockIo2ProtocolGuid, &Private->BlkIo2,
&gEfiDevicePathProtocolGuid, Private->DevPath,
NULL
);
RemoveEntryList (&Private->ListEntry);
if (Private->FromFile)
FreePool ((VOID *)(UINTN)Private->BaseAddress);
FreePool (Private->DevPath);
FreePool (Private);
Link = Next;
Next = Link->ForwardLink;
}
}
/* sub_146C: RamDestroyPrivate */
VOID
RamDestroyPrivate (
RAM_DISK_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
if (Private->HiiHandle != NULL) {
Status = gHiiDatabase->RemovePackageList (gHiiDatabase,
Private->HiiHandle);
if (EFI_ERROR (Status)) {
DebugPrint (EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT (FALSE);
}
Private->HiiHandle = NULL;
}
if (Private->ConfigAccessHandle != NULL) {
gBS->UninstallMultipleProtocolInterfaces (
Private->ConfigAccessHandle,
&gEfiHiiConfigAccessProtocolGuid,
&Private->ConfigAccess,
NULL
);
Private->ConfigAccessHandle = NULL;
}
FreePool (Private);
}
/* sub_13A4: RamInstallConfigAccess */
EFI_STATUS
RamInstallConfigAccess (
RAM_DISK_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->ConfigAccessHandle,
&gEfiHiiConfigAccessProtocolGuid,
&Private->ConfigAccess,
&gRamDiskHiiPackageListGuid,
(UINT8 *)Private + 24,
NULL
);
if (EFI_ERROR (Status)) return Status;
Private->HiiHandle = RamCreateHiiPackageList (
&gRamDiskHiiGuid,
(VOID *)&Private->ConfigAccess,
&gRamDiskHiiPackageListGuid,
&gRamDiskHiiStorageGuid,
0
);
if (Private->HiiHandle == NULL) {
gBS->UninstallMultipleProtocolInterfaces (
Private->ConfigAccessHandle,
&gEfiHiiConfigAccessProtocolGuid,
&Private->ConfigAccess,
NULL
);
Private->ConfigAccessHandle = NULL;
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/*============================================================================
* SECTION 4: Block I/O Protocol Implementation
*============================================================================*/
/* sub_1FBC: RamDiskBlkIoReadBlocks */
EFI_STATUS
EFIAPI
RamDiskBlkIoReadBlocks (
EFI_BLOCK_IO_PROTOCOL *This,
UINT32 MediaId,
EFI_LBA Lba,
UINTN BufSize,
VOID *Buf
)
{
RAM_DISK_PRIVATE_DATA *Private;
Private = CR (This, RAM_DISK_PRIVATE_DATA, BlkIo, RAM_DISK_SIGNATURE);
if (Buf == NULL) return EFI_INVALID_PARAMETER;
if (BufSize == 0) return EFI_SUCCESS;
if (MediaId != Private->Media.MediaId) return EFI_MEDIA_CHANGED;
if (BufSize % Private->Media.BlockSize) return EFI_BAD_BUFFER_SIZE;
if (Lba > Private->Media.LastBlock ||
Lba + BufSize / Private->Media.BlockSize - 1 > Private->Media.LastBlock)
return EFI_INVALID_PARAMETER;
CopyMem (Buf,
(VOID *)(Private->BaseAddress + (UINTN)Lba * Private->Media.BlockSize),
BufSize);
return EFI_SUCCESS;
}
/* sub_20A0: RamDiskBlkIoWriteBlocks */
EFI_STATUS
EFIAPI
RamDiskBlkIoWriteBlocks (
EFI_BLOCK_IO_PROTOCOL *This,
UINT32 MediaId,
EFI_LBA Lba,
UINTN BufSize,
VOID *Buf
)
{
RAM_DISK_PRIVATE_DATA *Private;
Private = CR (This, RAM_DISK_PRIVATE_DATA, BlkIo, RAM_DISK_SIGNATURE);
if (Buf == NULL) return EFI_INVALID_PARAMETER;
if (BufSize == 0) return EFI_SUCCESS;
if (MediaId != Private->Media.MediaId) return EFI_MEDIA_CHANGED;
if (Private->Media.ReadOnly) return EFI_WRITE_PROTECTED;
if (BufSize % Private->Media.BlockSize) return EFI_BAD_BUFFER_SIZE;
if (Lba > Private->Media.LastBlock ||
Lba + BufSize / Private->Media.BlockSize - 1 > Private->Media.LastBlock)
return EFI_INVALID_PARAMETER;
CopyMem ((VOID *)(Private->BaseAddress + (UINTN)Lba * Private->Media.BlockSize),
Buf,
BufSize);
return EFI_SUCCESS;
}
/* sub_22CC: RamDiskBlkIoFlushBlocks */
EFI_STATUS
EFIAPI
RamDiskBlkIoFlushBlocks (
EFI_BLOCK_IO_PROTOCOL *This
)
{
RAM_DISK_PRIVATE_DATA *Private;
Private = CR (This, RAM_DISK_PRIVATE_DATA, BlkIo, RAM_DISK_SIGNATURE);
return Private->Media.ReadOnly ? EFI_WRITE_PROTECTED : EFI_SUCCESS;
}
/* sub_2194: RamDiskBlkIo2ReadBlocksEx */
EFI_STATUS
EFIAPI
RamDiskBlkIo2ReadBlocksEx (
EFI_BLOCK_IO2_PROTOCOL *This,
UINT32 MediaId,
EFI_LBA Lba,
VOID *Token,
UINTN BufSize,
VOID *Buf
)
{
RAM_DISK_PRIVATE_DATA *Private;
EFI_STATUS Status;
Private = CR (This, RAM_DISK_PRIVATE_DATA, BlkIo2, RAM_DISK_SIGNATURE);
Status = RamDiskBlkIoReadBlocks (&Private->BlkIo, MediaId, Lba,
BufSize, Buf);
if (!EFI_ERROR (Status) && Token != NULL && *(VOID **)Token != NULL) {
*((UINT64 *)Token + 1) = 0;
gBS->SignalEvent (*(VOID **)Token);
}
return Status;
}
/* sub_2230: RamDiskBlkIo2WriteBlocksEx */
EFI_STATUS
EFIAPI
RamDiskBlkIo2WriteBlocksEx (
EFI_BLOCK_IO2_PROTOCOL *This,
UINT32 MediaId,
EFI_LBA Lba,
VOID *Token,
UINTN BufSize,
VOID *Buf
)
{
RAM_DISK_PRIVATE_DATA *Private;
EFI_STATUS Status;
Private = CR (This, RAM_DISK_PRIVATE_DATA, BlkIo2, RAM_DISK_SIGNATURE);
Status = RamDiskBlkIoWriteBlocks (&Private->BlkIo, MediaId, Lba,
BufSize, Buf);
if (!EFI_ERROR (Status) && Token != NULL && *(VOID **)Token != NULL) {
*((UINT64 *)Token + 1) = 0;
gBS->SignalEvent (*(VOID **)Token);
}
return Status;
}
/* sub_1FB8: RamDiskBlkIoNoop (Reset - always EFI_SUCCESS) */
EFI_STATUS
EFIAPI
RamDiskBlkIoNoop (
EFI_BLOCK_IO_PROTOCOL *This,
BOOLEAN ExtendedVerification
)
{
return EFI_SUCCESS;
}
/*============================================================================
* SECTION 5: Component Name Protocol stubs
*============================================================================*/
/* sub_1610: GetDriverName stub */
EFI_STATUS
EFIAPI
RamDiskGetDriverName (
EFI_COMPONENT_NAME2_PROTOCOL *This,
CHAR8 *Language,
CHAR16 **DriverName
)
{
if (DriverName == NULL || Language == NULL) return EFI_INVALID_PARAMETER;
*DriverName = (CHAR16 *)Language;
return EFI_UNSUPPORTED;
}
/* sub_1634: GetControllerName stub returning EFI_UNSUPPORTED */
EFI_STATUS
EFIAPI
RamDiskGetControllerName (
EFI_COMPONENT_NAME2_PROTOCOL *This,
EFI_HANDLE Controller,
EFI_HANDLE ChildHandle,
CHAR8 *Language,
CHAR16 **ControllerName
)
{
if (ControllerName == NULL || Language == NULL) return EFI_INVALID_PARAMETER;
return EFI_UNSUPPORTED;
}
/*============================================================================
* SECTION 6: NFIT ACPI Table Publication/Renovation
*============================================================================*/
/* sub_884: RamDiskPublishNfit */
EFI_STATUS
RamDiskPublishNfit (
RAM_DISK_PRIVATE_DATA *Private
)
{
/* See RamDiskProtocol.c for full body.
* Summary:
* 1. Locate &gEfiAcpiTableProtocolGuid and &gEfiAcpiSdtProtocolGuid
* 2. Walk memory map for EfiReservedMemoryType covering [Base, Base+Size]
* 3. Search ACPI tables for existing NFIT (signature 0x5449464E)
* 4. If NFIT exists: extend with NVDIMM Region Mapping structure
* 5. If NFIT missing: allocate new NFIT header + first region mapping
* 6. Update checksum via sub_2A90
* 7. Install/update table via ACPI Table Protocol
* 8. Set Private->NfitPublished = TRUE
*/
return EFI_UNSUPPORTED; /* See protocol file for full impl */
}
/* sub_C88: RamDiskDepublishNfit */
EFI_STATUS
RamDiskDepublishNfit (
RAM_DISK_PRIVATE_DATA *Private
)
{
/* Removes matching NVDIMM Region Mapping from NFIT */
return EFI_UNSUPPORTED;
}
/*============================================================================
* SECTION 7: HII/IFR Support Functions
*============================================================================*/
/* sub_4794: RamCreateHiiPackageList */
EFI_HII_HANDLE
RamCreateHiiPackageList (
EFI_GUID *PackageListGuid,
VOID *PackageData,
EFI_GUID *PackageDataGuid,
EFI_GUID *StorageGuid,
UINTN PackageSize
)
{
/* Builds and registers an HII package list with the HII database */
return NULL;
}
/* sub_48D0: RamCreateOpCodeHandle */
VOID *
RamCreateOpCodeHandle (
VOID
)
{
VOID *Handle;
VOID *Buffer;
Handle = AllocatePool (sizeof (VOID *) * 3);
if (Handle == NULL) return NULL;
Buffer = AllocatePool (512);
*(VOID **)Handle = Buffer;
if (Buffer == NULL) {
FreePool (Handle);
return NULL;
}
*((UINTN *)Handle + 2) = 0;
*((UINTN *)Handle + 1) = 512;
return Handle;
}
/* sub_49C4: RamCreateOpCode generic */
VOID
RamCreateOpCode (
VOID *OpCodeHandle,
UINT8 *OpCodeTemplate,
UINT8 OpCode,
UINTN OpCodeSize,
UINTN ExtensionSize,
UINT8 Flags
)
{
UINTN TotalSize;
ASSERT (OpCodeTemplate != NULL);
TotalSize = OpCodeSize + ExtensionSize;
ASSERT (TotalSize <= 0x7F);
*OpCodeTemplate = OpCode;
OpCodeTemplate[1] = (Flags << 7) | (UINT8)(TotalSize & 0x7F);
/* RamAddOpCodeToHandle then CopyMem */
}
/* sub_4A78: RamCreateEndOpCode */
VOID
RamCreateEndOpCode (
VOID *OpCodeHandle
)
{
UINT8 Buf[18];
ZeroMem (Buf, sizeof (Buf));
/* Sets GUID for form set, then creates END opcode (0x5F) */
/* RamCreateOpCode(Handle, Buf, 0x5F, 18, 3, 0) */
}
/* sub_42BC: RamDisplayPopup */
VOID
RamDisplayPopup (
UINTN Column,
... /* variable lines followed by L"Press ENTER" */
)
{
/* Draws box with ConOut->SetAttribute, SetCursorPosition,
* OutputString, then waits for ENTER key via ConIn */
}
/*============================================================================
* Function Rename Map (original sub_* names -> meaningful names)
*============================================================================
* sub_390 -> ZeroMem
* sub_3C4 -> RamDiskDxeDriverBindingStop
* sub_464 -> _ModuleEntryPoint
* sub_4DC -> EfiDriverEntry (save globals + locate HII)
* sub_6A4 -> RamDiskDxeDriverBindingStart
* sub_798 -> RamDiskAcpiCheck
* sub_884 -> RamDiskPublishNfit (NFIT ACPI table creation)
* sub_C88 -> RamDiskDepublishNfit (NFIT ACPI table removal)
* sub_EF8 -> RamDiskRegister (create + register new RAM disk)
* sub_11EC -> RamDiskUnregister (find + remove + free)
* sub_13A4 -> RamInstallConfigAccess (HII)
* sub_146C -> RamDestroyPrivate (free + cleanup)
* sub_1510 -> RamDiskUnregisterAll (clean sweep)
* sub_1610 -> RamDiskGetDriverName
* sub_1634 -> RamDiskGetControllerName
* sub_1654 -> RamDiskCreateFromFile
* sub_1890 -> RamDiskImplPopulateHii
* sub_1C2C -> RamDiskConfigAccess (HII Callback)
* sub_1FBC -> RamDiskBlkIoReadBlocks
* sub_1FB8 -> RamDiskBlkIoNoop (Reset)
* sub_20A0 -> RamDiskBlkIoWriteBlocks
* sub_2194 -> RamDiskBlkIo2ReadBlocksEx
* sub_2230 -> RamDiskBlkIo2WriteBlocksEx
* sub_22CC -> RamDiskBlkIoFlushBlocks
* sub_23F4 -> RamDiskExtractConfig
* sub_25AC -> GetDebugProtocol
* sub_262C -> DebugPrint
* sub_26B4 -> DebugAssert
* sub_26F4 -> CopyGuid
* sub_273C -> CompareGuid
* sub_27A4 -> CopyMem
* sub_2840 -> CompareMem
* sub_2918 -> InternalBaseLibIsListValid
* sub_2984 -> InitializeListHead
* sub_29BC -> InsertTailList
* sub_2A10 -> IsListEmpty
* sub_2A48 -> RemoveEntryList
* sub_2A90 -> RamCalculateChecksum
* sub_2B0C -> ReadUnaligned16
* sub_2B3C -> ReadUnaligned64
* sub_2B6C -> WriteUnaligned64
* sub_2C94 -> UNICODE_STRING_TO_BUF? (sprintf)
* sub_2CB4 -> UnicodeSPrint
* sub_2D98 -> UnicodeVSPrint
* sub_3BD8 -> AllocatePool
* sub_3C08 -> AllocateZeroPool
* sub_3C34 -> AllocateCopyPool
* sub_3D2C -> FreePool
* sub_3D70 -> GetDevicePathInstanceSize
* sub_3EA8 -> FileDevicePath?
* sub_3F5C -> IsDevicePathValid / GetDevicePathSize
* sub_3FE4 -> GetDevPathNodeType
* sub_4010 -> GetDevPathNodeSubType
* sub_4040 -> GetDevPathNodeLength
* sub_408C -> GetNextDevPathNode
* sub_40C4 -> IsDevicePathEndType
* sub_4100 -> IsDevicePathEnd
* sub_4154 -> SetDevicePathNodeLength
* sub_4214 -> StrLen (UTF-16)
* sub_42BC -> RamDisplayPopup
* sub_46B4 -> LocateHiiProtocols
* sub_4794 -> RamCreateHiiPackageList
* sub_48D0 -> RamCreateOpCodeHandle
* sub_4920 -> RamAddOpCodeToHandle
* sub_49C4 -> RamCreateOpCode
* sub_4A78 -> RamCreateEndOpCode
* sub_4ACC -> RamOpCodeCompare?
* sub_4D4C -> RamUpdateForm
* sub_4FBC -> RamGetSupportedLanguage
* sub_50AC -> RamCreateStringPackage
* sub_5060 -> RamGetOneofOption?
* sub_5158 -> RamRegisterProtocol (HII)
* sub_5418 -> RamFreePool / cleanup
* sub_5664 -> RamComparator (BaseSortLib)
* sub_57D8 -> RamGetLanguageData?
* sub_59D4 -> RamLanguageIter?
* sub_5B4C -> RamLanguageFree?
* sub_5BB8 -> RamLanguageNext?
* sub_5D98 -> RamProcessLanguageList
* sub_61C0 -> RamGetFirmwareLanguage?
* sub_63E8 -> RamGetFirmwareLanguage2?
* sub_660C -> ZeroMem (wrap)
* sub_6670 -> SetMem16
* sub_6738 -> StrSize (safe)
* sub_67A0 -> StrCpyS (safe)
* sub_696C -> AsciiStrToUnicodeStrS?
* sub_6B58 -> StrLen
* sub_6CB8 -> AsciiStrLen
* sub_6D24 -> AsciiStrCmp
*/