Newer
Older
AMI-Aptio-BIOS-Reversed / SetupConfigUpdateDxeLightningRidgeEXECB2 / SetupConfigUpdateDxeLightningRidgeEXECB2.c
@Ajax Dong Ajax Dong 2 days ago 24 KB Init
/**
 * @file SetupConfigUpdateDxeLightningRidgeEXECB2.c
 *
 * @brief UBA (Unified Board Architecture) Setup Configuration Update DXE driver
 *        for the LightningRidgeEXECB2 platform.
 *
 * This module is a DXE driver dispatched by the UEFI DXE core. It locates the
 * HOB (Hand-Off Block) list and the UBA board-type protocol, then registers
 * the platform-specific setup configuration data (size 0x48C bytes) via
 * the protocol's RegisterSetupConfig callback.
 *
 * The driver contains inline code from several EDK2 libraries:
 *   - UefiBootServicesTableLib (gImageHandle, gST, gBS globals)
 *   - UefiRuntimeServicesTableLib (gRT)
 *   - DxeHobLib (HOB list scanning)
 *   - BaseLib (unaligned read)
 *   - DebugLib (protocol-based assert/print)
 *
 * Build path: e:\hs\...\PurleyRpPkg\Uba\UbaMain\Dxe\TypeLightningRidgeEXECB2\...
 * Toolchain: VS2015, X64 DEBUG build
 *
 * This is the LightningRidgeEXECB2-specific variant; the NeonCityFPGA variant
 * differs only in the UBA protocol GUIDs and the debug print string.
 */

#include "SetupConfigUpdateDxeLightningRidgeEXECB2.h"

/*=============================================================================
 * Module Globals (in .data section, 0xB98-0xBC8)
 *============================================================================*/

/** 0xB98 -- EFI_SYSTEM_TABLE pointer cached from entry argument. */
EFI_SYSTEM_TABLE      *gSystemTable      = NULL;

/** 0xBA0 -- EFI_BOOT_SERVICES pointer cached from gST->BootServices. */
EFI_BOOT_SERVICES     *gBootServices     = NULL;

/** 0xBA8 -- Module image handle from entry argument. */
EFI_HANDLE             gImageHandle      = NULL;

/** 0xBB0 -- EFI_RUNTIME_SERVICES pointer cached from gST->RuntimeServices. */
EFI_RUNTIME_SERVICES  *gRuntimeServices  = NULL;

/** 0xBB8 -- Lazily-cached DebugLib protocol pointer. NULL when uninitialized. */
VOID                  *gDebugProtocol    = NULL;

/** 0xBC0 -- Lazily-cached HOB list pointer (VOID*). NULL when uninitialized. */
VOID                  *gHobList          = NULL;

/** 0xBC8 -- Cached CMOS debug level byte, read from RTC register 0x4B. */
UINT8                  gCmosDebugLevel   = 0;

/*=============================================================================
 * GUID constants embedded in .rdata/.data (0xB40-0xB97)
 *============================================================================*/

/**
 * 0xB40 -- DebugLib protocol GUID.
 * {36232936-0E76-31C8-A13A-3AF2FC1C3932}
 */
EFI_GUID gDebugProtocolGuid = { 0x36232936, 0x0E76, 0x31C8,
    { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } };

/**
 * 0xB50 -- UBA LightningRidgeEXECB2 board-type protocol GUID.
 * {E03E0D46-5263-4845-B0A4-58D57B3177E2}
 */
EFI_GUID gUbaBoardTypeProtocolGuid = { 0xE03E0D46, 0x5263, 0x4845,
    { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } };

/**
 * 0xB60 -- EFI HOB list GUID (standard UEFI).
 * {7739F24C-93D7-11D4-9A3A-0090273FC14D}
 *
 * The two halves (0xB60-0xB67 and 0xB68-0xB6F) are used for fast
 * inline comparison in IsHobListGuid() without calling CompareGuid().
 */
EFI_GUID gEfiHobListGuid = { 0x7739F24C, 0x93D7, 0x11D4,
    { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } };

/** 0xB60 -- First 8 bytes of gEfiHobListGuid (for fast compare). */
UINT64 gEfiHobListGuidFirstHalf  = 0;

/** 0xB68 -- Last 8 bytes of gEfiHobListGuid (for fast compare). */
UINT64 gEfiHobListGuidSecondHalf = 0;

