/**
 * @file SetupConfigUpdateDxeLightningRidgeEXECB1.c
 * @brief UBA Setup Configuration Update DXE Driver for LightningRidge EXECB1.
 *
 * Source build path (from PDB):
 *   e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\
 *     PurleyRpPkg\Uba\UbaMain\Dxe\TypeLightningRidgeEXECB1\SetupCfgUpdateDxe\
 *     SetupCfgUpdateDxe\DEBUG\SetupConfigUpdateDxeLightningRidgeEXECB1.pdb
 *
 * Build toolchain: VS2015 DEBUG, X64, PE32+ image
 * Image size: 0xCA0 bytes
 *
 * This DXE driver is part of the PurleyRpPkg/Uba/UbaMain UBA (Universal BIOS
 * Aggregator) subsystem. It provides platform-specific setup configuration
 * data ("PSET" block) for the LightningRidge EXECB1 board variant during
 * the DXE phase.
 *
 * Architecture summary:
 *   - 8 functions total, ~2.9KB code (.text at 0x2C0-0x760)
 *   - Links against UefiBootServicesTableLib, UefiRuntimeServicesTableLib,
 *     DxeHobLib, and BaseLib
 *   - Standard UEFI driver entry pattern: save globals -> locate HOB list ->
 *     detect board -> register configuration via UBA protocol
 *
 * Key addresses:
 *   .text:   0x2C0 - 0x760 (0x4A0 bytes, RX)
 *   .rdata:  0x760 - 0xB40 (0x3E0 bytes, R)
 *   .data:   0xB40 - 0xBE0 (0xA0 bytes, RW)
 *   seg004:  0xBE0 - 0xC40 (0x60 bytes, R)
 *   .xdata:  0xC40 - 0xC80 (0x40 bytes, R)
 *   .reloc:  0xC80 - 0xCA0 (0x20 bytes, R)
 *
 * @note This file uses compiler intrinsics __inbyte() and __outbyte() for
 *       x86 I/O port access. These are MSVC/ICC intrinsics that compile to
 *       IN/OUT instructions. For GCC/Clang, use __builtin_ia32_inb/outb or
 *       inline assembly.
 */

#include "SetupConfigUpdateDxeLightningRidgeEXECB1.h"


//=============================================================================
// x86 I/O Port Access Intrinsics
//=============================================================================

/**
 * @brief Read a byte from an x86 I/O port.
 *
 * MSVC provides __inbyte() as a compiler intrinsic. For GCC/Clang,
 * use __builtin_ia32_inb() or inline assembly.
 * This wrapper provides a portable name for the CMOS access code.
 *
 * @param Port  16-bit I/O port address
 * @return Byte value read from the port
 */
static inline UINT8 IoRead8(UINT16 Port) {
#if defined(_MSC_VER)
  return __inbyte(Port);
#elif defined(__GNUC__) || defined(__clang__)
  UINT8 Value;
  __asm__ __volatile__("inb %w1, %b0" : "=a"(Value) : "Nd"(Port));
  return Value;
#else
  return 0;
#endif
}

/**
 * @brief Write a byte to an x86 I/O port.
 *
 * MSVC provides __outbyte() as a compiler intrinsic. For GCC/Clang,
 * use __builtin_ia32_outb() or inline assembly.
 *
 * @param Port  16-bit I/O port address
 * @param Value Byte value to write to the port
 */
static inline VOID IoWrite8(UINT16 Port, UINT8 Value) {
#if defined(_MSC_VER)
  __outbyte(Port, Value);
#elif defined(__GNUC__) || defined(__clang__)
  __asm__ __volatile__("outb %b0, %w1" : : "a"(Value), "Nd"(Port));
#else
  (void)Port;
  (void)Value;
#endif
}


//=============================================================================
// Global Variables (.data section, 0xB98 - 0xBC8)
//=============================================================================

/** @brief ImageHandle passed to the entry point. @address 0xBA8 */
EFI_HANDLE            gImageHandle   = 0;

/** @brief Pointer to the EFI System Table. @address 0xB98 */
EFI_SYSTEM_TABLE     *gSystemTable   = NULL;

/** @brief Cached BootServices pointer (from SystemTable->BootServices). @address 0xBA0 */
EFI_BOOT_SERVICES    *gBootServices  = NULL;

