Newer
Older
AMI-Aptio-BIOS-Reversed / EsrtDxe / EsrtDxe.c
@Ajax Dong Ajax Dong 2 days ago 39 KB Init
/** @file EsrtDxe.c -- UEFI ESRT (EFI System Resource Table) DXE Driver This module manages the ESRT (EFI System Resource Table) on UEFI systems.
 It maintains two firmware resource repositories as UEFI variables:
 - "EsrtFmp" : FMP (Firmware Management Protocol) entries
 - "EsrtNonFmp" : Non-FMP entries (legacy capsule updates)

 On ReadyToBoot, the driver enumerates all FMP protocols installed on the system, collects their firmware image descriptors, and builds the combined ESRT configuration table. The table is installed into the UEFI configuration table for consumption by the OS.

 Source: MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c Module: EsrtDxe.efi (Lenovo HR650X BIOS)
 EDK2 Path: MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf Copyright (c) 2014, Intel Corporation. All rights reserved.
 SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "EsrtDxe.h"

//
// ---------------------------------------------------------------------------
// Module Global Variables
// ---------------------------------------------------------------------------

EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gST = NULL;
EFI_BOOT_SERVICES *gBS = NULL;
EFI_RUNTIME_SERVICES *gRT = NULL;
VOID *mHobList = NULL;
VOID *gDS = NULL;

EFI_LOCK mFmpLock; ///< Lock for EsrtFmp variable EFI_LOCK mNonFmpLock; ///< Lock for EsrtNonFmp variable

//
// GUID definitions (module-local)
//
EFI_GUID gEfiEsrtTableProtocolGuid = ESRT_TABLE_PROTOCOL_GUID;
EFI_GUID gEfiEsrtManagementProtocolGuid = ESRT_MANAGEMENT_PROTOCOL_GUID;
EFI_GUID gEfiHobListGuid = HOB_LIST_GUID;
EFI_GUID gEfiDxeServicesTableGuid = DXE_SERVICES_TABLE_GUID;
EFI_GUID gEfiVariableVendorGuid = ESRT_VARIABLE_VENDOR_GUID;
EFI_GUID gEfiReadyToBootGuid = READY_TO_BOOT_EVENT_GUID;
EFI_GUID gEfiVirtualAddrChangeGuid = VIRTUAL_ADDRESS_CHANGE_EVENT_GUID;

//
// ---------------------------------------------------------------------------
// Internal Memory Helpers (Minimal implementations)
// ---------------------------------------------------------------------------

STATIC VOID *InternalCopyMem (
 OUT VOID *Destination,
 IN CONST VOID *Source,
 IN UINTN Length
 )
{
 CHAR8 *Dst8 = (CHAR8 *)Destination;
 CHAR8 *Src8 = (CHAR8 *)Source;

 if (Src8 < Dst8 && &Src8[Length - 1] >= Dst8) {
 //
 // Overlapping: copy backwards
 //
 Dst8 += Length - 1;
 Src8 += Length - 1;
 while (Length--) {
 *Dst8-- = *Src8--;
 }
 } else {
 //
 // Non-overlapping: copy forward in 8-byte chunks
 //
 UINTN Count = Length >> 3;
 for (Count = 0; Count < Length >> 3; Count++) {
 ((UINT64 *)Dst8)[Count] = ((UINT64 *)Src8)[Count];
 }
 Dst8 += Count << 3;
 Src8 += Count << 3;
 Length &= 7;
 while (Length--) {
 *Dst8++ = *Src8++;
 }
 }

 return Destination;
}

STATIC VOID *InternalZeroMem (
 OUT VOID *Buffer,
 IN UINTN Length
 )
{
 CHAR8 *Buf8 = (CHAR8 *)Buffer;
 UINTN Count;
 BOOLEAN Safe;

 //
 // Overlap/safety checks (from BaseMemoryLibRepStr)
 //
 Count = Length - 1;
 Safe = (Count <= (UINTN)(-1) - (UINTN)Buffer);

 for (Count = 0; Count < Length >> 3; Count++) {
 ((UINT64 *)Buf8)[Count] = 0;
 }
 Buf8 += Count << 3;
 Length &= 7;
 while (Length--) {
 *Buf8++ = 0;
 }

 return Buffer;
}

//
// ---------------------------------------------------------------------------
// Library Function Wrappers (from EDK2 libraries)
// ---------------------------------------------------------------------------

/**Copy memory with bounds checking.
**/
VOID *EFIAPI CopyMem (
 OUT VOID *DestinationBuffer,
 IN CONST VOID *SourceBuffer,
 IN UINTN Length
 )
{
 UINTN CountMinusOne;

 CountMinusOne = Length - 1;
 if (CountMinusOne > (UINTN)(-1) - (UINTN)DestinationBuffer) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c", 56,
 "(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)DestinationBuffer)");
 }
 if (CountMinusOne > (UINTN)(-1) - (UINTN)SourceBuffer) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c", 57,
 "(Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)SourceBuffer)");
 }
 if (DestinationBuffer == SourceBuffer) {
 return DestinationBuffer;
 }
 return InternalCopyMem (DestinationBuffer, SourceBuffer, Length);
}

/**Zero memory with bounds checking.
**/
VOID *EFIAPI ZeroMem (
 OUT VOID *Buffer,
 IN UINTN Length
 )
{
 if (Length == 0) {
 return Buffer;
 }
 if (Buffer == NULL) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\ZeroMemWrapper.c", 53,
 "Buffer != ((void *) 0)");
 }
 if (Length > (UINTN)(-1) - (UINTN)Buffer + 1) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\ZeroMemWrapper.c", 54,
 "Length <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)Buffer + 1)");
 }
 return InternalZeroMem (Buffer, Length);
}

//
// ---------------------------------------------------------------------------
// Allocation Helpers
// ---------------------------------------------------------------------------

/**Allocate a pool buffer.
**/
VOID *EFIAPI AllocatePool (
 IN UINTN Size
 )
{
 VOID *Buffer;

 if (gBS->AllocatePool (EfiBootServicesData, Size, &Buffer) < 0) {
 return NULL;
 }
 return Buffer;
}