/**
 * 0xB70 -- LightningRidgeEXECB2 setup config protocol GUID installed by
 * RegisterSetupConfig.
 * {CD1F9574-DD03-4196-96AD-4965146F9665}
 */
EFI_GUID gUbaSetupConfigProtocolGuid = { 0xCD1F9574, 0xDD03, 0x4196,
    { 0x96, 0xAD, 0x49, 0x65, 0x14, 0x6F, 0x96, 0x65 } };

/**
 * 0xB80 -- UBA_SETUP_CONFIG_DATA descriptor.
 * Signature: 'PSET' (0x54455350)
 * Version:   1
 * DataSize:  0x48C (1164 bytes)
 * Reserved duplicate: 0x48C
 */
UBA_SETUP_CONFIG_DATA gSetupConfigData = {
    .Signature        = 0x54455350,     ///< 'PSET' -- reversed "SETP" from "SETUP"
    .Version          = 1,              ///< Format version 1
    .DataSize         = 0x48C,          ///< 1164 bytes of setup config data
    .DataSizeDuplicate = 0x48C,         ///< Duplicate for validation
};


/*=============================================================================
 * Function: ReturnNotFound (at 0x48C)
 *============================================================================*/

/**
 * @brief Returns EFI_NOT_FOUND status code.
 *
 * A tiny 2-instruction leaf (size 0xB = 11 bytes) that returns the constant
 * EFI_NOT_FOUND (0x800000000000000E). This function has no callers in the
 * binary -- it appears to be dead code or a utility placeholder.
 *
 * The value 0x800000000000000E is:
 *   - High bit set (error bit)
 *   - Encoded as EFIERR(0x0E) = EFI_NOT_FOUND
 *
 * @return EFI_NOT_FOUND (0x800000000000000E).
 */
EFI_STATUS
ReturnNotFound (
    VOID
    )
{
    /* return 0x800000000000000EuLL -- EFI_NOT_FOUND */
    return EFI_NOT_FOUND;
}


/*=============================================================================
 * Function: GetDebugProtocol (at 0x498)
 *============================================================================*/

/**
 * @brief Lazily resolves and caches the DebugLib protocol interface.
 *
 * This function implements a singleton pattern for the DebugLib protocol:
 *   - If gDebugProtocol (0xBB8) is non-NULL, returns it immediately.
 *   - Otherwise, validates the UEFI environment by performing a pool
 *     alloc (0 bytes) + free cycle.
 *     - If the returned pool buffer is at a low address (<= 0x10),
 *       the boot services are considered non-functional and we return NULL.
 *   - Calls gBS->LocateProtocol(&gDebugProtocolGuid, NULL, &gDebugProtocol).
 *   - If LocateProtocol succeeds, caches the result and returns it.
 *   - If LocateProtocol fails, sets gDebugProtocol to NULL and returns NULL.
 *
 * The pool alloc/free guard serves as a UEFI environment canary: on a real
 * UEFI, a 0-byte AllocatePool returns a valid non-NULL pointer. On broken
 * or missing boot services, it returns NULL or some small value.
 *
 * @return Pointer to DEBUG_LIB_PROTOCOL interface, or NULL if not found
 *         or environment is non-functional.
 */
VOID *
GetDebugProtocol (
    VOID
    )
{
    VOID *Buffer;
    VOID *Protocol;

    /* Check if already cached */
    if (gDebugProtocol != NULL) {
        return gDebugProtocol;
    }

    /* Environment validation: alloc & free 0 bytes */
    Buffer = gBootServices->AllocatePool (EfiBootServicesData, 0);
    gBootServices->FreePool (Buffer);

    /*
     * If Buffer is at a very low address (<= 0x10), the alloc likely failed
     * or returned a sentinel value indicating non-functional boot services.
     */
    if ((UINTN)Buffer <= 0x10) {
        return NULL;
    }

    /*
     * Locate the DebugLib protocol.
     * gBS->LocateProtocol (at offset 320 = 0x140) is the standard
     * EFI_BOOT_SERVICES.LocateProtocol function:
     *   LocateProtocol (IN EFI_GUID *ProtocolGuid, IN VOID *Registration OPTIONAL,
     *                   OUT VOID **Interface)
     *
     * 4th parameter &gDebugProtocol is the output Interface pointer.
     */
    Protocol = gBootServices->LocateProtocol (&gDebugProtocolGuid, NULL, &gDebugProtocol);
    if ((UINTN)Protocol < 0) {
        /* Error: LocateProtocol failed, clear cached value */
        gDebugProtocol = NULL;
        return gDebugProtocol;
    }

    return gDebugProtocol;
}