/** @brief Cached RuntimeServices pointer (from SystemTable->RuntimeServices). @address 0xBB0 */
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;

/**
 * @brief Cached pointer to the UBA SetupConfig Protocol instance.
 * Located by GetUBASetupConfigProtocol() via gBS->LocateProtocol() with
 * UBA_SETUP_CONFIG_PROTOCOL_GUID. NULL until first successful location.
 * @address 0xBB8
 */
VOID                 *gUBASetupConfigProtocol = NULL;

/**
 * @brief Cached HOB List pointer, found by walking the System Table's
 * ConfigurationTable array for gEfiHobListGuid. NULL until found.
 * @address 0xBC0
 */
VOID                 *gHobList       = NULL;

/**
 * @brief Cached board type index read from CMOS register 0x4B.
 * @address 0xBC8
 * @note This is stored as a full UINT64 in the binary (8 bytes at 0xBC8)
 *       but only the low byte is meaningful.
 */
UINT8                 gBoardType     = 0;


//=============================================================================
// Static Data (.data section, 0xB40 - 0xB97)
//=============================================================================

/**
 * UBA SetupConfig Protocol GUID (first copy, used by GetUBASetupConfigProtocol).
 * {36232936-0E76-31C8-A13A-3AF2FC1C3932}
 * @address 0xB40
 */
static CONST GUID mUbaSetupConfigProtocolGuid1 = UBA_SETUP_CONFIG_PROTOCOL_GUID;

/**
 * UBA SetupConfig Protocol GUID (second copy, used by _ModuleEntryPoint).
 * {36232936-0E76-31C8-A13A-3AF2FC1C3932}
 * The same GUID stored at two different addresses in .data (0xB40 and 0xB50).
 * @address 0xB50
 */
static CONST GUID mUbaSetupConfigProtocolGuid2 = UBA_SETUP_CONFIG_PROTOCOL_GUID;

/**
 * HOB List GUID, stored as two 8-byte halves for efficient comparison.
 * First half at 0xB60:  0x11D493D7 7739F24C (LE bytes: 4C F2 39 77 D7 93 D4 11)
 * Second half at 0xB68: 0x9A3A0090 273FC14D
 * {7739F24C-93D7-11D4-9A3A-0090273FC14D}
 * @address 0xB60/0xB68
 */
static CONST GUID mHobListGuid = EFI_HOB_LIST_GUID;

/**
 * LightningRidge EXECB1 Protocol GUID.
 * Used as the registration key identifier when calling the UBA protocol's
 * RegisterConfig function (telling the framework which platform this config
 * belongs to).
 * {E03E0D46-5263-4845-B0A4-58D57B3177E2}
 * @address 0xB70
 */
static CONST GUID mLightningRidgeExecb1ProtocolGuid = LIGHTNING_RIDGE_EXECB1_PROTOCOL_GUID;

/**
 * Default platform setup configuration ("PSET" block).
 * This is the initial platform configuration data registered with the UBA
 * framework. It identifies itself with signature "PSET" v1.
 *
 * Structure layout (24 bytes total):
 *   +0x00: UINT32 Signature = 0x50455354 ("PSET")
 *   +0x04: UINT32 Version   = 1
 *   +0x08: UINT32 Reserved1 (has base relocation - may be pointer in production)
 *   +0x0C: UINT32 Reserved2
 *   +0x10: UINT32 Reserved3 (has base relocation - may be pointer in production)
 *   +0x14: UINT32 Reserved4
 *
 * @address 0xB80
 * @note Fields at +0x08 and +0x10 have base relocations pointing to
 *       GetEfiInvalidParameterStatus (0x48C), suggesting these may be
 *       function pointers set during debug or in production builds.
 */
static PLATFORM_SETUP_CONFIG mPlatformSetupConfig = {
  .Signature  = 0x54455350,  /* "PSET" in little-endian */
  .Version    = 1,
  .Reserved1  = 0,           /* Has base reloc -> may be a pointer in production */
  .Reserved2  = 0,
  .Reserved3  = 0,           /* Has base reloc -> may be a pointer in production */
  .Reserved4  = 0,
};


//=============================================================================
// Function: ReadUnaligned64 (0x728, 47 bytes)
//=============================================================================