/**Allocate and zero a pool buffer.
**/
VOID *EFIAPI AllocateZeroPool (
 IN UINTN Size
 )
{
 VOID *Buffer;

 Buffer = AllocatePool (Size);
 if (Buffer != NULL) {
 ZeroMem (Buffer, Size);
 }
 return Buffer;
}

/**Free a pool buffer.
**/
VOID EFIAPI FreePool (
 IN VOID *Buffer
 )
{
 EFI_STATUS Status;

 Status = gBS->FreePool (Buffer);
 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiMemoryAllocationLib\\MemoryAllocationLib.c",
 819,
 "!EFI_ERROR (Status)"
 );
 }
}

//
// ---------------------------------------------------------------------------
// GUID Comparison
// ---------------------------------------------------------------------------

/**Read an unaligned 64-bit value.
**/
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 EFI_GUIDs via 64-bit unaligned reads.
**/
BOOLEAN EFIAPI CompareGuid (
 IN EFI_GUID *Guid1,
 IN EFI_GUID *Guid2
 )
{
 UINT64 Data1_1;
 UINT64 Data1_2;
 UINT64 Data2_1;
 UINT64 Data2_2;

 Data1_1 = ReadUnaligned64 (Guid1);
 Data2_1 = ReadUnaligned64 ((UINT8 *)Guid1 + 8);
 Data1_2 = ReadUnaligned64 (Guid2);
 Data2_2 = ReadUnaligned64 ((UINT8 *)Guid2 + 8);

 return (Data1_1 == Data1_2 && Data2_1 == Data2_2);
}

//
// ---------------------------------------------------------------------------
// Debug Output Support
// ---------------------------------------------------------------------------

/**Locate and cache the debug output protocol pointer.
**/
UINTN GetDebugOutputProtocol (
 VOID
 )
{
 UINTN CmosData;
 EFI_STATUS Status;
 VOID *Protocol;

 if (mDebugProtocol != NULL) {
 return (UINTN)mDebugProtocol;
 }

 CmosData = gBS->ReadCmosCounter (31);
 gBS->WriteCmosCounter (CmosData);

 if (CmosData <= 0x10) {
 Status = gBS->LocateProtocol (&gEfiDebugProtocolGuid, NULL, &Protocol);
 if (Status >= 0 && Protocol != NULL) {
 mDebugProtocol = Protocol;
 return (UINTN)Protocol;
 }
 }

 mDebugProtocol = NULL;
 return 0;
}

/**Debug print to the debug output protocol.
**/
VOID EFIAPI DebugPrint (
 IN UINTN ErrorLevel,
 IN CONST CHAR8 *Format,
 ...
 )
{
 UINTN Protocol;
 UINT8 CmosByte;

 Protocol = GetDebugOutputProtocol ();
 if (Protocol == 0) {
 return;
 }

 //
 // Check debug enable via CMOS register 0x4B.
 //
 __outbyte (0x70, __inbyte (0x70) & 0x80 | 0x4B);
 CmosByte = __inbyte (0x71);

 if (CmosByte > 3) {
 //
 // Determine debug level
 //
 if (CmosByte == 0) {
 CmosByte = (*(UINT8 *)(UINTN)0xFDAF0490 & 2) | 1;
 }
 } else if (CmosByte > 1 && CmosByte <= 0xFE) {
 CmosByte = 4;
 }

 CmosByte--;

 //
 // Map decoded level to standard DEBUG masks.
 //
 if (CmosByte == 0) {
 if ((UINTN)0x80000000 & ErrorLevel) {
 goto PRINT;
 }
 } else if (CmosByte == 1) {
 if ((UINTN)0x00400000 & ErrorLevel) {
 goto PRINT;
 }
 }
 return;

PRINT:
 //
 // Call the protocol's Print routine.
 //
 (*(UINTN ( **)(UINTN, CONST CHAR8 *, UINTN))Protocol)(
 ErrorLevel, Format, (UINTN)&Format + sizeof(Format));
}

/**Debug assert callback.
**/
VOID EFIAPI DebugAssert (
 IN CONST CHAR8 *FileName,
 IN UINTN LineNumber,
 IN CONST CHAR8 *Description
 )
{
 UINTN Protocol;

 Protocol = GetDebugOutputProtocol ();
 if (Protocol == 0) {
 return;
 }

 (*(VOID ( **)(CONST CHAR8 *, UINTN, CONST CHAR8 *))(Protocol + 8))(
 FileName, LineNumber, Description);
}

//
// ---------------------------------------------------------------------------
// Lock Management (from UefiLib)
// ---------------------------------------------------------------------------

/**Initialize a lock structure.
**/
VOID EFIAPI EfiInitializeLock (
 IN OUT EFI_LOCK *Lock
 )
{
 if (Lock == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 418,
 "Lock != ((void *) 0)");
 }
 Lock->Tpl = 8; // TPL_NOTIFY Lock->OwnerTpl = 4; // Default saved TPL Lock->LockState = 1; // EfiLockReleased
}

/**Acquire a lock (raise to lock TPL and save old TPL).
**/
EFI_STATUS EFIAPI EfiAcquireLock (
 IN OUT EFI_LOCK *Lock
 )
{
 EFI_TPL OldTpl;

 if (Lock == NULL) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 476,
 "Lock != ((void *) 0)");
 }
 if (Lock->LockState == 0) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 477,
 "Lock->Lock != EfiLockUninitialized");
 }
 if (Lock->LockState == 2) {
 return (UINTN)0x800000000000000FuLL; // EFI_ACCESS_DENIED
 }

 OldTpl = gBS->RaiseTPL (Lock->Tpl);
 Lock->OwnerTpl = OldTpl;
 Lock->LockState = 2; // EfiLockAcquired return 0;
}

/**Release a lock (restore old TPL).
**/
EFI_STATUS EFIAPI EfiReleaseLock (
 IN OUT EFI_LOCK *Lock
 )
{
 EFI_TPL OldTpl;

 if (Lock == NULL) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 514,
 "Lock != ((void *) 0)");
 }
 if (Lock->LockState != 2) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 515,
 "Lock->Lock == EfiLockAcquired");
 }

 OldTpl = (UINTN)Lock->OwnerTpl;
 Lock->LockState = 1; // EfiLockReleased gBS->RestoreTPL (OldTpl);

 return 0;
}