/*=============================================================================
 * Function: DebugPrint (at 0x518)
 *============================================================================*/

/**
 * @brief Debug output with platform-specific filtering.
 *
 * Before printing, this function reads the CMOS RTC register 0x4B (via
 * I/O ports 0x70/0x71) to determine the platform's debug verbosity level.
 *
 * CMOS 0x4B encoding:
 *   Bits 7..1: NMI status / reserved
 *   Bit  0:    Debug output enable?
 *
 * Logic:
 *   1. Read CMOS register 0x4B.
 *   2. If (level > 3) it's an invalid/uninitialized value:
 *        - If level == 0: treat as uninitialized, fall back to MMIO 0xFDAF0490
 *          to read the board config register (bit 1 = output enable?).
 *        - Otherwise: just use the raw value.
 *   3. Compute ErrorLevelFilter = (cmosLevel - 1).
 *   4. If (cmosLevel - 1) <= 0xFD (i.e., cmosLevel != 0):
 *        - Set mask = 0x80000006 (bits 1, 2, 31 set).
 *        - If cmosLevel == 1: mask = 0x80000004 (bit 2 + 31).
 *        - Actually: 0x80000006 = info+error, 0x80000004 = error-only.
 *   5. If (mask & ErrorLevel) matches, call DebugLib protocol->DebugPrint.
 *
 * @param ErrorLevel  Error level mask for filtering.
 * @param Format      Print format string.
 * @param ...         Format arguments.
 *
 * @return Non-zero if printed, 0 if filtered / no protocol.
 */
CHAR8
DebugPrint (
    IN UINTN  ErrorLevel,
    IN CHAR8  *Format,
    ...
    )
{
    DEBUG_LIB_PROTOCOL  *Protocol;
    UINT64               FilterMask;
    UINT8                CmosValue;
    UINT8                Port70Save;

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

    /*
     * Read CMOS register 0x4B from RTC.
     * __inbyte(0x70) saves current CMOS address port value first.
     */
    Port70Save = __inbyte (CMOS_ADDRESS_PORT);
    __outbyte (CMOS_ADDRESS_PORT, (Port70Save & CMOS_NMI_ENABLE_BIT) | CMOS_REG_DEBUG_LEVEL);
    CmosValue = __inbyte (CMOS_DATA_PORT);

    /*
     * Validate CMOS value: if >3, treat as invalid/uninitialized.
     * If value == 0, fall back to board config MMIO.
     */
    if (CmosValue > 3) {
        if (CmosValue == 0) {
            /*
             * Read board config register from MMIO.
             * Bit 1 of this register indicates debug output support.
             * CmosValue = (MMIO_READ(0xFDAF0490) & 2) | 1;
             */
            CmosValue = (*(volatile UINT8 *)BOARD_CONFIG_MMIO_ADDR & 2) | 1;
        }
    }

    /*
     * Compute filter mask based on CMOS level.
     */
    if ((CmosValue - 1) <= 0xFD) {
        /*
         * Default filter:
         *   0x80000006 = bit 31 (error) + bit 2 + bit 1 (info)
         */
        FilterMask = 0x80000006;
        if (CmosValue == 1) {
            /*
             * Level 1 = error-only filter:
             *   0x80000004 = bit 31 (error) + bit 2
             */
            FilterMask = 0x80000004;
        }

        /*
         * Only print if the error level has bits matching the filter mask.
         */
        if ((FilterMask & ErrorLevel) != 0) {
            /*
             * Call DebugLib protocol's DebugPrint function at offset 0.
             * This is the standard DebugLib protocol interface.
             */
            return Protocol->DebugPrint (ErrorLevel, Format, ...);
        }
    }

    return CmosValue;
}


/*=============================================================================
 * Function: DebugAssert (at 0x5A0)
 *============================================================================*/

/**
 * @brief ASSERT failure handler via DebugLib protocol.
 *
 * When an ASSERT condition fails, this function resolves the DebugLib
 * protocol via GetDebugProtocol(), then calls the DebugAssert entry
 * at protocol offset 0x08 with the source file, line number, and
 * expression text.
 *
 * If no DebugLib protocol is available, the function is a no-op
 * (but the ASSERT will eventually halt the system via the protocol's
 * own assertion handler).
 *
 * @param FileName   Source file name (NUL-terminated ASCII).
 * @param LineNumber Line number of the assertion.
 * @param Expression Assertion expression (e.g. "gST != ((void *) 0)").
 */
