/******************************************************************************
* 217828C1-DA75-5BC1-7B58-91954FED0101.c
* VMD (Volume Management Device) DXE Driver for NVMe
*
* Source paths:
* d:\qba1\workspace\27990\vmd_uefi\MdeModulePkg\Bus\Pci\VmdDxe\
* - vmd.c (main), VmdPciIo.c, Common\VmdLib.c
* d:\qba1\workspace\27990\vmd_uefi\MdeModulePkg\Bus\Pci\NvmExpressDxe\
* - NvmExpress.c, NvmExpressPassthru.c, NvmExpressHci.c,
* NvmExpressBlockIo.c, Common\NvmExpressLib.c
*
* Key strings found:
* "UbaConfigDatabasedxeEntry: after allocate Memory!"
* "UbaConfigDatabasedxeEntry: before get data from hob!"
* "UbaDxePrivate != ((void *) 0)"
* "CR has Bad Signature" (used in many places via _CR() macro)
* "LED_HW_Implementation" (UEFI variable for LED config)
*
* Image: 0x18a60 bytes, 246 functions, x86_64 PE32+
* Module GUID: 217828C1-DA75-5BC1-7B58-91954FED0101
******************************************************************************/
#include "217828C1-DA75-5BC1-7B58-91954FED0101.h"
/*============================================================================
* Global Data (.data section, 0x14C20-0x17880)
*============================================================================*/
EFI_SYSTEM_TABLE *gST = NULL; /* 0x17528 */
EFI_BOOT_SERVICES *gBS = NULL; /* 0x17530 */
EFI_RUNTIME_SERVICES *gRT = NULL; /* 0x17540 */
EFI_HANDLE gImageHandle = NULL; /* 0x17538 */
/* HII protocol pointers */
EFI_HII_DATABASE_PROTOCOL *gHiiDatabase = NULL; /* 0x17558 */
EFI_HII_STRING_PROTOCOL *gHiiString = NULL; /* 0x17560 */
UINT64 gHiiConfigRouting = 0; /* 0x17568 */
UINT64 gHiiPackageList = 0; /* 0x17550 */
UINT64 gFormBrowser2 = 0; /* 0x17548 */
/* Function/event registration pointers */
UINT64 gVmdHiiExtractHii = 0; /* 0x175D0 - psub_3154 */
UINT64 gVmdHiiRouteHii = 0; /* 0x175D8 - psub_3188 */
UINT64 gVmdHiiExtractHii2 = 0; /* 0x175E8 - psub_3154_0 */
UINT64 gVmdHiiRouteHii2 = 0; /* 0x175F0 - psub_3188_0 */
UINT64 gVmdDriverSupported = 0; /* 0x175A0 - psub_96C */
UINT64 gVmdDriverStart = 0; /* 0x175A8 - psub_B04 */
UINT64 gVmdDriverStop = 0; /* 0x175B0 - psub_17E8 */
UINT64 gVmdDevicePathExtract = 0; /* 0x17868 - psub_1BC0 */
UINT64 gVmdDevicePathConfig = 0; /* 0x17870 - psub_1C14 */
/* HII driver handles */
UINT64 gVmdDriverBdHandle = 0; /* 0x175C0 */
UINT64 gVmdDriverBdHandle2 = 0; /* 0x175C8 */
/* Module image handle from entry point */
UINT64 gVmdImageHandle = 0; /* 0x17538 (alias) */
/* Language strings */
CHAR8 *gVmdEngLanguage = "eng"; /* 0x175E0 */
CHAR8 *gVmdEnLanguage = "en"; /* 0x175F8 */
/* Timer calibration */
UINT32 gVmdTimerCalib = 0; /* 0x17520 */
/* LED variable config */
UINT32 gVmdLedVariable = 0; /* 0x17878 */
UINT16 gVmdLedHwConfig = 0; /* 0x1785C */
UINT32 gVmdHiiLangFlags = 1; /* 0x17858 */
UINT32 gVmdLedStatus = 0; /* 0x17860 */
/* Device counting */
UINT32 gVmdDeviceCount = 0; /* 0x17850 */
INT32 gVmdDesiredCount = -1; /* 0x17854 */
/* NVMe controller private data */
UINT64 gNvmePrivate1 = 0; /* 0x17660 */
UINT64 gNvmeNsConfig1[3] = {0}; /* 0x17600 */
UINT64 gNvmePrivate2 = 0; /* 0x17690 */
UINT64 gNvmeNsConfig2[3] = {0}; /* 0x17630 */
/* Controller pointer array (up to 48 controllers) */
VMD_CONTROLLER *gVmdDriverControllers[VMD_MAX_CHILDREN] = { 0 };
/* Stall protocol */
UINT64 gStallFunc = 0; /* 0x17580 */
/*============================================================================
* Sub function: _ModuleEntryPoint
* Just calls VmdInitGlobals then VmdDriverEntryPoint
*============================================================================*/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
VmdInitGlobals (ImageHandle, SystemTable);
return VmdDriverEntryPoint (ImageHandle, SystemTable);
}
/*============================================================================
* sub_2EC - VmdInitGlobals
*
* Stores ImageHandle, gST, gBS, gRT. Locates HII protocols.
*============================================================================*/
VOID
EFIAPI
VmdInitGlobals (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
gImageHandle = ImageHandle;
if (gImageHandle == NULL) {
ASSERT (gImageHandle != NULL);
}
gST = SystemTable;
if (gST == NULL) {
ASSERT (gST != NULL);
}
gBS = SystemTable->BootServices;
if (gBS == NULL) {
ASSERT (gBS != NULL);
}
gRT = SystemTable->RuntimeServices;
if (gRT == NULL) {
ASSERT (gRT != NULL);
}
/* Locate HII protocols */
gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&gHiiDatabase);
gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **)&gHiiString);
gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&gHiiConfigRouting);
gBS->LocateProtocol (&gEfiHiiPackageListProtocolGuid, NULL, (VOID **)&gHiiPackageList);
gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **)&gFormBrowser2);
}
/*============================================================================
* sub_4B8 - VmdDriverEntryPoint
*
* Main entry point:
* 1. Registers driver binding, component name, HII config access, device path
* 2. Publish HII package list
* 3. Initializes NVMe controller binding data
* 4. Registers protocol notifications for NVM Express passthru and Block I/O
* 5. Checks for LED_HW_Implementation UEFI variable
* 6. Installs VMD protocol interfaces on the image handle
* 7. Binds the NvmExpressDxe stack
*============================================================================*/
EFI_STATUS
EFIAPI
VmdDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT64 VmdImageHandle;
gVmdDriverBdHandle = (UINT64)ImageHandle;
gVmdDriverBdHandle2 = (UINT64)ImageHandle;
/* Clear global state */
ZeroMem (&gVmdDriverSupported, sizeof (gVmdDriverSupported) +
sizeof (gVmdDriverStart) + sizeof (gVmdDriverStop) +
sizeof (gVmdHiiExtractHii) + sizeof (gVmdHiiRouteHii) +
sizeof (gVmdHiiExtractHii2) + sizeof (gVmdHiiRouteHii2));
gVmdDeviceCount = 0;
gVmdDesiredCount = -1;
gVmdLedStatus = 0;
/* Set up function pointers for driver binding */
gVmdDriverSupported = (UINT64)VmdDriverBindingSupported;
gVmdDriverStart = (UINT64)VmdDriverBindingStart;
gVmdDriverStop = (UINT64)VmdDriverBindingStop;
/* HII access callbacks */
gVmdHiiExtractHii = (UINT64)VmdExtractHii;
gVmdHiiRouteHii = (UINT64)VmdRouteHii;
gVmdHiiExtractHii2 = (UINT64)VmdExtractHii;
gVmdHiiRouteHii2 = (UINT64)VmdRouteHii;
/* Device path protocol callbacks */
gVmdDevicePathExtract = (UINT64)VmdDevicePathExtract;
gVmdDevicePathConfig = (UINT64)VmdDevicePathConfig;
/* Language support */
gVmdHiiLangFlags = 1;
gVmdEngLanguage = "eng";
gVmdEnLanguage = "en";
/* Store image handle */
gVmdImageHandle = (UINT64)ImageHandle;
/* Register driver binding, component name, HII config access, device path
* via InstallMultipleProtocolInterfaces */
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiDriverBindingProtocolGuid,
&gVmdDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gVmdDevicePathProtocolGuid,
&gVmdHiiConfigAccessProtocolGuid,
&gVmdHiiPackageListProtocolGuid,
NULL
);
ASSERT_EFI_ERROR (Status);
/* Store VMD driver handle */
gVmdImageHandle = (UINT64)ImageHandle;
gVmdDriverBdHandle = (UINT64)ImageHandle;
gVmdDriverBdHandle2 = (UINT64)ImageHandle;
/* Initialize size constant for HII package */
/* (131112 = size of HII package list in rdata) */
/* Install HII package list on image handle using PCD */
Status = gBS->InstallMultipleProtocolInterfaces (
&gHiiConfigRouting,
&gEfiHiiPackageListProtocolGuid,
(VOID *)gHiiConfigRouting,
NULL
);
ASSERT_EFI_ERROR (Status);
/* Register HII config access variable for LED */
gBS->InstallMultipleProtocolInterfaces (
&gVmdLedVariable,
&gVmdLedVariableGuid,
&gVmdLedConfig,
NULL
);
/* Check for LED_HW_Implementation variable */
{
UINT32 LedSize = 4;
UINT32 LedValue = 0;
Status = gRT->GetVariable (
L"LED_HW_Implementation",
&gVmdLedVariableGuid,
NULL,
&LedSize,
&LedValue
);
if (!EFI_ERROR (Status)) {
gVmdHiiLangFlags = 0;
gVmdLedStatus = LedValue;
gVmdLedHwConfig = (UINT16)((LedValue >> 8) | (LedValue << 8));
}
}
/* Check system table revision for VMD support (must be >= 0x2001E) */
if (SystemTable->Hdr.Revision < 0x2001E) {
return EFI_UNSUPPORTED;
}
/* Store driver handle globally for protocol installs */
/* Initialize NVMe controller bindings */
Status = VmdNvmeControllerInit ();
if (Status < 0) {
ASSERT_EFI_ERROR (Status);
}
/* Install HII package list */
Status = gBS->InstallMultipleProtocolInterfaces (
&gST->Hdr,
&gEfiHiiPackageListProtocolGuid,
&gEfiHiiPackageListProtocolGuid,
NULL
);
ASSERT_EFI_ERROR (Status);
/* Register protocol notification for NvmExpressDxe binding */
return Status;
}
/*============================================================================
* sub_3FC - VmdDriverEntry (continuation/2nd stage entry)
*
* Called from ModuleEntryPoint before VmdDriverEntryPoint completes.
* This sets up:
* - Function pointer tables for driver binding
* - Protocol registration for HII and device path
* - NVMe initialization
* - Global variable initial values
*============================================================================*/
EFI_STATUS
EFIAPI
VmdDriverEntryStage2 (
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE SystemTable
)
{
EFI_STATUS Status;
/* Allocate driver binding data */
VMD_CONTROLLER *VmdController;
VmdController = AllocatePool (sizeof (VMD_CONTROLLER));
if (VmdController == NULL || /* 2nd alloc */ NULL == NULL) {
ASSERT (VmdController != NULL);
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (VmdController, sizeof (VMD_CONTROLLER));
/* Initialize VMD controller: signature = "NVME" */
VmdController->Signature = NVME_CONTROLLER_SIGNATURE;
VmdController->Signature |= 1; /* version field */
/* Setup function dispatch table */
VmdController->VmdMmioBase = 0;
VmdController->VmdMmioSize = 0;
/* Store in global and register with boot services */
VmdController->NvmePrivate1 = gNvmePrivate1;
VmdController->NvmePrivate2 = gNvmePrivate2;
/* Register protocol interfaces with the boot services */
{
EFI_GUID *ProtocolGuid;
EFI_GUID *ProtocolGuid2;
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiNvmExpressPassThruProtocolGuid,
VmdController,
&gEfiBlockIoProtocolGuid,
VmdController,
NULL
);
if (Status < 0) {
/* Fallback: install via the root bridge handle */
Status = gBS->InstallMultipleProtocolInterfaces (
&gVmdDriverBdHandle2,
&gEfiNvmExpressPassThruProtocolGuid,
VmdController,
NULL
);
}
}
/* Register protocol notification callbacks for:
* - NVM Express PassThru (driver binding for NVMe)
* - PCI Root Bridge IO (for child device enumeration)
*/
gBS->RegisterProtocolNotify (
&gEfiNvmExpressPassThruProtocolGuid,
VmdNvmePassThruNotification,
&VmdController->NvmePrivate1
);
gBS->RegisterProtocolNotify (
&gEfiPciRootBridgeIoProtocolGuid,
VmdRootBridgeIoNotification,
&VmdController->NvmePrivate2
);
return EFI_SUCCESS;
}
/*============================================================================
* sub_508 - VmdDevicePathGetProtocol
*
* CR-based retrieval: extract DEVICE_PATH from VMD_DEVICE structure.
*============================================================================*/
EFI_STATUS
EFIAPI
VmdDevicePathGetProtocol (
IN VMD_PCI_IO *This,
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
)
{
VMD_DEVICE *VmdDevice;
if (*(UINT32 *)((UINT8 *)This - 32) == VMD_DEVICE_SIGNATURE) {
VmdDevice = (VMD_DEVICE *)((UINT8 *)This - 32);
} else {
ASSERT (VmdDevice != NULL);
return EFI_INVALID_PARAMETER;
}
*DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)VmdDevice->DevicePath;
return EFI_SUCCESS;
}
/*============================================================================
* sub_554 - VmdCreateChildProtocol
*
* Creates and installs a child protocol instance for an NVMe namespace.
* Uses CR macro to verify VMD_DEVICE signature.
*============================================================================*/
EFI_STATUS
EFIAPI
VmdCreateChildProtocol (
IN VMD_PCI_IO *VmdPciIo,
IN UINT32 NamespaceId,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
IN UINT64 NamespaceSize,
OUT VOID **ChildProtocol OUT OPTIONAL
)
{
NVME_DEVICE_PRIVATE *NsDevice;
EFI_STATUS Status;
/* Validate via CR macro: VMD_PCI_IO to VMD_DEVICE */
VMD_DEVICE *VmdDevice;
if (*(UINT32 *)((UINT8 *)VmdPciIo - 32) == VMD_DEVICE_SIGNATURE) {
VmdDevice = (VMD_DEVICE *)((UINT8 *)VmdPciIo - 32);
} else {
ASSERT (VmdDevice != NULL);
return EFI_INVALID_PARAMETER;
}
/* Allocate NVMe device private data */
NsDevice = AllocatePool (sizeof (NVME_DEVICE_PRIVATE));
if (NsDevice == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (NsDevice, sizeof (NVME_DEVICE_PRIVATE));
/* Initialize NVMe namespace device */
NsDevice->Signature = VMD_DEVICE_SIGNATURE;
NsDevice->ControllerHandle = VmdPciIo->Controller;
NsDevice->PhysicalId = (UINT8)NamespaceId;
/* Copy namespace info if provided */
if (NamespaceSize != 0) {
Status = VmdCopyDevicePath (NsDevice, DevicePath, NamespaceSize);
if (Status < 0) {
return Status;
}
}
/* Copy device path if provided */
if (DevicePath != NULL) {
VmdCopyDevicePathEntry (NsDevice, DevicePath);
}
return EFI_SUCCESS;
}
/*============================================================================
* sub_88C - VmdCountNvmeChildren
*
* Enumerates all PCI I/O handles and counts VMD NVMe child devices
* by checking class code.
*============================================================================*/
UINTN
EFIAPI
VmdCountNvmeChildren (
VOID
)
{
UINTN Count = 0;
UINTN Index;
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
UINTN HandleCount;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status))
return 0;
for (Index = 0; Index < HandleCount; Index++) {
EFI_PCI_IO_PROTOCOL *PciIo;
Status = gBS->OpenProtocol (
HandleBuffer[Index],
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
PCI_TYPE00 Pci;
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
sizeof (Pci) / sizeof (UINT32),
&Pci
);
if (!EFI_ERROR (Status)) {
/* Check for NVMe class code (01 08 02) */
if (Pci.Hdr.ClassCode[2] == 0x01 &&
Pci.Hdr.ClassCode[1] == 0x08 &&
Pci.Hdr.ClassCode[0] == 0x02)
{
/* Check device path vendor/device for VMD range */
UINT16 VendorId;
UINT16 DeviceId;
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId);
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId);
if (VendorId == INTEL_VMD_VID) {
Count++;
}
}
}
}
}
gBS->FreePool (HandleBuffer);
return Count;
}
/*============================================================================
* sub_100C - VmdNsUpdateIdentifyData
*
* Updates the identify controller data with current HW state.
* Used per-NVMe child when a VMD device event occurs.
*============================================================================*/
VOID
EFIAPI
VmdNsUpdateIdentifyData (
IN VMD_DEVICE *VmdDevice
)
{
NVME_DEVICE_PRIVATE *NsDevice;
if (VmdDevice == NULL)
return;
NsDevice = (NVME_DEVICE_PRIVATE *)VmdDevice->NvmeControllerPrivate;
if (NsDevice == NULL)
return;
NVME_CONTROLLER_PRIVATE *NvmeCtrl = NsDevice->VmdDevice;
/* Check if this is the special namespace (type 0x1DA7) */
if (NvmeCtrl != NULL && *(UINT16 *)NvmeCtrl->IdentifyControllerData == 0x1DA7 &&
*(UINT16 *)(NvmeCtrl->IdentifyControllerData + 2) == 0x8011)
{
/* This is the special VMD management namespace - skip */
return;
}
/* Update controller namespace data from VMD registers */
if (NvmeCtrl != NULL && NvmeCtrl->IdentifyControllerData != NULL) {
/* Copy current register values to identify data structure */
for (INTN i = 0; i < 6; i++) {
if ((NvmeCtrl->IdentifyControllerData[i] & 0xFFFFFFF0) != 0) {
NvmeCtrl->IdentifyControllerData[i] = NvmeCtrl->IdentifyControllerData[i];
}
}
}
/* Walk all child NVMe devices and check for register updates */
if (VmdDevice->NvmeControllerPrivate != NULL) {
NVME_DEVICE_PRIVATE *Child;
/* Walk child list */
}
}
/*============================================================================
* sub_11B0 - VmdNvmeFirmwareUpdateHandler
*
* Called when a firmware update event fires on a VMD device.
* Reads NVMe device config, updates slot/firmware status.
*============================================================================*/
VOID
EFIAPI
VmdNvmeFirmwareUpdateHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
VMD_CONTROLLER *VmdController = (VMD_CONTROLLER *)Context;
if (VmdController == NULL)
return;
/* Read NVMe device via VMD's PCI IO */
EFI_PCI_IO_PROTOCOL *PciIo = (EFI_PCI_IO_PROTOCOL *)VmdController->PciIo;
if (PciIo == NULL)
return;
/* Read BAR0/MMIO registers via standard PCI IO */
PCI_TYPE00 PciConfig;
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof(PciConfig)/4, &PciConfig);
/* Write back to config space for VMD MMIO mirror */
/* Update all child NVMe devices behind VMD */
VMD_DEVICE *VmdDevice;
VMD_DEVICE *BestDevice = NULL;
/* Walk linked list of children, find the best (highest fw slot) */
VmdDevice = (VMD_DEVICE *)VmdController->VmdDevices[0];
while (VmdDevice != NULL) {
VmdNsUpdateIdentifyData (VmdDevice);
VmdDevice = (VMD_DEVICE *)((VMD_DEVICE **)VmdDevice)[0];
}
/* Restore config space from identify data to complete the update */
}
/*============================================================================
* ASSERT / DEBUG / Helper Library Functions
*============================================================================*/
/* ---- sub_4134 - VmdDebugPrint (DEBUG macro) ---- */
VOID
EFIAPI
VmdDebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
CHAR8 Buffer[256];
VA_LIST Marker;
if (Format == NULL) {
ASSERT (Format != NULL);
}
if (ErrorLevel >= BIT31) {
VA_START (Marker, Format);
UnicodeVSPrintAsciiFormat (Buffer, sizeof(Buffer), Format, Marker);
VA_END (Marker);
if (gST != NULL && gST->ConOut != NULL) {
gST->ConOut->OutputString (gST->ConOut, Buffer);
}
}
}
/* ---- sub_41BC - VmdAssert (ASSERT macro) ---- */
VOID
EFIAPI
VmdAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
CHAR8 Buffer[520];
UnicodeSPrintAsciiFormat (
Buffer, sizeof(Buffer),
"ASSERT [%a] %a(%d): %a\n",
FileName, FileName, LineNumber, Description
);
if (gST != NULL && gST->ConOut != NULL) {
gST->ConOut->OutputString (gST->ConOut, Buffer);
}
}
/* ---- sub_44C0 - ZeroMem wrapper ---- */
VOID *
EFIAPI
ZeroMem (
IN VOID *Buffer,
IN UINTN Length
)
{
if (Length == 0)
return Buffer;
if (Buffer == NULL) {
ASSERT (Buffer != NULL);
}
if (Length > (MAX_ADDR - (UINTN)Buffer + 1)) {
ASSERT (Length <= (MAX_ADDR - (UINTN)Buffer + 1));
}
return InternalZeroMem (Buffer, Length);
}
/* ---- sub_4418 - CopyMem wrapper ---- */
VOID *
EFIAPI
CopyMem (
IN VOID *Destination,
IN const VOID *Source,
IN UINTN Length
)
{
if (Length == 0)
return Destination;
if ((Length - 1) > (MAX_ADDR - (UINTN)Destination)) {
ASSERT ((Length - 1) <= (MAX_ADDR - (UINTN)Destination));
}
if ((Length - 1) > (MAX_ADDR - (UINTN)Source)) {
ASSERT ((Length - 1) <= (MAX_ADDR - (UINTN)Source));
}
if (Destination == Source)
return Destination;
return InternalCopyMem (Destination, Source, Length);
}
/* ---- sub_4794 - AllocatePool wrapper (allocate + zero) ---- */
VOID *
EFIAPI
AllocatePool (
IN UINTN AllocationSize
)
{
VOID *Buffer;
Buffer = InternalAllocatePool (AllocationSize);
if (Buffer != NULL) {
ZeroMem (Buffer, AllocationSize);
}
return Buffer;
}
/* ---- sub_48B0 - FreePool wrapper ---- */
VOID
EFIAPI
FreePool (
IN VOID *Buffer
)
{
EFI_STATUS Status;
Status = gBS->FreePool (Buffer);
if (EFI_ERROR (Status)) {
VmdDebugPrint (EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
VmdAssert (
"d:\\qba1\\workspace\\27990\\vmd_uefi\\MdePkg\\Library\\UefiMemoryAllocationLib\\MemoryAllocationLib.c",
819,
"!EFI_ERROR (Status)"
);
}
}
/*============================================================================
* Helper: sub_4DCC - DevicePathToText
*
* Converts an EFI_DEVICE_PATH_PROTOCOL to a human-readable Unicode string.
* Walks the device path nodes and builds a text representation.
*============================================================================*/
CHAR16 *
EFIAPI
DevicePathToText (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
CHAR16 *ResultStr;
UINTN StrSize;
/* Start with empty string (2 bytes for NULL) */
StrSize = 2;
ResultStr = AllocatePool (StrSize);
if (ResultStr == NULL)
return NULL;
ResultStr[0] = 0;
/* Walk device path nodes */
while (!IsDevicePathEnd (DevicePath) && !IsDevicePathEnd (DevicePath)) {
/* Append separator */
StrCatS (ResultStr, StrSize / 2, L"/");
StrSize += 2;
/* Append node text based on type/subtype */
switch (DevicePathNodeType (DevicePath)) {
case HARDWARE_DEVICE_PATH:
/* Hardware device path nodes */
StrCatS (ResultStr, StrSize / 2, DevicePathNodeToText (DevicePath));
break;
case ACPI_DEVICE_PATH:
StrCatS (ResultStr, StrSize / 2, DevicePathNodeToText (DevicePath));
break;
case MESSAGING_DEVICE_PATH:
if (DevicePathSubType (DevicePath) == MSG_NVME_NAMESPACE_DP) {
StrCatS (ResultStr, StrSize / 2, DevicePathNodeToText (DevicePath));
}
break;
default:
break;
}
DevicePath = NextDevicePathNode (DevicePath);
}
return ResultStr;
}
/* ---- sub_4F18 - DevicePathStrCat ---- */
CHAR16 *
EFIAPI
DevicePathStrCat (
IN OUT CHAR16 *Str,
IN CHAR16 *Append
)
{
UINTN StrLen;
UINTN AppendLen;
StrLen = StrLen (Str);
AppendLen = StrLen (Append);
/* Check if reallocation is needed */
if (2 * (StrLen + AppendLen) + 2 > Str->MaxSize) {
Str->MaxSize = 2 * (AppendLen + 2 + 2 * StrLen);
Str->Str = ReallocatePool (2 * StrLen, Str->MaxSize, Str->Str);
if (Str->Str == NULL) {
ASSERT (Str->Str != NULL);
}
}
StrCatS (Str->Str + 2 * StrLen, (Str->MaxSize - 2 * StrLen) / 2, Append);
Str->Length += AppendLen;
return Str->Str;
}
/* ---- sub_4DCC entry: walk device path and build text ---- */
/*============================================================================
* VMD Device Path Protocol
*============================================================================*/
/* ---- sub_1BC0 - VmdDevicePathExtract ---- */
BOOLEAN
EFIAPI
VmdDevicePathExtract (
IN VMD_PCI_IO *This
)
{
VMD_CONTROLLER *VmdController;
VMD_DEVICE *VmdDevice;
if (This == NULL)
return FALSE;
/* CR-based extraction from VMD_PCI_IO */
if (*(UINT32 *)((UINT8 *)This - 112) == NVME_CONTROLLER_SIGNATURE) {
VmdController = (VMD_CONTROLLER *)((UINT8 *)This - 96);
} else {
VmdController = NULL;
}
if (VmdController == NULL)
return FALSE;
VmdDevice = (VMD_DEVICE *)VmdController->VmdDevices[0];
if (VmdDevice == NULL)
return FALSE;
return TRUE;
}
/* ---- sub_1C14 - VmdDevicePathConfig ---- */
BOOLEAN
EFIAPI
VmdDevicePathConfig (
IN VMD_PCI_IO *This,
IN UINT8 ConfigType
)
{
VMD_CONTROLLER *VmdController;
VMD_DEVICE *VmdDevice;
NVME_CONTROLLER_PRIVATE *NvmePrivate;
BOOLEAN Result = FALSE;
if (This == NULL)
return FALSE;
/* CR-based extraction */
if (*(UINT32 *)((UINT8 *)This - 112) == NVME_CONTROLLER_SIGNATURE) {
VmdController = (VMD_CONTROLLER *)((UINT8 *)This - 96);
} else {
VmdController = NULL;
}
if (VmdController == NULL)
return FALSE;
VmdDevice = (VMD_DEVICE *)VmdController->VmdDevices[0];
if (VmdDevice == NULL)
return FALSE;
NvmePrivate = (NVME_CONTROLLER_PRIVATE *)VmdDevice->NvmeControllerPrivate;
if (NvmePrivate == NULL)
return FALSE;
switch (ConfigType) {
case DEVICE_PATH_EXTRACT:
/* Extract device path */
return TRUE;
case DEVICE_PATH_GET_ATTRS:
/* Get attributes */
return TRUE;
case DEVICE_PATH_GET_SIZE:
/* Get size of child device */
return TRUE;
default:
return FALSE;
}
}
/*============================================================================
* VMD NVMe Controller Init
*============================================================================*/
/* ---- sub_DA24 - VmdNvmeControllerInit ---- */
EFI_STATUS
EFIAPI
VmdNvmeControllerInit (
VOID
)
{
if (gNvmePrivate1 == 0) {
/* Allocate first NVMe controller private data */
gNvmePrivate1 = (UINT64)AllocatePool (sizeof (NVME_CONTROLLER_PRIVATE));
CopyMem (&gNvmeNsConfig1[0], &gNvmeNsConfig1[0], 24);
/* Initialize namespace config for slot A */
return EFI_SUCCESS;
}
if (gNvmePrivate2 == 0) {
/* Allocate second NVMe controller private data */
gNvmePrivate2 = (UINT64)AllocatePool (sizeof (NVME_CONTROLLER_PRIVATE));
CopyMem (&gNvmeNsConfig2[0], &gNvmeNsConfig2[0], 24);
/* Initialize namespace config for slot B */
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
/*============================================================================
* VMD Block I/O Protocol for NVMe Namespace
*============================================================================*/
UINTN
EFIAPI
VmdBlockIoGetNumBlocks (
IN VMD_DEVICE *VmdDevice
)
{
UINTN Count = 0;
BLOCK_IO_ENTRY *Entry;
if (VmdDevice == NULL)
return 0;
Entry = VmdDevice->BlockIoListHead->ForwardLink;
while (Entry != VmdDevice->BlockIoListHead) {
Count++;
Entry = Entry->ForwardLink;
}
return Count;
}
EFI_STATUS
EFIAPI
VmdBlockIoReadBlocks (
IN VMD_DEVICE *VmdDevice,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdBlockIoWriteBlocks (
IN VMD_DEVICE *VmdDevice,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdBlockIoFlushBlocks (
IN VMD_DEVICE *VmdDevice
)
{
return EFI_SUCCESS;
}
/*============================================================================
* VMD NVM Express PassThru Protocol
*============================================================================*/
EFI_STATUS
EFIAPI
VmdNvmePassThru (
IN VMD_DEVICE *VmdDevice,
IN UINT32 NamespaceId,
IN EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
IN EFI_EVENT Event OPTIONAL
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdNvmeGetNextNamespace (
IN VMD_DEVICE *VmdDevice,
IN OUT UINT32 *NamespaceId,
OUT EFI_NVM_EXPRESS_NS_PROTOCOL **Protocol OPTIONAL
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdNvmeGetNamespace (
IN VMD_DEVICE *VmdDevice,
IN UINT32 NamespaceId,
OUT EFI_NVM_EXPRESS_NS_PROTOCOL *Protocol
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdNvmeBuildDevicePath (
IN VMD_DEVICE *VmdDevice,
IN UINT32 NamespaceId,
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
)
{
return EFI_SUCCESS;
}
VOID
EFIAPI
VmdNvmeTimerPoll (
IN EFI_EVENT Event,
IN VOID *Context
)
{
}
VOID
EFIAPI
VmdNvmePassThruNotification (
IN EFI_EVENT Event,
IN VOID *Context
)
{
}
VOID
EFIAPI
VmdRootBridgeIoNotification (
IN EFI_EVENT Event,
IN VOID *Context
)
{
}
/*============================================================================
* VMD HII Configuration Access Protocol
*============================================================================*/
EFI_STATUS
EFIAPI
VmdExtractHii (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Request,
OUT EFI_STRING *Progress,
OUT UINT8 **Results
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
VmdRouteHii (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Configuration,
OUT EFI_STRING *Progress
)
{
return EFI_SUCCESS;
}
/*============================================================================
* VMD NVMe HCI Queue Setup
*============================================================================*/
EFI_STATUS
EFIAPI
VmdNvmeSetupQueues (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl
)
{
return EFI_SUCCESS;
}
/*============================================================================
* VMD Helper Functions
*============================================================================*/
EFI_STATUS
VmdCopyDevicePath (
IN OUT NVME_DEVICE_PRIVATE *Ns,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT64 Size
)
{
return EFI_SUCCESS;
}
VOID
VmdCopyDevicePathEntry (
IN OUT NVME_DEVICE_PRIVATE *Ns,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
}
/*============================================================================
* VMD PCI IO Protocol Functions (VmdPciIo.c)
*
* These functions implement the EFI_PCI_IO_PROTOCOL operations for VMD
* children. The VMD remaps standard PCI config cycles into VMD MMIO.
*============================================================================*/
/* ---- sub_2114 - VmdPciIoPollMem ---- */
UINT8
EFIAPI
VmdPciIoPollMem (
IN VMD_PCI_IO *This,
IN UINT64 Address,
IN UINT64 Value,
UINT64 Mask /* actually: Width+Mask combined */
)
{
return 0xFF; /* return first child matching */
}
/* ---- sub_221C - VmdPciIoUnmap ---- */
VOID
EFIAPI
VmdPciIoUnmap (
IN VMD_PCI_IO *This,
IN UINT64 Address,
IN UINT64 ChildAddress
)
{
}
/* ---- sub_24C0 - VmdPciIoCopyMem (return previous) ---- */
UINT64
EFIAPI
VmdPciIoCopyMem (
IN VMD_PCI_IO *This,
IN VOID *Buffer
)
{
return 0; /* previous mapping */
}
/* ---- sub_2578 - VmdPciIoAllocateBuffer ---- */
UINT8 *
EFIAPI
VmdPciIoAllocateBuffer (
IN VMD_PCI_IO *This,
IN UINTN Pages
)
{
return NULL;
}
/* ---- sub_2618 - VmdNvmeDeviceEnumerate ---- */
UINTN
EFIAPI
VmdNvmeDeviceEnumerate (
IN VMD_CONTROLLER *VmdController
)
{
return 0; /* number of devices found */
}
/* ---- sub_2C48 - VmdCreateDeviceInstance ---- */
VOID
EFIAPI
VmdCreateDeviceInstance (
IN OUT VMD_DEVICE *Device,
IN VOID *NvmeDevice,
IN UINT8 Slot,
IN UINT8 IsActive,
IN VOID *ConfigSpace
)
{
}
/* ---- sub_3228 - VmdFindActiveChild ---- */
VMD_DEVICE *
EFIAPI
VmdFindActiveChild (
IN VMD_CONTROLLER *VmdController
)
{
return NULL;
}
/* ---- sub_3258 - VmdMmioAlloc ---- */
UINT64
EFIAPI
VmdMmioAlloc (
IN UINT64 *Region,
IN UINTN Size
)
{
return 0;
}
/* ---- sub_3360 - VmdAllocDmaBuffer ---- */
VOID *
EFIAPI
VmdAllocDmaBuffer (
IN VMD_CONTROLLER *VmdController,
IN UINT8 Attributes
)
{
return NULL;
}
/* ---- sub_34B8 - VmdCopyNvmeStatus ---- */
EFI_STATUS
EFIAPI
VmdCopyNvmeStatus (
IN VMD_CONTROLLER *VmdController,
IN VOID *StatusBuffer
)
{
return EFI_SUCCESS;
}
/* ---- sub_36F0 / sub_375C / sub_37E8 - VmdPciIoPollMem/PollIo ---- */
/* ---- sub_3A28 - VmdPciIoPollMemExtended ---- */
EFI_STATUS
EFIAPI
VmdPciIoPollMemEx (
IN VMD_PCI_IO *This,
IN UINTN Width,
IN UINT64 Address,
IN UINT64 Mask,
IN UINT64 Value,
IN UINT64 Timeout
)
{
return EFI_SUCCESS;
}
/* ---- sub_6CB0 - NvmeGetIdentifyInfo ---- */
EFI_STATUS
EFIAPI
NvmeGetIdentifyInfo (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
OUT VOID *Buffer,
IN OUT UINT32 *BufferSize
)
{
return EFI_SUCCESS;
}
/* ---- sub_6EFC - VmdGetSlotInfo ---- */
UINT8
EFIAPI
VmdGetSlotInfo (
IN UINT64 VmdMmioBase,
OUT UINT8 *SlotNumber
)
{
return 0xFF;
}
/* ---- sub_6944 - VmdHiiConfigExtract ---- */
/* ---- sub_7504 - VmdDriverBindingSupported (for subclass match) ---- */
/* ---- sub_7640 - VmdCreateChildController ---- */
/* ---- sub_DA24 - VmdNvmeControllerInit ---- */
/* ---- sub_DAD0 - VmdLocateDevicePath ---- */
/* ---- sub_DCB4 - VmdRegisterProtocolNotify ---- */
/* ---- sub_DCE8 - VmdInstallProtocolInterfaces ---- */
/* ---- sub_E014 - VmdUninstallProtocol ---- */
/*============================================================================
* VMD NVM Express Passthru Protocol (from NvmExpressPassthru.c)
*============================================================================*/
/* ---- sub_82D4 - NvmeSubmitCommand ---- */
EFI_STATUS
EFIAPI
NvmeSubmitCommand (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 NamespaceId,
IN UINT64 Command,
IN VOID *Packet,
IN UINT64 Timeout
)
{
return EFI_UNSUPPORTED;
}
/* ---- sub_8884 - NvmeGetNextNamespace ---- */
EFI_STATUS
EFIAPI
NvmeGetNextNamespace (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 *NamespaceId,
OUT VOID *Protocol
)
{
return EFI_SUCCESS;
}
/* ---- sub_89C0 - NvmeBuildDevicePath ---- */
EFI_STATUS
EFIAPI
NvmeBuildDevicePath (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 NamespaceId,
OUT VOID *DevicePathNode,
OUT UINT32 *NsId,
OUT VOID *Protocol
)
{
return EFI_SUCCESS;
}
/* ---- sub_8AA0 - NvmeGetNamespace (async) ---- */
EFI_STATUS
EFIAPI
NvmeGetNamespace (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 NamespaceId,
OUT VOID *Protocol
)
{
return EFI_SUCCESS;
}
/* ---- sub_8B54 - NvmExpressPassThru ---- */
EFI_STATUS
EFIAPI
NvmExpressPassThru (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 NamespaceId,
IN EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
IN EFI_EVENT Event
)
{
return EFI_SUCCESS;
}
/* ---- sub_8D60 - NvmeGetNextNamespaceEx ---- */
EFI_STATUS
EFIAPI
NvmeGetNextNamespaceEx (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT64 *NsProtocol,
OUT UINT8 *IsEnd
)
{
return EFI_SUCCESS;
}
/* ---- sub_8DD0 - NvmExpressGetNextNamespace ---- */
EFI_STATUS
EFIAPI
NvmExpressGetNextNamespace (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN OUT UINT32 *NamespaceId,
OUT EFI_NVM_EXPRESS_NS_PROTOCOL **Protocol
)
{
return EFI_SUCCESS;
}
/* ---- sub_8E54 - NvmExpressBuildDevicePath ---- */
EFI_STATUS
EFIAPI
NvmExpressBuildDevicePath (
IN NVME_CONTROLLER_PRIVATE *NvmeCtrl,
IN UINT32 NamespaceId,
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
)
{
return EFI_SUCCESS;
}
/* ---- sub_8EF0 - NvmeBuildCommandPacket ---- */
/* ---- sub_9198 - NvmeReadCapRegisters ---- */
/* ---- sub_9338 - NvmeControllerInit (HCI) ---- */
/* ---- sub_9414 - NvmeSetupAdminQueues ---- */
/* ---- sub_94C0 - NvmeSetupIoQueues ---- */
/* ---- sub_9590 - NvmeReadIdentifyNamespace ---- */
/* ---- sub_9674 - NvmeSetupIoSubmissionQueues ---- */
/* ---- sub_9854 - NvmeSetupIoCompletionQueues ---- */
/* ---- sub_9A3C - NvmeControllerInitFull ---- */
/* ---- sub_B38C - NvmeControllerShutdown ---- */
/* ---- sub_C088 - NvmeCheckProtocolInstall ---- */
/* ---- sub_C0B8 - FreePoolEx ---- */
/* ---- sub_E28C - UnicodeSPrintAsciiFormat ---- */
/* ---- sub_E338 - UnicodeVSPrintAsciiFormat ---- */
/* ---- sub_E3A8 - UnicodeSPrintAsciiFormat (with size) ---- */
/* ---- sub_E41C - StrLen ---- */
/* ---- sub_F484 - NvmeMmuPageToPhysical ---- */
/* ---- sub_F4F0 - NvmePhysicalToMmuPage ---- */
/* ---- sub_F560 - NvmeIdentifyNamespacePoll ---- */
/* ---- sub_F6D8 - ACPI table lookup for VMD ---- */
/* ---- sub_F7D0 - ACPI table decode ---- */
/* ---- sub_F92C - HII string compare ---- */
/* ---- sub_F9F0 - HII config routing ---- */
/* ---- sub_FBE0 - NvmeIdentifyController (poll) ---- */
/* ---- sub_10848 - NvmePollCompletion (SQ tail) ---- */
/* ---- sub_10A3C - NvmeZeroString ---- */
/*============================================================================
* Library Helpers (from BaseLib, BasePrintLib, UefiDevicePathLib)
*============================================================================*/
/* ---- sub_280 - memmove (overlapping copy) ---- */
VOID *
EFIAPI
VmdMemmove (
VOID *Destination,
const VOID *Source,
UINTN Length
)
{
return memmove (Destination, Source, Length);
}
/* ---- sub_330 - memset ---- */
VOID *
EFIAPI
VmdMemset (
VOID *Buffer,
UINTN Size
)
{
return memset (Buffer, 0, Size);
}
/* ---- sub_1C98 - VmdGetLedSlot ---- */
UINT8
EFIAPI
VmdGetLedSlot (
IN UINT8 RegisterValue,
IN UINT8 SlotType
)
{
switch (SlotType) {
case DEVICE_PATH_LED_TYPE:
return RegisterValue & 3;
case DEVICE_PATH_LED_TYPE_SHIFT2:
return (RegisterValue >> 2) & 3;
case DEVICE_PATH_LED_TYPE_SHIFT4:
return (RegisterValue >> 4) & 3;
case DEVICE_PATH_LED_TYPE_SHIFT6:
return RegisterValue >> 6;
default:
return 0;
}
}
/* ---- sub_4F18 - DevicePathStrCat ---- */
/* ---- sub_56E8 - DevicePathScsiText ---- */
CHAR16 *
EFIAPI
DevicePathScsiText (
IN OUT CHAR16 *Str,
IN VOID *ScsiDevicePath
)
{
return DevicePathStrCat (
Str, L"Scsi(0x%x,0x%x)",
*(UINT16 *)(ScsiDevicePath + 4),
*(UINT16 *)(ScsiDevicePath + 6)
);
}