Newer
Older
AMI-Aptio-BIOS-Reversed / AmiModulePkg / SecureFlash / SecFlashUpd / SecFlashUpdDXE / SecFlashUpdDXE.c
@Ajax Dong Ajax Dong 2 days ago 30 KB Full restructure
/**
 * @file SecFlashUpdDXE.c
 * @brief Secure Flash Update DXE Driver
 *
 * Handles authenticated BIOS capsule updates. This DXE driver registers
 * a Flash_Ready_To_Lock notification callback that:
 *   1. Queries UEFI Runtime Services for "CapsuleUpdateData" variables
 *   2. Iterates through CapsuleUpdateData, CapsuleUpdateData0, CapsuleUpdateData1, ...
 *   3. Finds the first valid capsule payload and triggers the secure update
 *
 * Source file: AmiModulePkg/SecureFlash/SecFlashUpd/SecFlashUpdDxe.c
 * Builder:      e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\...
 * Debug file:   SecFlashUpdDXE.pdb
 *
 * Module:  SecFlashUpdDXE.efi (HR650X BIOS, index 0063)
 * Size:    0x1e60 (7.5 KB)
 * Arch:    x86_64
 * MD5:     d2b8f923a93a1787c4a1a6efa64d2c50
 * SHA256:  22b4ce86fed6df3a8e5c9ca587e09972686b78fd1205eb30de25ed088ca02675
 */

#include "SecFlashUpdDXE.h"

//=============================================================================
// Module Global Variables
//=============================================================================

EFI_HANDLE            gImageHandle    = NULL;
EFI_SYSTEM_TABLE     *gST             = NULL;
EFI_BOOT_SERVICES    *gBS             = NULL;
EFI_RUNTIME_SERVICES *gRT             = NULL;
VOID                 *gHobList        = NULL;
PCD_PROTOCOL         *mPcd            = NULL;

//=============================================================================
// GUID Definitions (Protocols, Events, Variables)
//=============================================================================

// AMI Flash Update Protocol GUID: {0x974231D5, 0xED4B, 0x44D1, {0x88, 0x70, 0xCE, 0x51, 0x5C, 0xC1, 0x4D, 0x68}}
STATIC CONST EFI_GUID mAmiFlashUpdProtocolGuid = AMI_FLASH_UPD_PROTOCOL_GUID;

// Capsule Update Data Variable GUID: {0x711C703F, 0xC285, 0x4B10, {0xA3, 0xB0, 0x36, 0xEC, 0xBD, 0x3C, 0x8B, 0xE2}}
STATIC CONST EFI_GUID mCapsuleUpdateDataVariableGuid = CAPSULE_UPDATE_DATA_VARIABLE_GUID;

// DXE SMM Ready To Lock Protocol GUID: {0x49D34AE7, 0x9454, 0x4551, {0x8F, 0x71, 0x46, 0x7D, 0x8C, 0x0E, 0x4E, 0xF5}}
STATIC CONST EFI_GUID mDxeSmmReadyToLockProtocolGuid = DXE_SMM_READY_TO_LOCK_PROTOCOL_GUID;

// Event Ready To Boot Group GUID: {0x60FF8964, 0xE906, 0x41D0, {0xAF, 0xED, 0xF2, 0x41, 0xE9, 0x74, 0xE0, 0x8E}}
STATIC CONST EFI_GUID mEventReadyToBootGuid = EVENT_READY_TO_BOOT_GUID;

//=============================================================================
// Forward Declarations
//=============================================================================

STATIC
EFI_STATUS
EFIAPI
FlashReadyToLockCallback (
  IN EFI_EVENT  Event,
  IN VOID      *Context
  );

//=============================================================================
// Helper Functions
//=============================================================================

/**
 * Retrieves the HOB list pointer.
 *
 * Searches through system configuration tables for the EFI_HOB_LIST_GUID
 * entry. If not found, falls back to the PCD database pointer.
 *
 * @return Pointer to the HOB list, or NULL on failure
 */