//
// ---------------------------------------------------------------------------
// Configuration Table Access (from UefiLib)
// ---------------------------------------------------------------------------

/**Look up an entry in the EFI System Configuration Table by GUID.
**/
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable (
 IN EFI_GUID *TableGuid,
 OUT VOID **Table
 )
{
 UINTN Index;
 UINTN TableCount;

 if (TableGuid == NULL) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 97,
 "TableGuid != ((void *) 0)");
 }
 if (Table == NULL) {
 DebugAssert ("e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 98,
 "Table != ((void *) 0)");
 }

 *Table = NULL;
 TableCount = gST->NumberOfTableEntries;

 if (TableCount == 0) {
 return (UINTN)0x800000000000000EuLL; // EFI_NOT_FOUND
 }

 for (Index = 0; Index < TableCount; Index++) {
 if (CompareGuid (
 &gST->ConfigurationTable[Index].VendorGuid,
 TableGuid
 )) {
 *Table = gST->ConfigurationTable[Index].VendorTable;
 return 0; // EFI_SUCCESS
 }
 }

 return (UINTN)0x800000000000000EuLL; // EFI_NOT_FOUND
}

//
// ---------------------------------------------------------------------------
// HOB List Initialization
// ---------------------------------------------------------------------------

/**Initialize the HOB list pointer from the configuration table.
**/
EFI_STATUS EFIAPI HobLibConstructor (
 VOID
 )
{
 EFI_STATUS Status;

 if (mHobList != NULL) {
 return 0;
 }

 Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &mHobList);

 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 54,
 "!EFI_ERROR (Status)"
 );
 }
 if (mHobList == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c", 55,
 "mHobList != ((void *) 0)");
 }

 return 0;
}

//
// ---------------------------------------------------------------------------
// Variable Access (from UefiLib)
// ---------------------------------------------------------------------------

/**Read a UEFI variable into a dynamically-allocated buffer.
**/
EFI_STATUS EFIAPI GetEfiVariable (
 IN CONST CHAR16 *VariableName,
 IN EFI_GUID *VendorGuid,
 OUT VOID **Value,
 OUT UINTN *Size OPTIONAL
 )
{
 EFI_STATUS Status;
 UINTN BufferSize;
 VOID *Buffer;

 if (VariableName == NULL || Value == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 1401,
 "Name != ((void *) 0) && Guid != ((void *) 0) && Value != ((void *) 0)");
 }

 *Value = NULL;
 if (Size != NULL) {
 *Size = 0;
 }
 BufferSize = 0;

 //
 // First query: get size.
 //
 Status = gRT->GetVariable (
 VariableName,
 VendorGuid,
 NULL,
 &BufferSize,
 NULL
 );

 if (Status == (UINTN)0x8000000000000005uLL) { // EFI_BUFFER_TOO_SMALL Buffer = AllocatePool (BufferSize);
 if (Buffer == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiLib\\UefiLib.c", 1421,
 "*Value != ((void *) 0)");
 }

 if (Buffer != NULL) {
 Status = gRT->GetVariable (
 VariableName,
 VendorGuid,
 NULL,
 &BufferSize,
 Buffer
 );
 if (Status < 0) {
 FreePool (Buffer);
 *Value = NULL;
 } else {
 *Value = Buffer;
 }

 if (Size != NULL) {
 *Size = BufferSize;
 }
 } else {
 return (UINTN)0x8000000000000009uLL; // EFI_OUT_OF_RESOURCES
 }
 }

 return Status;
}

//
// ===========================================================================
// ESRT Repository: Find, Copy, Update, Append, Delete Operations
// ===========================================================================

#define ESRT_FMP_TYPE 1
#define ESRT_NONFMP_TYPE 2
#define ESRT_ENTRY_SIZE sizeof(ESRT_ENTRY)
#define ESRT_REPO_MAX 0x500 // 1280 bytes = 32 entries

//
// ---------------------------------------------------------------------------
// Helper: Look up variable name for repository type.
// ---------------------------------------------------------------------------

STATIC CONST CHAR16 *EsrtVariableForType (
 IN UINTN RepositoryType
 )
{
 if (RepositoryType == ESRT_FMP_TYPE) {
 return ESRT_FMP_VARIABLE_NAME;
 }
 return ESRT_NONFMP_VARIABLE_NAME;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeFindAndCopyEntry
// ---------------------------------------------------------------------------

/**Find an ESRT entry by FwClass GUID and copy it to the output buffer.

 @return EFI_SUCCESS Found and copied.
 @return EFI_NOT_FOUND No matching entry in repository.
 @return EFI_UNSUPPORTED Repository data corrupt.
**/
EFI_STATUS EsrtDxeFindAndCopyEntry (
 IN EFI_GUID *FwClass,
 IN UINTN RepositoryType,
 OUT ESRT_ENTRY *EntryData
 )
{
 CONST CHAR16 *VariableName;
 EFI_STATUS Status;
 ESRT_ENTRY *Repository;
 UINTN RepoSize;
 UINTN EntryCount;
 UINTN Index;

 VariableName = EsrtVariableForType (RepositoryType);

 Status = GetEfiVariable (VariableName, &gEfiVariableVendorGuid,
 (VOID **)&Repository, &RepoSize);
 if (Status < 0) {
 return Status;
 }

 //
 // Validate repository alignment.
 //
 EntryCount = RepoSize / ESRT_ENTRY_SIZE;
 if (RepoSize != EntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "Repository Corrupt. Need to rebuild Repository.\n");
 FreePool (Repository);
 return (UINTN)0x8000000000000015uLL; // EFI_UNSUPPORTED
 }

 //
 // Scan for matching GUID.
 //
 Status = (UINTN)0x800000000000000EuLL; // EFI_NOT_FOUND for (Index = 0; Index < EntryCount; Index++) {
 if (CompareGuid (FwClass, &Repository[Index].FwClass)) {
 CopyMem (EntryData, &Repository[Index], ESRT_ENTRY_SIZE);
 Status = 0; // EFI_SUCCESS break;
 }
 }

 FreePool (Repository);
 return Status;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeAppendNonFmpEntry
// ---------------------------------------------------------------------------