VOID
DebugAssert (
    IN CHAR8   *FileName,
    IN UINTN   LineNumber,
    IN CHAR8   *Expression
    )
{
    DEBUG_LIB_PROTOCOL *Protocol;

    Protocol = GetDebugProtocol ();
    if (Protocol != NULL) {
        /*
         * Call DebugAssert at protocol + 8.
         * Standard DebugAssert signature:
         *   DebugAssert(FileName, LineNumber, Expression)
         */
        Protocol->DebugAssert (FileName, LineNumber, Expression);
    }
}


/*=============================================================================
 * Function: ReadUnaligned64 (at 0x728)
 *============================================================================*/

/**
 * @brief Reads a UINT64 from potentially unaligned memory with NULL guard.
 *
 * This is a trivial dereference of a UINT64* pointer, but includes an
 * ASSERT that the input Buffer is not NULL. If NULL is passed, it triggers
 * DebugAssert with the source location in BaseLib Unaligned.c line 192.
 *
 * @param Buffer  Pointer to read from (must be non-NULL).
 *
 * @return UINT64  8-byte value read at Buffer location.
 */
UINT64
ReadUnaligned64 (
    IN VOID   *Buffer
    )
{
    if (Buffer == NULL) {
        DebugAssert (
            "e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
            192,
            "Buffer != ((void *) 0)"
            );
    }
    return *(volatile UINT64 *)Buffer;
}


/*=============================================================================
 * Function: IsHobListGuid (at 0x6B8)
 *============================================================================*/

/**
 * @brief Compares a configuration table GUID against EFI_HOB_LIST_GUID
 *        using fast 8-byte halves comparison.
 *
 * Instead of calling the full CompareGuid(), this function compares the
 * GUID in memory using two ReadUnaligned64 calls -- one for the first
 * 8 bytes (Data1 + Data2 + first 2 of Data3 in little-endian) and one
 * for the last 8 bytes (remaining Data3 + Data4).
 *
 * The comparison is:
 *   ReadUnaligned64(&gEfiHobListGuid) == ReadUnaligned64(a2) &&
 *   ReadUnaligned64(gEfiHobListGuidSecondHalf) == ReadUnaligned64(a2+8)
 *
 * @param a1  Unused context (passed from GetHobList as SystemTable entry
 *            pointer calculation context, but not used in comparison).
 * @param a2  Pointer to the 16-byte EFI_GUID in the configuration table entry.
 *
 * @return TRUE  if GUID matches EFI_HOB_LIST_GUID.
 * @return FALSE otherwise.
 */
BOOLEAN
IsHobListGuid (
    IN UINT64  a1,       ///< [unused]
    IN VOID    *a2       ///< Pointer to 16-byte GUID
    )
{
    UINT64 GuidFirstHalf;
    UINT64 GuidSecondHalf;

    /*
     * Read reference GUID from gEfiHobListGuidFirstHalf (0xB60) and
     * gEfiHobListGuidSecondHalf (0xB68). These are constants placed in
     * the .data section adjacent to gEfiHobListGuid.
     */
    UINT64 RefFirstHalf  = (UINT64)&gEfiHobListGuidFirstHalf;
    UINT64 RefSecondHalf = (UINT64)&gEfiHobListGuidSecondHalf;

    /*
     * Read candidate GUID in two 8-byte parts.
     */
    GuidFirstHalf  = ReadUnaligned64 (a2);           /* First 8 bytes */
    GuidSecondHalf = ReadUnaligned64 ((UINT8 *)a2 + 8); /* Second 8 bytes */

    /*
     * Compare both halves. If either half differs, it's not a match.
     */
    return (GuidFirstHalf  == ReadUnaligned64 ((VOID *)RefFirstHalf)) &&
           (GuidSecondHalf == ReadUnaligned64 ((VOID *)RefSecondHalf));
}


/*=============================================================================
 * Function: GetHobList (at 0x5E0)
 *============================================================================*/