STATIC
VOID *
GetHobList (
  VOID
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  UINTN                   HobCount;
  EFI_GUID               **HobGuidArray;
  VOID                    **HobTableArray;

  //
  // Check if HOB list has already been located
  //
  if (gHobList != NULL) {
    return gHobList;
  }

  //
  // Default to NULL
  //
  gHobList = NULL;

  //
  // Iterate through configuration table entries to find the HOB list GUID
  //
  HobCount = gST->NumberOfTableEntries;
  HobGuidArray  = (EFI_GUID **)(&gST->ConfigurationTable);
  HobTableArray = (VOID **)((CHAR8 *)&gST->ConfigurationTable + sizeof(UINTN));

  for (Index = 0; Index < HobCount; Index++) {
    if (IsHobGuidMatch((VOID *)(HobTableArray + Index))) {
      //
      // Found the HOB list; extract its GUID and table pointer
      //
      break;
    }
  }

  if (Index < HobCount) {
    gHobList = *(VOID **)((UINTN)HobTableArray + 24 * Index + 16);
  } else {
    //
    // HOB list not found in configuration table -- assertion
    //
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
    ASSERT (!EFI_ERROR (EFI_NOT_FOUND));
    ASSERT (mHobList != NULL);
  }

  return gHobList;
}

/**
 * Checks whether a HOB entry matches the HOB list GUID.
 *
 * Compares the 16-byte GUID at the HOB entry against the well-known
 * EFI_HOB_LIST_GUID using an 8-byte-per-side comparison.
 *
 * @param[in] HobEntry  Pointer to the HOB entry to check
 * @return TRUE if the GUID matches, FALSE otherwise
 */
STATIC
BOOLEAN
IsHobGuidMatch (
  IN CONST VOID *HobEntry
  )
{
  UINT64  GuidFirstHalf;
  UINT64  GuidSecondHalf;
  UINT64  EntryFirstHalf;
  UINT64  EntrySecondHalf;

  //
  // Read the two 8-byte halves of the reference HOB GUID
  //
  GuidFirstHalf  = ReadUnaligned64 (&HOB_LIST_GUID);
  GuidSecondHalf = ReadUnaligned64 ((VOID *)((UINTN)&HOB_LIST_GUID + 8));

  //
  // Read the two 8-byte halves from the candidate HOB entry
  //
  EntryFirstHalf  = ReadUnaligned64 (HobEntry);
  EntrySecondHalf = ReadUnaligned64 ((UINTN)(HobEntry + 8));

  //
  // Match if both halves are equal
  //
  return (GuidFirstHalf == EntryFirstHalf) &&
         (GuidSecondHalf == EntrySecondHalf);
}

/**
 * Reads a 64-bit unaligned value from memory.
 *
 * @param[in] Buffer  Pointer to the unaligned buffer (must not be NULL)
 * @return 64-bit value
 */
STATIC
UINT64
ReadUnaligned64 (
  IN CONST VOID *Buffer
  )
{
  ASSERT (Buffer != NULL);
  return *(UINT64 *)Buffer;
}

//=============================================================================
// Debug / Formatting Helpers
//=============================================================================

/**
 * Debug print helper.
 *
 * Wraps the UEFI debug print infrastructure with level checking.
 * Retrieves the debug mask from PCD protocol and prints if the
 * requested error level matches the current debug mask.
 *
 * @param[in] ErrorLevel  Debug error level mask (e.g., EFI_D_ERROR, EFI_D_INFO)
 * @param[in] Format      Format string
 * @param[in] ...         Variable arguments
 */
STATIC
VOID
DebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8 *Format,
  ...
  )
{
  VA_LIST     Marker;
  PCD_PROTOCOL *PcdProtocol;
  UINT64       DebugMask;
  BOOLEAN      DebugPrintEnabled;

  PcdProtocol = GetPcdProtocol ();
  if (PcdProtocol == NULL) {
    return;
  }

  DebugMask = DebugGetLevel ();
  if ((DebugMask & ErrorLevel) == 0) {
    return;
  }

  VA_START (Marker, Format);
  //
  // Forward to the UEFI debug print routine stored in the DebugLib protocol
  //
  PcdProtocol->DebugPrint (ErrorLevel, Format, Marker);
  VA_END (Marker);
}

/**
 * Assertion failure handler.
 *
 * Called when an ASSERT() expression evaluates to FALSE.
 * Prints the source file name, line number, and the assertion text.
 *
 * @param[in] FileName    Source file name
 * @param[in] LineNumber   Line number of the assertion
 * @param[in] Description  Assertion expression text
 */
STATIC
VOID
EFIAPI
AssertHandler (
  IN CONST CHAR8 *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8 *Description
  )
{
  PCD_PROTOCOL *PcdProtocol;

  PcdProtocol = GetPcdProtocol ();
  if (PcdProtocol == NULL) {
    return;
  }

  PcdProtocol->AssertHandler (FileName, LineNumber, Description);
}