/**
 * Reads an unaligned 64-bit value from memory with NULL pointer assertion.
 *
 * This is an inlined version of the BaseLib unaligned read function
 * (Unaligned.c, line 192). On x64, unaligned memory access is natively
 * supported, so the implementation is a plain 8-byte MOV preceded by
 * a NULL pointer check.
 *
 * @param[in] Buffer  Pointer to the 8-byte value to read (must not be NULL)
 *
 * @return The 64-bit value at Buffer, read as unaligned.
 *
 * @address 0x728
 * @callee_count 1 (UBADebugPrint, called on NULL assertion)
 * @caller_count 4 (from CompareGuidUnaligned, 2x for each GUID half)
 */
static
UINT64
EFIAPI
ReadUnaligned64 (
  IN CONST VOID *Buffer
  )
{
  //
  // ASSERT if Buffer is NULL (BaseLib Unaligned.c:192)
  //
  if (Buffer == NULL) {
    //
    // ASSERT: Buffer must not be NULL
    // Original source: e:\hs\MdePkg\Library\BaseLib\Unaligned.c, line 192
    //
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
      192,
      (UINTN)"Buffer != ((void *) 0)"
      );
  }

  //
  // x64 supports unaligned loads natively; the compiler emits
  // a simple MOV instruction for this dereference.
  //
  return *(volatile UINT64 *)Buffer;
}


//=============================================================================
// Function: CompareGuidUnaligned (0x6B8, 110 bytes)
//=============================================================================

/**
 * Compares two GUIDs by reading them as two 64-bit halves.
 *
 * The function compares the first 8 bytes and second 8 bytes of the
 * reference GUID (mHobListGuid, stored at 0xB60/0xB68) against the
 * provided entry address. This is functionally equivalent to
 * CompareMem(Guid1, Guid2, 16) == 0 but uses explicit unaligned reads.
 *
 * UEFI GUID memory layout:
 *   [0..3]:   Data1 (UINT32, little-endian)
 *   [4..5]:   Data2 (UINT16, little-endian)
 *   [6..7]:   Data3 (UINT16, little-endian)
 *   [8..15]:  Data4 (UINT8[8])
 *
 * When read as UINT64[0..1]:
 *   [0] = Data1 | (Data2 << 32) | (Data3 << 48)   [8 bytes]
 *   [1] = Data4                                     [8 bytes]
 *
 * @param[in] Guid1  Pointer to the reference GUID to match against
 * @param[in] Entry  Pointer to the entry GUID being compared
 *
 * @return TRUE if both halves match, FALSE otherwise.
 *
 * @address 0x6B8
 * @callee_count 4 (ReadUnaligned64)
 * @caller_count 1 (GetHobListFromConfigTable, once per iteration)
 */
static
BOOLEAN
EFIAPI
CompareGuidUnaligned (
  IN CONST GUID *Guid1,
  IN CONST VOID *Entry
  )
{
  //
  // Read first 8 bytes of each GUID
  //
  UINT64 GuidFirstHalf  = ReadUnaligned64 (Guid1);
  UINT64 EntryFirstHalf = ReadUnaligned64 (Entry);

  //
  // Read second 8 bytes of each GUID (offset +8 from base)
  //
  UINT64 GuidSecondHalf  = ReadUnaligned64 ((CONST UINT8 *)Guid1 + 8);
  UINT64 EntrySecondHalf = ReadUnaligned64 ((CONST UINT8 *)Entry + 8);

  //
  // Both halves must match
  //
  return (GuidFirstHalf == EntryFirstHalf) && (GuidSecondHalf == EntrySecondHalf);
}


//=============================================================================
// Function: GetEfiInvalidParameterStatus (0x48C, 11 bytes)
//=============================================================================

/**
 * Returns the EFI_INVALID_PARAMETER status constant.
 *
 * This helper function provides the status value used by ASSERT_EFI_ERROR
 * calls in this driver. The value 0x800000000000000E has bit 63 set
 * (UEFI error indicator), which makes it a valid error status for
 * ASSERT_EFI_ERROR macro evaluation.
 *
 * The value encodes:
 *   - High bit (63):   1 = error (EFI_ERROR macro check)
 *   - Low 28 bits:    0x000000E = EFI_INVALID_PARAMETER (14)
 *
 * @return  EFI_STATUS with value 0x800000000000000E
 *
 * @address 0x48C
 * @caller_count 2 (from GetHobListFromConfigTable ASSERT path)
 */
