/** @file
UsbOcUpdateDxeLightningRidgeEXECB3 -- USB Overcurrent Mapping Driver
This DXE driver implements USB Overcurrent (OC) mapping configuration for
the LightningRidge EX EC B3 platform. It registers OC mapping data with
the UBA (Universal BIOS Architecture) configuration database protocol.
The OC mapping tables describe how physical USB ports on the platform are
associated with overcurrent protection channels. The data is consumed by
the platform USB controller driver during initialization to properly
configure OC detection hardware.
The driver performs the following during initialization:
1. Initializes UEFI Boot Services and Runtime Services table pointers
2. Retrieves the UBA platform HOB for board type validation
3. Locates the UBA Configuration Database protocol
4. Registers the USB OC configuration data for this platform
Reconstructed from binary analysis of the original UEFI driver.
Source: UsbOcUpdateDxeLightningRidgeEXECB3.efi (SHA256: b440ac1d8dfa...)
Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UsbOcUpdateDxeLightningRidgeEXECB3.h"
//
// Global UEFI table pointers (filled in by entry point)
//
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gSystemTable = NULL;
EFI_BOOT_SERVICES *gBootServices = NULL;
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;
//
// Cached HOB list pointer
//
VOID *gHobList = NULL;
//
// Cached UBA Configuration Database protocol pointer
//
UBA_CONFIG_DATABASE_PROTOCOL *gUbaConfigDb = NULL;
//
// UBA configuration database protocol GUID
//
EFI_GUID mUbaConfigDatabaseProtocolGuid = USB_OC_UBA_PROTOCOL_GUID;
//
// Parameter GUID for USB OC configuration
//
EFI_GUID mUsbOcConfigGuid = USB_OC_PARAM_GUID;
//
// HOB GUID for locating UBA platform data
//
EFI_GUID mUbaPlatformHobGuid = USB_OC_HOB_GUID;
///
/// PUSB table metadata
///
#define PUSB_TABLE_SIZE 0x48C
///
/// Combined UBA OC configuration data structure containing all mapping tables.
///
UBA_OC_CONFIG_DATA mUsbOcConfigData = {
//
// USB port numbers -- logical index to physical port number mapping.
// 0 = unused/unavailable port slot.
//
.PortNumber = { 0, 1, 1, 2, 3, 3, 8, 8, 8, 8, 0, 0 },
//
// OC channel index per physical port.
// 8 = no overcurrent channel (port not physically connected or no OC).
//
.OcIndex = { 0, 1, 8, 8, 8, 2, 1, 2, 8, 8, 8, 4, 8, 4 },
//
// PUSB table header
//
.PusbSignature = PUSB_TABLE_SIGNATURE,
.PusbVersion = PUSB_TABLE_VERSION_EXECB3,
.PusbSize = PUSB_TABLE_SIZE,
//
// OC data mapping entries.
// All entries identical: 0x01020007 encodes channel and attribute info.
//
.OcData = {
USB_OC_DATA_ENTRY,
USB_OC_DATA_ENTRY,
USB_OC_DATA_ENTRY,
USB_OC_DATA_ENTRY,
},
};
/**
Reads a 64-bit unaligned value from memory.
@param[in] Buffer Pointer to the memory location to read from.
@return The 64-bit value read from the given address.
**/
UINT64
EFIAPI
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
ASSERT (Buffer != NULL);
//
// Read the 64-bit value as two 32-bit halves to handle unaligned access.
// The UEFI specification guarantees this is safe.
//
return *(CONST UINT64 *)Buffer;
}
/**
Checks whether a HOB entry matches the UBA platform GUID.
@param[in] HobGuid Pointer to the GUID to compare against the UBA platform GUID.
@retval TRUE The GUIDs match (this is a UBA platform HOB).
@retval FALSE The GUIDs do not match.
**/
BOOLEAN
IsUbaPlatformHob (
IN CONST EFI_GUID *HobGuid
)
{
UINT64 GuidFirstHalf;
UINT64 GuidSecondHalf;
//
// Compare the GUID as two 64-bit halves for efficiency.
//
GuidFirstHalf = ReadUnaligned64 (HobGuid);
GuidSecondHalf = ReadUnaligned64 ((UINT8 *)HobGuid + 8);
return (GuidFirstHalf == ReadUnaligned64 (&mUbaPlatformHobGuid)) &&
(GuidSecondHalf == ReadUnaligned64 ((UINT8 *)&mUbaPlatformHobGuid + 8));
}
/**
Retrieves the UBA platform HOB data pointer.
Walks the system HOB list to find the UBA platform configuration HOB
with the matching GUID, and caches the data pointer for later reuse.
@return Pointer to the UBA platform HOB data, or NULL if not found.
**/
VOID *
GetUbaPlatformHob (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
//
// Check for cached HOB list pointer
//
if (gHobList != NULL) {
return gHobList;
}
//
// Find the first GUID HOB that matches the UBA platform GUID.
//
GuidHob = GetFirstGuidHob (&mUbaPlatformHobGuid);
if (GuidHob != NULL && IsUbaPlatformHob (&GuidHob->Name)) {
//
// Cache and return pointer to the HOB data portion (immediately after the GUID)
//
gHobList = (VOID *)(GuidHob + 1);
return gHobList;
}
//
// UBA platform HOB not found -- error condition
//
DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
ASSERT (!EFI_ERROR (EFI_NOT_FOUND));
return NULL;
}
/**
Locates the UBA Configuration Database protocol.
Uses the UEFI Boot Services LocateProtocol to find the UBA Config DB
protocol, used for registering platform-specific configuration data.
@return Pointer to the UBA_CONFIG_DATABASE_PROTOCOL interface,
or NULL if the protocol was not found.
**/
UBA_CONFIG_DATABASE_PROTOCOL *
GetUbaConfigDb (
VOID
)
{
EFI_STATUS Status;
//
// Return cached pointer if already resolved
//
if (gUbaConfigDb != NULL) {
return gUbaConfigDb;
}
//
// Locate the UBA Configuration Database protocol
//
Status = gBootServices->LocateProtocol (
&mUbaConfigDatabaseProtocolGuid,
NULL,
(VOID **)&gUbaConfigDb
);
if (EFI_ERROR (Status)) {
gUbaConfigDb = NULL;
}
return gUbaConfigDb;
}
/**
Returns three pointers used by the UBA callback to access platform
configuration data:
- Board ID / platform type identifier
- USB port-to-OC index mapping table
- Combined USB OC configuration data
@param[out] BoardId Pointer to receive the board/platform ID.
@param[out] PortMapping Pointer to receive the USB port mapping table.
@param[out] OcConfig Pointer to receive the USB OC configuration data.
@retval EFI_SUCCESS The pointers were successfully returned.
**/
EFI_STATUS
GetUsbOcConfigPointers (
OUT UINT32 **BoardId,
OUT UINT32 **PortMapping,
OUT UBA_OC_CONFIG_DATA **OcConfig
)
{
*BoardId = mUsbPortNumber; // Board type identification via port topology
*PortMapping = mUsbOcIndex; // Port-to-OC index mapping table
*OcConfig = &mUsbOcConfigData; // Combined OC config including PUSB header
return EFI_SUCCESS;
}
/**
Registers the USB OC configuration data with the UBA Configuration
Database protocol.
@param[in] UbaConfigDb Pointer to the UBA_CONFIG_DATABASE_PROTOCOL.
@retval EFI_SUCCESS The OC data was registered successfully.
@retval Others The registration failed.
**/
EFI_STATUS
RegisterUsbOcData (
IN UBA_CONFIG_DATABASE_PROTOCOL *UbaConfigDb
)
{
EFI_STATUS Status;
//
// Register the OC configuration data with the UBA protocol.
// The protocol call uses:
// - &mUsbOcConfigGuid : Parameter GUID identifying the OC data
// - &mUsbOcConfigData : The OC configuration data structure
// - sizeof (UINT32) * USB_OC_ENTRY_COUNT : Size of OC data portion
//
Status = UbaConfigDb->SetData (
UbaConfigDb,
&mUsbOcConfigGuid,
&mUsbOcConfigData,
sizeof (UINT32) * USB_OC_ENTRY_COUNT
);
return Status;
}
/**
Entry point for USB OC Update DXE driver.
Initializes global UEFI table pointers, validates the UBA platform,
and registers USB OC mapping configuration with the UBA database.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@return EFI_SUCCESS The driver initialized successfully.
@return EFI_UNSUPPORTED The UBA config database was not found.
@return EFI_INVALID_PARAMETER ImageHandle or SystemTable was NULL.
@return Others An error occurred during initialization.
**/
EFI_STATUS
EFIAPI
UsbOcUpdateEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UBA_CONFIG_DATABASE_PROTOCOL *UbaConfigDb;
//
// Validate parameters
//
if (ImageHandle == NULL) {
DEBUG ((EFI_D_ERROR, "gImageHandle != ((void *) 0)\n"));
ASSERT (ImageHandle != NULL);
return EFI_INVALID_PARAMETER;
}
if (SystemTable == NULL) {
DEBUG ((EFI_D_ERROR, "gST != ((void *) 0)\n"));
ASSERT (SystemTable != NULL);
return EFI_INVALID_PARAMETER;
}
//
// Initialize global table pointers
//
gImageHandle = ImageHandle;
gSystemTable = SystemTable;
gBootServices = SystemTable->BootServices;
gRuntimeServices = SystemTable->RuntimeServices;
if (gBootServices == NULL) {
DEBUG ((EFI_D_ERROR, "gBS != ((void *) 0)\n"));
ASSERT (gBootServices != NULL);
return EFI_INVALID_PARAMETER;
}
if (gRuntimeServices == NULL) {
DEBUG ((EFI_D_ERROR, "gRT != ((void *) 0)\n"));
ASSERT (gRuntimeServices != NULL);
return EFI_INVALID_PARAMETER;
}
//
// Initialize HOB subsystem
//
GetUbaPlatformHob ();
//
// Log the UBA configuration being applied
//
DEBUG ((EFI_D_INFO, "UBA:UsbOcUpdate-TypeLightningRidgeEXECB3\n"));
//
// Locate the UBA Configuration Database protocol
//
UbaConfigDb = GetUbaConfigDb ();
if (UbaConfigDb == NULL) {
DEBUG ((EFI_D_ERROR, "Failed to locate UBA Config Database protocol\n"));
return EFI_UNSUPPORTED;
}
//
// Register the USB OC mapping configuration
//
Status = RegisterUsbOcData (UbaConfigDb);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Failed to register USB OC config: %r\n", Status));
return Status;
}
DEBUG ((EFI_D_INFO, "USB OC configuration registered successfully for LightningRidge EX EC B3\n"));
return EFI_SUCCESS;
}