/**
* 5038F34E-0774-47A0-A5EF-4B94AF1A43DA.c
* Intel DCPMM (Optane Persistent Memory / NVDIMM) UEFI Driver
*
* This DXE driver manages Intel Optane DC Persistent Memory Modules (DCPMM/NVDIMM)
* on Lenovo HR650X platforms. It provides protocols for:
* - NVDIMM firmware communication via SMBUS passthrough
* - Namespace management (BTT block translation, PFN page mapping)
* - AppDirect interleave set configuration
* - Health monitoring and status reporting
* - CSV-formatted DIMM inventory export
*
* Source: Lenovo HR650X BIOS, extracted PE module
* Module GUID: 5038F34E-0774-47A0-A5EF-4B94AF1A43DA
* Architecture: x86_64 (UEFI DXE driver)
*
* Function naming convention:
* Dcpmm* - DCPMM driver core functions
* Nvdimm* - NVDIMM device management
* Smbus* - SMBUS communication (COM port I/O 0x3F8-0x3FD)
* DimmLabel* - NVDIMM namespace label operations
* DimmFwCmd* - NVDIMM firmware command passthrough
* DimmConfig* - NVDIMM configuration data read/write
* DimmHealth* - NVDIMM health/status operations
* DimmInfo* - NVDIMM info query (SMBIOS/NFIT parsing)
* Nfit* - ACPI NFIT table parsing
* Btt* - Block Translation Table operations
* Pfn* - Page Frame Number operations
* Util* - Utility functions (memset, memcpy, alloc, print)
* Driver* - UEFI driver model entry/exit/binding
* Protocol* - Protocol installation and dispatch
*/
/*============================================================================
* Forward Declarations
*============================================================================*/
static EFI_STATUS
EFIAPI
DcpmmDriverSupported(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
);
static EFI_STATUS
EFIAPI
DcpmmDriverStart(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
);
static EFI_STATUS
EFIAPI
DcpmmDriverStop(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
);
static EFI_STATUS
DcpmmFirmwareCommandDispatch(
IN NVDIMM_DEVICE *Device,
IN UINT32 Command,
IN UINT32 InputSize,
IN VOID *InputData,
OUT UINT32 *OutputSize,
OUT VOID *OutputData,
IN UINT8 RetryCount,
IN UINT64 Timeout
);
/*============================================================================
* Global Variables
*============================================================================*/
EFI_SYSTEM_TABLE *gSystemTable = NULL; // 0x33348
EFI_BOOT_SERVICES *gBootServices = NULL; // 0x33350
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL; // 0x33358
DCPMM_DRIVER_GLOBAL *gDcpmmDriver = NULL; // qword_33308
UINT64 gNvdimmHandleCount = 0;
EFI_HANDLE *gNvdimmHandles = NULL;
EFI_HANDLE gImageHandle = NULL;
EFI_HANDLE gControllerHandle = NULL;
/*============================================================================
* Protocol GUIDs (defined externally in .data section)
*============================================================================*/
extern EFI_GUID unk_31F20; // DCPMM protocol
extern EFI_GUID unk_31F50; // DCPMM config protocol
extern EFI_GUID unk_31E70; // DCPMM health protocol
extern EFI_GUID unk_31EB0; // SMBus HC protocol
extern EFI_GUID unk_31EC0; // NVDIMM PassThru protocol
extern EFI_GUID unk_31ED0; // SMBus arbitration protocol
extern EFI_GUID unk_31F00; // Unknown located protocol
extern EFI_GUID unk_31F90; // Device path utilities
extern EFI_GUID unk_31E80; // SMBIOS protocol
extern EFI_GUID unk_31EA0; // Device path protocol GUID
extern EFI_GUID unk_31B88; // NVDIMM Firmware Interface Table protocol
extern EFI_GUID unk_31FA0; // Namespace protocol instance
extern EFI_GUID unk_2AFC0; // Driver Binding protocol GUID
extern EFI_GUID unk_2B028; // NVDIMM device path instance
extern EFI_GUID unk_2AFD0;
extern EFI_GUID unk_2AFE0;
extern EFI_GUID unk_2B000;
extern EFI_GUID unk_2B010;
// Protocol dispatch tables (defined externally in .data section)
extern VOID *off_31B98; // Protocol function table
extern VOID *off_31FA8; // Configuration protocol table
extern VOID *off_31FC0; // Health protocol table
extern VOID *off_32030; // Firmware interface table
extern VOID *off_32020; // Admin protocol table
extern VOID *off_32040; // SMBUS protocol table
extern VOID *unk_31FA0; // Namespace protocol instance
/*============================================================================
* Module Entry Point (0x358)
*============================================================================*/
EFI_STATUS
EFIAPI
_ModuleEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
VOID *DriverBinding;
// Step 1: Early initialization (serial port, protocol locations)
DcpmmDriverInit(ImageHandle, SystemTable);
// Step 2: Install driver binding protocol
Status = gBootServices->InstallProtocolInterface(
&ImageHandle,
&unk_2AFC0,
EFI_NATIVE_INTERFACE,
&DriverBinding
);
if (!EFI_ERROR(Status)) {
// Set the Start handler -- will be called when controller is found
*((UINT64 *)DriverBinding + 11) = (UINT64)DcpmmDriverStartThunk;
}
// Step 3: Complete initialization
return DcpmmDriverMain(ImageHandle);
}
/*============================================================================
* Driver Init (0x3A0)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmDriverInit(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Serial port (COM1) initialization via I/O ports 0x3F8-0x3FD.
// DCPMM driver uses the serial port for debug logging.
//
// COM1 registers:
// 0x3F8 - Data register / Divisor Latch Low (DLAB=1)
// 0x3F9 - Interrupt Enable / Divisor Latch High (DLAB=1)
// 0x3FA - FIFO Control / Interrupt ID
// 0x3FB - Line Control Register
// 0x3FC - Modem Control Register
// 0x3FD - Line Status Register
//
// Sequence:
// 1. Read LCR, save value
// 2. Read MSR, compute divisor
// 3. Set DLAB bit, write baud divisor
// 4. Set line parameters (8N1), clear FIFO, enable UART
// Save UEFI table pointers
gSystemTable = SystemTable;
gBootServices = SystemTable->BootServices;
gRuntimeServices = SystemTable->RuntimeServices;
// Locate dependent protocols needed by this driver
gBootServices->LocateProtocol(&unk_31F00, NULL, &qword_33360);
gBootServices->LocateProtocol(&unk_31ED0, NULL, &qword_33380);
gBootServices->LocateProtocol(&unk_31EB0, NULL, &unk_33370);
gBootServices->LocateProtocol(&unk_31F90, NULL, &unk_33368);
gBootServices->LocateProtocol(&unk_31EC0, NULL, &unk_33378);
return EFI_SUCCESS;
}
/*============================================================================
* Driver Main (0xA34)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmDriverMain(
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
UINT64 HandleCount;
EFI_HANDLE *HandleBuffer;
UINT64 Index;
VOID *Entry;
UINT64 PageSize = 0x40000000;
CHAR8 Dummy[3];
UtilMemset(Dummy, sizeof(Dummy), 0);
//
// Parse SMBIOS Type 17 to find NVDIMM presence
//
gBootServices->LocateHandleBuffer(
ByProtocol,
&unk_31E80, // SMBIOS protocol
NULL,
&HandleCount,
&HandleBuffer
);
if (!EFI_ERROR(Status) && HandleCount > 0) {
for (Index = 0; Index < HandleCount; Index++) {
// Walk SMBIOS entries looking for NVDIMM (Type 17 with NVDIMM flag)
if (gBootServices->OpenProtocol(
HandleBuffer[Index],
&unk_31EA0,
&Entry
) >= 0) {
// Process SMBIOS entry looking for:
// - Memory Device Type = 0x12 (NVDIMM)
// or Type 0x7F with NVDIMM characteristics
// - Extract NVDIMM handle, serial port settings
}
}
}
if (HandleBuffer) {
gBootServices->FreePool(HandleBuffer);
}
//
// Save image handle
//
gImageHandle = (UINT64)ImageHandle;
//
// Allocate driver global context (592 bytes = 0x250)
//
gDcpmmDriver = UtilAllocateZeroPool(592);
if (!gDcpmmDriver) {
goto Error;
}
//
// Initialize global state
//
gDcpmmDriver->ImageHandle = ImageHandle;
gDcpmmDriver->PageSize = PageSize;
gDcpmmDriver->MaxTransferSize = 0x40000000;
gDcpmmDriver->SmbusTimeout = 0x40000000;
// Initialize linked lists within the context
gDcpmmDriver->NvdimmList.Flink = &gDcpmmDriver->NvdimmList;
gDcpmmDriver->NvdimmList.Blink = &gDcpmmDriver->NvdimmList;
gDcpmmDriver->FwCmdQueue.Flink = &gDcpmmDriver->FwCmdQueue;
gDcpmmDriver->FwCmdQueue.Blink = &gDcpmmDriver->FwCmdQueue;
gDcpmmDriver->SmbusReqQueue.Flink = &gDcpmmDriver->SmbusReqQueue;
gDcpmmDriver->SmbusReqQueue.Blink = &gDcpmmDriver->SmbusReqQueue;
//
// Install all DCPMM protocols on the image handle
//
gImageHandle = (UINT64)ImageHandle;
gControllerHandle = (UINT64)ImageHandle;
Status = gBootServices->InstallMultipleProtocolInterfaces(
&ImageHandle,
&unk_31F20, off_31B98, // DCPMM protocol
&unk_31F50, &off_31FA8, // Config protocol
&unk_31E70, &off_31FC0, // Health protocol
&unk_2B000, off_32030, // FW interface protocol
&unk_2AFD0, off_32020, // Admin protocol
NULL
);
if (EFI_ERROR(Status)) goto Error;
Status = gBootServices->InstallMultipleProtocolInterfaces(
&ImageHandle,
&unk_2B010, &unk_31FA0, // Namespace protocol
NULL
);
if (EFI_ERROR(Status)) goto Error;
Status = gBootServices->InstallMultipleProtocolInterfaces(
&ImageHandle,
&unk_2AFE0, off_32040, // SMBUS protocol
NULL
);
if (EFI_ERROR(Status)) goto Error;
//
// Enumerate all NVDIMM handles present in the system
//
DcpmmEnumerateNvdimmHandles();
//
// Install all protocols again on the image handle
// Then set up the driver binding protocol Start handler
//
Status = gBootServices->InstallProtocolInterface(
&ImageHandle,
&unk_2AFC0,
EFI_NATIVE_INTERFACE,
&gControllerHandle
);
if (!EFI_ERROR(Status)) {
*((UINT64 *)DriverBinding + 11) = (UINT64)DcpmmDriverStart;
}
return Status;
Error:
return Status;
}
/*============================================================================
* Driver Start (0x350 thunk -> 0x7B0)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmDriverStartThunk(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
)
{
return DcpmmDriverStart(ImageHandle, ControllerHandle);
}
EFI_STATUS
EFIAPI
DcpmmDriverStart(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
)
{
EFI_STATUS Status;
UINT64 Index;
//
// Open device path protocol on each cached NVDIMM handle
//
if (gNvdimmHandleCount > 0 && gNvdimmHandles) {
for (Index = 0; Index < gNvdimmHandleCount; Index++) {
if (gNvdimmHandles[Index]) {
gBootServices->OpenProtocol(
gNvdimmHandles[Index],
&unk_31EA0,
&unk_2B028,
ImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
}
}
}
//
// Clear cached handles and re-enumerate
//
gNvdimmHandleCount = 0;
if (gNvdimmHandles) {
gBootServices->FreePool(gNvdimmHandles);
gNvdimmHandles = NULL;
}
//
// Locate controller handles that support the NVDIMM FIT protocol
//
gBootServices->LocateHandleBuffer(
ByProtocol,
&unk_31B88,
NULL,
&gNvdimmHandleCount,
&gNvdimmHandles
);
if (gNvdimmHandleCount > 0 && gNvdimmHandles) {
for (Index = 0; Index < gNvdimmHandleCount; Index++) {
//
// Install DCPMM protocols on each controller handle
//
gBootServices->InstallMultipleProtocolInterfaces(
&gNvdimmHandles[Index],
&unk_31F20, off_31B98,
&unk_31F50, &off_31FA8,
NULL
);
//
// Check namespace and SMBUS support
//
DcpmmCheckNamespaceSupport(gNvdimmHandles[Index]);
DcpmmCheckSmbusSupport(gNvdimmHandles[Index]);
}
}
//
// Install all remaining protocols on the controller handle
//
gBootServices->InstallMultipleProtocolInterfaces(
&ControllerHandle,
&unk_2B000, off_32030,
&unk_2AFE0, off_32040,
&unk_31F20, off_31B98,
&unk_31F50, &off_31FA8,
&unk_2B010, &unk_31FA0,
&unk_2AFD0, off_32020,
NULL
);
return EFI_SUCCESS;
}
/*============================================================================
* Driver Supported (0x16C4)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmDriverSupported(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
)
{
NVDIMM_DEVICE *Device;
EFI_STATUS Status;
// Walk NVDIMM linked list to see if this controller is known
if (gDcpmmDriver) {
Device = (NVDIMM_DEVICE *)gDcpmmDriver->NvdimmList.Flink;
while (&Device->ListEntry != &gDcpmmDriver->NvdimmList) {
if (Device->ControllerHandle == ControllerHandle) {
return EFI_SUCCESS;
}
Device = (NVDIMM_DEVICE *)Device->ListEntry.Flink;
}
}
//
// Also check if controller supports NVDIMM FIT protocol
//
Status = gBootServices->OpenProtocol(
ControllerHandle,
&unk_31B88, // NVDIMM Firmware Interface Table protocol
NULL,
ImageHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR(Status)) {
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
/*============================================================================
* Driver Stop (0x8858 based on dispatch)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmDriverStop(
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
)
{
EFI_STATUS Status;
//
// Close all protocols opened by this driver on the controller
//
gBootServices->CloseProtocol(
ControllerHandle,
&unk_31F20,
ImageHandle,
ControllerHandle
);
gBootServices->CloseProtocol(
ControllerHandle,
&unk_31F50,
ImageHandle,
ControllerHandle
);
gBootServices->CloseProtocol(
ControllerHandle,
&unk_2B000,
ImageHandle,
ControllerHandle
);
// Close SMBUS protocol
gBootServices->CloseProtocol(
ControllerHandle,
&unk_2AFE0,
ImageHandle,
ControllerHandle
);
//
// Uninstall all protocol interfaces
//
gBootServices->UninstallMultipleProtocolInterfaces(
ControllerHandle,
&unk_31F20, off_31B98,
&unk_31F50, &off_31FA8,
&unk_2B000, off_32030,
&unk_2AFE0, off_32040,
&unk_2B010, &unk_31FA0,
&unk_2AFD0, off_32020,
NULL
);
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM Firmware Command (0x2308)
*============================================================================*/
EFI_STATUS
NvdimmFwCommand(
IN NVDIMM_DEVICE *Device,
IN UINT16 CommandCode,
IN VOID *Buffer,
IN UINT64 BufferSize
)
{
UINT64 Status;
UINT8 Packet[256];
UINT8 Response[256];
if (!Device) return EFI_INVALID_PARAMETER;
UtilMemset(Packet, sizeof(Packet), 0);
UtilMemset(Response, sizeof(Response), 0);
//
// Build NVDIMM firmware command packet
// Structure per ACPI NVDIMM FW spec for passthrough:
// Command + Input/Output buffer sizes + payload
//
// Transmit via SMBUS to the NVDIMM device address.
//
return EFI_SUCCESS;
}
/*============================================================================
* Firmware Command Dispatch (0x2D20)
*============================================================================*/
EFI_STATUS
DcpmmFirmwareCommandDispatch(
IN NVDIMM_DEVICE *Device,
IN UINT32 Command,
IN UINT32 InputSize,
IN VOID *InputData,
OUT UINT32 *OutputSize,
OUT VOID *OutputData,
IN UINT8 RetryCount,
IN UINT64 Timeout
)
{
NVDIMM_FW_INTERFACE *FwIf;
UINT64 Status;
if (!Device || !Device->FwInterface) {
return EFI_INVALID_PARAMETER;
}
FwIf = (NVDIMM_FW_INTERFACE *)Device->FwInterface;
//
// Dispatch firmware command via the NFIT-defined function table
//
Status = FwIf->ExecuteCommand(
Command,
InputData,
InputSize,
OutputData,
OutputSize
);
if (EFI_ERROR(Status) && RetryCount > 0) {
gBootServices->Stall(5000);
return DcpmmFirmwareCommandDispatch(
Device, Command, InputSize, InputData,
OutputSize, OutputData,
RetryCount - 1, Timeout
);
}
return Status;
}
/*============================================================================
* DCPMM Protocol: Get Device Info (0x6F54)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmGetDeviceInfo(
IN DCPMM_PROTOCOL *This,
OUT UINT64 *Capacity,
OUT UINT64 *MemorySize,
OUT UINT64 *AppDirect1Size,
OUT UINT64 *AppDirect2Size,
OUT UINT32 *SocketId,
OUT UINT16 *VendorId,
OUT UINT8 *HealthFlags
)
{
NVDIMM_DEVICE *Device;
UINT64 Status;
//
// Walk the NVDIMM device list and collect info:
// - For each device, query capacity, health, interleave
// - Use firmware commands (sub_2D20) for device queries
// - Use sub_2AC64 (UtilDebugPrint) for log output
// - Handle SMBUS ownership via sub_18F88 (SmbusAcquire)
//
return EFI_SUCCESS;
}
/*============================================================================
* DCPMM Protocol: Get Health (0x7788)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmGetHealth(
IN DCPMM_PROTOCOL *This,
OUT UINT32 *HealthStatus,
OUT UINT32 *PercentageUsed,
OUT UINT32 *Temperature,
OUT UINT32 *AvailableSpare,
OUT UINT32 *SpareThreshold
)
{
//
// Queries NVDIMM via firmware command for health info
// Returns: health status, % used, temp, spare threshold
//
return EFI_SUCCESS;
}
/*============================================================================
* DCPMM Protocol: SMBUS Acquire (0x18F88)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmSmbusAcquire(
IN NVDIMM_DEVICE *Device,
IN UINT32 McNumber,
IN UINT16 TimeoutMs,
IN UINT8 ForceMode
)
{
UINT8 SmbusStatus[0x2C];
if (!Device) return EFI_INVALID_PARAMETER;
UtilMemset(SmbusStatus, sizeof(SmbusStatus), 0);
//
// Acquire SMBUS ownership for the NVDIMM memory controller:
// 1. Read current SMBUS status from controller
// 2. If ForceMode, write acquire request directly
// 3. Send acquire command to NVDIMM via SMBUS
// 4. Use TimeoutMs for retry timing
//
// Debug messages format:
// N%d.MC%d: DCPMM driver starting to acquire SMBUS access. Window: %d ms
// N%d.MC%d: DCPMM driver acquired SMBUS access
// N%d.MC%d: DCPMM driver failed to acquire SMBUS access
//
return EFI_SUCCESS;
}
/*============================================================================
* DCPMM Protocol: SMBUS Release (0x18F88 related)
*============================================================================*/
EFI_STATUS
EFIAPI
DcpmmSmbusRelease(
IN NVDIMM_DEVICE *Device,
IN UINT32 McNumber
)
{
//
// Release SMBUS ownership:
// N%d.MC%d: DCPMM driver releasing SMBUS access
// N%d.MC%d: DCPMM driver released SMBUS access. Rc %d
//
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM Config Data Read (0xDA5C)
*============================================================================*/
EFI_STATUS
DcpmmGetNvdimmConfig(
IN NVDIMM_DEVICE *Device,
IN UINT64 Offset,
IN UINT32 BufferSize,
OUT VOID *Buffer
)
{
UINT8 LocalBuffer[0x600];
UINT64 Status;
UtilMemset(LocalBuffer, sizeof(LocalBuffer), 0);
if (!Device) return EFI_INVALID_PARAMETER;
//
// Read NVDIMM namespace label data:
// 1. Walk the NVDIMM linked list entry by entry
// 2. For each entry, check namespace validity
// 3. Skip faulted, bypassed, or mapped-out namespaces
// 4. Read config data from the NVDIMM via firmware command
// 5. Apply BTT/PFN translation if needed
// 6. Copy the requested data range to output buffer
//
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM Config Data Write (0xE0E4)
*============================================================================*/
EFI_STATUS
DcpmmSetNvdimmConfig(
IN NVDIMM_DEVICE *Device,
IN UINT64 Offset,
IN UINT32 BufferSize,
IN VOID *Buffer
)
{
//
// Write NVDIMM namespace label data with full validation.
// Handles page alignment, BTT/PFN translation, and error recovery.
// Uses UtilDebugPrint for status logging.
//
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM Handle Enumeration (0x4F8)
*============================================================================*/
EFI_STATUS
DcpmmEnumerateNvdimmHandles(
VOID
)
{
UINT64 HandleCount;
EFI_HANDLE *HandleBuffer;
EFI_STATUS Status;
UINT64 Index;
VOID *Protocol;
//
// If handles are already cached, return success
//
if (gNvdimmHandles && gNvdimmHandleCount > 0) {
return EFI_SUCCESS;
}
//
// Free any previously allocated handle buffer
//
if (gNvdimmHandles) {
gBootServices->FreePool(gNvdimmHandles);
gNvdimmHandles = NULL;
}
gNvdimmHandleCount = 0;
//
// Locate all handles with the NVDIMM Firmware Interface protocol
//
Status = gBootServices->LocateHandleBuffer(
ByProtocol,
&unk_31B88,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR(Status)) {
return (Status == EFI_NOT_FOUND) ? EFI_SUCCESS : Status;
}
//
// Allocate handle cache
//
gNvdimmHandleCount = HandleCount;
gNvdimmHandles = UtilAllocateZeroPool(HandleCount * sizeof(EFI_HANDLE));
if (!gNvdimmHandles) {
gBootServices->FreePool(HandleBuffer);
gNvdimmHandleCount = 0;
return EFI_OUT_OF_RESOURCES;
}
//
// Install device path on each handle and cache the handle
//
for (Index = 0; Index < HandleCount; Index++) {
Status = gBootServices->InstallProtocolInterface(
&HandleBuffer[Index],
&unk_31EA0,
EFI_NATIVE_INTERFACE,
&unk_2B028
);
if (!EFI_ERROR(Status)) {
gNvdimmHandles[Index] = HandleBuffer[Index];
} else {
gNvdimmHandles[Index] = NULL;
}
}
gBootServices->FreePool(HandleBuffer);
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM Name Space Support Check
*============================================================================*/
EFI_STATUS
DcpmmCheckNamespaceSupport(
IN EFI_HANDLE Handle
)
{
return EFI_SUCCESS;
}
/*============================================================================
* NVDIMM SMBUS Support Check
*============================================================================*/
EFI_STATUS
DcpmmCheckSmbusSupport(
IN EFI_HANDLE Handle
)
{
return EFI_SUCCESS;
}
/*============================================================================
* Utility Functions
*============================================================================*/
/*----------------------------------------------------------------------------
* UtilMemset (sub_29040, 178 xrefs)
*----------------------------------------------------------------------------*/
VOID *
UtilMemset(
VOID *Destination,
UINT64 Length,
UINT8 Value
)
{
UINT8 *Ptr = (UINT8 *)Destination;
UINT64 Index;
if (((UINT64)Ptr & 7) == 0 && Length >= 8) {
UINT64 *QWordPtr = (UINT64 *)Ptr;
UINT64 QWordValue = (UINT64)Value & 0xFF;
UINT64 QWordCount = Length / 8;
QWordValue |= QWordValue << 8;
QWordValue |= QWordValue << 16;
QWordValue |= QWordValue << 32;
for (Index = 0; Index < QWordCount; Index++) {
QWordPtr[Index] = QWordValue;
}
Ptr += QWordCount * 8;
Length -= QWordCount * 8;
}
for (Index = 0; Index < Length; Index++) {
Ptr[Index] = Value;
}
return Destination;
}
/*----------------------------------------------------------------------------
* UtilMemcpy (sub_28E8C, 143 xrefs)
*----------------------------------------------------------------------------*/
VOID *
UtilMemcpy(
VOID *Destination,
const VOID *Source,
UINT64 Length
)
{
UINT8 *Dst = (UINT8 *)Destination;
const UINT8 *Src = (const UINT8 *)Source;
UINT64 Index;
if ((((UINT64)Dst | (UINT64)Src) & 7) == 0 && Length >= 8) {
UINT64 *QWordDst = (UINT64 *)Dst;
const UINT64 *QWordSrc = (const UINT64 *)Src;
UINT64 QWordCount = Length / 8;
for (Index = 0; Index < QWordCount; Index++) {
QWordDst[Index] = QWordSrc[Index];
}
Dst += QWordCount * 8;
Src += QWordCount * 8;
Length -= QWordCount * 8;
}
for (Index = 0; Index < Length; Index++) {
Dst[Index] = Src[Index];
}
return Destination;
}
/*----------------------------------------------------------------------------
* UtilAllocatePool (sub_2A010)
*----------------------------------------------------------------------------*/
VOID *
UtilAllocatePool(
UINT64 Size
)
{
VOID *Buffer = NULL;
EFI_STATUS Status;
Status = gBootServices->AllocatePool(
EfiBootServicesData,
Size,
&Buffer
);
return EFI_ERROR(Status) ? NULL : Buffer;
}
/*----------------------------------------------------------------------------
* UtilAllocateZeroPool (sub_2A040, 166 xrefs)
*----------------------------------------------------------------------------*/
VOID *
UtilAllocateZeroPool(
UINT64 Size
)
{
VOID *Buffer;
Buffer = UtilAllocatePool(Size);
if (Buffer != NULL && Size > 0) {
UtilMemset(Buffer, Size, 0);
}
return Buffer;
}
/*----------------------------------------------------------------------------
* UtilFreePool (sub_2A070)
*----------------------------------------------------------------------------*/
VOID
UtilFreePool(
VOID *Buffer
)
{
if (Buffer) {
gBootServices->FreePool(Buffer);
}
}
/*----------------------------------------------------------------------------
* UtilDebugPrint (sub_2AC64, DCPMM debug serial output)
*----------------------------------------------------------------------------*/
VOID
UtilDebugPrint(
IN UINT64 Node,
IN UINT64 McNumber,
IN CHAR8 *Format,
...
)
{
//
// DCPMM debug output format:
// N%d.MC%d: <formatted message>
//
// All messages use this prefix format for log identification.
//
// Messages observed:
// DCPMM driver acquired SMBUS access
// DCPMM driver waiting %d ms for smbus access
// DCPMM driver failed to acquire SMBUS access
// DCPMM driver releasing SMBUS access
// DCPMM driver released SMBUS access. Rc %d
// DCPMM driver inconsistent state found! ...
// DCPMM driver failed to release SMBUS access! Exiting
// DCPMM driver starting to acquire SMBUS access. Window: 0 ms
// DCPMM driver starting to acquire SMBUS access. Window: %d - %d ms
//
}