Newer
Older
AMI-Aptio-BIOS-Reversed / LnvPurleyDriverDxe / LnvPurleyDriverDxe.c
@Ajax Dong Ajax Dong 2 days ago 11 KB Init
/** @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);
}