static
EFI_STATUS
EFIAPI
GetEfiInvalidParameterStatus (
  VOID
  )
{
  return 0x800000000000000EULL;
}


//=============================================================================
// Function: GetUBASetupConfigProtocol (0x498, 127 bytes)
//=============================================================================

/**
 * Locates and caches the UBA SetupConfig Protocol interface.
 *
 * Uses gBS->LocateProtocol() with UBA_SETUP_CONFIG_PROTOCOL_GUID
 * ({36232936-0E76-31C8-A13A-3AF2FC1C3932}) to obtain the protocol
 * instance. The result is cached in gUBASetupConfigProtocol so that
 * subsequent calls do not re-query the protocol database.
 *
 * TPL safety probe:
 *   Before calling LocateProtocol, the function raises the TPL to 31
 *   (TPL_NOTIFY = 16 in standard UEFI, but this driver uses 31 = 0x1F)
 *   and immediately restores it. The returned original TPL is checked:
 *   - If original TPL <= 16: LocateProtocol is called (safe TPL level)
 *   - If original TPL > 16:  Return NULL (already in notification context)
 *
 * This is a defensive measure. Standard UEFI does not restrict
 * LocateProtocol based on TPL, but the UBA framework may have
 * re-entrancy constraints.
 *
 * @return  Pointer to the UBA_SETUP_CONFIG_PROTOCOL instance, or NULL
 *          if not found, LocateProtocol failed, or TPL is too high.
 *
 * @address 0x498
 * @callee_count 1 (gBS->LocateProtocol)
 * @caller_count 2 (UBADebugPrint, CheckBoardTypeAndLog)
 */
static
VOID *
EFIAPI
GetUBASetupConfigProtocol (
  VOID
  )
{
  EFI_STATUS Status;
  EFI_TPL    OriginalTpl;

  //
  // Return cached pointer if already located
  //
  if (gUBASetupConfigProtocol != NULL) {
    return gUBASetupConfigProtocol;
  }

  //
  // TPL safety probe: raise to 31 (above TPL_NOTIFY=16), then restore.
  // The returned old TPL tells us if we are at a safe calling level.
  //
  OriginalTpl = gBootServices->RaiseTPL (31);
  gBootServices->RestoreTPL (OriginalTpl);

  //
  // Only call LocateProtocol if original TPL was <= 16 (TPL_APPLICATION
  // or TPL_CALLBACK). Skip if already at or above TPL_NOTIFY to avoid
  // potential re-entrancy issues.
  //
  if (OriginalTpl <= 16) {
    //
    // gBS->LocateProtocol is at BootServices offset +0x140 (+320 decimal)
    //
    Status = gBootServices->LocateProtocol (
                              &mUbaSetupConfigProtocolGuid1,
                              NULL,                     // No registration key
                              &gUBASetupConfigProtocol
                              );

    //
    // Check for error (EFI_ERROR macro: test bit 63)
    //
    if (Status >> 63) {
      gUBASetupConfigProtocol = NULL;
    }
  }

  return gUBASetupConfigProtocol;
}


//=============================================================================
// Function: UBADebugPrint (0x5A0, 62 bytes)
//=============================================================================

/**
 * Debug print wrapper that forwards to the UBA protocol's output function.
 *
 * Gets the UBA protocol via GetUBASetupConfigProtocol() and calls
 * the function at protocol offset +8. This is used as the ASSERT
 * handler for this driver, taking (file name, line number, expression)
 * triplets matching the standard UEFI ASSERT macro pattern.
 *
 * If the UBA protocol is unavailable, the function is a silent no-op
 * (returns 0).
 *
 * @param[in] FileName    Source file name string pointer
 * @param[in] LineNumber  Source line number
 * @param[in] Expression  Assertion expression string pointer
 *
 * @return  Result from the protocol's debug function, or 0 if protocol
 *          is unavailable.
 *
 * @address 0x5A0
 * @callee_count 1 (GetUBASetupConfigProtocol)
 * @caller_count 7 (3 from _ModuleEntryPoint, 2 from GetHobListFromConfigTable,
 *                   1 from ReadUnaligned64, 1 from CheckBoardTypeAndLog path)
 *                  [highest call count in module]
 */
