/** @file LnvPurleyDriverDxe - Lenovo Purley Server Driver DXE Binary: LnvPurleyDriverDxe.efi (index 0099)
SHA256: 671add961defd0d2fe7ff345d358a541771b2e476ae385b319cecbd0b67e4f10 Image size: 0x1060 bytes Architecture: X64 This module serves as a combined constructor for:
- UefiBootServicesTableLib (MdePkg)
- UefiRuntimeServicesTableLib (MdePkg)
- DxeHobLib (MdePkg)
- DxeLnvSendIpmiCmdLib (LenovoServerPkg/LnvIpmiLib)
- LnvPurleyDriverDXE (LenovoServerPkg/LnvPurleyDriver)
Source paths referenced in debug strings:
e:\hs\MdePkg\Library\UefiBootServicesTableLib\UefiBootServicesTableLib.c e:\hs\MdePkg\Library\UefiRuntimeServicesTableLib\UefiRuntimeServicesTableLib.c e:\hs\MdePkg\Library\DxeHobLib\HobLib.c e:\hs\MdePkg\Library\BaseLib\Unaligned.c e:\hs\LenovoServerPkg\LnvPurleyDriver\LnvPurleyDriverDXE.c e:\hs\LenovoServerPkg\Library\LnvIpmiLib\IpmiCmd\DxeLnvSendIpmiCmdLib.c
**/
#include "LnvPurleyDriverDxe.h"
//
// .data section globals
//
UINT64 gImageHandle = 0; // qword_F20 UINT64 gST = 0; // qword_F10 UINT64 gBS = 0; // qword_F18 UINT64 gRT = 0; // qword_F28 UINT64 mHobList = 0; // qword_F38 UINT64 gBS_Internal = 0; // qword_F30 UINT64 gSystemTable = 0; // qword_F50 UINT64 gBootServices = 0; // qword_F40 UINT64 gRuntimeServices = 0; // qword_F48
//=============================================================================
// UEFI Service Library Functions
//=============================================================================
/**Read unaligned 64-bit value from Buffer.
Corresponds to BaseLib Unaligned.c stub.
@param[in] Buffer Pointer to read from (must not be NULL).
@return The 64-bit value read.
**/
UINT64 EFIAPI ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
if (Buffer == NULL) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
192,
"Buffer != ((void *) 0)"
);
}
return *(UINT64 *)Buffer;
}
/**Compare two 64-bit-aligned values as GUID comparison.
Corresponds to a simplified GUID comparison using two 64-bit reads.
@param[in] Guid1 Pointer to reference GUID.
@param[in] Guid2 Pointer to comparison GUID data.
@retval TRUE GUIDs match.
@retval FALSE GUIDs do not match.
**/
BOOLEAN EFIAPI CompareGuid (
IN UINT64 *Guid1,
IN UINT64 *Guid2
)
{
UINT64 Data1;
UINT64 Data2;
Data1 = ReadUnaligned64 (Guid1);
Data2 = ReadUnaligned64 (Guid2);
if (Data1 != Data2) {
return FALSE;
}
Data1 = ReadUnaligned64 ((UINT8 *)Guid1 + 8);
Data2 = ReadUnaligned64 ((UINT8 *)Guid2 + 8);
return Data1 == Data2;
}
//=============================================================================
// CMOS Platform Detection
//=============================================================================
/**Get platform type by reading CMOS register 0x4B.
Reads current CMOS index, preserves bit 7 (NMI mask), sets index 0x4B,
reads the value from CMOS data port, then interprets:
- 0 => read MMIO 0xFDAF0490 bits [1:0], OR with 1
- 1 => EFI_SUCCESS (specific platform)
- 2, 3 => EFI_INVALID_PARAMETER
- other => 0 (unknown)
@return Platform type encoding.
**/
UINT64 EFIAPI GetPlatformType (
VOID
)
{
UINT8 SavedIndex;
UINT8 PlatformType;
UINT64 Result;
SavedIndex = __inbyte (0x70);
__outbyte (0x70, SavedIndex & 0x80 | 0x4B);
PlatformType = __inbyte (0x71);
if (PlatformType > 3) {
if (PlatformType == 0) {
PlatformType = (*(volatile UINT8 *)0xFDAF0490 & 2) | 1;
}
}
if ((UINT8)(PlatformType - 1) > 0xFD) {
Result = 0;
} else {
Result = 0x8000000000000006ULL; // EFI_INVALID_PARAMETER if (PlatformType == 1) {
Result = 0; // EFI_SUCCESS
}
}
return Result;
}
//=============================================================================
// Debug Library Functions
//=============================================================================
/**Debug print wrapper with level mask filtering.
Corresponds to DxeLnvSendIpmiCmdLib debug output.
@param[in] ErrorLevel Error level bitmask.
@param[in] Format Format string.
@param[in] ... Variable arguments.
@return Status.
**/
UINT64 EFIAPI DebugPrint (
IN UINT64 ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
UINT64 Result;
VA_LIST Va;
VA_START (Va, Format);
Result = GetDebugConfig ();
if (Result != 0) {
if ((GetPlatformType () & (UINT32)ErrorLevel) != 0) {
return (*(UINT64 ( **)(UINT64, CONST CHAR8 *, VA_LIST))(Result + 8))(
ErrorLevel,
Format,
Va
);
}
}
VA_END (Va);
return Result;
}
/**ASSERT implementation with call to the registered assert handler.
@param[in] FileName Source file path.
@param[in] LineNumber Line number of the ASSERT.
@param[in] Description Description string.
**/
VOID EFIAPI DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
UINT64 Result;
Result = GetDebugConfig ();
if (Result != 0) {
(*(VOID ( **)(CONST CHAR8 *, UINTN, CONST CHAR8 *))(Result + 8))(
FileName,
LineNumber,
Description
);
}
}
/**Get the debug/protocol configuration handle.
Attempts to locate a protocol by GUID (unk_EC0 / gEfiGlobalVariableGuid).
Caches the result in gBS_Internal.
@return Pointer to the located protocol interface, or 0.
**/
UINT64 EFIAPI GetDebugConfig (
VOID
)
{
UINT64 Result;
UINT64 Status;
Result = gBS_Internal;
if (gBS_Internal != 0) {
return Result;
}
Status = ((UINT64 ( *)(VOID *, UINT64, UINT64 *))gBS + 320)(
&gBS_Internal,
0,
&gBS_Internal
);
if (Status < 0) {
gBS_Internal = 0;
}
return gBS_Internal;
}
//=============================================================================
// HOB List Retrieval
//=============================================================================
/**Get the HOB list by locating a GUID HOB from the system configuration table.
Searches through the system table configuration table entries for a matching GUID and walks to find the HOB list.
@param[in] a1 Caller context.
@param[in] HobList Not directly used.
@return Pointer to the HOB list, or causes an ASSERT if not found.
**/
UINT64 EFIAPI GetHobList (
IN UINT64 a1,
IN UINT64 HobList
)
{
UINT64 Result;
UINT64 HobCount;
UINT64 ConfigEntry;
Result = mHobList;
if (mHobList != 0) {
return Result;
}
//
// Walk the system configuration table to find gEfiDxeServicesTableGuid entry
//
ConfigEntry = *(UINT64 *)(gST + 104);
mHobList = 0;
if (ConfigEntry != 0) {
HobCount = 0;
while (TRUE) {
if (CompareGuid (
&gEfiDxeServicesTableGuid,
(UINT64 *)(*(UINT64 *)(gST + 112) + HobCount)
))
{
break;
}
HobCount++;
ConfigEntry = *(UINT64 *)(gST + 112) + HobCount *24;
if (HobCount >= *(UINT64 *)(gST + 104)) {
goto NOT_FOUND;
}
}
Result = *(UINT64 *)(ConfigEntry + 16);
mHobList = Result;
return Result;
}
NOT_FOUND:
DebugPrint (0x80000000ULL, "\nASSERT_EFI_ERROR (Status = %r)\n", 0x800000000000000EULL);
DebugAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
54,
"!EFI_ERROR (Status)"
);
Result = mHobList;
if (Result == 0) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
55,
"mHobList != ((void *) 0)"
);
return mHobList;
}
return Result;
}
//=============================================================================
// UefiBootServicesTableLib Constructor
//=============================================================================
/**Constructor for the combined UefiBootServicesTableLib + UefiRuntimeServicesTableLib.
Initializes gImageHandle, gST, gBS, gRT from SystemTable, locates the HOB list,
and attempts to locate the debug configuration protocol.
@param[in] ImageHandle The firmware-allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@return EFI_SUCCESS or error from protocol location.
**/
UINT64 EFIAPI UefiBootServicesTableLibConstructor (
IN UINT64 ImageHandle,
IN UINT64 SystemTable
)
{
UINT64 Status;
gImageHandle = ImageHandle;
if (ImageHandle == 0) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
51,
"gImageHandle != ((void *) 0)"
);
}
gST = SystemTable;
if (SystemTable == 0) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
57,
"gST != ((void *) 0)"
);
}
gBS = *(UINT64 *)(SystemTable + 96);
if (gBS == 0) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
63,
"gBS != ((void *) 0)"
);
}
gRT = *(UINT64 *)(SystemTable + 88);
if (gRT == 0) {
DebugAssert (
"e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
47,
"gRT != ((void *) 0)"
);
}
//
// Get the HOB list from the configuration table
//
GetHobList (ImageHandle, 0);
//
// Locate the debug/protocol configuration
//
Status = ((UINT64 ( *)(VOID *, UINT64, UINT64 *))(gBS + 320))(
&gBS_Internal,
0,
&gBS_Internal
);
if (Status < 0) {
Status = ((UINT64 ( *)(VOID *, UINT64, UINT64 *))(gBS + 168))(
&gBS_Internal,
GetPlatformType,
&Status
);
if (Status < 0) {
DebugPrint (-1, "DxeLnvSendIpmiCmdLibConstructor Status = %r \n", Status);
}
}
return Status;
}
//=============================================================================
// LnvPurleyDriver DXE Init
//=============================================================================
/**Initialize the LnvPurleyDriver DXE module.
Creates two notification events for NotifyFunction.
@param[in] a1 Caller context.
@param[in] SystemTable A pointer to the EFI System Table.
@return EFI_SUCCESS always.
**/
UINT64 EFIAPI DxeLnvPurleyDriverInit (
IN UINT64 a1,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
if (gSystemTable != 0) {
gBootServices = gBS;
} else {
gSystemTable = (UINT64)SystemTable;
gBootServices = (UINT64)(SystemTable->BootServices);
gRuntimeServices = (UINT64)(SystemTable->RuntimeServices);
gBS = gBootServices;
gRT = gRuntimeServices;
}
if (((UINT64 ( *)(UINT64, UINT64, VOID *))gBootServices + 320)(
512,
8,
NotifyFunction
) < 0)
{
DebugPrint (
64,
"LnvPurleyDriverDxeInitCalled, File:: %a Line:: %d , Status = %r \n",
"e:\\hs\\LenovoServerPkg\\LnvPurleyDriver\\LnvPurleyDriverDXE.c"
);
}
if (((UINT64 ( *)(UINT64, UINT64, VOID *))(gBootServices + 368))(
512,
8,
NotifyFunction
) < 0)
{
DebugPrint (
64,
"LnvPurleyDriverDxeInitCalled, File:: %a Line:: %d , Status = %r \n",
"e:\\hs\\LenovoServerPkg\\LnvPurleyDriver\\LnvPurleyDriverDXE.c"
);
}
return 0;
}
//=============================================================================
// Notification Callback (Event handler)
//=============================================================================
/**Notification function registered as an event callback.
Simply returns gBS->SignalEvent.
@return Value from gBS->SignalEvent.
**/
UINT64 EFIAPI NotifyFunction (
VOID
)
{
return ((UINT64 ( *)(VOID))(gBS + 112))();
}
//=============================================================================
// Module Entry Point
//=============================================================================
/**Module entry point for LnvPurleyDriverDxe.
Calls UefiBootServicesTableLibConstructor followed by DxeLnvPurleyDriverInit.
@param[in] ImageHandle The firmware-allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@return Status code.
**/
UINT64 EFIAPI ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINT64 Status;
Status = UefiBootServicesTableLibConstructor ((UINT64)ImageHandle, (UINT64)SystemTable);
if (Status < 0) {
return Status;
}
return DxeLnvPurleyDriverInit ((UINT64)ImageHandle, SystemTable);
}