/**Append an entry to the Non-FMP repository.

 If the repository does not exist, create it with one entry.
 If the repository already has 32 entries (0x500 bytes), fail.
**/
EFI_STATUS EsrtDxeAppendNonFmpEntry (
 IN ESRT_ENTRY *Entry
 )
{
 EFI_STATUS Status;
 ESRT_ENTRY *Repository;
 UINTN RepoSize;
 UINTN EntryCount;
 VOID *NewRepo;
 VOID *NewRepoWrite;

 Status = GetEfiVariable (ESRT_NONFMP_VARIABLE_NAME, &gEfiVariableVendorGuid,
 (VOID **)&Repository, &RepoSize);

 if (Status == (UINTN)0x800000000000000EuLL) { // EFI_NOT_FOUND
 //
 // Create a new variable with single entry.
 //
 return gRT->SetVariable (
 ESRT_NONFMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid,
 3,
 ESRT_ENTRY_SIZE,
 Entry
 );
 }

 if (Status < 0) {
 return Status;
 }

 //
 // Validate repository.
 //
 EntryCount = RepoSize / ESRT_ENTRY_SIZE;
 if (RepoSize != EntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "Repository Corrupt. Need to rebuild Repository.\n");

 //
 // Delete corrupt variable, then create new with this entry.
 //
 gRT->SetVariable (
 ESRT_NONFMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid,
 3,
 0,
 NULL
 );

 FreePool (Repository);
 RepoSize = 0;
 EntryCount = 0;
 Repository = NULL;
 }

 if (RepoSize >= ESRT_REPO_MAX) {
 //
 // Repository is full (1280 bytes / 40 = 32 entries).
 //
 if (Repository != NULL) {
 FreePool (Repository);
 }
 return (UINTN)0x8000000000000009uLL; // EFI_OUT_OF_RESOURCES
 }

 //
 // Allocate larger buffer, copy existing, append new entry.
 //
 NewRepo = AllocatePool (RepoSize + ESRT_ENTRY_SIZE);
 if (NewRepo == NULL) {
 if (Repository != NULL) {
 FreePool (Repository);
 }
 return (UINTN)0x8000000000000009uLL;
 }

 if (RepoSize > 0 && Repository != NULL) {
 CopyMem (NewRepo, Repository, RepoSize);
 }

 NewRepoWrite = (UINT8 *)NewRepo + RepoSize;
 CopyMem (NewRepoWrite, Entry, ESRT_ENTRY_SIZE);

 Status = gRT->SetVariable (
 ESRT_NONFMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid,
 3,
 RepoSize + ESRT_ENTRY_SIZE,
 NewRepo
 );

 FreePool (NewRepo);
 if (Repository != NULL) {
 FreePool (Repository);
 }

 return Status;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeDeleteNonFmpEntry
// ---------------------------------------------------------------------------

/**Remove an entry (by GUID) from the Non-FMP ESRT repository.
 Shifts remaining entries to fill the gap.
**/
EFI_STATUS EsrtDxeDeleteNonFmpEntry (
 IN EFI_GUID *FwClass
 )
{
 EFI_STATUS Status;
 ESRT_ENTRY *Repository;
 UINTN RepoSize;
 UINTN EntryCount;
 UINTN Index;

 Status = GetEfiVariable (ESRT_NONFMP_VARIABLE_NAME, &gEfiVariableVendorGuid,
 (VOID **)&Repository, &RepoSize);
 if (Status < 0) {
 return Status;
 }

 EntryCount = RepoSize / ESRT_ENTRY_SIZE;
 if (RepoSize != EntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "Repository Corrupt. Need to rebuild Repository.\n");
 FreePool (Repository);
 return (UINTN)0x8000000000000015uLL;
 }

 //
 // Find the entry to delete.
 //
 for (Index = 0; Index < EntryCount; Index++) {
 if (CompareGuid (FwClass, &Repository[Index].FwClass)) {
 break;
 }
 }

 if (Index >= EntryCount) {
 FreePool (Repository);
 return (UINTN)0x800000000000000EuLL; // EFI_NOT_FOUND
 }

 //
 // Shift entries after gap.
 //
 if (Index < EntryCount - 1) {
 CopyMem (
 &Repository[Index],
 &Repository[Index + 1],
 (EntryCount - Index - 1) *ESRT_ENTRY_SIZE
 );
 }

 //
 // Write updated (smaller) repository.
 //
 Status = gRT->SetVariable (
 ESRT_NONFMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid,
 3,
 (EntryCount - 1) *ESRT_ENTRY_SIZE,
 Repository
 );

 FreePool (Repository);
 return Status;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeUpdateRepositoryEntry
// ---------------------------------------------------------------------------

/**Find a matching entry in the repository and overwrite it with new data.

 If the entry is not found and the repository has room (< 0x500 bytes),
 the entry is appended. If EntryData is NULL and the entry is found,
 it is zeroed out (not removed).
**/
EFI_STATUS EsrtDxeUpdateRepositoryEntry (
 IN EFI_GUID *FwClass,
 IN UINTN RepositoryType
 )
{
 CONST CHAR16 *VariableName;
 EFI_STATUS Status;
 ESRT_ENTRY *Repository;
 UINTN RepoSize;
 UINTN EntryCount;
 UINTN Index;

 VariableName = EsrtVariableForType (RepositoryType);

 Status = GetEfiVariable (VariableName, &gEfiVariableVendorGuid,
 (VOID **)&Repository, &RepoSize);
 if (Status < 0) {
 return Status;
 }

 EntryCount = RepoSize / ESRT_ENTRY_SIZE;
 if (RepoSize != EntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "Repository Corrupt. Need to rebuild Repository.\n");

 //
 // Corrupt: delete and return NOT_FOUND.
 //
 gRT->SetVariable (VariableName, &gEfiVariableVendorGuid, 3, 0, NULL);
 FreePool (Repository);
 return (UINTN)0x800000000000000EuLL;
 }

 //
 // Scan for matching GUID.
 //
 for (Index = 0; Index < EntryCount; Index++) {
 if (CompareGuid (FwClass, &Repository[Index].FwClass)) {
 //
 // Found: overwrite.
 //
 CopyMem (&Repository[Index], FwClass, ESRT_ENTRY_SIZE);

 Status = gRT->SetVariable (
 VariableName,
 &gEfiVariableVendorGuid,
 3,
 RepoSize,
 Repository
 );

 FreePool (Repository);
 return Status;
 }
 }

 //
 // Not found: append if space available.
 //
 if (RepoSize < ESRT_REPO_MAX) {
 //
 // Allocate larger buffer, append entry.
 //
 VOID *NewRepo = AllocatePool (RepoSize + ESRT_ENTRY_SIZE);
 if (NewRepo == NULL) {
 FreePool (Repository);
 return (UINTN)0x8000000000000009uLL;
 }

 if (RepoSize > 0 && Repository != NULL) {
 CopyMem (NewRepo, Repository, RepoSize);
 }

 CopyMem ((UINT8 *)NewRepo + RepoSize, FwClass, ESRT_ENTRY_SIZE);

 Status = gRT->SetVariable (
 VariableName,
 &gEfiVariableVendorGuid,
 3,
 RepoSize + ESRT_ENTRY_SIZE,
 NewRepo
 );

 FreePool (NewRepo);
 }

 FreePool (Repository);
 return Status;
}