/**
 * Retrieves the PCD protocol pointer (singleton).
 *
 * Lazily initializes the protocol pointer via BootServices->LocateProtocol
 * on first call. Subsequent calls return the cached pointer.
 *
 * @return Pointer to the PCD protocol, or NULL on failure
 */
STATIC
PCD_PROTOCOL *
GetPcdProtocol (
  VOID
  )
{
  EFI_STATUS  Status;

  if (mPcd == NULL) {
    //
    // Allocate a small buffer to check heap availability
    //
    UINTN BufferSize = gBS->GetFreePoolSize ();
    if (BufferSize <= 0x10) {
      //
      // Heap not yet available; return NULL
      //
      return NULL;
    }

    Status = gBS->LocateProtocol (
                    &gEfiPcdProtocolGuid,
                    NULL,
                    (VOID **)&mPcd
                    );
    if (EFI_ERROR (Status)) {
      mPcd = NULL;
    }
  }

  return mPcd;
}

/**
 * Returns the current debug print level from the PCD database.
 *
 * @return Current debug print error level mask
 */
STATIC
UINT64
DebugGetLevel (
  VOID
  )
{
  UINT64  DebugMask;
  EFI_STATUS  Status;
  UINTN       BufferSize;

  BufferSize = sizeof (DebugMask);
  Status = gRT->GetVariable (
                  L"DebugLevel",
                  &mAmiFlashUpdProtocolGuid,
                  NULL,
                  &BufferSize,
                  &DebugMask
                  );
  if (EFI_ERROR (Status)) {
    DebugMask = EFI_D_INFO;
  }

  return DebugMask;
}

/**
 * Converts an EFI_STATUS code to a human-readable string.
 *
 * Handles all standard UEFI error codes including warning and error
 * classifications, as well as interrupt-pending status codes.
 *
 * @param[in] Status  EFI status value
 * @return Pointer to a static string
 */
STATIC
CONST CHAR8 *
StatusToString (
  IN EFI_STATUS Status
  )
{
  UINT8       Index;
  CONST CHAR8 *StatusText;

  if (Status == EFI_SUCCESS) {
    return "EFI_SUCCESS";
  }

  //
  // Check for warning codes
  //
  if ((Status & 0x2000000000000000LL) != 0) {
    Index = (UINT8)(Status & 0x1FFFFFFFFFFFFFFFLL);
    if (Index >= 2) {
      return NULL;
    }
    StatusText = (CONST CHAR8 *)((UINTN)_ImageBase + 35 * Index);
    return StatusText;
  }

  //
  // Check for error codes
  //
  if (Status >= 0) {
    //
    // Non-error codes (0 < Status < MAX_BIT)
    //
    if ((UINTN)Status > 4) {
      return NULL;
    }
    StatusText = (CONST CHAR8 *)((UINTN)_ImageBase + 26 * Status + 6102);
    return StatusText;
  }

  //
  // Negative status values
  //
  Index = (UINT8)(Status & 0x1FFFFFFFFFFFFFFFLL);

  if ((Status & 0xA000000000000000LL) == 0xA000000000000000LL) {
    //
    // Interrupt pending / high severity errors
    //
    if (Index >= 3) {
      return NULL;
    }
    StatusText = (CONST CHAR8 *)((UINTN)_ImageBase + 25 * Index);
    return StatusText;
  }

  if ((Status & 0xC000000000000000LL) == 0xC000000000000000LL) {
    //
    // Extended error codes
    //
    if (Index > 2) {
      return NULL;
    }
    StatusText = (CONST CHAR8 *)((UINTN)_ImageBase + 25 * Index + 6391);
    return StatusText;
  }

  //
  // Standard error codes
  //
  if (Index > 0x1E) {
    return NULL;
  }
  StatusText = (CONST CHAR8 *)((UINTN)_ImageBase + 25 * Index + 6455);
  return StatusText;
}

/**
 * Converts a numeric value to a string in the given base.
 *
 * Supports decimal (base 10) with negative sign handling and
 * hexadecimal (base 16). Stores the result in reversed digit
 * order in the buffer, then null-terminates.
 *
 * @param[in]  Value   Value to convert
 * @param[out] Buffer  Output character buffer (must be large enough)
 * @param[in]  Base    Numeric base (10 or 16)
 * @param[in]  Signed  TRUE for signed conversion (adds '-' for negatives
 *                     when base is 10)
 * @return Pointer to the last character written (pre- or post-reversal)
 */