static
UINT64
EFIAPI
UBADebugPrint (
  IN UINT64  FileName,
  IN UINT64  LineNumber,
  IN UINT64  Expression
  )
{
  VOID *Protocol;

  Protocol = GetUBASetupConfigProtocol ();
  if (Protocol == NULL) {
    return 0;
  }

  //
  // The debug print function is at offset +8 (function [1]) in the
  // UBA protocol interface. It takes 3 arguments after the This pointer.
  // On x64 (Microsoft calling convention):
  //   RCX = Protocol (This pointer)
  //   RDX = FileName
  //   R8  = LineNumber
  //   R9  = Expression
  //
  return (*(UINT64 (EFIAPI **)(VOID *, UINT64, UINT64, UINT64))((UINT8 *)Protocol + 8))(
           Protocol,
           FileName,
           LineNumber,
           Expression
           );
}


//=============================================================================
// Function: CheckBoardTypeAndLog (0x518, 136 bytes)
//=============================================================================

/**
 * Detects the LightningRidge board variant via CMOS register 0x4B and
 * conditionally logs the board identification string.
 *
 * Board detection flow:
 *   1. Get the UBA SetupConfig protocol (for potential debug output)
 *   2. If protocol is available:
 *      a. Read CMOS register 0x4B via x86 I/O ports 0x70/0x71
 *         - inb(0x70) reads current CMOS index, preserving NMI mask
 *         - outb(0x70, (val & 0x80) | 0x4B) selects register 0x4B
 *         - inb(0x71) reads the board index value
 *      b. Cache result in gBoardType
 *      c. Handle unprogrammed case (index > 3 and value == 0):
 *         - Fallback to MMIO read at 0xFDAF0490
 *         - Take bit 1 as variant indicator:
 *           result = (mmio_value & 2) | 1
 *      d. Compute debug filter mask:
 *         - Board type 1 (EXECB1): mask = 0x80000004
 *         - Board type 2+ (others): mask = 0x80000006
 *      e. If (mask & DebugLevel) != 0:
 *         Call protocol debug function at offset +8 with the varargs
 *
 * @param[in] DebugLevel  Debug severity level bitmask
 * @param[in] DebugString Format string pointer
 * @param[in] ...         Variable arguments for the format string
 *
 * @return  Board detection result:
 *          0 = protocol not available
 *          1 = LightningRidge EXECB1
 *          4 = Other board variant (or unprogrammed)
 *
 * @address 0x518
 * @callee_count 2 (GetUBASetupConfigProtocol, optional protocol debug)
 * @caller_count 2 (_ModuleEntryPoint, GetHobListFromConfigTable)
 */
