/** @file
OpromUpdateDxeCLX64L - UEFI Driver for Option ROM Update Policy on CLX64L Platform
This module implements platform-specific Option ROM (OpROM) update policy
for the CLX64L (Cascade Lake Xeon 64L) server platform using the UBA
(Universal BIOS Architecture) framework.
The driver provides:
1. PCIe slot number assignment - maps physical BDF to logical slot numbers
for CLX64L-specific slot topology.
2. Bus scan limits - restricts PCI bus enumeration ranges per device,
ensuring correct resource allocation on the CLX64L platform.
3. ACPI support integration - registers with ACPI support protocol via UBA.
Functional Overview:
- ModuleEntryPoint initializes UEFI boot/runtime services globals and the
HOB (Hand-Off Block) list, then installs the UBA OpromUpdate protocol
configuration for the CLX64L platform.
- SetPcieSlotNumber() checks a given bus/device/function against the
CLX64L slot mapping table and validates a caller-supplied value against
the slot's valid range.
- GetBusScanLimit/GetBusScanLimit2 return platform-specific tables of
PCI devices whose bus scan range should be limited.
- SetPcieSlotCallback() is invoked when a slot number update occurs,
logging the event via UBA debug output.
Build Dependencies:
- MdePkg
- UefiBootServicesTableLib
- UefiRuntimeServicesTableLib
- DxeHobLib
- BaseLib
Copyright (C) 2025 Insyde Software Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "OpromUpdateDxeCLX64L.h"
//
// ---------------------------------------------------------------------------
// Global data
// ---------------------------------------------------------------------------
//
EFI_HANDLE gImageHandle = NULL;
EFI_SYSTEM_TABLE *gSystemTable = NULL;
EFI_BOOT_SERVICES *gBootServices = NULL;
EFI_RUNTIME_SERVICES *gRuntimeServices = NULL;
VOID *mHobList = NULL;
//
// GUIDs used by this driver:
// gEfiPciRootBridgeIoProtocolGuid - protocol for PCI root bridge I/O
// gEfiHobListGuid - HOB list identifier
// gEfiVariableArchProtocolGuid - variable architecture protocol
// gEfiAcpiSupportProtocolGuid - ACPI support protocol
//
// These are referenced via the UBA configuration tables below.
//
EFI_GUID gEfiPciRootBridgeIoProtocolGuid = {0x2F707EBB, 0x4A1A, 0x11D4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}};
EFI_GUID gEfiHobListGuid = {0x36232936, 0x0E76, 0x31C8, {0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32}};
EFI_GUID gEfiVariableArchProtocolGuid = {0xE03E0D46, 0x5263, 0x4845, {0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2}};
EFI_GUID gEfiAcpiSupportProtocolGuid = {0x7739F24C, 0x93D7, 0x11D4, {0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}};
//
// ---------------------------------------------------------------------------
// Bus Scan Limit Tables
//
// These tables define the PCIe devices on the CLX64L platform whose secondary
// bus range is constrained for PCI enumeration. Each entry identifies a device
// by Segment/Bus/Device/Function and VendorId/DeviceId, and specifies the
// allowed primary and secondary bus limits.
// ---------------------------------------------------------------------------
//
//
// Table 1: Primary bus scan limits (6 entries).
// Covers on-board PCIe devices for CLX64L.
//
UBA_OPROM_BUS_SCAN_LIMIT_ENTRY mBusScanLimitTable[] = {
//
// Entry 0: 8086:1528 (Intel I350 PCIe Controller) at Bus 1, Dev 2, Func 0
// Rev 0x02, BaseClass 0x02 (Network Controller)
// Bus scan range: primary up to 0x2D, secondary up to 0x2C
// Slot 0x01, BDF range [0, 0xFF] x [0x2E, 0x2F]
//
{ 0x0001, 0x00000001, 0x00000000, 0x00000002, 0x8086, 0x1528, 0x02, 0x00, 0x00, 0x02,
0x00000001, 0x2D, 0x2C, 0x00000001, 0x00000001, 0x00, 0x2E, 0xFFFF },
//
// Entry 1: 8086:1521 (Intel I350 PCIe Controller) at Bus 1, Dev 1, Func 0
// Rev 0x02, BaseClass 0x02 (Network Controller)
// Bus scan range: primary up to 0x2D, secondary up to 0x2C
// Slot 0x01, BDF range [0, 0xFF] x [0x2E, 0x2F]
//
{ 0x0001, 0x00010000, 0x00000000, 0x00000001, 0x8086, 0x1521, 0x02, 0x01, 0x00, 0x02,
0x00000001, 0x2D, 0x2C, 0x00000001, 0x00000001, 0x00, 0x2E, 0xFFFF },
//
// Entry 2: 8086:10FB (Intel X550/X557 10GbE Controller) at wildcard BDF
// Rev 0x02, BaseClass 0x02 (Network Controller)
// Broad wildcard bus range
//
{ 0x0002, 0x00000000, 0x00000000, 0x00000002, 0x8086, 0x10FB, 0x02, 0x05, 0xFFFFFFFF, 0x02,
0xFFFFFFFF, 0xFF, 0xFF, 0xFFFFFFFF, 0x00000002, 0x00, 0x2E, 0xFFFF },
//
// Entry 3: 8086:1521 at Dev 4, Func 4 (second instance)
// Bus scan range: primary up to 0x2D, secondary up to 0x2C
// Slot 0x04, BDF range [0, 0xFF] x [0x2E, 0x2F]
//
{ 0x0002, 0x00000000, 0x00000000, 0x00000004, 0x8086, 0x1521, 0x04, 0x04, 0xFFFFFFFF, 0x02,
0xFFFFFFFF, 0xFF, 0xFF, 0xFFFFFFFF, 0x00000002, 0x00, 0x2E, 0xFFFF },
//
// Entry 4: 8086:1528 at Dev 2, Func 9 (third instance)
// Bus scan range wildcard
//
{ 0x0002, 0x00000000, 0x00000000, 0x00000002, 0x8086, 0x1528, 0x02, 0x09, 0xFFFFFFFF, 0x02,
0xFFFFFFFF, 0xFF, 0xFF, 0xFFFFFFFF, 0x00000002, 0x00, 0x2E, 0xFFFF },
//
// Entry 5: Additional device at Bus 2, Dev 16, Func 3
// Vendor 0x15B3 (Mellanox), Device 0x1003
// BaseClass 0x02 (Network Controller)
// Bus scan range: secondary up to 0x06
//
{ 0x0001, 0x00010000, 0x00000000, 0x00000002, 0x15B3, 0x1003, 0x03, 0x10, 0x01, 0x02,
0x00000006, 0xFF, 0xFF, 0xFFFFFFFF, 0x00000001, 0x00, 0x2E, 0xFFFF },
};
UINT32 mBusScanLimitTableCount = sizeof (mBusScanLimitTable) / sizeof (mBusScanLimitTable[0]);
//
// Table 2: Secondary bus scan limits (not populated for CLX64L).
//
UBA_OPROM_BUS_SCAN_LIMIT_ENTRY mBusScanLimitTable2[10] = { 0 };
UINT32 mBusScanLimitTable2Count = 10;
//
// ---------------------------------------------------------------------------
// PCIe Slot Mapping Table (CLX64L)
//
// Maps physical PCIe Root Port (Bus/Device/Function) to logical slot numbers.
// 8 entries correspond to the 8 PCIe root ports on the CLX64L platform.
// ---------------------------------------------------------------------------
//
// NOTE: These entries are indexed by slot bit position. Entry[i] defines the
// BDF for slot bit i. The slot number in byte 3 is 0 for all entries since
// slot numbering is derived from the bit position (not an explicit number).
//
UBA_OPROM_SLOT_MAPPING mSlotMappingTable[] = {
{ 0x00, 0x03, 0x00, 0x00 }, // Slot 0: Bus 0, Dev 3, Func 0
{ 0x00, 0x01, 0x80, 0x00 }, // Slot 1: Bus 80h, Dev 1, Func 0 (PCH)
{ 0x00, 0x02, 0x80, 0x00 }, // Slot 2: Bus 80h, Dev 2, Func 0 (PCH)
{ 0x02, 0x03, 0x80, 0x00 }, // Slot 3: Bus 80h, Dev 3, Func 2 (PCH)
{ 0x00, 0x02, 0x00, 0x00 }, // Slot 4: Bus 0, Dev 2, Func 0
{ 0x00, 0x01, 0x00, 0x00 }, // Slot 5: Bus 0, Dev 1, Func 0
{ 0x05, 0x1C, 0x00, 0x00 }, // Slot 6: Bus 0, Dev 1Ch, Func 5
{ 0x00, 0x03, 0x80, 0x00 }, // Slot 7: Bus 80h, Dev 3, Func 0 (PCH)
};
UINT32 mSlotMappingTableCount = sizeof (mSlotMappingTable) / sizeof (mSlotMappingTable[0]);
//
// UBA protocol instance. Registered with the UBA framework during
/// ModuleEntryPoint to provide CLX64L-specific OpROM update callbacks.
//
UBA_OPROM_UPDATE_PROTOCOL mUbaOpromUpdateProtocol = {
SetPcieSlotNumber,
(EFI_GUID **)GetPcieSlotNumber,
(VOID *)mBusScanLimitTable,
(VOID *)mBusScanLimitTable2,
SetPcieSlotCallback,
0
};
//
// ---------------------------------------------------------------------------
// UBA Debug Print
//
// Writes a debug message through the UBA protocol's debug channel.
//
// @param[in] DebugLevel Debug level mask (typically 0x80000000 for UBA).
// @param[in] Format Print format string.
// @param[in] ... Variable arguments for format string.
// ---------------------------------------------------------------------------
//
VOID
UbaDebugPrint (
IN UINT64 DebugLevel,
IN CHAR8 *Format,
...
)
{
VA_LIST Marker;
UBA_OPROM_UPDATE_PROTOCOL *Protocol;
UINT64 CmosValue;
UINT8 PlatformType;
Protocol = GetUbaProtocol ();
if (Protocol == NULL) {
return;
}
//
// Read CMOS register 0x70 to check platform type
// CMOS 0x4B bit 7 = reserved, bits [1:0] = platform type
// Type 0 = unknown, Type 1 = CLX platform, Type 2-3 = other
//
CmosValue = IoRead8 (0x70);
IoWrite8 (0x70, (CmosValue & 0x80) | 0x4B);
PlatformType = IoRead8 (0x71);
if (PlatformType > 3) {
if (PlatformType == 0) {
PlatformType = (MmioRead8 (0xFDAF0490) & 2) | 1;
}
}
if ((PlatformType - 1) <= 0xFD) {
//
// Platform type is valid (not -1/0xFF)
//
if (DebugLevel & 0x80000000) {
if (PlatformType == 1) {
//
// CLX platform: write through debug function
//
VA_START (Marker, Format);
// Output through registered UBA debug function (offset 0 in protocol)
Protocol->SetPcieSlotCallback ((UINT8)DebugLevel);
VA_END (Marker);
}
}
}
}
//
// ---------------------------------------------------------------------------
// SetPcieSlotNumber
//
// Determines whether a given Bus/Device/Function is within the valid slot
// range for the specified slot bitmask on CLX64L.
//
// For each slot bit set in SlotMask, this function retrieves the PCI root
// bridge protocol, reads the bridge's bus number range (via
// SetAttributes with PCI attributes 0x19 and 0x1A), and checks whether
// BusDeviceFunction falls within that range.
//
// @param[in] BusDeviceFunction Encoded bus/device/function value to check.
// @param[in] SlotMask Bitmask of PCIe slots to check.
//
// @retval TRUE BusDeviceFunction is valid for one of the enabled slots.
// @retval FALSE BusDeviceFunction is not valid for any enabled slot.
//
// ---------------------------------------------------------------------------
//
BOOLEAN
EFIAPI
SetPcieSlotNumber (
IN UINT64 BusDeviceFunction,
IN UINT32 SlotMask
)
{
UINT32 Index;
UINT8 *SlotEntry;
EFI_STATUS Status;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo;
UINT64 RootBridgeHandle;
UINT8 MinBus;
UINT8 MaxBus;
BOOLEAN InRange;
InRange = FALSE;
SlotEntry = (UINT8 *)&mSlotMappingTable;
DEBUG_CODE_BEGIN ();
for (Index = 0; Index < mSlotMappingTableCount; Index++) {
if ((SlotMask & (1 << Index)) == 0) {
//
// This slot is not enabled in the bitmask; skip it.
//
SlotEntry += sizeof (UBA_OPROM_SLOT_MAPPING);
continue;
}
//
// Locate the PCI Root Bridge I/O protocol for this root port.
//
Status = gBootServices->LocateProtocol (
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID **)&RootBridgeHandle
);
if (EFI_ERROR (Status)) {
SlotEntry += sizeof (UBA_OPROM_SLOT_MAPPING);
continue;
}
RootBridgeIo = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *)RootBridgeHandle;
//
// Build the PCI address from slot mapping entry:
// SlotEntry[-1] = Function
// SlotEntry[0] = Device
// SlotEntry[1] = Bus
// These are packed into the "DeviceFunction" field used
// for PCI root bridge operations.
//
{
UINT8 Function;
UINT8 Device;
UINT8 Bus;
Function = SlotEntry[-1];
Device = SlotEntry[0];
Bus = SlotEntry[1];
//
// Get bus number range for this root port.
// Attribute 0x19 = Get primary bus number
// Attribute 0x1A = Get secondary bus number (subordinate)
//
RootBridgeIo->SetAttributes (
RootBridgeIo,
0,
((Bus << 16) | (Device << 11) | (Function << 8)) | 0x19,
1,
&MinBus
);
RootBridgeIo->SetAttributes (
RootBridgeIo,
0,
((Bus << 16) | (Device << 11) | (Function << 8)) | 0x1A,
1,
&MaxBus
);
if (BusDeviceFunction >= MinBus) {
InRange = (BOOLEAN)(BusDeviceFunction <= MaxBus);
}
}
SlotEntry += sizeof (UBA_OPROM_SLOT_MAPPING);
}
DEBUG_CODE_END ();
return InRange;
}
//
// ---------------------------------------------------------------------------
// GetPcieSlotNumber
//
// Returns a pointer to gEfiAcpiSupportProtocolGuid, which identifies the
// ACPI support protocol used for slot number querying.
//
// @param[out] Guid Pointer to receive the protocol GUID.
//
// @retval EFI_SUCCESS
//
// ---------------------------------------------------------------------------
//
UINTN
EFIAPI
GetPcieSlotNumber (
IN EFI_GUID **Guid
)
{
*Guid = &gEfiAcpiSupportProtocolGuid;
return 0;
}
//
// ---------------------------------------------------------------------------
// GetBusScanLimit
//
// Returns the primary bus scan limit table for CLX64L.
// The table defines which PCIe devices on this platform have restricted
// bus ranges for enumeration.
//
// @param[out] Table Pointer to the bus scan limit entry table.
// @param[out] Count Number of entries in the table.
//
// @retval EFI_SUCCESS
//
// ---------------------------------------------------------------------------
//
UINTN
EFIAPI
GetBusScanLimit (
IN VOID **Table,
IN UINT32 *Count
)
{
*Table = mBusScanLimitTable;
*Count = mBusScanLimitTableCount;
return 0;
}
//
// ---------------------------------------------------------------------------
// GetBusScanLimit2
//
// Returns the secondary bus scan limit table for CLX64L.
// This table is reserved and currently contains zero-initialized entries.
//
// @param[out] Table Pointer to the bus scan limit entry table.
// @param[out] Count Number of entries in the table.
//
// @retval EFI_SUCCESS
//
// ---------------------------------------------------------------------------
//
UINTN
EFIAPI
GetBusScanLimit2 (
IN VOID **Table,
IN UINT32 *Count
)
{
*Table = mBusScanLimitTable2;
*Count = mBusScanLimitTable2Count;
return 0;
}
//
// ---------------------------------------------------------------------------
// SetPcieSlotCallback
//
// Called when a PCIe slot number assignment callback occurs.
// This function sets the slot value to 2 and logs the event.
//
// @param[in] SlotNumber The slot number being assigned.
//
// @retval EFI_SUCCESS
//
// ---------------------------------------------------------------------------
//
EFI_STATUS
EFIAPI
SetPcieSlotCallback (
IN UINT8 SlotNumber
)
{
*((volatile UINT8 *)SlotNumber) = 2;
UbaDebugPrint (UBA_DEBUG_LEVEL, "[UBA]:SetPcieSlotNumber callback - %d\n");
return 0;
}
//
// ---------------------------------------------------------------------------
// GetUbaProtocol
//
// Retrieves the UBA protocol instance. On first call, searches the HOB list
// for the gEfiVariableArchProtocolGuid HOB and records the HOB data pointer.
//
// @return Pointer to the UBA protocol structure, or NULL if not found.
//
// ---------------------------------------------------------------------------
//
EFI_HANDLE
GetUbaProtocol (
VOID
)
{
EFI_HANDLE Handle;
if (mHobList != NULL) {
return (EFI_HANDLE)mHobList;
}
//
// Search the HOB list for the Variable Arch protocol HOB.
// The HOB list is obtained from SystemTable->HobList.
//
Handle = NULL;
mHobList = NULL;
if (gSystemTable != NULL && gSystemTable->NumberOfTableEntries > 0) {
UINTN Index;
UINTN *HobList;
HobList = (UINTN *)gSystemTable->ConfigurationTable;
for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) {
if (CompareGuid (
(EFI_GUID *)HobList,
&gEfiVariableArchProtocolGuid
)) {
Handle = (EFI_HANDLE)((UINT8 *)HobList + sizeof (EFI_GUID));
mHobList = (VOID *)Handle;
break;
}
HobList += 3; // ConfigurationTable entries are 24 bytes each
}
if (Handle == NULL) {
DEBUG ((DEBUG_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_INVALID_PARAMETER));
ASSERT_EFI_ERROR (FALSE);
}
}
if (mHobList == NULL) {
ASSERT (mHobList != NULL);
}
return (EFI_HANDLE)mHobList;
}
//
// ---------------------------------------------------------------------------
// ReadUnaligned64
//
// Reads a 64-bit value from an unaligned address, with NULL pointer assertion.
//
// @param[in] Buffer Pointer to the unaligned 64-bit value.
//
// @return The 64-bit value at Buffer.
//
// ---------------------------------------------------------------------------
//
UINT64
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
if (Buffer == NULL) {
ASSERT (Buffer != NULL);
}
return *(const UINT64 *)Buffer;
}
//
// ---------------------------------------------------------------------------
// IsGuidMatch
//
// Compares two GUID values as a pair of 64-bit quantities.
//
// @param[in] Guid1 First GUID to compare.
// @param[in] Guid2 Second GUID to compare.
//
// @retval TRUE GUIDs are equal.
// @retval FALSE GUIDs are not equal.
//
// ---------------------------------------------------------------------------
//
BOOLEAN
IsGuidMatch (
IN CONST EFI_GUID *Guid1,
IN CONST EFI_GUID *Guid2
)
{
return (BOOLEAN)(
ReadUnaligned64 (Guid1) == ReadUnaligned64 (Guid2) &&
ReadUnaligned64 ((UINT8 *)Guid1 + 8) == ReadUnaligned64 ((UINT8 *)Guid2 + 8)
);
}
//
// ---------------------------------------------------------------------------
// GetHobList
//
// Retrieves the HOB (Hand-Off Block) list pointer by searching the system
// configuration table for the gEfiHobListGuid entry.
//
// On first call, scans the configuration table, validates the retrieved HOB
// pointer, and caches it in the module global mHobList.
//
// @return Pointer to the HOB list, or NULL if not found.
//
// ---------------------------------------------------------------------------
//
VOID *
GetHobList (
VOID
)
{
EFI_STATUS Status;
VOID *HobList;
UINT64 EfiMemoryBase;
UINTN HobLength;
if (mHobList != NULL) {
return mHobList;
}
//
// The HOB list physical address is stored in the first configuration table
// entry if the table reports at least 16 entries (EfiMemoryMap).
//
if (gBootServices == NULL) {
return NULL;
}
Status = gBootServices->LocateProtocol (
&gEfiHobListGuid,
NULL,
(VOID **)&EfiMemoryBase
);
if (EFI_ERROR (Status)) {
return NULL;
}
if (EfiMemoryBase <= 0x10) {
//
// Memory base must be > 16 to be valid (below 16 is ISA/memory reserved).
//
Status = gBootServices->LocateProtocol (
&gEfiVariableArchProtocolGuid,
NULL,
&HobList
);
if (EFI_ERROR (Status)) {
HobList = NULL;
}
mHobList = HobList;
} else {
mHobList = NULL;
}
return mHobList;
}
//
// ---------------------------------------------------------------------------
// ModuleEntryPoint (also UefiMain)
//
// UEFI driver entry point for OpromUpdateDxeCLX64L.
//
// Initializes global service pointers (ImageHandle, SystemTable, BootServices,
// RuntimeServices), retrieves the HOB list, registers the CLX64L-specific
// UBA OpromUpdate configuration with the UBA framework.
//
// The UBA configuration includes:
// - PCIe slot mapping table for CLX64L
// - Bus scan limit tables for CLX64L-specific devices
// - Slot assignment callback functions
//
// @param[in] ImageHandle The firmware allocated handle for the UEFI image.
// @param[in] SystemTable A pointer to the EFI System Table.
//
// @retval EFI_SUCCESS The driver initialized successfully.
// @retval EFI_INVALID_PARAMETER A required protocol could not be located.
//
// ---------------------------------------------------------------------------
//
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UBA_OPROM_UPDATE_PROTOCOL *ConfigTable;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo;
//
// Save UEFI global pointers for library functions.
//
gImageHandle = ImageHandle;
if (ImageHandle == NULL) {
DEBUG ((
DEBUG_ERROR,
"%a(%d): %a\n",
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
51,
"gImageHandle != ((void *) 0)"
));
ASSERT (ImageHandle != NULL);
}
gSystemTable = SystemTable;
if (SystemTable == NULL) {
DEBUG ((
DEBUG_ERROR,
"%a(%d): %a\n",
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
57,
"gST != ((void *) 0)"
));
ASSERT (SystemTable != NULL);
}
gBootServices = SystemTable->BootServices;
if (gBootServices == NULL) {
DEBUG ((
DEBUG_ERROR,
"%a(%d): %a\n",
"e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
63,
"gBS != ((void *) 0)"
));
ASSERT (gBootServices != NULL);
}
gRuntimeServices = SystemTable->RuntimeServices;
if (gRuntimeServices == NULL) {
DEBUG ((
DEBUG_ERROR,
"%a(%d): %a\n",
"e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
47,
"gRT != ((void *) 0)"
));
ASSERT (gRuntimeServices != NULL);
}
//
// Initialize the HOB list.
//
GetHobList ();
//
// Log the UBA OpromUpdate registration for CLX64L.
//
UbaDebugPrint (UBA_DEBUG_LEVEL, "UBA:OpromUpdate-TypeClx64L\n");
//
// Locate the PCI Root Bridge I/O protocol and install the UBA
// OpromUpdate configuration table.
//
ConfigTable = &mUbaOpromUpdateProtocol;
Status = gBootServices->LocateProtocol (
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID **)&RootBridgeIo
);
if (!EFI_ERROR (Status)) {
//
// Register the UBA configuration with the root bridge driver.
// The configuration includes the slot mapping table, bus scan limits,
// and callback functions.
//
Status = RootBridgeIo->SetAttributes (
RootBridgeIo,
0,
(UINT64)-1, // Use default configuration
48, // Size of UBA configuration structure
ConfigTable
);
}
return Status;
}