/**
* @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;
}