static
UINT8
EFIAPI
CheckBoardTypeAndLog (
  IN UINTN        DebugLevel,
  IN CONST CHAR8 *DebugString,
  ...
  )
{
  VOID    *Protocol;
  UINT8    BoardIndex;
  UINT8    CmosIndex;
  UINTN    FilterMask;
  VA_LIST Args;

  //
  // Get the UBA protocol for potential debug output
  //
  Protocol = GetUBASetupConfigProtocol ();
  FilterMask = 0;

  if (Protocol != NULL) {
    //
    // Read CMOS register 0x4B (board index).
    // Port 0x70 = CMOS index register (bit 7 = NMI enable)
    // Port 0x71 = CMOS data register
    //
    //
    // Access CMOS/RTC indexed register 0x4B via x86 I/O ports:
    //   Port 0x70 = CMOS index register (bit 7 = NMI mask, preserve it)
    //   Port 0x71 = CMOS data register
    //
    CmosIndex  = IoRead8 (CMOS_INDEX_PORT);                       // Read current CMOS index (preserve NMI)
    IoWrite8 (CMOS_INDEX_PORT, (CmosIndex & 0x80) | CMOS_REGISTER_BOARD_INDEX);  // Select reg 0x4B
    BoardIndex = IoRead8 (CMOS_DATA_PORT);                        // Read board index value

    //
    // Cache the board type
    //
    gBoardType = BoardIndex;

    //
    // Handle unprogrammed CMOS register (value 0 when register > 3):
    // Fall back to MMIO-based board detection.
    //
    if (BoardIndex > 3 && BoardIndex == 0) {
      //
      // Read MMIO register at 0xFDAF0490 (platform-specific strapping/GPIO register)
      // Bit 1 selects board variant:
      //   Bit 1 = 0: variant maps to EXECB1
      //   Bit 1 = 1: variant maps to EXECB2/other
      //
      BoardIndex = (*(volatile UINT8 *)BOARD_DETECT_MMIO_ADDR & 2) | 1;
      gBoardType = BoardIndex;
    }

    //
    // Set debug filter mask based on board type:
    //   EXECB1 (1):  mask = 0x80000004  (bit 31 | bit 2)
    //   Other:       mask = 0x80000006  (bit 31 | bit 2 | bit 1)
    //
    // Both masks have bit 31 set, which means DebugLevel values with
    // bit 31 set (like the 0x80000000 passed from _ModuleEntryPoint)
    // will always pass the filter.
    //
    if (BoardIndex == BOARD_TYPE_LR_EXECB1) {
      FilterMask = 0x80000004;
    } else if (BoardIndex >= 0x02) {
      FilterMask = 0x80000006;
    }

    //
    // If filter mask and debug level overlap, call protocol debug function
    //
    if ((FilterMask & DebugLevel) != 0) {
      VA_START (Args, DebugString);

      //
      // Call protocol function at offset +8 (debug print)
      // Args: (This=Protocol, DebugLevel, DebugString, va_list)
      //
      (*(VOID (EFIAPI **)(VOID *, UINTN, CONST CHAR8 *, VA_LIST))((UINT8 *)Protocol + 8))(
        Protocol,
        DebugLevel,
        DebugString,
        Args
        );

      VA_END (Args);
    }

    return (BoardIndex == BOARD_TYPE_LR_EXECB1) ? 1 : 4;
  }

  return 0;
}


//=============================================================================
// Function: GetHobListFromConfigTable (0x5E0, 214 bytes)
//=============================================================================

/**
 * Locates the HOB List pointer from the EFI System Table's ConfigurationTable.
 *
 * Walks the gSystemTable->ConfigurationTable array searching for an entry
 * whose VendorGuid matches gEfiHobListGuid ({7739F24C-93D7-11D4-9A3A-0090273FC14D}).
 * When found, caches the Table pointer in gHobList.
 *
 * This is functionally identical to DxeHobLib's GetHobList() implementation
 * but inlined here to avoid a library dependency for this single operation.
 *
 * SystemTable field layout (offset-based, since EFI_SYSTEM_TABLE struct
 * may not be fully defined):
 *   +0x00: EFI_TABLE_HEADER Hdr          (24 bytes)
 *   +0x18: CHAR16*          FirmwareVendor (8)
 *   +0x20: UINT32           FirmwareRevision (4)
 *   +0x24: (padding 4)
 *   +0x28: EFI_HANDLE       ConsoleInHandle (8)
 *   +0x30: VOID*            ConIn (8)
 *   +0x38: EFI_HANDLE       ConsoleOutHandle (8)
 *   +0x40: VOID*            ConOut (8)
 *   +0x48: EFI_HANDLE       StdErrHandle (8)
 *   +0x50: VOID*            StdErr (8)
 *   +0x58: EFI_RUNTIME_SERVICES*  RuntimeServices (8)
 *   +0x60: EFI_BOOT_SERVICES*     BootServices (8)
 *   +0x68: UINTN                   NumberOfTableEntries (8)
 *   +0x70: EFI_CONFIGURATION_TABLE* ConfigurationTable (8)
 *
 * Each ConfigurationTable entry is 24 bytes:
 *   +0x00: EFI_GUID VendorGuid (16 bytes)
 *   +0x10: VOID*    VendorTable (8 bytes)
 *
 * On failure (no HOB list entry found): calls ASSERT_EFI_ERROR with
 * EFI_INVALID_PARAMETER and logs the HOB library assertion messages.
 *
 * @return  Pointer to the HOB List (cached in gHobList), or NULL.
 *          Note: returns NULL only in extreme failure; ASSERT is hit first.
 *
 * @address 0x5E0
 * @callee_count 4 (CompareGuidUnaligned, CheckBoardTypeAndLog, UBADebugPrint x2)
 * @caller_count 1 (_ModuleEntryPoint)
 */