STATIC
CHAR8 *
ValueToString (
  IN  INT64   Value,
  OUT CHAR8  *Buffer,
  IN  UINTN   Base,
  IN  BOOLEAN Signed
  )
{
  UINT64   Remainder;
  UINT64   AbsValue;
  CHAR8    Digit;
  CHAR8   *WritePtr;

  //
  // Determine absolute value
  //
  if (Signed && Base == 10) {
    AbsValue = (Value < 0) ? -(UINT64)Value : (UINT64)Value;
  } else {
    AbsValue = (UINT64)Value;
  }

  WritePtr = Buffer;

  if (AbsValue == 0) {
    *WritePtr++ = '0';
  } else {
    //
    // Convert digits in reverse order
    //
    while (AbsValue > 0) {
      Remainder = AbsValue % Base;
      AbsValue /= Base;

      if (Remainder >= 10) {
        Digit = (CHAR8)(Remainder + 87);  // 'a' - 10
      } else {
        Digit = (CHAR8)(Remainder + 48);  // '0'
      }
      *WritePtr++ = Digit;
    }
  }

  //
  // Add negative sign for base-10 signed negative values
  //
  if (Base == 10 && Value < 0 && Signed) {
    *WritePtr++ = '-';
  }

  *WritePtr = '\0';
  return WritePtr - 1;
}

/**
 * Parses a decimal or hexadecimal integer from a wide string.
 *
 * Skips leading spaces/tabs, handles optional '+'/'-' sign,
 * and parses digits until a non-digit character is found.
 * Limits value to 32-bit range (overflow clamped to INT_MAX/INT_MIN).
 *
 * @param[in]  String    Pointer to the wide string to parse
 * @param[out] EndString On return, points to the first unparsed character
 * @param[in]  Base      Numeric base (defaults to decimal if 0)
 * @return Parsed integer value
 */
STATIC
UINTN
ParseInteger (
  IN  CONST CHAR16 *String,
  OUT CONST CHAR16 **EndString,
  IN  INTN          Base
  )
{
  INTN        Sign;
  UINTN       Value;
  BOOLEAN     Overflow;
  CHAR16      Char;

  Sign    = 1;
  Value   = 0;
  Overflow = FALSE;

  //
  // Skip leading whitespace (space = 0x0020, tab = 0x0009)
  //
  while (*String == L' ' || *String == L'\t') {
    String++;
  }

  if (*String == L'\0') {
    *EndString = String;
    return 0;
  }

  //
  // Handle sign
  //
  if (*String == L'-') {
    Sign = -1;
    String++;
  } else if (*String == L'+') {
    String++;
  }

  //
  // Parse digits
  //
  CONST CHAR16 *ParsePtr = String;
  if (*String != L'+' && *String != L'-') {
    ParsePtr = String;
  }

  while (*ParsePtr != L'\0') {
    Char = *ParsePtr;

    if (Char >= L'0' && Char <= L'9') {
      Char = Char - L'0';
    } else if ((Char | 0x20) >= L'a' && (Char | 0x20) <= L'f') {
      //
      // Handle hex digits (a-f or A-F) -- but for base=10 parsing
      // we stop at non-decimal
      //
      if (Base != 10) {
        Char = (Char | 0x20) - L'a' + 10;
      } else {
        break;
      }
    } else {
      break;
    }

    //
    // Base 10 only accepts digits 0-9
    //
    if (Char >= 10) {
      break;
    }

    Value = Value * 10 + Char;

    //
    // Check for overflow (32-bit boundary)
    //
    if (Sign == 1) {
      if (Value >= 0x80000000) {
        Overflow = TRUE;
      }
    } else if (Value > 0x80000000) {
      Overflow = TRUE;
    }

    ParsePtr++;
  }

  *EndString = ParsePtr;

  if (Overflow) {
    Value = (Sign == 1) ? 0x7FFFFFFF : 0x80000000;
  }

  return Value * Sign;
}

/**
 * Unicode (wide) sprintf wrapper.
 *
 * Calls UnicodeVSPrint with va_list extracted from variable arguments.
 *
 * @param[out] Buffer   Output wide string buffer
 * @param[in]  MaxSize  Maximum number of wide characters to write
 * @param[in]  Format   Format string
 * @param[in]  ...      Variable arguments
 * @return Number of wide characters written
 */