//
// ===========================================================================
// ESRT Protocol Entry Points
// ===========================================================================

//
// ---------------------------------------------------------------------------
// EsrtDxeUpdateEntry
// ---------------------------------------------------------------------------

/**Update an ESRT entry. Tries Non-FMP first, then FMP repository.
**/
EFI_STATUS EsrtDxeUpdateEntry (
 IN EFI_GUID *FwClass,
 IN ESRT_ENTRY *EntryData
 )
{
 EFI_STATUS Status;

 if (FwClass == NULL || EntryData == NULL) {
 return (UINTN)0x8000000000000002uLL; // EFI_INVALID_PARAMETER
 }

 Status = EfiAcquireLock (&mNonFmpLock);
 if (Status < 0) {
 return Status;
 }

 Status = EsrtDxeUpdateRepositoryEntry (FwClass, ESRT_NONFMP_TYPE);

 if (Status < 0) {
 //
 // Not in Non-FMP; try FMP.
 //
 EfiReleaseLock (&mNonFmpLock);

 Status = EfiAcquireLock (&mFmpLock);
 if (Status < 0) {
 return Status;
 }

 Status = EsrtDxeUpdateRepositoryEntry (FwClass, ESRT_FMP_TYPE);
 EfiReleaseLock (&mFmpLock);
 } else {
 EfiReleaseLock (&mNonFmpLock);
 }

 return Status;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeDeleteEntry
// ---------------------------------------------------------------------------

/**Delete an ESRT entry. Tries FMP first, then Non-FMP.
**/
EFI_STATUS EsrtDxeDeleteEntry (
 IN EFI_GUID *FwClass
 )
{
 EFI_STATUS Status;
 EFI_STATUS DeleteStatus;

 if (FwClass == NULL) {
 return (UINTN)0x8000000000000002uLL;
 }

 Status = EfiAcquireLock (&mFmpLock);
 if (Status < 0) {
 return Status;
 }

 DeleteStatus = EsrtDxeUpdateRepositoryEntry (FwClass, ESRT_FMP_TYPE);
 EfiReleaseLock (&mFmpLock);

 if (DeleteStatus >= 0) {
 return 0; // EFI_SUCCESS
 }

 //
 // Not in FMP; try Non-FMP.
 //
 Status = EfiAcquireLock (&mNonFmpLock);
 if (Status < 0) {
 return Status;
 }

 DeleteStatus = EsrtDxeUpdateRepositoryEntry (FwClass, ESRT_NONFMP_TYPE);
 EfiReleaseLock (&mNonFmpLock);

 return DeleteStatus;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeRemoveEntry
// ---------------------------------------------------------------------------

/**Remove an entry from just the Non-FMP repository.
**/
EFI_STATUS EsrtDxeRemoveEntry (
 IN EFI_GUID *FwClass
 )
{
 EFI_STATUS Status;

 if (FwClass == NULL) {
 return (UINTN)0x8000000000000002uLL;
 }

 Status = EfiAcquireLock (&mNonFmpLock);
 if (Status < 0) {
 return Status;
 }

 Status = EsrtDxeDeleteNonFmpEntry (FwClass);
 EfiReleaseLock (&mNonFmpLock);

 return Status;
}

//
// ---------------------------------------------------------------------------
// EsrtDxeAddEntry
// ---------------------------------------------------------------------------

/**Try to find an entry in Non-FMP; if not present, append it.
**/
EFI_STATUS EsrtDxeAddEntry (
 IN ESRT_ENTRY *Entry
 )
{
 EFI_STATUS Status;
 ESRT_ENTRY ExistingEntry;

 if (Entry == NULL) {
 return (UINTN)0x8000000000000002uLL;
 }

 Status = EfiAcquireLock (&mNonFmpLock);
 if (Status < 0) {
 return Status;
 }

 Status = EsrtDxeFindAndCopyEntry (
 &Entry->FwClass,
 ESRT_NONFMP_TYPE,
 &ExistingEntry
 );

 if (Status == (UINTN)0x800000000000000EuLL) { // EFI_NOT_FOUND Status = EsrtDxeAppendNonFmpEntry (Entry);
 }

 EfiReleaseLock (&mNonFmpLock);
 return Status;
}

//
// ===========================================================================
// FMP Entry Collection
// ===========================================================================

/**Copy a firmware descriptor into the collected entry format.
**/
VOID EsrtDxeCopyCollectedEntry (
 OUT ESRT_COLLECTED_ENTRY *Dest,
 IN ESRT_ENTRY *Src,
 IN UINT32 Attributes
 )
{
 //
 // Initialize collected entry fields.
 //
 Dest->FwType = 2; // System firmware type Dest->LastAttemptVersion = *(UINT32 *)((UINT8 *)Src + 40);
 Dest->CapsuleFlags = 0;
 Dest->LastAttemptStatus = 0;
 Dest->RollbackVersion = 0;

 //
 // Copy GUID (from src offset 4).
 //
 CopyMem (&Dest->FwClass, (UINT8 *)Src + 4, sizeof (EFI_GUID));

 //
 // Optional fields based on descriptor attributes.
 //
 if (Attributes >= 2) {
 Dest->CapsuleFlags = *(UINT32 *)((UINT8 *)Src + 88);
 }
 if (Attributes >= 3) {
 Dest->LastAttemptStatus = *(UINT32 *)((UINT8 *)Src + 92);
 Dest->RollbackVersion = *(UINT32 *)((UINT8 *)Src + 96);
 }
}

/**Enumerate all installed FMP protocols, collect their firmware image descriptors, and build the combined FMP ESRT repository variable.

 Algorithm:
 1. Locate all handles with EFI_FIRMWARE_MANAGEMENT_PROTOCOL.
 2. Query each for its image descriptors.
 3. Deduplicate by firmware class GUID (higher version wins).
 4. Write to EsrtFmp UEFI variable (under mFmpLock).
**/
EFI_STATUS EsrtDxeCollectFmpEntries (
 VOID
 )
{
 EFI_STATUS Status;
 EFI_HANDLE *HandleBuffer;
 UINTN HandleCount;
 EFI_HANDLE *HandleWalker;
 UINTN BufferIndex;
 //
 // Working buffers per handle.
 //
 UINTN *FmpImageInfoSizes;
 ESRT_ENTRY **FmpImageInfoBuffers;
 UINT8 *HasDescriptor;
 UINT32 *FmpImageAttribs;

 UINTN DescIndex;
 UINTN ImageInfoCount;
 ESRT_ENTRY *ImageInfo;

 ESRT_COLLECTED_ENTRY Collected[ESRT_COLLECTED_MAX_ENTRIES];
 UINTN NumCollected;
 UINTN EntryIndex;
 UINTN CollectedIndex;
 VOID *Repository;
 UINTN TotalEntries;

 //
 // Initialization.
 //
 HandleBuffer = NULL;
 HandleCount = 0;
 FmpImageInfoSizes = NULL;
 FmpImageInfoBuffers = NULL;
 HasDescriptor = NULL;
 FmpImageAttribs = NULL;
 NumCollected = 0;

 //
 // Locate all FMP protocol handles.
 //
 Status = gBS->LocateHandleBuffer (
 ByProtocol,
 &gEfiFirmwareManagementProtocolGuid,
 NULL,
 &HandleCount,
 &HandleBuffer
 );

 if (Status == (UINTN)0x800000000000000EuLL) { // EFI_NOT_FOUND goto WRITE_REPOSITORY;
 }
 if (Status < 0) {
 goto CLEANUP;
 }

 //
 // Allocate workspace arrays.
 //
 FmpImageInfoSizes = AllocateZeroPool (HandleCount *sizeof (UINTN));
 FmpImageInfoBuffers = AllocateZeroPool (HandleCount *sizeof (VOID *));
 HasDescriptor = AllocateZeroPool (HandleCount);
 FmpImageAttribs = AllocateZeroPool (HandleCount *sizeof (UINT32));

 if (FmpImageInfoSizes == NULL ||
 FmpImageInfoBuffers == NULL ||
 HasDescriptor == NULL ||
 FmpImageAttribs == NULL) {
 Status = (UINTN)0x8000000000000009uLL; // EFI_OUT_OF_RESOURCES goto CLEANUP;
 }

 //
 // Phase 1: Query all FMP protocol instances for image info.
 //
 for (BufferIndex = 0; BufferIndex < HandleCount; BufferIndex++) {
 VOID *Fmp;
 UINTN ImageInfoSize;
 UINT32 DescriptorVersion;
 UINTN DescriptorSize;

 Status = gBS->HandleProtocol (
 HandleBuffer[BufferIndex],
 &gEfiFirmwareManagementProtocolGuid,
 &Fmp
 );
 if (Status < 0) {
 continue;
 }

 //
 // Query size.
 //
 ImageInfoSize = 0;
 Status = ((EFI_FIRMWARE_MANAGEMENT_PROTOCOL *)Fmp)->GetImageInfo (
 Fmp,
 &ImageInfoSize,
 NULL,
 &DescriptorVersion,
 &DescriptorSize,
 &FmpImageAttribs[BufferIndex],
 &DescriptorVersion
 );

 if ((UINTN)Status == (UINTN)0x8000000000000005uLL) { // EFI_BUFFER_TOO_SMALL ESRT_ENTRY *InfoBuffer;

 InfoBuffer = AllocateZeroPool (ImageInfoSize);
 FmpImageInfoBuffers[BufferIndex] = (ESRT_ENTRY *)InfoBuffer;
 if (InfoBuffer == NULL) {
 Status = (UINTN)0x8000000000000009uLL;
 goto CLEANUP;
 }

 Status = ((EFI_FIRMWARE_MANAGEMENT_PROTOCOL *)Fmp)->GetImageInfo (
 Fmp,
 &ImageInfoSize,
 InfoBuffer,
 &DescriptorVersion,
 &DescriptorSize,
 &FmpImageAttribs[BufferIndex],
 &DescriptorVersion
 );

 if (Status >= 0) {
 HasDescriptor[BufferIndex] = 1;
 FmpImageInfoSizes[BufferIndex] = ImageInfoSize;
 }
 }
 }

 //
 // Phase 2: Collect entries, deduplicating by firmware class GUID.
 //
 for (BufferIndex = 0; BufferIndex < HandleCount; BufferIndex++) {
 if (HasDescriptor[BufferIndex] == 0) {
 continue;
 }

 ImageInfo = FmpImageInfoBuffers[BufferIndex];
 ImageInfoCount = FmpImageInfoSizes[BufferIndex];

 //
 // Walk descriptors for this handle.
 //
 DescIndex = 0;
 while (DescIndex < ImageInfoCount) {
 //
 // Check descriptor validity flags.
 //
 if ((*(UINT8 *)((UINT8 *)&ImageInfo[DescIndex] + 64) & 8) != 0 &&
 (*(UINT8 *)((UINT8 *)&ImageInfo[DescIndex] + 72) & 8) != 0) {
 //
 // Look for existing entry with same FwClass GUID.
 //
 EntryIndex = NumCollected;
 for (CollectedIndex = 0; CollectedIndex < NumCollected; CollectedIndex++) {
 if (CompareGuid (
 (EFI_GUID *)((UINT8 *)&ImageInfo[DescIndex] + 4),
 (EFI_GUID *)&Collected[CollectedIndex].FwClass
 )) {
 //
 // Duplicate: keep the one with higher version.
 //
 if (Collected[CollectedIndex].LastAttemptVersion <=
 *(UINT32 *)((UINT8 *)&ImageInfo[DescIndex] + 40)) {
 EsrtDxeCopyCollectedEntry (
 &Collected[CollectedIndex],
 &ImageInfo[DescIndex],
 FmpImageAttribs[BufferIndex]
 );
 }
 EntryIndex = NumCollected; // force skip append break;
 }
 }

 if (CollectedIndex == NumCollected && NumCollected < ESRT_COLLECTED_MAX_ENTRIES) {
 EsrtDxeCopyCollectedEntry (
 &Collected[NumCollected],
 &ImageInfo[DescIndex],
 FmpImageAttribs[BufferIndex]
 );
 NumCollected++;
 }
 }

 DescIndex++;
 }
 }

WRITE_REPOSITORY:
 //
 // Phase 3: Write collected entries to EsrtFmp variable.
 //
 if (NumCollected > 0) {
 TotalEntries = NumCollected *ESRT_ENTRY_SIZE;
 Repository = AllocateZeroPool (TotalEntries);
 if (Repository != NULL) {
 //
 // Copy collected entries.
 //
 for (Index = 0; Index < NumCollected; Index++) {
 CopyMem (
 (UINT8 *)Repository + Index *ESRT_ENTRY_SIZE,
 &Collected[Index],
 ESRT_ENTRY_SIZE
 );
 }

 //
 // Write under lock.
 //
 Status = EfiAcquireLock (&mFmpLock);
 if (Status >= 0) {
 Status = gRT->SetVariable (
 ESRT_FMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid,
 3, // NV + BS + RT TotalEntries,
 Repository
 );
 EfiReleaseLock (&mFmpLock);
 }

 FreePool (Repository);
 } else {
 Status = (UINTN)0x8000000000000009uLL;
 }
 }

CLEANUP:
 //
 // Free all allocated buffers.
 //
 if (HandleBuffer != NULL) {
 FreePool (HandleBuffer);
 }
 if (FmpImageInfoSizes != NULL) {
 FreePool (FmpImageInfoSizes);
 }
 if (FmpImageInfoBuffers != NULL) {
 for (BufferIndex = 0; BufferIndex < HandleCount; BufferIndex++) {
 if (FmpImageInfoBuffers[BufferIndex] != NULL) {
 FreePool (FmpImageInfoBuffers[BufferIndex]);
 }
 }
 FreePool (FmpImageInfoBuffers);
 }
 if (HasDescriptor != NULL) {
 FreePool (HasDescriptor);
 }
 if (FmpImageAttribs != NULL) {
 FreePool (FmpImageAttribs);
 }

 return Status;
}

//
// ===========================================================================
// Variable Lock (ReadyToBoot / VirtualAddressChange callback)
// ===========================================================================

/**Lock the ESRT variables to prevent further modification.
 Called at ReadyToBoot and VirtualAddressChange.
**/
EFI_STATUS EsrtDxeLockVariables (
 VOID
 )
{
 EFI_STATUS Status;
 VOID *VariableLock;

 //
 // Locate the Variable Lock protocol.
 //
 Status = gBS->LocateProtocol (
 &gEfiVariableLockProtocolGuid,
 NULL,
 &VariableLock
 );
 if (Status < 0) {
 return Status;
 }

 Status = ((EDKII_VARIABLE_LOCK_PROTOCOL *)VariableLock)->RequestToLock (
 VariableLock,
 ESRT_FMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid
 );
 DebugPrint (64, "EsrtDxe Lock EsrtFmp Variable Status 0x%x", Status);

 Status = ((EDKII_VARIABLE_LOCK_PROTOCOL *)VariableLock)->RequestToLock (
 VariableLock,
 ESRT_NONFMP_VARIABLE_NAME,
 &gEfiVariableVendorGuid
 );
 DebugPrint (64, "EsrtDxe Lock EsrtNonFmp Variable Status 0x%x", Status);

 return 0;
}

//
// ===========================================================================
// ReadyToBoot Notification: Build & Install ESRT Configuration Table
// ===========================================================================

/**On ReadyToBoot, combine FMP and Non-FMP entries and install the complete ESRT configuration table for the OS.
**/
VOID EFIAPI EsrtDxeNotifyInstallEsrtTable (
 IN EFI_EVENT Event,
 IN VOID *Context
 )
{
 EFI_STATUS Status;
 ESRT_ENTRY *FmpRepository;
 ESRT_ENTRY *NonFmpRepository;
 UINTN FmpSize;
 UINTN NonFmpSize;
 UINTN FmpEntryCount;
 UINTN NonFmpEntryCount;
 UINTN TotalEntries;
 VOID *TableBuffer;

 FmpRepository = NULL;
 NonFmpRepository = NULL;

 //
 // Step 1: Read Non-FMP repository (under lock).
 //
 Status = EfiAcquireLock (&mNonFmpLock);
 if (Status < 0) {
 return;
 }

 Status = GetEfiVariable (ESRT_NONFMP_VARIABLE_NAME, &gEfiVariableVendorGuid,
 (VOID **)&NonFmpRepository, &NonFmpSize);
 if (Status < 0) {
 NonFmpSize = 0;
 }

 NonFmpEntryCount = NonFmpSize / ESRT_ENTRY_SIZE;
 if (NonFmpSize != NonFmpEntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "NonFmp Repository Corrupt. Need to rebuild NonFmp Repository.\n");
 NonFmpSize = 0;
 NonFmpEntryCount = 0;
 if (NonFmpRepository != NULL) {
 FreePool (NonFmpRepository);
 NonFmpRepository = NULL;
 }
 }

 EfiReleaseLock (&mNonFmpLock);

 //
 // Step 2: Read FMP repository (under lock).
 //
 Status = EfiAcquireLock (&mFmpLock);
 if (Status < 0) {
 goto CLEANUP;
 }

 Status = GetEfiVariable (ESRT_FMP_VARIABLE_NAME, &gEfiVariableVendorGuid,
 (VOID **)&FmpRepository, &FmpSize);
 if (Status < 0) {
 FmpSize = 0;
 }

 FmpEntryCount = FmpSize / ESRT_ENTRY_SIZE;
 if (FmpSize != FmpEntryCount *ESRT_ENTRY_SIZE) {
 DebugPrint (0x80000000,
 "Fmp Repository Corrupt. Need to rebuild Fmp Repository.\n");
 FmpSize = 0;
 FmpEntryCount = 0;
 if (FmpRepository != NULL) {
 FreePool (FmpRepository);
 FmpRepository = NULL;
 }
 }

 EfiReleaseLock (&mFmpLock);

 //
 // Step 3: Build and install combined ESRT table.
 //
 TotalEntries = NonFmpEntryCount + FmpEntryCount;

 if (TotalEntries > 0) {
 //
 // Buffer: ESRT header (16 bytes) + entries.
 //
 TableBuffer = AllocateZeroPool (TotalEntries *ESRT_ENTRY_SIZE + 16);
 if (TableBuffer != NULL) {
 //
 // ESRT header fields:
 // +0: FwResourceCount (UINT32)
 // +4: FwResourceCountMax (UINT32) = 64
 // +8: FwResourceVersion (UINT64) = 1
 //
 *(UINT32 *)TableBuffer = TotalEntries;
 *(UINT32 *)((UINT8 *)TableBuffer + 4) = 64;
 *(UINT64 *)((UINT8 *)TableBuffer + 8) = 1;

 //
 // Non-FMP entries first, then FMP entries.
 //
 if (NonFmpSize > 0 && NonFmpRepository != NULL) {
 CopyMem ((UINT8 *)TableBuffer + 16, NonFmpRepository, NonFmpSize);
 }
 if (FmpSize > 0 && FmpRepository != NULL) {
 CopyMem (
 (UINT8 *)TableBuffer + 16 + NonFmpSize,
 FmpRepository,
 FmpSize
 );
 }

 //
 // Install configuration table.
 //
 gBS->InstallConfigurationTable (
 &gEfiEsrtTableProtocolGuid,
 TableBuffer
 );

 //
 // Signal the context event (may be a notification registration).
 //
 gBS->SignalEvent ((EFI_EVENT)Context);
 } else {
 DebugPrint (0x80000000, "Esrt table memory allocation failure\n");
 }
 }

CLEANUP:
 if (NonFmpRepository != NULL) {
 FreePool (NonFmpRepository);
 }
 if (FmpRepository != NULL) {
 FreePool (FmpRepository);
 }
}

//
// ===========================================================================
// Driver Initialization
// ===========================================================================

/**Validate and store all UEFI global service pointers.
**/
EFI_STATUS EFIAPI EsrtDxeEntryInit (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 EFI_STATUS Status;

 //
 // Store globals.
 //
 ::ImageHandle = ImageHandle;
 if (::ImageHandle == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 51,
 "gImageHandle != ((void *) 0)");
 }

 ::SystemTable = SystemTable;
 if (::SystemTable == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 57,
 "gST != ((void *) 0)");
 }

 ::BootServices = SystemTable->BootServices;
 if (::BootServices == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 63,
 "gBS != ((void *) 0)");
 }

 ::RuntimeServices = SystemTable->RuntimeServices;
 if (::RuntimeServices == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
 47,
 "gRT != ((void *) 0)");
 }

 //
 // Initialize HOB list.
 //
 HobLibConstructor ();

 //
 // Locate DxeServicesTable.
 //
 Status = EfiGetSystemConfigurationTable (
 &gEfiDxeServicesTableGuid,
 &gDS
 );
 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\DxeServicesTableLib\\DxeServicesTableLib.c",
 64,
 "!EFI_ERROR (Status)"
 );
 }
 if (gDS == NULL) {
 DebugAssert (
 "e:\\hs\\MdePkg\\Library\\DxeServicesTableLib\\DxeServicesTableLib.c",
 65,
 "gDS != ((void *) 0)");
 }

 return Status;
}