static
VOID *
EFIAPI
GetHobListFromConfigTable (
  VOID
  )
{
  UINTN   NumEntries;
  UINT8  *ConfigTable;
  UINTN   Index;

  //
  // Return cached pointer if already found
  //
  if (gHobList != NULL) {
    return gHobList;
  }

  //
  // Initialize to NULL; set only on successful match
  //
  gHobList = NULL;

  //
  // Read NumberOfTableEntries and ConfigurationTable from SystemTable
  //
  NumEntries  = *(UINTN *)((UINT8 *)gSystemTable + 0x68);
  ConfigTable = *(UINT8 **)((UINT8 *)gSystemTable + 0x70);

  if (NumEntries > 0) {
    //
    // Walk the ConfigurationTable array looking for gEfiHobListGuid
    //
    for (Index = 0; Index < NumEntries; Index++) {
      //
      // Compare GUID at current entry against mHobListGuid
      //
      if (CompareGuidUnaligned (
            &mHobListGuid,
            &ConfigTable[Index * 24]
            )) {
        //
        // Match found: the interface pointer is at entry offset +16
        //
        gHobList = *(VOID **)&ConfigTable[Index * 24 + 16];
        return gHobList;
      }
    }

    //
    // GUID not found in ConfigurationTable: ASSERT path
    //
    CheckBoardTypeAndLog (
      0x80000000,
      "\nASSERT_EFI_ERROR (Status = %r)\n",
      GetEfiInvalidParameterStatus ()
      );
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
      54,
      (UINTN)"!EFI_ERROR (Status)"
      );
  }

  //
  // If gHobList is still NULL after the search, log another assertion
  // (HOB list must exist during DXE phase for proper memory management)
  //
  if (gHobList == NULL) {
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
      55,
      (UINTN)"mHobList != ((void *) 0)"
      );
  }

  return gHobList;
}


//=============================================================================
// Function: SetupConfigUpdateEntryPoint (0x390, 250 bytes)
//=============================================================================

/**
 * Main entry point for the SetupConfigUpdateDxeLightningRidgeEXECB1 driver.
 *
 * Standard UEFI DXE driver entry point that performs the following:
 *
 *   1. Save ImageHandle and SystemTable to globals (gImageHandle, gSystemTable)
 *       - ASSERT if either is NULL
 *   2. Cache BootServices from SystemTable->BootServices (offset +0x60)
 *       - ASSERT if NULL
 *   3. Cache RuntimeServices from SystemTable->RuntimeServices (offset +0x58)
 *       - ASSERT if NULL
 *   4. Initialize HOB list via GetHobListFromConfigTable()
 *   5. Log platform identification via CheckBoardTypeAndLog()
 *       - String: "UBA:SETUPConfigUpdate-TypeLightningRidgeEXECB1\n"
 *   6. Locate the UBA SetupConfig protocol via gBS->LocateProtocol()
 *       - GUID: mUbaSetupConfigProtocolGuid2 = UBA_SETUP_CONFIG_PROTOCOL_GUID
 *         (second copy at 0xB50, same GUID as mUbaSetupConfigProtocolGuid1 at 0xB40)
 *       - On failure: return error status
 *   7. Register the platform config via the protocol's function at offset +16:
 *       - Args: (This, RegistrationGUID, ConfigData, ConfigSize)
 *       - RegistrationGUID = mLightningRidgeExecb1ProtocolGuid (platform identifier)
 *       - ConfigData       = &mPlatformSetupConfig (PSET block at 0xB80)
 *       - ConfigSize       = sizeof(PLATFORM_SETUP_CONFIG) = 24
 *   8. Return status from registration call
 *
 * @param[in] ImageHandle  The firmware allocated handle for the EFI image
 * @param[in] SystemTable  A pointer to the EFI System Table
 *
 * @return  EFI_SUCCESS on successful registration, or error status from
 *          LocateProtocol if the UBA protocol is not available.
 *
 * @address 0x390
 * @callee_count 6 (UBADebugPrint x4, GetHobListFromConfigTable,
 *                  CheckBoardTypeAndLog, gBS->LocateProtocol,
 *                  protocol->RegisterConfig)
 * @caller_count 1 (DXE dispatcher)
 */