STATIC
UINTN
UnicodeSPrint (
  OUT CHAR16       *Buffer,
  IN  UINTN         MaxSize,
  IN  CONST CHAR16 *Format,
  ...
  )
{
  UINTN   Count;
  VA_LIST Marker;

  VA_START (Marker, Format);
  Count = UnicodeVSPrint (Buffer, MaxSize, Format, Marker);
  VA_END (Marker);

  return Count;
}

//=============================================================================
// Core Driver Functions
//=============================================================================

/**
 * Entry point for SecFlashUpdDXE driver.
 *
 * @param[in] ImageHandle  Handle of this EFI image
 * @param[in] SystemTable  Pointer to EFI System Table
 * @return EFI_STATUS
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS Status;

  //
  // Initialize UEFI boot services table pointers from the system table
  //
  Status = SecFlashUpdDriverInit (ImageHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Create ReadyToBoot event and register Flash Ready To Lock callback
  //
  Status = SecFlashUpdRegisterCallbacks (ImageHandle, SystemTable);

  return Status;
}

/**
 * Initializes the driver globals and UEFI service table pointers.
 *
 * Sets up:
 *   - gImageHandle
 *   - gST, gBS, gRT
 *   - HOB list pointer
 *   - PCD protocol
 *   - Publishes the ReadyToBoot event group GUID
 *
 * @param[in] ImageHandle  Handle of this EFI image
 * @return 0 on success
 */
STATIC
EFI_STATUS
SecFlashUpdDriverInit (
  IN EFI_HANDLE ImageHandle
  )
{
  EFI_STATUS           Status;
  EFI_EVENT            ReadyToBootEvent;
  EFI_BOOT_SERVICES   *BootServices;
  EFI_RUNTIME_SERVICES *RuntimeServices;
  EFI_TPL              OldTpl;

  //
  // Save the image handle and system table
  //
  gImageHandle = ImageHandle;
  ASSERT (gImageHandle != NULL);

  gST = SystemTable;
  ASSERT (gST != NULL);

  //
  // Extract BootServices and RuntimeServices from the system table
  //
  BootServices = gST->BootServices;
  gBS = BootServices;
  ASSERT (gBS != NULL);

  RuntimeServices = gST->RuntimeServices;
  gRT = RuntimeServices;
  ASSERT (gRT != NULL);

  //
  // Initialize the HOB list pointer
  //
  GetHobList ();

  //
  // Create event in the ReadyToBoot event group
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL | EVT_GROUP,
                  TPL_CALLBACK,
                  FlashReadyToLockCallback,
                  NULL,
                  &ReadyToBootEvent
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Install the DXE SMM Ready To Lock protocol
  //
  Status = gBS->InstallProtocolInterface (
                  &ImageHandle,
                  &mDxeSmmReadyToLockProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    gBS->CloseEvent (ReadyToBootEvent);
    return Status;
  }

  ASSERT (ReadyToBootEvent != NULL);

  return EFI_SUCCESS;
}

/**
 * Registers the Flash_Ready_To_Lock notification callback by creating
 * an event in the EFI_EVENT_GROUP_READY_TO_BOOT group.
 *
 * @param[in] ImageHandle  Handle of this EFI image
 * @param[in] SystemTable  Pointer to EFI System Table
 * @return EFI_STATUS
 */
STATIC
EFI_STATUS
SecFlashUpdRegisterCallbacks (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Create the ReadyToBoot group event. The event will fire the
  // FlashReadyToLockCallback at TPL_CALLBACK when the group is signaled.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL | EVT_GROUP,
                  TPL_CALLBACK,
                  FlashReadyToLockCallback,
                  NULL,
                  &mReadyToBootEvent
                  );

  return Status;
}

/**
 * Flash_Ready_To_Lock notification callback.
 *
 * Invoked when the DXE Foundation signals the ReadyToBoot event group.
 * This callback:
 *   1. Prints a debug banner
 *   2. Reads the "AmiFlashUpd" variable from RT services to check
 *      for update availability
 *   3. Iterates through CapsuleUpdateData, CapsuleUpdateData0, ... variables
 *   4. On finding a valid capsule payload, closes the variable and proceeds
 *   5. Finally signals the DXE SMM Ready To Lock protocol installation
 *
 * @param[in] Event   ReadyToBoot event that triggered this callback
 * @param[in] Context Not used (may be NULL)
 * @return EFI_STATUS
 */