/**Register all protocol notifications and install protocol interfaces.

 This function:
 - Initializes repository locks (FmpLock, NonFmpLock)
 - Registers ReadyToBoot and VirtualAddressChange events
 - Installs the HII Config Access protocol
 - Registers for FMP protocol notification
**/
EFI_STATUS EsrtDxeRegisterCallbacks (
 VOID
 )
{
 EFI_STATUS Status;
 VOID *Registration1;
 VOID *Registration2;

 //
 // Initialize locks.
 //
 EfiInitializeLock (&mFmpLock);
 EfiInitializeLock (&mNonFmpLock);

 //
 // Register ReadyToBoot event -> build ESRT table.
 //
 Status = gBS->CreateEventEx (
 EVT_NOTIFY_SIGNAL,
 TPL_CALLBACK,
 EsrtDxeNotifyInstallEsrtTable,
 NULL,
 &gEfiReadyToBootGuid,
 &Registration1
 );
 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugAssert (
 "e:\\hs\\MdeModulePkg\\Universal\\EsrtDxe\\EsrtDxe.c",
 651,
 "!EFI_ERROR (Status)");
 }

 //
 // Register VirtualAddressChange event -> lock variables.
 //
 Status = gBS->CreateEventEx (
 EVT_NOTIFY_SIGNAL,
 TPL_CALLBACK,
 EsrtDxeLockVariables,
 NULL,
 &gEfiVirtualAddrChangeGuid,
 &Registration2
 );
 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugAssert (
 "e:\\hs\\MdeModulePkg\\Universal\\EsrtDxe\\EsrtDxe.c",
 664,
 "!EFI_ERROR (Status)");
 }

 //
 // Install protocol interfaces and FMP protocol notify.
 //
 Status = gBS->InstallProtocolInterface (
 &::ImageHandle,
 &gEfiEsrtManagementProtocolGuid,
 EFI_NATIVE_INTERFACE,
 // Note: The protocol notification function table is omitted
 // from the decompiled output; it is stored in an init data
 // array (off_2470).
 NULL
 );

 return 0;
}

//
// ---------------------------------------------------------------------------
// _ModuleEntryPoint (UefiMain)
// ---------------------------------------------------------------------------

/**UEFI driver entry point.
 Calls the main initialization routine.
**/
EFI_STATUS EFIAPI UefiMain (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 EFI_STATUS Status;

 Status = EsrtDxeEntryInit (ImageHandle, SystemTable);
 if (Status < 0) {
 return Status;
 }

 return EsrtDxeRegisterCallbacks ();
}