/**
 * @brief Locates and caches the HOB (Hand-Off Block) list pointer from the
 *        UEFI Configuration Table.
 *
 * This function scans SystemTable->ConfigurationTable for an entry whose
 * VendorGuid matches EFI_HOB_LIST_GUID (gEfiHobListGuid). The configuration
 * table is an array of EFI_CONFIGURATION_TABLE entries:
 *
 *   typedef struct {
 *       EFI_GUID  VendorGuid;       ///< 16 bytes
 *       VOID      *VendorTable;     ///< 8 bytes
 *   } EFI_CONFIGURATION_TABLE;      ///< Total: 24 bytes (0x18)
 *
 * Located at SystemTable offset +104 (NumberOfTableEntries, UINTN) and
 * +112 (ConfigurationTable, EFI_CONFIGURATION_TABLE*).
 *
 * The function caches the matching HOB pointer in gHobList (0xBC0).
 * If no matching HOB is found:
 *   1. Fires ASSERT_EFI_ERROR (Status = EFI_NOT_FOUND) via DebugPrint.
 *   2. Asserts via DebugAssert that mHobList != NULL.
 *
 * The unused a1 parameter is the ImageHandle passed from the entry point
 * -- the function does not actually use it but it takes the slot.
 *
 * @param ImageHandle  [unused] Module image handle (on stack).
 *
 * @return VOID*  Pointer to the HOB list, or NULL on failure.
 */
VOID *
GetHobList (
    IN EFI_HANDLE  ImageHandle   ///< [unused]
    )
{
    UINTN                   Index;
    EFI_CONFIGURATION_TABLE *Entry;

    /*
     * Check if already cached.
     */
    if (gHobList != NULL) {
        return gHobList;
    }

    /*
     * Initialize cached value to NULL.
     */
    gHobList = NULL;

    /*
     * Walk the configuration table.
     * gSystemTable->ConfigurationTable is at offset 112 (0x70) from
     * the system table base, stored as a flat pointer. The number of
     * entries is at offset 104 (0x68).
     *
     * Per UEFI spec:
     *   SystemTable->NumberOfEntries     = offset 104
     *   SystemTable->ConfigurationTable  = offset 112
     */
    for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) {
        Entry = &gSystemTable->ConfigurationTable[Index];

        /*
         * Compare the GUID of this entry against EFI_HOB_LIST_GUID.
         * Use the fast inline comparison (IsHobListGuid).
         */
        if (IsHobListGuid (0, Entry)) {
            /*
             * Found a match. Extract the VendorTable pointer.
             * In EFI_CONFIGURATION_TABLE:
             *   +0x00: EFI_GUID VendorGuid (16 bytes)
             *   +0x10: VOID*    VendorTable  (8 bytes)
             * Entry is at gSystemTable->ConfigurationTable[Index]
             * as EFI_CONFIGURATION_TABLE.
             */
            gHobList = (VOID *)((UINT64)Entry->VendorTable);
            return gHobList;
        }
    }

    /*
     * HOB list not found in configuration table.
     * ASSERT_EFI_ERROR: this is a fatal condition.
     */
    DebugPrint (0x80000000LL, "\nASSERT_EFI_ERROR (Status = %r)\n", 0x800000000000000ELL);
    DebugAssert (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        54,
        "!EFI_ERROR (Status)"
        );

    /*
     * After assert failure, re-assert that mHobList != NULL.
     * This second assert will likely halt the system.
     */
    if (gHobList == NULL) {
        DebugAssert (
            "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
            55,
            "mHobList != ((void *) 0)"
            );
    }

    return gHobList;
}


/*=============================================================================
 * Function: ModuleEntryPoint (at 0x390)
 *============================================================================*/