EFI_STATUS
EFIAPI
SetupConfigUpdateEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS Status;
  VOID      *UbaProtocol;
  VOID      *ProtocolOut;     /* Output from LocateProtocol */

  //
  // ========================================================================
  // Step 1: Save ImageHandle and SystemTable to module globals
  // ========================================================================
  //

  gImageHandle = ImageHandle;
  if (ImageHandle == NULL) {
    //
    // ASSERT: ImageHandle must not be NULL
    //
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      51,
      (UINTN)"gImageHandle != ((void *) 0)"
      );
  }

  gSystemTable = SystemTable;
  if (SystemTable == NULL) {
    //
    // ASSERT: SystemTable must not be NULL
    //
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      57,
      (UINTN)"gST != ((void *) 0)"
      );
  }

  //
  // ========================================================================
  // Step 2: Cache BootServices from SystemTable (offset +0x60 = +96)
  // ========================================================================
  //

  gBootServices = SystemTable->BootServices;
  if (gBootServices == NULL) {
    //
    // ASSERT: BootServices must not be NULL
    //
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
      63,
      (UINTN)"gBS != ((void *) 0)"
      );
  }

  //
  // ========================================================================
  // Step 3: Cache RuntimeServices from SystemTable (offset +0x58 = +88)
  // ========================================================================
  //

  gRuntimeServices = SystemTable->RuntimeServices;
  if (gRuntimeServices == NULL) {
    //
    // ASSERT: RuntimeServices must not be NULL
    //
    UBADebugPrint (
      (UINTN)"e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
      47,
      (UINTN)"gRT != ((void *) 0)"
      );
  }

  //
  // ========================================================================
  // Step 4: Initialize HOB List (find gEfiHobListGuid in ConfigTable)
  // ========================================================================
  //

  GetHobListFromConfigTable ();

  //
  // ========================================================================
  // Step 5: Log the platform identification string
  // ========================================================================
  //
  // This call also triggers the CMOS board type detection and caches
  // the board index in gBoardType.
  //

  CheckBoardTypeAndLog (
    DEBUG_LEVEL_INFO,
    "UBA:SETUPConfigUpdate-TypeLightningRidgeEXECB1\n"
    );

  //
  // ========================================================================
  // Step 6: Locate the UBA SetupConfig protocol
  // ========================================================================
  //
  // Uses the second copy of UBA_SETUP_CONFIG_PROTOCOL_GUID at 0xB50.
  // This is the same GUID as the first copy at 0xB40 (used by
  // GetUBASetupConfigProtocol) but stored at a different .data address.
  //
  // gBS->LocateProtocol is at BootServices offset +0x140 (function index 40).
  //

  ProtocolOut = NULL;

  Status = gBootServices->LocateProtocol (
                            &mUbaSetupConfigProtocolGuid2,
                            NULL,
                            &UbaProtocol
                            );

  //
  // ========================================================================
  // Step 7: Register platform configuration via protocol
  // ========================================================================
  //
  // If LocateProtocol succeeded (no error bit set), call the protocol's
  // RegisterConfig function at offset +16 (function index 2).
  //
  // RegisterConfig signature:
  //   EFI_STATUS (*)(VOID       *This,
  //                  EFI_GUID   *ConfigGuid,    -- platform identifier GUID
  //                  VOID       *ConfigData,    -- PSET configuration block
  //                  UINTN       ConfigSize)    -- 24 bytes = sizeof(PSET)
  //
  // Note on GUID usage:
  //   - mLightningRidgeExecb1ProtocolGuid ({E03E0D46-...}) is used as the
  //     registration KEY/IDENTIFIER, NOT as a protocol GUID for LocateProtocol.
  //     It tells the UBA framework which platform this configuration applies to.
  //   - mPlatformSetupConfig at 0xB80 is the PSET data block.
  //

  if (!(Status >> 63)) {
    //
    // Success path: call RegisterConfig at protocol +16
    //
    return (*(EFI_STATUS (EFIAPI **)(VOID *, CONST GUID *, VOID *, UINTN))(
              (UINT8 *)UbaProtocol + 16))(
              UbaProtocol,
              &mLightningRidgeExecb1ProtocolGuid,
              &mPlatformSetupConfig,
              sizeof (PLATFORM_SETUP_CONFIG)
              );
  }

  //
  // Error path: return the status from LocateProtocol
  //
  return Status;
}