STATIC
EFI_STATUS
EFIAPI
FlashReadyToLockCallback (
  IN EFI_EVENT  Event,
  IN VOID      *Context
  )
{
  EFI_STATUS             Status;
  EFI_RUNTIME_SERVICES  *RtServices;
  UINT32                 Attributes;
  UINTN                  DataSize;
  UINT64                 CapsuleBlockDesc;
  UINTN                  CapsuleIndex;
  CHAR16                 VariableName[30];
  VOID                   *ProtocolInterface;
  EFI_HANDLE             ProtocolHandle;

  //
  // Ensure the Runtime Services pointer is valid
  //
  RtServices = gRT;
  ASSERT (RtServices != NULL);

  //
  // Debug trace
  //
  DEBUG ((EFI_D_INFO, "\nSecure Fl Upd:\nFlash_Ready_To_Lock callback\n"));

  //
  // Check if the AmiFlashUpd variable exists (signals that an update
  // has been staged)
  //
  DataSize = sizeof (UINT64);
  CapsuleBlockDesc = 0;
  Status = RtServices->GetVariable (
                         AMI_FLASH_UPD_VARIABLE_NAME,
                         &mAmiFlashUpdProtocolGuid,
                         &Attributes,
                         &DataSize,
                         &CapsuleBlockDesc
                         );

  if (!EFI_ERROR (Status)) {
    //
    // AmiFlashUpd variable found -- close it (we're done reading)
    //
    RtServices->SetVariable (
                  AMI_FLASH_UPD_VARIABLE_NAME,
                  &mAmiFlashUpdProtocolGuid,
                  Attributes,
                  0,
                  NULL
                  );

    //
    // Search for CapsuleUpdateData variables
    // First try "CapsuleUpdateData", then "CapsuleUpdateData0", "CapsuleUpdateData1", ...
    //
    CapsuleIndex = 0;

    do {
      if (CapsuleIndex == 0) {
        UnicodeSPrint (
          VariableName,
          30,
          L"%s",
          CAPSULE_UPDATE_DATA_NAME
          );
      } else {
        UnicodeSPrint (
          VariableName,
          30,
          L"%s%d",
          CAPSULE_UPDATE_DATA_NAME,
          CapsuleIndex
          );
      }

      DataSize = sizeof (CapsuleBlockDesc);
      Status = RtServices->GetVariable (
                             VariableName,
                             &mCapsuleUpdateDataVariableGuid,
                             &Attributes,
                             &DataSize,
                             &CapsuleBlockDesc
                             );

      DEBUG ((
        EFI_D_INFO,
        "Find '%s' %r, %lX[=%lx]\n",
        VariableName,
        Status,
        CapsuleBlockDesc,
        CapsuleBlockDesc
        ));

      if (!EFI_ERROR (Status)) {
        //
        // Found a valid capsule update data variable! Check if the
        // descriptor size matches the expected size stored in
        // CapsuleBlockDesc + 8.
        //
        UINT64 ExpectedSize = *(UINT64 *)((UINTN)&CapsuleBlockDesc + 8);
        if (CapsuleBlockDesc == ExpectedSize) {
          //
          // Descriptor matches -- close the variable and proceed
          //
          RtServices->SetVariable (
                        VariableName,
                        &mCapsuleUpdateDataVariableGuid,
                        Attributes,
                        0,
                        NULL
                        );
          break;
        }
      }

      CapsuleIndex++;
    } while (!EFI_ERROR (Status));
  }

  //
  // Install the DXE SMM Ready To Lock protocol to signal that flash
  // should now be locked for write protection
  //
  ProtocolInterface = NULL;
  gBS->InstallProtocolInterface (
         &ProtocolHandle,
         &mDxeSmmReadyToLockProtocolGuid,
         EFI_NATIVE_INTERFACE,
         ProtocolInterface
         );

  //
  // Close the event so this callback doesn't fire again
  //
  gBS->CloseEvent (Event);

  return Status;
}

//=============================================================================
// Unicode Formatted Print (vsnprintf for CHAR16)
//=============================================================================

/**
 * Unicode (wide) string formatting function - vsnprintf equivalent.
 *
 * Supports the following format specifiers:
 *   %s   - CHAR16* (wide string argument)
 *   %S   - CHAR8*  (narrow string argument, up-casted)
 *   %a   - CHAR8*  (narrow string argument)
 *   %d, %i - decimal integer
 *   %x, %X - hexadecimal (lower/upper case)
 *   %p   - pointer (hexadecimal with uppercase)
 *   %08x - zero-padded hex
 *   %r   - EFI_STATUS to string
 *   %g   - GUID to string (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)
 *   %ld, %li - long (64-bit) decimal
 *   %lx, %lX - long (64-bit) hex
 *
 * @param[out] Buffer   Output wide string buffer
 * @param[in]  MaxSize  Maximum number of wide characters to write
 * @param[in]  Format   Format string
 * @param[in]  VaList   Variable argument list
 * @return Number of wide characters written (excluding null terminator)
 */
