/** @file
SetupConfigUpdateDxeLightningRidgeEXECB4 — UBA Slot Data Update DXE driver.
This DXE driver is part of the UBA (Universal BIOS Architecture) slot
configuration framework. It installs slot data update configuration
protocols for the LightningRidge EX EC B4 platform, allowing the
system firmware to apply platform-specific slot configuration data
during the boot process.
The driver performs the following operations:
* Initializes the UEFI Boot/Runtime Services table pointers.
* Locates the HOB (Hand-Off Block) list from the system table.
* Registers the UBA slot data update configuration for LightningRidge
EX EC B4 via the UBA configuration protocol.
Copyright (c) 2025, Insyde Software Corp. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include "SetupConfigUpdateDxeLightningRidgeEXECB4.h"
//
// Globals for UEFI boot/runtime services.
//
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gST = NULL;
EFI_BOOT_SERVICES *gBS = NULL;
EFI_RUNTIME_SERVICES *gRT = NULL;
//
// HOB list pointer, cached for use by HOB library functions.
//
VOID *mHobList = NULL;
//
// UBA protocol interface pointer, obtained via LocateProtocol.
//
VOID *gUbaProtocolInterface = NULL;
//
// UBA debug print routing function pointer; obtained via
// LocateProtocol using the UBA debug protocol GUID.
//
UBA_DEBUG_PRINT gUbaDebugPrint = NULL;
//
// GUID definitions
//
EFI_GUID gUbaSlotDataUpdateConfigProtocolGuid =
UBA_SLOT_DATA_UPDATE_CONFIG_PROTOCOL_GUID;
EFI_GUID gUbaSlotDataUpdateProtocolGuid =
UBA_SLOT_DATA_UPDATE_PROTOCOL_GUID_EXECB4;
EFI_GUID gUbaSlotDataUpdateConfigTableGuid =
UBA_SLOT_DATA_UPDATE_CONFIG_TABLE_GUID;
EFI_GUID gUbaSlotDataGuid =
UBA_SLOT_DATA_GUID_EXECB4;
EFI_GUID gUbaDebugProtocolGuid =
UBA_DEBUG_PROTOCOL_GUID;
//
// Slot data update configuration table data.
//
// This structure is published via the UBA protocol to describe the
// slot data update configuration for the LightningRidge EX EC B4
// platform.
//
UBA_SLOT_DATA_UPDATE_CONFIG mSlotDataUpdateConfig = {
.Revision = 1,
.Reserved = { 0, 0, 0 },
.SlotDataConfig = (VOID *)(UINTN)0xBB0,
.SlotDataConfigSize = sizeof (UBA_SLOT_DATA_UPDATE_CONFIG),
.SlotDataUpdateTable = NULL,
.SlotDataUpdateTableSize = 0,
};
//
// Slot data payload descriptor GUID table
//
// Each entry in this table describes a slot data payload by GUID and
// size, which is consumed by the UBA framework to map platform-specific
// slot data.
//
typedef struct {
EFI_GUID Guid;
UINT32 DataSize;
} SLOT_DATA_PAYLOAD_DESCRIPTOR;
SLOT_DATA_PAYLOAD_DESCRIPTOR mSlotDataPayloads[] = {
{ UBA_SLOT_DATA_UPDATE_CONFIG_TABLE_GUID, 32 },
{ UBA_SLOT_DATA_GUID_EXECB4, 40 },
};
//
// Forward declarations.
//
EFI_STATUS
EFIAPI
SetupConfigUpdateDxeLightningRidgeEXECB4EntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
/**
Resolves the HOB list pointer from the system table configuration table.
Iterates through the system table's configuration tables to locate the
HOB list. The HOB list is published by the PEI phase and consumed by
DXE drivers via the HOB Library.
@retval Pointer to the start of the HOB list.
**/
VOID *
EFIAPI
GetHobList (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
EFI_CONFIGURATION_TABLE *ConfigTable;
VOID *HobList;
//
// Return cached HOB list if already resolved.
//
if (mHobList != NULL) {
return mHobList;
}
HobList = NULL;
ConfigTable = gST->ConfigurationTable;
if (gST->NumberOfTableEntries > 0) {
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (&ConfigTable[Index].VendorGuid, &gUbaSlotDataUpdateProtocolGuid)) {
HobList = ConfigTable[Index].VendorTable;
mHobList = HobList;
break;
}
}
}
//
// ASSERT if no HOB list entry was found matching the expected GUID.
//
if (HobList == NULL) {
DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
ASSERT_EFI_ERROR (Status);
ASSERT (mHobList != NULL);
}
return HobList;
}
/**
Locates and caches the UBA protocol interface pointer.
Uses the UBA protocol GUID to locate the protocol interface via
UEFI Boot Services. On success, stores the interface in the
module-global gUbaProtocolInterface variable for subsequent use
by the UBA library functions.
@retval Pointer to the UBA protocol interface, or NULL if not found.
**/
VOID *
EFIAPI
LocateUbaProtocol (
VOID
)
{
EFI_STATUS Status;
if (gUbaProtocolInterface != NULL) {
return gUbaProtocolInterface;
}
Status = gBS->LocateProtocol (
&gUbaSlotDataUpdateConfigProtocolGuid,
NULL,
&gUbaProtocolInterface
);
if (EFI_ERROR (Status)) {
gUbaProtocolInterface = NULL;
}
return gUbaProtocolInterface;
}
/**
UBA debug print hook.
Routes debug output through the UBA debug protocol if available.
Falls back to a no-op if the protocol is not installed.
@param[in] ErrorLevel Debug error level mask.
@param[in] Format Format string.
@param[in] ... Variable arguments for format string.
**/
VOID
EFIAPI
UbaDebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
VA_LIST Marker;
UBA_DEBUG_PRINT DebugPrint;
DebugPrint = LocateUbaDebugProtocol ();
if (DebugPrint == NULL) {
return;
}
VA_START (Marker, Format);
DebugPrint (ErrorLevel, Format, &Marker);
VA_END (Marker);
}
/**
Locates the UBA debug print function via protocol lookup.
@retval Pointer to the UBA debug print function, or NULL.
**/
UBA_DEBUG_PRINT
EFIAPI
LocateUbaDebugProtocol (
VOID
)
{
EFI_STATUS Status;
if (gUbaDebugPrint != NULL) {
return gUbaDebugPrint;
}
Status = gBS->LocateProtocol (
&gUbaDebugProtocolGuid,
NULL,
(VOID **)&gUbaDebugPrint
);
if (EFI_ERROR (Status)) {
gUbaDebugPrint = NULL;
}
return gUbaDebugPrint;
}
/**
Checks whether a HOB entry matches the expected platform GUID.
Compares two GUIDs: the platform HOB GUID and the GUID at the
supplied address in the HOB list. Used to locate the correct
HOB entry for the LightningRidge EX EC B4 platform.
@param[in] PlatformHobGuid Pointer to the platform HOB GUID.
@param[in] CandidateHobEntry Pointer to a candidate HOB entry GUID.
@retval TRUE The GUIDs match.
@retval FALSE The GUIDs do not match.
**/
BOOLEAN
EFIAPI
IsPlatformHob (
IN CONST EFI_GUID *PlatformHobGuid,
IN CONST VOID *CandidateHobEntry
)
{
EFI_GUID *CandidateGuid;
EFI_GUID *PlatformGuid;
EFI_GUID *SubGuid1;
EFI_GUID *SubGuid2;
//
// Read unaligned GUID values from the HOB entries.
//
CandidateGuid = (EFI_GUID *)ReadUnaligned64 ((UINT64 *)CandidateHobEntry);
PlatformGuid = (EFI_GUID *)ReadUnaligned64 ((UINT64 *)PlatformHobGuid);
if (CandidateGuid == NULL || PlatformGuid == NULL) {
DEBUG ((DEBUG_ERROR, "Buffer != ((void *) 0)\n"));
ASSERT (CandidateGuid != NULL);
ASSERT (PlatformGuid != NULL);
return FALSE;
}
SubGuid1 = (EFI_GUID *)ReadUnaligned64 ((UINT64 *)((UINT8 *)CandidateHobEntry + 8));
SubGuid2 = (EFI_GUID *)ReadUnaligned64 ((UINT64 *)((UINT8 *)PlatformHobGuid + 8));
return CompareGuid (CandidateGuid, PlatformGuid) &&
CompareGuid (SubGuid1, SubGuid2);
}
/**
Reads a 64-bit value from a potentially unaligned address.
Wrapper around the BaseLib ReadUnaligned64 function with ASSERT
protection.
@param[in] Buffer Pointer to the unaligned buffer.
@return The 64-bit value read from the buffer.
**/
UINT64
EFIAPI
ReadUnaligned64OrAssert (
IN CONST UINT64 *Buffer
)
{
if (Buffer == NULL) {
DEBUG ((DEBUG_ERROR, "Buffer != ((void *) 0)\n"));
ASSERT (Buffer != NULL);
}
return ReadUnaligned64 (Buffer);
}
/**
Platform-specific debug assertion handler.
If the UBA debug protocol is available, routes the assertion
failure message through it; otherwise discards the message.
@param[in] FileName Source file name where the assertion occurred.
@param[in] LineNumber Line number of the assertion.
@param[in] Description Assertion description string.
**/
VOID
EFIAPI
UbaAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
UBA_DEBUG_PRINT DebugPrint;
DebugPrint = LocateUbaDebugProtocol ();
if (DebugPrint != NULL) {
DebugPrint (
DEBUG_ERROR,
"%a(%d): %a\n",
(VA_LIST)&FileName
);
}
}
//
// Slot data update payload configuration
//
// The following table defines the GUID and size of each slot data
// payload that this driver registers with the UBA protocol.
//
// Payload 1: UBA Slot Data Update Config Table — 32 bytes
// Payload 2: UBA Slot Data GUID EXECB4 — 40 bytes
//
// These payloads are installed into the UBA configuration database
// during the entry point execution.
//
/**
Entry point for the SetupConfigUpdateDxeLightningRidgeEXECB4 driver.
This function is the module entry point called by the UEFI core
after the image is loaded. It performs the following initialization:
1. Caches ImageHandle, SystemTable, BootServices, and RuntimeServices.
2. Resolves the HOB list from the system configuration table.
3. Locates the UBA protocol interface.
4. Installs the slot data update configuration into the UBA protocol
database, publishing two payload entries:
- UBA Slot Data Update Config Table (32 bytes)
- UBA Slot Data GUID EXECB4 (40 bytes)
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The driver initialized successfully.
@retval EFI_INVALID_PARAMETER ImageHandle or SystemTable was NULL.
@retval EFI_NOT_FOUND Required protocol or HOB data was not found.
@retval Other Error from protocol installation.
**/
EFI_STATUS
EFIAPI
SetupConfigUpdateDxeLightningRidgeEXECB4EntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN Index;
UINTN PayloadCount;
UBA_SLOT_DATA_UPDATE_CONFIG *ConfigData;
UBA_PROTOCOL_INTERFACE *UbaProtocol;
//
// Step 1: Initialize UEFI service table pointers.
//
gImageHandle = ImageHandle;
ASSERT (gImageHandle != NULL);
gST = SystemTable;
ASSERT (gST != NULL);
gBS = SystemTable->BootServices;
ASSERT (gBS != NULL);
gRT = SystemTable->RuntimeServices;
ASSERT (gRT != NULL);
//
// Step 2: Resolve the HOB list. Required by the HOB library for
// subsequent HOB traversal.
//
GetHobList ();
//
// Step 3: Log the slot data update registration event.
//
UbaDebugPrint (
DEBUG_INFO,
"UBA:SlotDataUpdate-TypeLightningRidgeEXECB4\n"
);
//
// Step 4: Locate the UBA protocol interface.
//
Status = gBS->LocateProtocol (
&gUbaSlotDataUpdateConfigProtocolGuid,
NULL,
(VOID **)&UbaProtocol
);
if (!EFI_ERROR (Status)) {
//
// Step 5: Install slot data update payloads into the UBA database.
//
PayloadCount = sizeof (mSlotDataPayloads) / sizeof (mSlotDataPayloads[0]);
for (Index = 0; Index < PayloadCount; Index++) {
Status = UbaProtocol->SetData (
UbaProtocol,
&mSlotDataPayloads[Index].Guid,
&mSlotDataUpdateConfig,
mSlotDataPayloads[Index].DataSize
);
}
}
return Status;
}