/**
* RuntimeDxe.efi - MdeModulePkg Core Runtime DXE Driver
*
* Decompiled from: HR650X BIOS (0105_RuntimeDxe_be0d9d4b1690/RuntimeDxe.efi)
* Source: https://github.com/tianocore/edk2 (MdeModulePkg/Core/RuntimeDxe)
*
* This driver initializes the UEFI Runtime Services table, registers
* notification callbacks for ExitBootServices and SetVirtualAddressMap,
* and provides the runtime clock interface.
*
* File: RuntimeDxe.c
* Functions: 20
* Image size: 0x8000
* Arch: X64
*/
#include "RuntimeDxe.h"
/* ========================================================================
* Global Variables
* ======================================================================== */
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gSystemTable = NULL;
EFI_BOOT_SERVICES *gBootServices = NULL;
EFI_RUNTIME_SERVICES *gRuntime = NULL;
//
// Events registered during initialization
//
EFI_EVENT mRuntimeDriverExitBootServicesEvent = NULL;
EFI_EVENT mRuntimeDriverSetVirtualAddressMapEvent = NULL;
EFI_EVENT mEfiVirtualNotifyEvent = NULL;
EFI_EVENT mEfiExitBootServicesEvent = NULL;
EFI_EVENT mRuntimeDriverInitEndOfDxeEvent = NULL;
//
// Status code protocol table pointer
//
VOID *mRuntimeStatusCodeTable = NULL;
//
// Set TRUE after SetVirtualAddressMap has been called
//
BOOLEAN mEfiGoneVirtual = FALSE;
//
// Linked list head for registered images
//
LIST_ENTRY mRuntimeDriverImageList;
/* ========================================================================
* CRC32 lookup table (from BaseLib/CheckSum.c)
* ======================================================================== */
STATIC CONST UINT32 mCrc32Table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};
/* ========================================================================
* Module Entry Point
* ======================================================================== */
/**
* Driver entry point. Called by DXE core after image is loaded.
*
* @param[in] ImageHandle Handle for this image
* @param[in] SystemTable Pointer to EFI System Table
* @return EFI_SUCCESS or error code
*/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Initialize UEFI boot/runtime service table pointers
//
UefiBootServicesTableLibConstructor (ImageHandle, SystemTable);
//
// Perform runtime driver initialization
//
Status = RuntimeDriverInitialize (ImageHandle);
return Status;
}
/* ========================================================================
* UefiBootServicesTableLib Constructor (sub_1154)
* ======================================================================== */
/**
* Initializes global pointers for BootServices, RuntimeServices,
* and registers event notification callbacks.
*
* Registers:
* - VirtualAddressChange event (sub_1CF0)
* - ConvertPointer event (sub_1CFC)
* - RuntimeDriverInitializeEndOfDxe (sub_1E00)
* - SetVirtualAddressMap notify (nullsub_1)
* - ExitBootServices notify (sub_2044)
* - EndOfDxe notify (sub_206C)
*
* @param[in] ImageHandle Handle for this image
* @param[in] SystemTable Pointer to EFI System Table
* @return EFI_SUCCESS or ASSERT if parameters are invalid
*/
UINTN
EFIAPI
UefiBootServicesTableLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_BOOT_SERVICES *BootServices;
EFI_STATUS Status;
gImageHandle = ImageHandle;
ASSERT (gImageHandle != NULL);
gSystemTable = SystemTable;
ASSERT (gSystemTable != NULL);
gBootServices = SystemTable->BootServices;
ASSERT (gBootServices != NULL);
gRuntime = SystemTable->RuntimeServices;
ASSERT (gRuntime != NULL);
BootServices = SystemTable->BootServices;
//
// Register VirtualAddressChange notification (TPL_CALLBACK, notify function)
//
Status = BootServices->CreateEvent (
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
TPL_CALLBACK,
VirtualAddressChangeNotify,
NULL,
&mEfiVirtualNotifyEvent
);
//
// Register event to disable watchdog timer on ExitBootServices
//
Status = BootServices->CreateEvent (
EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_CALLBACK,
RuntimeDriverExitBootServicesNotify,
NULL,
&mEfiExitBootServicesEvent
);
RuntimeDriverInitializeEvent ();
ASSERT (gRuntime != NULL);
ASSERT (gBootServices != NULL);
//
// Register EndOfDxe notification
//
Status = gBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
RuntimeDriverInitializeEndOfDxe,
NULL,
&mRuntimeDriverInitEndOfDxeEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Register SetVirtualAddressMap notification
//
Status = gBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
RuntimeDriverSetVirtualAddressMapNotify,
NULL,
&mEfiGoneVirtual,
&mRuntimeDriverSetVirtualAddressMapEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Initialize the status code reporting interface
//
ReportStatusCodeConstructor ();
//
// Register ExitBootServices notification via status code protocol
//
Status = gBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
RuntimeDriverExitBootServicesHandler,
NULL,
&mRuntimeStatusCodeTable,
&mRuntimeDriverExitBootServicesEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Register SetVirtualAddressMap notification via status code protocol
//
Status = gBootServices->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
RuntimeDriverSetVirtualAddressMapHandler,
NULL,
&mRuntimeStatusCodeTable,
&mRuntimeDriverSetVirtualAddressMapEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
return Status;
}
/* ========================================================================
* Runtime Driver Initialize (sub_1628)
* ======================================================================== */
/**
* Initializes the runtime driver by:
* 1. Locating the runtime image protocol
* 2. Hooking the SetWatchdogTimer runtime service
* 3. Installing the runtime protocol interface
*
* @param[in] ImageHandle Handle for this image
* @return EFI_SUCCESS, EFI_INVALID_PARAMETER, or EFI_NOT_FOUND
*/
EFI_STATUS
EFIAPI
RuntimeDriverInitialize (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
VOID *RuntimeImageProtocol;
//
// Locate the Runtime Image protocol
//
Status = gBootServices->LocateProtocol (
&gEfiRuntimeImageProtocolGuid,
NULL,
&RuntimeImageProtocol
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
//
// Hook the SetWatchdogTimer runtime service
//
gBootServices->CalculateCrc32 = RuntimeDriverCalculateCrc32;
mRuntimeDriverImageList.ForwardLink = *(LIST_ENTRY **)(RuntimeImageProtocol + 64);
//
// Install the Runtime Driver protocol
//
gRuntime->SetVirtualAddressMap = RuntimeDriverSetVirtualAddressMap;
gRuntime->ConvertPointer = RuntimeDriverConvertPointer;
Status = gBootServices->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiRuntimeDriverProtocolGuid,
&mRuntimeDriverImageList,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
return Status;
}
/* ========================================================================
* RuntimeDriver ConvertPointer (sub_1724)
* ======================================================================== */
/**
* Converts a pointer from boot-time address to runtime address
* using the virtual address map.
*
* @param[in] DebugDisposition Type of debug disposition
* @param[in,out] ConvertAddress Address of pointer to convert
* @return EFI_SUCCESS, EFI_INVALID_PARAMETER, or EFI_NOT_FOUND
*/
EFI_STATUS
EFIAPI
RuntimeDriverConvertPointer (
IN UINTN DebugDisposition,
IN OUT VOID **ConvertAddress
)
{
EFI_MEMORY_DESCRIPTOR *Descriptor;
UINTN Index;
if (ConvertAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
if (*ConvertAddress == 0) {
return (DebugDisposition & 1) ? EFI_SUCCESS : EFI_INVALID_PARAMETER;
}
//
// Walk the virtual address map to find the descriptor covering
// the input address
//
Descriptor = (EFI_MEMORY_DESCRIPTOR *)mRuntimeDriverImageList.ForwardLink;
if (mRuntimeDriverImageList.ForwardLink == NULL) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < gRuntime->DescriptorCount; Index++) {
if ((Descriptor->Attribute & EFI_MEMORY_RUNTIME) != 0) {
if ((UINTN)*ConvertAddress >= (UINTN)Descriptor->PhysicalStart &&
(UINTN)*ConvertAddress < (UINTN)Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT)) {
//
// Apply the virtual address offset
//
*ConvertAddress = (VOID *)((UINTN)*ConvertAddress + Descriptor->VirtualStart - (UINTN)Descriptor->PhysicalStart);
return EFI_SUCCESS;
}
}
Descriptor = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Descriptor + gRuntime->DescriptorSize);
if (Index >= (UINTN)gRuntime->NumberOfTableEntries) {
return EFI_NOT_FOUND;
}
}
return EFI_NOT_FOUND;
}
/* ========================================================================
* RuntimeDriver SetVirtualAddressMap (sub_17B0)
* ======================================================================== */
/**
* Handles the SetVirtualAddressMap runtime service call.
* Converts all runtime pointers to virtual addresses, invokes
* registered virtual address change callbacks, and flushes
* instruction/data caches.
*
* @param[in] MemoryMapSize Size of the memory map
* @param[in] DescriptorSize Size of each descriptor
* @param[in] DescriptorVersion Version of descriptor format
* @param[in] VirtualMap The virtual address map
* @return EFI_SUCCESS, EFI_INVALID_PARAMETER, or EFI_UNSUPPORTED
*/
EFI_STATUS
EFIAPI
RuntimeDriverSetVirtualAddressMap (
IN UINT64 MemoryMapSize,
IN UINT64 DescriptorSize,
IN UINT32 DescriptorVersion,
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
)
{
EFI_MEMORY_DESCRIPTOR *Descriptor;
LIST_ENTRY *ImageEntry;
EFI_STATUS Status;
UINTN Index;
UINT32 Crc32Out;
if (!mEfiGoneVirtual || mEfiGoneVirtual) {
return EFI_UNSUPPORTED;
}
if (DescriptorVersion != 1 || DescriptorSize < sizeof(EFI_MEMORY_DESCRIPTOR)) {
return EFI_INVALID_PARAMETER;
}
mEfiGoneVirtual = TRUE;
DescriptorSize = DescriptorSize;
mRuntimeDriverImageList.ForwardLink = (LIST_ENTRY *)VirtualMap;
gRuntime->NumberOfTableEntries = (UINTN)(MemoryMapSize / DescriptorSize);
//
// Flush data and instruction caches for the memory map
//
RuntimeDriverCalculateCrc32 ((VOID *)(UINTN)MemoryMapSize, 51449860);
RuntimeDriverCalculateCrc32 ((VOID *)DescriptorSize, 50663428);
//
// Notify all registered virtual address change callbacks
//
ImageEntry = mRuntimeDriverImageList.ForwardLink;
if (ImageEntry != &mRuntimeDriverImageList) {
do {
if ((ImageEntry->Flags & EFI_MEMORY_RUNTIME | EFI_MEMORY_XP) ==
(EFI_MEMORY_RUNTIME | EFI_MEMORY_XP | EFI_MEMORY_RO))
{
//
// Convert the callback address
//
Index = (UINTN)ImageEntry->PhysicalStart;
Status = RuntimeDriverConvertPointer (0, (VOID **)&Index);
if (!EFI_ERROR (Status)) {
//
// Invoke the callback (OriginalImageBase, SizeOfImage, ImageEntry)
//
((VOID (*)(VOID *, VOID *))ImageEntry->PhysicalStart)(
ImageEntry->ImageBase,
ImageEntry->ImageSize
);
} else {
DEBUG ((EFI_D_ERROR,
"ERROR: Virtual address change callback at address %X resides in the boot time memory\n",
(UINT32)(UINTN)ImageEntry->PhysicalStart));
ASSERT (FALSE);
}
}
ImageEntry = ImageEntry->ForwardLink;
} while (ImageEntry != &mRuntimeDriverImageList);
}
//
// Walk the image list and convert each image's base address
//
for (ImageEntry = mRuntimeDriverImageList.ForwardLink;
ImageEntry != &mRuntimeDriverImageList;
ImageEntry = ImageEntry->ForwardLink)
{
if (ImageEntry->PhysicalStart != (VOID *)mRuntimeDriverImageList.PhysicalStart) {
Index = (UINTN)ImageEntry->PhysicalStart;
Status = RuntimeDriverConvertPointer (0, (VOID **)&Index);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT (!EFI_ERROR (Status));
}
RuntimeDriverPeCoffRelocateImage (
(UINTN)ImageEntry->PhysicalStart,
Index,
(UINTN)ImageEntry->ImageSize,
(UINT16 *)ImageEntry->ImageBase
);
//
// Flush instruction cache
//
if (ImageEntry->ImageSize != NULL &&
(UINTN)ImageEntry->ImageSize - 1 > ~(UINTN)ImageEntry->PhysicalStart)
{
ASSERT (
(UINTN)(ImageEntry->ImageSize - 1) <= (MAX_UINTN - (UINTN)ImageEntry->PhysicalStart)
);
}
}
}
//
// Convert all Runtime Services pointers
//
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->GetTime);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->SetTime);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->GetWakeupTime);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->SetWakeupTime);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->SetVirtualAddressMap);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->ConvertPointer);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->GetNextVariableName);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->SetVariable);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->GetNextVariableName);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->SetVariable);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->QueryVariableInfo);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->UpdateCapsule);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->QueryCapsuleCapabilities);
RuntimeDriverConvertPointer (0, (VOID **)&gRuntime->ResetSystem);
//
// Recalculate CRC32 for Runtime Services table
//
Crc32Out = 0;
gRuntime->Hdr.CRC32 = 0;
RuntimeDriverCalculateCrc32 (gRuntime, gRuntime->Hdr.HeaderSize, &Crc32Out);
gRuntime->Hdr.CRC32 = Crc32Out;
//
// Recalculate CRC32 for System Table
//
Crc32Out = 0;
gSystemTable->Hdr.CRC32 = 0;
RuntimeDriverCalculateCrc32 (gSystemTable, gSystemTable->Hdr.HeaderSize, &Crc32Out);
gSystemTable->Hdr.CRC32 = Crc32Out;
mRuntimeDriverImageList.ForwardLink = NULL;
//
// Notify POST card of successful virtual address switch
//
IoWrite8 (0x80, 0xB1);
return EFI_SUCCESS;
}
/* ========================================================================
* RuntimeDriver CalculateCrc32 (sub_1B00)
* ======================================================================== */
/**
* Calculates the CRC-32 checksum for a buffer.
*
* @param[in] Data Pointer to the buffer
* @param[in] DataSize Size of the buffer in bytes
* @param[out] CrcOut Receives the computed CRC-32
* @return EFI_SUCCESS, EFI_INVALID_PARAMETER
*/
EFI_STATUS
EFIAPI
RuntimeDriverCalculateCrc32 (
IN VOID *Data,
IN UINTN DataSize,
OUT UINT32 *CrcOut
)
{
UINTN Index;
UINT32 Crc;
if (Data == NULL || DataSize == 0 || CrcOut == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check for overflow
//
if (DataSize > (MAX_ADDRESS - (UINTN)Data + 1)) {
ASSERT (
DataSize <= (MAX_ADDRESS - (UINTN)Data + 1)
);
}
Crc = 0xFFFFFFFF;
if (DataSize != 0) {
for (Index = 0; Index < DataSize; Index++) {
Crc = (Crc >> 8) ^ mCrc32Table[(UINT8)Crc ^ ((UINT8 *)Data)[Index]];
}
}
*CrcOut = ~Crc;
return EFI_SUCCESS;
}
/* ========================================================================
* RuntimeDriver GetNextVariableName (sub_1BA8) / Debug Print router
* ======================================================================== */
/**
* Locates and returns the debug print protocol (used by DEBUG macro).
*
* @return Pointer to the debug print protocol, or NULL if not available
*/
UINTN
EFIAPI
RuntimeDriverDebugProtocol (
VOID
)
{
EFI_STATUS Status;
if (mRuntimeStatusCodeTable == NULL) {
//
// Check if this is boot-time and allocate protocol
//
if (gBootServices != NULL &&
gBootServices->GetMemoryMap (31, &gBootServices, &gBootServices->Hdr.Size) &&
gBootServices->Hdr.Size >= 0x10)
{
Status = gBootServices->LocateProtocol (
&gEfiStatusCodeProtocolGuid,
NULL,
&mRuntimeStatusCodeTable
);
if (EFI_ERROR (Status)) {
mRuntimeStatusCodeTable = NULL;
}
return (UINTN)mRuntimeStatusCodeTable;
} else {
return 0;
}
}
return (UINTN)mRuntimeStatusCodeTable;
}
/* ========================================================================
* DebugPrint (sub_1C30)
* ======================================================================== */
/**
* Prints a debug message conditionally based on error level and
* the current debug level state (CMOS register 0x4B).
*
* @param[in] ErrorLevel Error level mask
* @param[in] Format Format string
* @param[in] ... Variable arguments
* @return Status
*/
EFI_STATUS
EFIAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
VA_LIST Marker;
UINTN Result;
UINTN ErrorLevelMask;
UINT8 DebugLevel;
UINTN CmosIndex113;
VA_START (Marker, Format);
Result = 0;
//
// Check if the debug protocol is available
//
if (mRuntimeStatusCodeTable != NULL) {
//
// Read the current debug level from CMOS
//
DebugLevel = IoRead8 (0x70);
IoWrite8 (0x70, DebugLevel & 0x80 | 0x4B);
CmosIndex113 = 113;
CmosIndex113 = IoRead8 (0x71);
if (CmosIndex113 > 3) {
CmosIndex113 = 3;
}
ErrorLevelMask = (CmosIndex113 - 1);
if ((UINT8)(CmosIndex113 - 1) <= 0xFD) {
ErrorLevelMask = 0x80000004;
if (CmosIndex113 == 1) {
ErrorLevelMask = 0x80000004;
}
}
if ((ErrorLevelMask & ErrorLevel) != 0) {
Result = ((EFI_DEBUG_PRINT_PROTOCOL *)mRuntimeStatusCodeTable)->DebugPrint (
ErrorLevel,
Format,
&Marker
);
}
}
VA_END (Marker);
return Result;
}
/* ========================================================================
* DebugAssert (sub_1CB0)
* ======================================================================== */
/**
* Asserts that a condition is TRUE. If the condition evaluates to FALSE,
* then a breakpoint and deadloop are triggered.
*
* @param[in] FileName Source file name
* @param[in] LineNumber Line number
* @param[in] Description Assert description string
*/
VOID
EFIAPI
DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
UINTN Result;
Result = RuntimeDriverDebugProtocol ();
if (Result != 0) {
((EFI_DEBUG_PRINT_PROTOCOL *)Result)->DebugAssert (FileName, LineNumber, Description);
}
}
/* ========================================================================
* VirtualAddressChangeNotify (sub_1CF0)
* ======================================================================== */
/**
* Notify function for virtual address change event.
* Clears the BootServices pointer since it's no longer available.
*/
VOID
EFIAPI
VirtualAddressChangeNotify (
VOID
)
{
gBootServices = NULL;
}
/* ========================================================================
* RuntimeDriver ExitBootServices Notify (sub_1CFC)
* ======================================================================== */
/**
* Notify function called on ExitBootServices.
* Disables the watchdog timer via runtime services.
*
* @return EFI_SUCCESS or EFI_INVALID_PARAMETER
*/
EFI_STATUS
EFIAPI
RuntimeDriverExitBootServicesNotify (
VOID
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (mRuntimeStatusCodeTable != NULL) {
Status = gRuntime->SetWatchdogTimer (0, 0, 0, NULL);
}
return Status;
}
/* ========================================================================
* RuntimeDriver Initialize EndOfDxe (sub_1D24)
* ======================================================================== */
/**
* Initialize the runtime driver EndOfDxe event by locating
* the HOB list from the system table.
*
* @param[in] Event EndOfDxe event
* @param[out] Context HOB list pointer
* @return EFI_SUCCESS, EFI_NOT_FOUND
*/
UINTN
EFIAPI
RuntimeDriverInitializeEndOfDxe (
IN VOID *Event
)
{
EFI_STATUS Status;
EFI_HOB_HANDOFF_INFO_TABLE *Hob;
UINTN Index;
UINTN HobList;
//
// Check if HOB list is already cached
//
if (mRuntimeDriverBootServicesEvent == NULL) {
Index = 0;
mRuntimeDriverBootServicesEvent = 0;
if (gSystemTable->HobList != NULL) {
//
// Walk configuration table entries looking for HobList
//
for (Index = 0; Index < (UINTN)gSystemTable->NumberOfTableEntries; Index++) {
if (RuntimeDriverCompareGuid (
(EFI_GUID *)Event,
(EFI_GUID *)((UINTN)gSystemTable->ConfigurationTable +
Index * sizeof(EFI_CONFIGURATION_TABLE))
))
{
HobList = *(UINTN *)((UINTN)gSystemTable->ConfigurationTable +
Index * sizeof(EFI_CONFIGURATION_TABLE) +
sizeof(EFI_GUID));
mRuntimeDriverBootServicesEvent = (VOID *)HobList;
break;
}
}
if (Index >= (UINTN)gSystemTable->NumberOfTableEntries) {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
ASSERT (!EFI_ERROR (EFI_NOT_FOUND));
}
if (HobList == 0) {
ASSERT (mRuntimeDriverBootServicesEvent != NULL);
}
} else {
DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
ASSERT (!EFI_ERROR (EFI_NOT_FOUND));
}
}
return (UINTN)mRuntimeDriverBootServicesEvent;
}
/* ========================================================================
* RuntimeDriver InitializeEndOfDxe event callback (sub_1E00)
* ======================================================================== */
/**
* Callback for EndOfDxe event that saves the runtime services
* pointer for later use.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
RuntimeDriverInitializeEndOfDxeCallback (
VOID
)
{
return gRuntime->SetWatchdogTimer (0, 0, 0, NULL);
}
/* ========================================================================
* RuntimeDriver PeCoff Relocate (sub_1E14)
* ======================================================================== */
/**
* Relocates a PE/COFF image from its old base address to a new base address
* by walking the base relocations directory.
*
* @param[in] OldBase Old image base address
* @param[in] NewBase New image base address
* @param[in] ImageSize Size of the image
* @param[in,out] FixupData Buffer storing fixup data for delta calculation
* @return 0 on success or an abort code
*/
UINT16
EFIAPI
RuntimeDriverPeCoffRelocateImage (
IN UINTN OldBase,
IN UINTN NewBase,
IN UINTN ImageSize,
IN UINT16 *FixupData
)
{
UINT16 Result;
UINTN Delta;
UINTN ImageBase;
UINTN RelocDirEntryRva;
UINTN RelocDirEntrySize;
UINTN RelocBase;
UINTN RelocBaseEnd;
UINTN RelocBlockBase;
UINT32 *RelocHdr;
UINT16 *RelocData;
UINT16 *RelocDataEnd;
UINTN RelocCount;
UINT16 RelocType;
UINT16 Offset;
UINT16 *FixupDest16;
UINT32 *FixupDest32;
UINT64 *FixupDest64;
UINT16 *FixupPtr;
UINT32 *FixupPtrAligned32;
UINT64 *FixupPtrAligned64;
Result = IMAGE_DOS_SIGNATURE;
Delta = NewBase - OldBase;
//
// Check for DOS header magic
//
if (*(UINT16 *)OldBase == IMAGE_DOS_SIGNATURE) {
ImageBase = OldBase + *(UINT32 *)(OldBase + 0x3C); // e_lfanew
} else {
ImageBase = OldBase;
}
//
// Check for PE signature
//
if (*(UINT32 *)ImageBase != IMAGE_PE_SIGNATURE) {
return Result;
}
//
// Determine relocation directory RVA and size
//
if (*(UINT16 *)(ImageBase + 4) == 0x200 &&
*(UINT16 *)(ImageBase + 24) == 0x10B ||
*(UINT16 *)(ImageBase + 24) != 0x10B)
{
//
// PE32+ (64-bit)
//
RelocDirEntryRva = *(UINT32 *)(ImageBase + 0x84);
RelocDirEntrySize = *(UINT32 *)(ImageBase + 0x88);
} else {
//
// PE32 (32-bit)
//
RelocDirEntryRva = *(UINT32 *)(ImageBase + 0x74);
RelocDirEntrySize = *(UINT32 *)(ImageBase + 0x78);
}
//
// Validate relocation directory size
//
if (RelocDirEntrySize <= sizeof(UINT32) * 2) {
Result = DebugAssert (
"e:\\hs\\MdePkg\\Library\\BasePeCoffLib\\BasePeCoff.c",
1791,
"((BOOLEAN)(0==1))"
);
return Result;
}
//
// Calculate relocation base and end pointers
//
RelocBase = OldBase + RelocDirEntryRva;
RelocBaseEnd = OldBase + RelocDirEntryRva + RelocDirEntrySize;
if (RelocBase == 0 || RelocBaseEnd == 0) {
Result = DebugAssert (
"e:\\hs\\MdePkg\\Library\\BasePeCoffLib\\BasePeCoff.c",
1798,
"RelocBase != ((void *) 0) && RelocBaseEnd != ((void *) 0)"
);
return Result;
}
//
// Walk each base relocation block
//
RelocHdr = (UINT32 *)RelocBase;
while (RelocHdr < (UINT32 *)RelocBaseEnd) {
RelocBlockBase = OldBase + *RelocHdr;
if (RelocHdr[1] != 0) {
if (RelocHdr[1] <= (UINT32)(RelocDirEntrySize - ((UINTN)RelocHdr - (UINTN)RelocBase) + sizeof(UINT64))) {
RelocDataEnd = (UINT16 *)((UINTN)RelocHdr + RelocHdr[1]);
RelocData = (UINT16 *)(RelocHdr + 2);
while (RelocData < RelocDataEnd) {
RelocType = *RelocData >> 12;
Offset = *RelocData & 0xFFF;
FixupDest16 = (UINT16 *)(RelocBlockBase + Offset);
switch (RelocType) {
case EFI_IMAGE_REL_BASED_ABSOLUTE:
break;
case EFI_IMAGE_REL_BASED_HIGH:
if (*FixupData == *FixupDest16) {
*FixupDest16 = (UINT16)((UINTN)*FixupDest16 + (UINTN)(Delta >> 16));
}
FixupData++;
break;
case EFI_IMAGE_REL_BASED_LOW:
if (*FixupData == *FixupDest16) {
*FixupDest16 = (UINT16)((UINTN)*FixupDest16 + Delta);
}
FixupData++;
break;
case EFI_IMAGE_REL_BASED_HIGHLOW:
FixupDest32 = (UINT32 *)((UINTN)FixupDest16);
FixupPtr = (UINT16 *)((UINTN)FixupData + ALIGN_POINTER (FixupData, sizeof(UINT32)));
if (*FixupPtr == *(UINT32 *)FixupDest16) {
*(UINT32 *)FixupDest16 = *(UINT32 *)FixupDest16 + (UINT32)Delta;
}
FixupData = (UINT16 *)((UINTN)FixupPtr + sizeof(UINT32));
break;
case EFI_IMAGE_REL_BASED_DIR64:
FixupDest64 = (UINT64 *)((UINTN)FixupDest16);
FixupPtrAligned64 = (UINT64 *)((UINTN)FixupData + ALIGN_POINTER (FixupData, sizeof(UINT64)));
if (*FixupPtrAligned64 == *(UINT64 *)FixupDest64) {
*(UINT64 *)FixupDest64 += Delta;
}
FixupData = (UINT16 *)((UINTN)FixupPtrAligned64 + sizeof(UINT64));
break;
default:
return (UINT16)RelocType;
}
RelocData++;
}
}
}
RelocHdr = (UINT32 *)RelocDataEnd;
}
return Result;
}
/* ========================================================================
* ReportStatusCodeConstructor (sub_1FE4)
* ======================================================================== */
/**
* Initializes the status code reporting protocol by locating
* the ReportStatusCode protocol via gBootServices.
*/
VOID
EFIAPI
ReportStatusCodeConstructor (
VOID
)
{
EFI_STATUS Status;
if (mRuntimeDriverBootServicesEvent == NULL && !mEfiGoneVirtual) {
if (gBootServices != NULL) {
if (gBootServices->LocateProtocol != NULL) {
Status = (UINTN)gBootServices->LocateProtocol (
&gEfiStatusCodeRuntimeProtocolGuid,
NULL,
&mRuntimeStatusCodeTable
);
if (EFI_ERROR (Status)) {
mRuntimeStatusCodeTable = NULL;
}
}
}
}
}
/* ========================================================================
* RuntimeDriver SetVirtualAddressMap Handler (sub_2044)
* ======================================================================== */
/**
* Handler for the SetVirtualAddressMap status code callback.
* Relocates the status code table pointer to its virtual address.
*
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
RuntimeDriverSetVirtualAddressMapHandler (
VOID
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (mRuntimeStatusCodeTable != NULL) {
Status = gRuntime->ConvertPointer (0, &mRuntimeStatusCodeTable);
}
return Status;
}
/* ========================================================================
* RuntimeDriver SetVirtualAddressMap Notify (sub_206C / nullsub)
* ======================================================================== */
/**
* Notify function for SetVirtualAddressMap signal.
* Re-initializes the status code reporting and sets mEfiGoneVirtual.
*/
VOID
EFIAPI
RuntimeDriverSetVirtualAddressMapNotify (
VOID
)
{
ReportStatusCodeConstructor ();
mEfiGoneVirtual = TRUE;
}
/* ========================================================================
* RuntimeDriverCalculateCrc32 Wrapper (sub_2084)
* ======================================================================== */
/**
* Wrapper function for CRC32 calculation used by the status code protocol.
*
* @param[in] a1 Data pointer
* @param[in] n51449860 CRC32 parameter
* @return EFI_STATUS
*/
EFI_STATUS
EFIAPI
RuntimeDriverCalculateCrc32Event (
UINTN a1,
UINT32 n51449860
)
{
ReportStatusCodeConstructor ();
if (mRuntimeStatusCodeTable != NULL) {
return ((EFI_STATUS_CODE_PROTOCOL *)mRuntimeStatusCodeTable)->ReportStatusCode (
EFI_PROGRESS_CODE,
n51449860,
0,
&gEfiStatusCodeDataTypeGuid,
NULL
);
}
return EFI_NOT_AVAILABLE_YET;
}
/* ========================================================================
* RuntimeDriver CompareGuid (sub_20C8)
* ======================================================================== */
/**
* Compares two EFI_GUID structures for equality.
*
* @param[in] Guid1 Pointer to first GUID
* @param[in] Guid2 Pointer to second GUID
* @return TRUE if the GUIDs are equal, FALSE otherwise
*/
BOOLEAN
EFIAPI
RuntimeDriverCompareGuid (
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
)
{
UINT64 GuidData1;
UINT64 GuidData2;
GuidData1 = RuntimeDriverReadUnaligned64 (Guid1);
GuidData2 = RuntimeDriverReadUnaligned64 (Guid2);
return GuidData1 == GuidData2 &&
RuntimeDriverReadUnaligned64 ((UINT64 *)((UINTN)Guid1 + 8)) ==
RuntimeDriverReadUnaligned64 ((UINT64 *)((UINTN)Guid2 + 8));
}
/* ========================================================================
* RuntimeDriver ReadUnaligned64 (sub_2138)
* ======================================================================== */
/**
* Reads a 64-bit value from an unaligned address.
*
* @param[in] Buffer Pointer to the buffer to read from
* @return The 64-bit value read
*/
UINT64
EFIAPI
RuntimeDriverReadUnaligned64 (
IN VOID *Buffer
)
{
ASSERT (Buffer != NULL);
return *(UINT64 *)Buffer;
}
/* ========================================================================
* RuntimeDriver SetWatchdogTimer (nullsub_1 at 0x1DFC)
* ======================================================================== */
/**
* Null implementation of SetWatchdogTimer (placeholder).
*/
VOID
EFIAPI
RuntimeDriverSetWatchdogTimerHandler (
VOID
)
{
//
// Intentionally empty (no-op)
//
}