STATIC
UINTN
UnicodeVSPrint (
  OUT CHAR16       *Buffer,
  IN  UINTN         MaxSize,
  IN  CONST CHAR16 *Format,
  IN  VA_LIST       VaList
  )
{
  CONST CHAR16  *Fmt;
  CHAR16        *Dst;
  UINTN          Remaining;
  CHAR16         Ch;
  UINTN          Width;
  CHAR16         PadChar;
  UINTN          Value;
  UINTN          ArgIndex;
  BOOLEAN        LongArg;
  CHAR8          NarrowBuf[256];
  CHAR16         WideBuf[32];
  CHAR16        *StrPtr;
  UINTN          StrLen;
  CHAR8         *NarrowStr;

  Fmt       = Format;
  Dst       = Buffer;
  Remaining = MaxSize;

  if (Fmt == NULL) {
    *Dst = L'\0';
    return 0;
  }

  while (*Fmt != L'\0') {

    if (*Fmt != L'%') {
      //
      // Ordinary character -- copy to output
      //
      if (Remaining <= 1) {
        goto Overflow;
      }
      *Dst++ = *Fmt;
      Remaining--;
      Fmt++;
      continue;
    }

    //
    // Process format specifier
    //
    Fmt++;

    //
    // Check for "%%" (literal percent)
    //
    if (*Fmt == L'%') {
      if (Remaining <= 1) break;
      *Dst++ = L'%';
      Remaining--;
      Fmt++;
      continue;
    }

    //
    // Parse width and padding
    //
    Width   = 0;
    PadChar = L' ';

    if (*Fmt == L'0') {
      PadChar = L'0';
      Fmt++;
    }

    //
    // Parse '*' width from argument
    //
    if (*Fmt == L'*') {
      Fmt++;
      ArgIndex = VA_ARG (VaList, UINTN);
      Width = (UINTN)ArgIndex;
    } else {
      //
      // Parse numeric width
      //
      CONST CHAR16 *WidthStart = Fmt;
      CONST CHAR16 *WidthEnd;
      Width = ParseInteger (Fmt, &WidthEnd, 10);
      if (WidthEnd != WidthStart) {
        Fmt = WidthEnd;
      }
    }

    //
    // Check for 'l' prefix (long/64-bit)
    //
    LongArg = FALSE;
    if (*Fmt == L'l') {
      LongArg = TRUE;
      Fmt++;
    }

    //
    // Process the conversion specifier
    //
    switch (*Fmt) {

      case L's':
        //
        // Wide string argument
        //
        StrPtr = VA_ARG (VaList, CHAR16 *);
        if (StrPtr == NULL) {
          StrPtr = L"(null)";
        }
        while (*StrPtr != L'\0') {
          if (Remaining <= 1) goto Overflow;
          *Dst++ = *StrPtr++;
          Remaining--;
        }
        break;

      case L'S':
      case L'a':
        //
        // Narrow (CHAR8) string argument, zero-extended to CHAR16
        //
        NarrowStr = VA_ARG (VaList, CHAR8 *);
        if (NarrowStr == NULL) {
          NarrowStr = "(null)";
        }
        while (*NarrowStr != '\0') {
          if (Remaining <= 1) goto Overflow;
          *Dst++ = (CHAR16)(UINT8)(*NarrowStr);
          NarrowStr++;
          Remaining--;
        }
        break;

      case L'c':
        //
        // Character argument
        //
        if (Remaining <= 1) goto Overflow;
        *Dst++ = (CHAR16)(VA_ARG (VaList, UINTN));
        Remaining--;
        break;

      case L'd':
      case L'i':
        //
        // Signed decimal integer
        //
        if (LongArg) {
          Value = (INT64)VA_ARG (VaList, INT64);
        } else {
          Value = (INTN)VA_ARG (VaList, INTN);
        }
        ValueToString ((INT64)Value, NarrowBuf, 10, TRUE);
        //
        // Apply padding
        //
        StrLen = AsciiStrLen (NarrowBuf);
        while (Width > StrLen) {
          if (Remaining <= 1) goto Overflow;
          *Dst++ = PadChar;
          Remaining--;
          Width--;
        }
        //
        // Output digits
        //
        {
          CHAR8 *Np = NarrowBuf + StrLen;
          while (Np >= NarrowBuf) {
            if (Remaining <= 1) goto Overflow;
            *Dst++ = (CHAR16)(UINT8)(*Np--);
            Remaining--;
          }
        }
        break;

      case L'X':
      case L'x':
      case L'p':
        //
        // Hexadecimal (unsigned)
        //
        if (LongArg || *Fmt == L'p') {
          Value = VA_ARG (VaList, UINT64);
        } else {
          Value = VA_ARG (VaList, UINTN);
        }
        ValueToString ((INT64)Value, NarrowBuf, 16, FALSE);
        //
        // Apply padding
        //
        StrLen = AsciiStrLen (NarrowBuf);
        while (Width > StrLen) {
          if (Remaining <= 1) goto Overflow;
          *Dst++ = PadChar;
          Remaining--;
          Width--;
        }
        //
        // Output digits, applying uppercase conversion for %X
        //
        {
          CHAR8 *Np;
          Np = NarrowBuf + StrLen;
          while (Np >= NarrowBuf) {
            CHAR8 Digit = *Np--;
            if (*Fmt == L'X' || *Fmt == L'p') {
              if (Digit >= 'a' && Digit <= 'f') {
                Digit -= 32;
              }
            }
            if (Remaining <= 1) goto Overflow;
            *Dst++ = (CHAR16)(UINT8)Digit;
            Remaining--;
          }
        }
        break;

      case L'r':
        //
        // EFI_STATUS to string
        //
        {
          CONST CHAR8 *StatusStr;
          UINT64       StatusValue;

          StatusValue = VA_ARG (VaList, UINT64);
          StatusStr = StatusToString ((EFI_STATUS)StatusValue);

          if (StatusStr != NULL) {
            while (*StatusStr != '\0') {
              if (Remaining <= 1) goto Overflow;
              *Dst++ = (CHAR16)(UINT8)(*StatusStr);
              StatusStr++;
              Remaining--;
            }
          } else {
            //
            // Fallback: print raw hex value
            //
            ValueToString ((INT64)StatusValue, NarrowBuf, 16, FALSE);
            CHAR8 *Np = NarrowBuf;
            while (*Np != '\0') {
              if (Remaining <= 1) goto Overflow;
              *Dst++ = (CHAR16)(UINT8)(*Np);
              Np++;
              Remaining--;
            }
          }
        }
        break;

      case L'g':
      case L'G':
        //
        // GUID to string (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)
        //
        {
          UINT32 *GuidData;
          UINTN   GuidBytes[11];

          GuidData = VA_ARG (VaList, UINT32 *);

          GuidBytes[0]  = GuidData[0];                          // Data1
          GuidBytes[1]  = (GuidData[1] & 0xFFFF);               // Data2
          GuidBytes[2]  = ((GuidData[1] >> 16) & 0xFFFF);       // Data3
          GuidBytes[3]  = *((UINT8 *)GuidData + 8);             // Data4[0]
          GuidBytes[4]  = *((UINT8 *)GuidData + 9);             // Data4[1]
          GuidBytes[5]  = *((UINT8 *)GuidData + 10);            // Data4[2]
          GuidBytes[6]  = *((UINT8 *)GuidData + 11);            // Data4[3]
          GuidBytes[7]  = *((UINT8 *)GuidData + 12);            // Data4[4]
          GuidBytes[8]  = *((UINT8 *)GuidData + 13);            // Data4[5]
          GuidBytes[9]  = *((UINT8 *)GuidData + 14);            // Data4[6]
          GuidBytes[10] = *((UINT8 *)GuidData + 15);            // Data4[7]

          UnicodeSPrint (
            Dst,
            Remaining,
            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
            GuidBytes[0],
            GuidBytes[1],
            GuidBytes[2],
            GuidBytes[3],
            GuidBytes[4],
            GuidBytes[5],
            GuidBytes[6],
            GuidBytes[7],
            GuidBytes[8],
            GuidBytes[9],
            GuidBytes[10]
            );
        }
        break;

      default:
        //
        // Unknown format specifier - copy literal
        //
        if (Remaining <= 1) goto Overflow;
        *Dst++ = *Fmt;
        Remaining--;
        break;
    }

    Fmt++;
  }

Overflow:
  *Dst = L'\0';
  return (UINTN)(Dst - Buffer);
}