/**
 * @brief Module entry point. Called by DXE dispatcher.
 *
 * This is the sole entry point for the DXE driver. It performs all work
 * inline without registering timer callbacks or protocol notifications.
 *
 * Execution flow:
 *   1. Save and validate ImageHandle (assert if NULL).
 *   2. Save and validate gSystemTable (gST, assert if NULL).
 *   3. Extract and save gBootServices (gBS) from gST->BootServices (assert if NULL).
 *   4. Extract and save gRuntimeServices (gRT) from gST->RuntimeServices (assert if NULL).
 *   5. Call GetHobList() to locate the HOB list from configuration table.
 *   6. Call DebugPrint with "UBA:SETUPConfigUpdate-TypeLightningRidgeEXECB2\n"
 *      to log platform identification.
 *   7. Call gBS->LocateProtocol(&gUbaBoardTypeProtocolGuid) at BootServices + 320
 *      to resolve the UBA board-type protocol.
 *   8. Call protocol->RegisterSetupConfig(v4+16) with:
 *        - Protocol handle (v4)
 *        - gUbaSetupConfigProtocolGuid (&unk_B70)
 *        - gSetupConfigData descriptor (&unk_B80)
 *        - Size 24 (sizeof UBA_SETUP_CONFIG_DATA)
 *
 * @param ImageHandle  Module's image handle (must be non-NULL).
 * @param SystemTable  Pointer to UEFI system table (must be non-NULL).
 *
 * @return EFI_SUCCESS      Setup config registered.
 * @return EFI_NOT_FOUND    UBA protocol not found.
 * @return EFI_STATUS       Error from LocateProtocol or RegisterSetupConfig.
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
    IN EFI_HANDLE        ImageHandle,
    IN EFI_SYSTEM_TABLE  *SystemTable
    )
{
    EFI_STATUS              Status;
    UBA_BOARD_TYPE_PROTOCOL *UbaProtocol;
    UINT64                  ZeroContext;
    UINT64                  *ProtocolPtr;

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

    /*
     * Step 2: Validate and save SystemTable.
     */
    gSystemTable = SystemTable;
    if (SystemTable == NULL) {
        DebugAssert (
            "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
            57,
            "gST != ((void *) 0)"
            );
    }

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

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

    /*
     * Step 5: Locate HOB list.
     */
    GetHobList (ImageHandle);

    /*
     * Step 6: Log platform identification via debug print.
     * Error level = 0x80000000 (high bit set = EFI_D_ERROR).
     */
    DebugPrint (
        0x80000000LL,
        "UBA:SETUPConfigUpdate-TypeLightningRidgeEXECB2\n"
        );

    /*
     * Step 7: Locate the UBA board-type protocol.
     * gBS->LocateProtocol is at BootServices entry 320/8 = 40
     * (40th function in EFI_BOOT_SERVICES -- LocateProtocol).
     *
     * This resolves gUbaBoardTypeProtocolGuid (0xB40) to get the
     * protocol interface that contains RegisterSetupConfig.
     *
     * LocateProtocol signature:
     *   LocateProtocol (
     *       IN  EFI_GUID  *ProtocolGuid,
     *       IN  VOID      *Registration OPTIONAL,
     *       OUT VOID      **Interface
     *       )
     */
    ZeroContext = 0;
    ProtocolPtr = &ZeroContext;
    Status = gBootServices->LocateProtocol (
        &gUbaBoardTypeProtocolGuid,
        NULL,
        &ProtocolPtr
        );

    /*
     * Step 8: If protocol resolved successfully, call RegisterSetupConfig.
     * (v4 + 16) is the RegisterSetupConfig function pointer.
     *
     * RegisterSetupConfig signature:
     *   RegisterSetupConfig (
     *       IN     VOID   *ProtocolInstance,
     *       IN     VOID   *ProtocolGuid,   // &gUbaSetupConfigProtocolGuid
     *       IN     VOID   *SetupConfigData, // &gSetupConfigData
     *       IN     UINTN  Size              // 24 = sizeof(UBA_SETUP_CONFIG_DATA)
     *       )
     */
    if (Status == EFI_SUCCESS) {
        UbaProtocol = (UBA_BOARD_TYPE_PROTOCOL *)ProtocolPtr;
        /*
         * Cast to function pointer at protocol offset 0x10.
         * The RegisterSetupConfig function receives:
         *   a1 = ProtocolPtr (protocol instance)
         *   a2 = &gUbaSetupConfigProtocolGuid
         *   a3 = &gSetupConfigData (UBA_SETUP_CONFIG_DATA)
         *   a4 = 24 (size of config data descriptor)
         */
        return ((EFI_STATUS (*)(VOID *, VOID *, VOID *, UINTN))
                UbaProtocol->RegisterSetupConfig) (
            ProtocolPtr,
            &gUbaSetupConfigProtocolGuid,
            &gSetupConfigData,
            24
            );
    }

    return Status;
}


/*=============================================================================
 * Placeholder / Weak Functions
 *============================================================================*/

/**
 * @brief Stub function for WritesSetupConfig.
 *
 * This function is not called in the code path of this module.
 * It is provided for source compatibility.
 */
EFI_STATUS
WriteSetupConfig (
    IN EFI_HANDLE  a1
    )
{
    return EFI_UNSUPPORTED;
}


/*=============================================================================
 * End of file SetupConfigUpdateDxeLightningRidgeEXECB2.c
 *============================================================================*/