/** @file
UsbOcUpdateDxeNeonCityEPECB -- USB Overcurrent Update for NeonCity EPECB Platform
This UBA (Universal Board Architecture) DXE driver configures the USB
Overcurrent (OC) mapping for the NeonCity EPECB platform on Purley
(Grantley/PurleyRefresh) systems with Lewisburg (LBG) or CDF PCH.
The driver:
- Initializes UEFI boot/runtime services and DXE services table
- Locates the MM PCI Base protocol for PCH configuration space access
- Determines the PCH stepping (via LPC device VID/DID registers)
- Selects the appropriate USB OC pin mapping table based on stepping
- Registers the configuration with the platform via the UBA protocol
Build path:
PurleyRpPkg/Uba/UbaMain/Dxe/TypeNeonCityEPECB/UsbOcUpdateDxe
@copyright
Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
Auto-generated from IDB: UsbOcUpdateDxeNeonCityEPECB.efi.i64
SHA256: eecd2d931ef1798c5947768c5c98e7d92c02381dd21c4bbf48ce73b416be2462
**/
#include "UsbOcUpdateDxeNeonCityEPECB.h"
//
// ---------------------------------------------------------------------------
// Global variable declarations
// ---------------------------------------------------------------------------
//
#pragma pack(push, 1)
//
// MM PCI Base Protocol interface (used for PCH register access)
//
typedef struct {
UINT64 Signature;
//
// Function 0: Called to perform MM PCI read/write operations.
// Uses an INPUT/OUTPUT parameter block with:
// [0]: 0x00F80000 (PCIEXBAR base register address)
// [1]: 0 (reserved)
// [2]: 512 (register offset within config space)
// [3]: 0 (value)
//
UINT64 (*MmPciBaseOp)(UINT32 Param[6]);
} MM_PCI_BASE_PROTOCOL;
//
// UBA Protocol Entry Point structure
//
typedef struct {
//
// Function pointer table for platform-specific UBA operations.
// Typically indexed by offset to dispatch board-specific actions.
//
UINT64 (*Dispatch[4])(VOID);
} UBA_PROTOCOL;
#pragma pack(pop)
//
// Global data -- mapped from .data segment
//
//
// Driver global binding handles
//
#pragma section(".data")
//
// gImageHandle - stored copy of the EFI image handle (at 0x14B8)
//
STATIC EFI_HANDLE mImageHandle;
//
// gST - stored copy of the EFI System Table pointer (at 0x14A8)
//
STATIC EFI_SYSTEM_TABLE *mSystemTable;
//
// gBS - stored copy of the Boot Services table pointer (at 0x14B0)
//
STATIC EFI_BOOT_SERVICES *mBootServices;
//
// gRT - stored copy of the Runtime Services table pointer (at 0x14C0)
//
STATIC EFI_RUNTIME_SERVICES *mRuntimeServices;
//
// gDS - Dxe Services Table pointer (at 0x14D0)
//
STATIC VOID *mDxeServicesTable;
//
// mPciUsra - MM PCI Base Protocol pointer (at 0x14D8)
//
STATIC MM_PCI_BASE_PROTOCOL *mMmPciBase;
//
// Protocol cache: UEFI Debug Protocol (at 0x14C8)
//
STATIC VOID *mDebugProtocol;
//
// mHobList - HOB list pointer (at 0x14E0)
//
STATIC VOID *mHobList;
//
// mPcd - PCD Protocol pointer (at 0x14F0)
//
STATIC VOID *mPcd;
//
// PCH stepping cache (at 0x14A0)
//
STATIC UINTN mPchStepping = PCH_STEP_UNSUPPORTED;
//
// PCH stepping override / board type (from CMOS or SMBIOS) (at 0x14F8)
//
STATIC UINT8 mPchSteppingBoardType;
//
// UBA Protocol function table (queried during entry point)
// Stored at 0x14E8
//
STATIC UBA_PROTOCOL *mUbaProtocol;
//
// ---------------------------------------------------------------------------
// Forward declarations
// ---------------------------------------------------------------------------
//
/**
Locates and caches the UEFI DebugPort protocol.
Uses BootServices::LocateProtocol to find the UEFI DebugPort protocol
(GUID at unk_1340). Also checks the CMOS/RTC to determine the debug
log level mask.
@return Pointer to the DebugPort protocol, or NULL if not found
or if the UEFI memory map is too large ( > 0x10 entries).
**/
STATIC
VOID *
GetDebugProtocol (
VOID
);
/**
Debug print wrapper that conditionally prints based on log level.
Checks the current debug level (derived from CMOS register 0x4B)
and only prints if the requested level @p ErrorLevel matches the
current board configuration.
@param[in] ErrorLevel DEBUG_ERROR (0x80000000) or DEBUG_INFO (0x00000040)
@param[in] Format Format string for the debug message.
@param[in] ... Variable arguments for the format string.
@retval TRUE Message was printed.
@retval FALSE Message was suppressed or no DebugPort protocol available.
**/
STATIC
BOOLEAN
DebugPrintWorker (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
);
/**
ASSERT wrapper that reports an assertion failure via DebugPort.
@param[in] FileName Source file name of the assertion.
@param[in] LineNumber Line number of the assertion.
@param[in] Description Assertion description string.
**/
STATIC
VOID
AssertWorker (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
);
/**
Locates a configuration table in the System Table by GUID.
Iterates through the System Table's configuration table array
and returns the first table whose GUID matches.
@param[in] TableGuid Pointer to the GUID to match.
@param[out] Table Receives a pointer to the located table.
@retval EFI_SUCCESS The table was found.
@retval EFI_NOT_FOUND No matching table was found.
**/
STATIC
EFI_STATUS
EfiGetConfigTable (
IN EFI_GUID *TableGuid,
OUT VOID **Table
);
/**
Reads a 16-bit value from a UEFI configuration table using the GUID
at @p a1. Checks the pointer alignment before dereferencing.
@param[in] Buffer Pointer to the buffer to read from.
@return The 64-bit value at the buffer address.
**/
STATIC
UINT64
ReadUnaligned64 (
IN CONST VOID *Buffer
);
/**
Compares two GUIDs by checking their Data1 and Data2 fields
via alignment-safe reads.
@param[in] Guid1 Pointer to the first GUID.
@param[in] Guid2 Pointer to the second GUID.
@retval TRUE The GUIDs are equal.
@retval FALSE The GUIDs are not equal.
**/
STATIC
BOOLEAN
CompareGuid (
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
);
/**
Reads a 16-bit value from a memory-mapped IO port (unaligned safe).
@param[in] Address The address to read from (must be 16-bit aligned).
@return The 16-bit value at the address.
**/
STATIC
UINT16
MmioRead16 (
IN UINT16 *Address
);
/**
Gets the PCH Vendor ID / Device ID from the LPC bridge configuration
space via MM PCI.
Reads the LPC bridge device at Bus 0, Device 31, Function 0 and
returns the combined Vendor ID and Device ID register.
@return The PCI VID/DID register value (at offset 0x00).
**/
STATIC
UINT16
PchGetLpcDid (
VOID
);
/**
Gets the PCH stepping type from the combined VID/DID.
Maps the PCI Device ID of the LPC bridge to an internal stepping
enumeration used for USB OC table selection.
@return PCH stepping identifier (PCH_STEP_* constants).
**/
STATIC
UINTN
PchGetStepping (
VOID
);
//
// ---------------------------------------------------------------------------
// Debug Protocol GUID
// ---------------------------------------------------------------------------
//
EFI_GUID gEfiDebugPortProtocolGuid = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } };
//
// ---------------------------------------------------------------------------
// USB OC configuration data structures (referenced via UBA protocol)
// ---------------------------------------------------------------------------
//
//
// USB Overcurrent pin mapping table for NeonCity EPECB (A-step variant).
// Maps each USB port to its OC pin number. Index 0..47.
// (Referenced as unk_13B0 in the IDB)
//
USB_OC_UPDATE_CONFIG mUsbOcUpdateA = {
{
0, // Port 0 -> OC Pin 0
0, // Port 1 -> OC Pin 0
1, // Port 2 -> OC Pin 1
1, // Port 3 -> OC Pin 1
2, // Port 4 -> OC Pin 2
2, // Port 5 -> OC Pin 2
3, // Port 6 -> OC Pin 3
3, // Port 7 -> OC Pin 3
4, // Port 8 -> OC Pin 4
4, // Port 9 -> OC Pin 4
5, // Port 10 -> OC Pin 5
5, // Port 11 -> OC Pin 5
6, // Port 12 -> OC Pin 6
6, // Port 13 -> OC Pin 6
7, // Port 14 -> OC Pin 7
7, // Port 15 -> OC Pin 7
}
};
//
// USB Overcurrent pin mapping table for NeonCity EPECB (B-step variant).
// (Referenced as unk_1420 in the IDB)
//
USB_OC_UPDATE_CONFIG mUsbOcUpdateB = {
{
0, // Port 0 -> OC Pin 0
0, // Port 1 -> OC Pin 0
1, // Port 2 -> OC Pin 1
1, // Port 3 -> OC Pin 1
2, // Port 4 -> OC Pin 2
2, // Port 5 -> OC Pin 2
3, // Port 6 -> OC Pin 3
3, // Port 7 -> OC Pin 3
4, // Port 8 -> OC Pin 4
4, // Port 9 -> OC Pin 4
5, // Port 10 -> OC Pin 5
5, // Port 11 -> OC Pin 5
6, // Port 12 -> OC Pin 6
6, // Port 13 -> OC Pin 6
7, // Port 14 -> OC Pin 7
7, // Port 15 -> OC Pin 7
}
};
//
// USB OC update protocol dispatch table.
// (Referenced as unk_13F8 and unk_1460 in the IDB)
//
UINT64 mUsbOcUpdateDispatch[] = {
//
// Dispatch function 0: UsbOcGetSteppingMapping
// Returns the appropriate USB OC config table for the detected PCH stepping.
// Based on sub_5C8's logic.
//
(UINT64)UsbOcGetSteppingMapping,
//
// Dispatch function 1: (reserved)
//
(UINT64)0,
//
// Dispatch function 2: (reserved)
//
(UINT64)0,
//
// Dispatch function 3: (reserved)
//
(UINT64)0,
};
//
// UBA protocol instance for USB OC update.
//
UBA_PROTOCOL mUbaUsbOcInstance = {
{ (UINT64)UsbOcGetSteppingMapping }
};
//
// ---------------------------------------------------------------------------
// Helper function implementations
// ---------------------------------------------------------------------------
//
/**
Reads a 16-bit value from a pointer with unaligned-safe access.
Implements an MMIO read of a 16-bit value. If the address alignment
check fails (odd address), an assertion is triggered via the ASSERT
framework.
@param[in] Address A pointer to the 16-bit value to read.
Must be aligned to a 2-byte boundary.
@return The 16-bit value at the given address.
**/
STATIC
UINT16
MmioRead16 (
IN UINT16 *Address
)
{
ASSERT ((UINTN)Address % 2 == 0);
return *Address;
}
/**
Reads a 64-bit value from an unaligned buffer.
@param[in] Buffer Pointer to the buffer to read from (may be unaligned).
@return The 64-bit value read from the buffer.
**/
STATIC
UINT64
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
ASSERT (Buffer != NULL);
return *(UINT64 *)Buffer;
}
/**
Compares two GUID structures by their Data1 and Data2 fields.
Uses ReadUnaligned64 to safely read the first two QWORDs from each
GUID and compares them. This avoids alignment issues on platforms
where GUID structures may not be naturally aligned.
@param[in] Guid1 Pointer to the first GUID.
@param[in] Guid2 Pointer to the second GUID.
@return TRUE if both GUIDs are identical, FALSE otherwise.
**/
STATIC
BOOLEAN
CompareGuid (
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
)
{
UINT64 Data1;
UINT64 Data2;
//
// Read the GUID data in a single comparison-friendly way.
// GUID layout: Data1 (4 bytes) + Data2 (2 bytes) + Data3 (2 bytes) + Data4 (8 bytes)
// We compare the first 8 bytes and the remaining bytes.
//
Data1 = ReadUnaligned64 (Guid1);
Data2 = ReadUnaligned64 (Guid2);
return Data1 == Data2;
}
/**
Locates a configuration table in the System Table by matching its GUID.
Iterates through the configuration table array indexed from the EFI
System Table. The number of entries is stored at SystemTable + 104
(NumberOfTableEntries), and the table array is at SystemTable + 112
(ConfigurationTable).
@param[in] TableGuid Pointer to the GUID to search for.
@param[out] Table Receives a pointer to the matching configuration table.
@retval EFI_SUCCESS The table was found and returned in @p Table.
@retval EFI_NOT_FOUND No configuration table with the given GUID exists.
**/
STATIC
EFI_STATUS
EfiGetConfigTable (
IN EFI_GUID *TableGuid,
OUT VOID **Table
)
{
EFI_STATUS Status;
UINTN Index;
EFI_CONFIGURATION_TABLE *ConfigTable;
UINTN TableEntryCount;
ASSERT (TableGuid != NULL);
ASSERT (Table != NULL);
*Table = NULL;
Status = EFI_NOT_FOUND;
TableEntryCount = mSystemTable->NumberOfTableEntries;
ConfigTable = mSystemTable->ConfigurationTable;
if (TableEntryCount == 0) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < TableEntryCount; Index++) {
if (CompareGuid (TableGuid, ConfigTable[Index].VendorGuid)) {
*Table = ConfigTable[Index].VendorTable;
Status = EFI_SUCCESS;
break;
}
}
return Status;
}
/**
Locates and caches the DebugPort protocol.
Uses LocateProtocol through the Boot Services table to find the
DebugPort protocol (using gEfiDebugPortProtocolGuid). The result
is cached in a static variable for subsequent calls.
Checks the UEFI memory map descriptor count - if more than 16
descriptors are present, the protocol lookup is skipped.
@return Pointer to the DebugPort protocol instance.
NULL if not available.
**/
STATIC
VOID *
GetDebugProtocol (
VOID
)
{
VOID *Protocol;
UINTN MemoryMapSize;
UINTN MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
Protocol = mDebugProtocol;
if (Protocol == NULL) {
//
// Probe the UEFI memory map size as a sanity check.
// GetMemoryMap will return the required buffer size.
//
MemoryMapSize = 0;
mBootServices->GetMemoryMap (
&MemoryMapSize,
NULL,
&MapKey,
&DescriptorSize,
&DescriptorVersion
);
//
// Only attempt to locate the protocol if the memory map is small
// (<= 0x10 descriptors). This is a heuristic used by DebugLib.
//
if (MemoryMapSize / DescriptorSize <= 0x10) {
//
// Locate the DebugPort protocol
//
if (EFI_ERROR (mBootServices->LocateProtocol (
&gEfiDebugPortProtocolGuid,
NULL,
&Protocol
))) {
Protocol = NULL;
}
}
mDebugProtocol = Protocol;
}
return Protocol;
}
/**
Debug print with CMOS-based log level filtering.
Reads the board type / log level from CMOS register 0x4B and
filteres messages based on the requested ErrorLevel.
Also supports a fallback to memory-mapped I/O at 0xFDAF0490 for
platforms where CMOS returns 0.
@param[in] ErrorLevel The debug message error level.
@param[in] Format The format string.
@param[in] ... Variable arguments.
@return Whether the message was printed.
**/
STATIC
BOOLEAN
DebugPrintWorker (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
BOOLEAN Printed;
VA_LIST VaList;
DEBUG_PRINT_PROTOCOL *DebugPrintProtocol;
UINT8 BoardType;
Printed = FALSE;
DebugPrintProtocol = (DEBUG_PRINT_PROTOCOL *)GetDebugProtocol ();
if (DebugPrintProtocol != NULL) {
//
// Read board type / debug level from CMOS RTC register 0x4B.
// Bit 7 is the NMI disable bit, bits 6:0 indicate board type.
//
BoardType = IoRead8 (0x70);
IoWrite8 (0x70, (BoardType & 0x80) | 0x4B);
BoardType = IoRead8 (0x71);
//
// If board type > 3, and it is zero, fall back to MMIO read.
//
if (BoardType > 3) {
if (BoardType == 0) {
BoardType = (MmioRead8 (0xFDAF0490) & 2) | 1;
}
}
//
// Map BoardType to an EFI debug mask:
// BoardType 1 -> EFI_DAGENT_ERROR (bit 30 = 0x40000004)
// BoardType 2+ -> EFI_DAGENT_WARN (bit 31 = 0x80000006)
// BoardType 0 -> reserved
//
if (BoardType >= 1 && BoardType <= 0xFE) {
if (BoardType == 1) {
mPchSteppingBoardType = 4;
} else {
mPchSteppingBoardType = 4;
}
}
//
// Determine the log level mask for this board type
//
if (mPchSteppingBoardType & 2) {
//
// Use a mask based on actual board type:
// Type 1 boards: 0x40000004, others: 0x80000006
//
if ((mPchSteppingBoardType == 1) ? (ErrorLevel & 0x40000004) : (ErrorLevel & 0x80000006)) {
VA_START (VaList, Format);
DebugPrintProtocol->DebugPrint (ErrorLevel, Format, VaList);
VA_END (VaList);
Printed = TRUE;
}
}
}
return Printed;
}
/**
Report an assertion failure via DebugPort.
Translates an assertion into a formatted message sent through the
DebugPort protocol.
@param[in] FileName The source file name.
@param[in] LineNumber The line number of the assertion.
@param[in] Description The assertion description.
**/
STATIC
VOID
AssertWorker (
IN CONST CHAR8 *File,
IN UINTN Line,
IN CONST CHAR8 *Description
)
{
DEBUG_PRINT_PROTOCOL *DebugPrintProtocol;
DebugPrintProtocol = (DEBUG_PRINT_PROTOCOL *)GetDebugProtocol ();
if (DebugPrintProtocol != NULL) {
DebugPrintProtocol->DebugAssert (File, Line, Description);
}
}
// ---------------------------------------------------------------------------
// Debug macro expansion wrappers
// ---------------------------------------------------------------------------
#define DEBUG_PRINT(Level, ...) DebugPrintWorker (Level, __VA_ARGS__)
#define ASSERT_REPORT(File, Line, Desc) AssertWorker (File, Line, Desc)
// ---------------------------------------------------------------------------
// PCH Stepping Detection
// ---------------------------------------------------------------------------
/**
Performs an MM PCI configuration space read of the LPC bridge
Vendor ID / Device ID register.
Uses the MM PCI Base protocol to access the LPC bridge (Bus 0,
Device 31, Function 0, Register 0). The protocol requires a
parameter block:
param[0] = 0x00F80000 (PCIEXBAR address region)
param[1] = 0
param[2] = 512 (register offset 0x00 in config space)
param[3] = 0
@return The PCI VID/DID register value (upper 16 bits = DID, lower = VID).
**/
UINT16
PchGetLpcDid (
VOID
)
{
UINT32 Param[6];
Param[0] = 0x00F80000; // PCIEXBAR base region
Param[1] = 0;
Param[2] = 512; // Config space offset 0x00
Param[3] = 0;
if (mMmPciBase != NULL) {
return (UINT16)mMmPciBase->MmPciBaseOp (Param);
}
return 0;
}
/**
Determines the PCH stepping from the LPC device DID.
Maps the LPC bridge Device ID to the internal stepping enumeration:
DID 0xA14C -> PCH LBG A0 stepping (ID 0)
DID 0xA14D -> PCH LBG A1 stepping (ID 1)
DID 0xA150 -> PCH LBG B0 stepping (ID 2)
DID >= 0xA151 -> Unsupported
DID <= 0xA13F -> CDF PCH range (checked further)
For devices with DID between specific ranges:
DID 0xA14C, 0xA14D, 0xA150 are the main steppings
Additional USB OC pin assignment steppings for B-step:
PCH stepping 16+17 -> OC mapping 35, 36 (B0, B1 2-port OC variant)
PCH stepping 32+33 -> OC mapping 37, 38 (B0, B1 4-port OC variant)
PCH stepping 48-53 -> CDF steppings (A0-B3)
@return PCH stepping identifier as a UINTN.
**/
UINTN
PchGetStepping (
VOID
)
{
UINTN Stepping;
UINT16 LpcDid;
VOID *PchInfo;
UINT8 PchRevision;
Stepping = mPchStepping;
if (Stepping != PCH_STEP_UNSUPPORTED) {
return Stepping;
}
//
// Read the PCH info from board-specific data
//
PchInfo = PchGetLpcDid (); // Actually gets the PCH info struct
PchRevision = ((UINT8 *)PchInfo)[8]; // Stepping byte from PCH info
//
// Determine stepping based on Device ID
//
LpcDid = *((UINT16 *)PchInfo + 1); // Device ID from LPC DID register
if (LpcDid == 0xA14C) {
//
// Lewisburg PCH A0 stepping
//
switch (PchRevision) {
case 0x00:
Stepping = PCH_STEP_LBG_A0; // 0
break;
case 0x10:
Stepping = PCH_STEP_LBG_A1; // 1
break;
default:
Stepping = PCH_STEP_LBG_B0; // 2 (default)
break;
}
} else if (LpcDid < 0xA140) {
//
// CDF PCH family (DID <= 0xA13F)
// Further classified by PCH stepping revision:
// rev == 0 -> 48 (CDF A0)
// rev == 2 -> 49 (CDF A1)
// rev == 3 -> 50 (CDF B0)
// rev == 4 -> 51 (CDF B1)
// rev == 8 -> 52 (CDF B2)
// rev == 9 -> 53 (CDF B3)
//
if (PchRevision <= 48 && (LpcDid + 24128) & 0xFF80) {
Stepping = PCH_STEP_UNSUPPORTED;
} else {
//
// Check board type and PCH rev to determine exact stepping
//
if (PchRevision == 4) {
if (PchRevision < 2) {
Stepping = PCH_STEP_CDF_A0; // 48
} else {
Stepping = PCH_STEP_CDF_A1; // 49
}
} else if (PchRevision == 8) {
Stepping = PCH_STEP_CDF_B0; // 50
} else if (PchRevision == 9) {
Stepping = PCH_STEP_CDF_B1; // 51
} else if (PchRevision == 16) {
Stepping = PCH_STEP_CDF_B2; // 52
} else if (PchRevision == 17) {
Stepping = PCH_STEP_CDF_B3; // 53
} else {
Stepping = PCH_STEP_UNSUPPORTED;
}
}
} else {
//
// DID >= 0xA151 -> Unsupported
//
Stepping = PCH_STEP_UNSUPPORTED;
}
mPchStepping = Stepping;
return Stepping;
}
/**
Returns the USB OC pin mapping table appropriate for the current
PCH stepping.
Called as a dispatch function through the UBA protocol. Selects
the correct USB OC configuration data table based on the detected
PCH stepping.
@param[out] ConfigA Receives a pointer to the A-table dispatch
(or NULL if not applicable).
@param[out] ConfigB Receives a pointer to the B-table dispatch
(or NULL if not applicable).
@param[out] SteppingData Receives a pointer to the stepping-specific
USB OC config data table.
@retval EFI_SUCCESS The correct table was selected.
**/
EFI_STATUS
UsbOcGetSteppingMapping (
OUT VOID **ConfigA,
OUT VOID **ConfigB,
OUT VOID **SteppingData
)
{
UINTN Stepping;
*ConfigA = &mUbaUsbOcInstance;
*ConfigB = &mUsbOcUpdateDispatch;
Stepping = PchGetStepping ();
if (Stepping <= 48) {
*SteppingData = &mUsbOcUpdateA;
} else {
*SteppingData = &mUsbOcUpdateB;
}
return EFI_SUCCESS;
}
// ---------------------------------------------------------------------------
// Library constructor-style initializers
// ---------------------------------------------------------------------------
/**
Process Library Constructor for UefiBootServicesTableLib.
Sets up the global ImageHandle, SystemTable, BootServices, and
RuntimeServices pointers from the entry point parameters.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
**/
STATIC
VOID
ProcessLibraryConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Save global image handle
//
mImageHandle = ImageHandle;
ASSERT (ImageHandle != NULL);
//
// Save system table
//
mSystemTable = SystemTable;
ASSERT (SystemTable != NULL);
//
// Save boot services pointer
//
mBootServices = SystemTable->BootServices;
ASSERT (mBootServices != NULL);
//
// Save runtime services pointer
//
mRuntimeServices = SystemTable->RuntimeServices;
ASSERT (mRuntimeServices != NULL);
}
/**
Process Library Constructor for DxeServicesTableLib.
Uses EfiGetConfigTable to locate the DXE Services Table by GUID
and caches the pointer in mDxeServicesTable.
**/
STATIC
VOID
ProcessDxeServicesTableConstructor (
VOID
)
{
EFI_GUID gEfiDxeServicesTableGuid = DXE_SERVICES_TABLE_GUID;
EFI_STATUS Status;
Status = EfiGetConfigTable (&gEfiDxeServicesTableGuid, &mDxeServicesTable);
if (EFI_ERROR (Status)) {
DEBUG_PRINT (DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT_REPORT (
__FILE__,
__LINE__,
"!EFI_ERROR (Status)"
);
}
ASSERT (mDxeServicesTable != NULL);
}
/**
Process Library Constructor for DxeMmPciBaseLib.
Locates the MM PCI Base Protocol via LocateProtocol and caches
the pointer in mMmPciBase.
**/
STATIC
VOID
ProcessMmPciBaseConstructor (
VOID
)
{
EFI_GUID gEfiMmPciBaseProtocolGuid = MM_PCI_BASE_PROTOCOL_GUID;
EFI_STATUS Status;
if (mMmPciBase == NULL) {
Status = mBootServices->LocateProtocol (
&gEfiMmPciBaseProtocolGuid,
NULL,
(VOID **)&mMmPciBase
);
if (EFI_ERROR (Status)) {
DEBUG_PRINT (DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT_REPORT (
__FILE__,
__LINE__,
"!EFI_ERROR (Status)"
);
}
ASSERT (mMmPciBase != NULL);
}
}
/**
Process Library Constructor for DxeHobLib.
Locates the HOB List via EfiGetConfigTable and caches the pointer.
**/
STATIC
VOID
ProcessHobLibConstructor (
VOID
)
{
EFI_GUID gEfiHobListGuid = HOB_LIST_GUID;
EFI_STATUS Status;
if (mHobList == NULL) {
Status = EfiGetConfigTable (&gEfiHobListGuid, &mHobList);
if (EFI_ERROR (Status)) {
DEBUG_PRINT (DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT_REPORT (
__FILE__,
__LINE__,
"!EFI_ERROR (Status)"
);
}
ASSERT (mHobList != NULL);
}
}
/**
Process Library Constructor for DxePcdLib.
Locates the PCD protocol via LocateProtocol and caches the pointer.
**/
STATIC
VOID
ProcessPcdLibConstructor (
VOID
)
{
EFI_GUID gEfiPcdProtocolGuid = PCD_PROTOCOL_GUID;
EFI_STATUS Status;
if (mPcd == NULL) {
Status = mBootServices->LocateProtocol (
&gEfiPcdProtocolGuid,
NULL,
(VOID **)&mPcd
);
if (EFI_ERROR (Status)) {
DEBUG_PRINT (DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
ASSERT_REPORT (
__FILE__,
__LINE__,
"!EFI_ERROR (Status)"
);
}
ASSERT (mPcd != NULL);
}
}
// ---------------------------------------------------------------------------
// Entry Point
// ---------------------------------------------------------------------------
/**
Driver entry point for UsbOcUpdateDxeNeonCityEPECB.
Initializes the UEFI library constructors, registers the debug trace,
locates the UBA protocol, and installs the USB OC configuration via
the UBA protocol's board-specific dispatch mechanism.
@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 USB OC configuration was installed.
@retval EFI_PROTOCOL_ERROR The UBA protocol could not be located.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
**/
EFI_STATUS
EFIAPI
UsbOcUpdateInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_GUID gUsbOcProtocolGuid = USB_OC_UPDATE_PROTOCOL_GUID;
UBA_PROTOCOL *UbaProtocolInterface;
EFI_STATUS Status;
//
// Initialize library constructors (sets up global service pointers)
//
ProcessLibraryConstructor (ImageHandle, SystemTable);
ProcessDxeServicesTableConstructor ();
ProcessMmPciBaseConstructor ();
ProcessHobLibConstructor ();
ProcessPcdLibConstructor ();
//
// Log the board type trace
//
DEBUG_PRINT (DEBUG_INFO, "UBA:UsbOcUpdate-TypeNeonCityEPECB\n");
//
// Locate the UBA protocol
//
Status = mBootServices->LocateProtocol (
&gUsbOcProtocolGuid,
NULL,
(VOID **)&UbaProtocolInterface
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Install the USB OC configuration by calling the UBA protocol's
// board-specific entry point (offset 16 in the protocol interface).
// The entry point receives the USB OC config data tables.
//
return ((EFI_STATUS (EFIAPI *)(VOID *, VOID *, UINTN))(
UbaProtocolInterface->Dispatch[0])) (
&mUbaUsbOcInstance,
&mUsbOcUpdateDispatch,
16
);
}