/** @file
FpgaConfigDataDxeNeonCityFPGA -- UEFI DXE driver that provides FPGA
configuration data access for the NeonCityFPGA platform.
This driver registers a UBA protocol that exposes a callback for querying
HSSI (High Speed Serial Interface) card-specific FPGA configuration data
(PXB register offsets and configuration pointers). The protocol GUID is
platform-specific: 332B3586-F0B4-46EE-A39C-786330E2D328.
Build path:
e:\hs\PurleyRpPkg\Uba\UbaMain\Dxe\TypeNeonCityFPGA\FpgaConfigDataDxe\
Toolchain: VS2015, X64 DEBUG build
Image size: 0x6B00 bytes (.text: 0xA60, .rdata: 0x740, .data: 0x5540)
**/
#ifndef FPGA_CONFIG_DATA_DXE_NEON_CITY_FPGA_H
#define FPGA_CONFIG_DATA_DXE_NEON_CITY_FPGA_H
#include "../uefi_headers/Uefi.h"
// ---------------------------------------------------------------------------
// GUID Definitions
// ---------------------------------------------------------------------------
///
/// Protocol GUID exposed by this driver. Other UBA drivers use this GUID to
/// locate the GetFpgaConfigData function via gBS->LocateProtocol().
///
#define FPGA_CONFIG_PROTOCOL_GUID \
{ 0x332B3586, 0xF0B4, 0x46EE, { 0xA3, 0x9C, 0x78, 0x63, 0x30, 0xE2, 0xD3, 0x28 } }
extern EFI_GUID gFpgaConfigProtocolGuid;
///
/// EFI_HOB_LIST_GUID (standard UEFI) -- used to locate the HOB list from
/// the system configuration table.
///
#define EFI_HOB_LIST_GUID \
{ 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
extern EFI_GUID gEfiHobListGuid;
///
/// EFI_GENERIC_VARIABLE_GUID -- used to read/write the "FpgaSocketConfig"
/// UEFI variable for persisting FPGA socket configuration across boots.
///
#define EFI_GENERIC_VARIABLE_GUID \
{ 0x59D7C710, 0x49EA, 0x4D26, { 0x9F, 0x7C, 0xDE, 0x10, 0x64, 0x87, 0x6E, 0x2F } }
extern EFI_GUID gEfiGenericVariableGuid;
///
/// Second GUID at 0x1470 - unknown purpose, used in HOB GUID comparison
/// for gEfiHobListGuid. Acts as a sentinel or dual-GUID matching pattern.
///
#define HOB_SENTINEL_GUID \
{ 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }
extern EFI_GUID gHobSentinelGuid;
///
/// Third GUID at 0x1480 -- used as vendor GUID for the "FpgaSocketConfig"
/// UEFI variable when calling gRT->SetVariable().
///
#define FPGA_SOCKET_CONFIG_VENDOR_GUID \
{ 0x75839B0B, 0x0A99, 0x4233, { 0x8A, 0xA4, 0x38, 0x66, 0xF6, 0xCE, 0xF4, 0xB3 } }
extern EFI_GUID gFpgaSocketConfigVendorGuid;
// ---------------------------------------------------------------------------
// HSSI Card Type Definitions
// ---------------------------------------------------------------------------
///
/// HSSI card type values stored in the HOB at offset mFpgaConfigData.HssiCardId[i]
///
#define HSSI_CARD_TYPE_NONE 0x00 ///< No HSSI card present
#define HSSI_CARD_TYPE_UNKNOWN 0x07 ///< Reserved/reserved type
#define HSSI_CARD_TYPE_1 0x04 ///< Type 1 (e.g., 2-port 10G/25G)
#define HSSI_CARD_TYPE_2 0x06 ///< Type 2 (e.g., 4-port 10G/25G)
///
/// Maximum number of sockets supported
///
#define MAX_SOCKET_COUNT 4
///
/// Maximum number of HSSI card config table entries
///
#define MAX_HSSI_CONFIG_ENTRIES 2
// ---------------------------------------------------------------------------
// HOB Data Structure
// ---------------------------------------------------------------------------
///
/// Size of the FPGA configuration HOB (Hand-Off Block).
/// This HOB is identified by checking the first two GUIDs in sequence
/// (gFpgaConfigProtocolGuid followed by the sentinel), then extracting
/// the payload that starts at offset +0x18 within the matched HOB block.
///
#define FPGA_CONFIG_HOB_SIZE 38
#pragma pack(push, 1)
///
/// FPGA configuration data structure stored in a UEFI HOB.
/// This is the per-socket FPGA and HSSI card configuration.
///
typedef struct {
///
/// +0x00 (byte_6960[0]): Initialized flag. Set to 1 when configuration is
/// fully loaded from HOB or variable.
///
UINT8 Initialized;
///
/// +0x01 (byte_6961): Reserved / version field.
///
UINT8 Reserved1;
///
/// +0x02 (byte_6962): FpgaSktIoApicId -- IO APIC ID for the FPGA socket.
///
UINT8 FpgaSktIoApicId;
///
/// +0x03 (byte_6963): FpgaSktActive -- bitmask of active FPGA sockets.
/// Bit 0 = Socket 0 active
/// Bit 1 = Socket 1 active
/// ...
///
UINT8 FpgaSktActive;
///
/// +0x04 (byte_6964): SktIioApicId0 -- IIO APIC ID 0.
///
UINT8 SktIioApicId0;
///
/// +0x05 (byte_6965): ActiveIioStackMask -- bitmask of active IIO stacks.
///
UINT8 ActiveIioStackMask;
///
/// +0x06 (byte_6966): CpuNum -- number of CPUs in the socket.
///
UINT8 CpuNum;
///
/// +0x07-0x0A: Padding.
///
UINT8 Reserved2[4];
///
/// +0x0B (byte_6960[11]): HssiCardId[0] -- HSSI card type for socket 0.
///
UINT8 HssiCardId_0;
///
/// +0x0C (byte_6960[12]): Reserved/hssi card sub-ID.
///
UINT8 HssiCardSubId_0;
///
/// +0x0D (byte_6960[13]): Unused/padding.
///
UINT8 Padding1;
///
/// +0x0E (byte_6960[14]): HssiBifurcation[0] -- PCIe bifurcation setting
/// for HSSI card on socket 0.
///
UINT8 HssiBifurcation_0;
///
/// +0x0F (byte_6967): HssiCardId[1] -- HSSI card type for socket 1.
///
UINT8 HssiCardId_1;
///
/// +0x10 (byte_6967+1): HssiCardSubId[1].
///
UINT8 HssiCardSubId_1;
///
/// +0x11 (byte_6967+2): Unused.
///
UINT8 Padding2;
///
/// +0x12 (byte_6967+3): HssiBifurcation[1].
///
UINT8 HssiBifurcation_1;
///
/// +0x13 (byte_6960[19]): HssiCardId[2].
///
UINT8 HssiCardId_2;
///
/// +0x14 (byte_6960[20]): HssiCardSubId[2].
///
UINT8 HssiCardSubId_2;
///
/// +0x15 (byte_6960[21]): Unused.
///
UINT8 Padding3;
///
/// +0x16 (byte_6960[22]): HssiBifurcation[2].
///
UINT8 HssiBifurcation_2;
///
/// +0x17 (byte_6960[23]): HssiCardId[3].
///
UINT8 HssiCardId_3;
///
/// +0x18 (byte_6960[24]): HssiCardSubId[3].
///
UINT8 HssiCardSubId_3;
///
/// +0x19 (byte_6960[25]): Unused.
///
UINT8 Padding4;
///
/// +0x1A (byte_6960[26]): HssiBifurcation[3].
///
UINT8 HssiBifurcation_3;
///
/// +0x1B-0x1E: Padding / reserved (byte_6960[27-30]).
///
UINT8 Reserved3[4];
///
/// +0x1F (byte_697F): FpgaSktIoApicId2 -- alternate/secondary IO APIC ID.
///
UINT8 FpgaSktIoApicId2;
///
/// +0x20 (byte_6980): IioApicId0 -- APIC ID 0 for IIO.
///
UINT8 IioApicId0;
///
/// +0x21-0x24: Reserved.
///
UINT8 Reserved4[4];
///
/// +0x25 (byte_6985): IioApicIdOverride -- override value for IIO APIC ID.
///
UINT8 IioApicIdOverride;
} FPGA_CONFIG_DATA;
#pragma pack(pop)
// ---------------------------------------------------------------------------
// HSSI Card Configuration Table
// ---------------------------------------------------------------------------
///
/// Per-socket HSSI card configuration entry.
/// Each entry maps a (socket, card_type) pair to platform-specific data.
/// There are up to MAX_HSSI_CONFIG_ENTRIES entries at 0x3ED0 in .data.
///
#pragma pack(push, 1)
typedef struct {
///
/// +0x00: Socket index (0, 1, ...)
///
UINT8 Socket;
///
/// +0x01: HSSI card type (see HSSI_CARD_TYPE_* defines)
///
UINT8 CardType;
///
/// +0x02-0x07: Padding.
///
UINT8 Reserved[6];
///
/// +0x08: Pointer to PXB (PCI Express Root Port) configuration data.
///
VOID *PxbConfig;
///
/// +0x10: Pointer to the GetFpgaConfigData callback function (sub_51C
/// wrapper or actual config access function at offset 0x448).
///
VOID *ConfigDataPtr;
} HSSI_CARD_CONFIG_ENTRY;
#pragma pack(pop)
///
/// HSSI card configuration table -- array of MAX_HSSI_CONFIG_ENTRIES entries.
///
extern HSSI_CARD_CONFIG_ENTRY mHssiCardConfigTable[MAX_HSSI_CONFIG_ENTRIES];
// ---------------------------------------------------------------------------
// Debug Error Level Constants
// ---------------------------------------------------------------------------
///
/// Error level masks used in debug output filtering.
/// These are the DP_* constants defined in MdePkg for the DebugLib protocol.
///
#define DEBUG_ERROR 0x80000000 ///< Error messages
#define DEBUG_INFO 0x80000040 ///< Informational messages
// ---------------------------------------------------------------------------
// Protocol Interface
// ---------------------------------------------------------------------------
///
/// FPGA Configuration Protocol interface.
/// This protocol is installed at 0x1460 with GUID 332B3586-F0B4-46EE-A39C-786330E2D328.
/// The single function in the interface is GetFpgaConfigData.
///
typedef struct {
///
/// Get FPGA configuration data for a given socket and HSSI card type.
///
/// @param[in] Socket Socket index (0-based).
/// @param[in] HssiCardType HSSI card type identifier.
/// @param[out] PxbConfig Pointer to receive the PXB configuration data pointer.
/// @param[out] ConfigDataPtr Pointer to receive the config data callback pointer.
///
/// @retval EFI_SUCCESS Data returned successfully.
/// @retval EFI_INVALID_PARAMETER PxbConfig or ConfigDataPtr is NULL.
/// @retval EFI_NOT_FOUND No entry matches the given Socket/HssiCardType.
/// @retval EFI_UNSUPPORTED The HSSI card type is not supported.
///
EFI_STATUS
(EFIAPI *GetFpgaConfigData)(
IN UINT8 Socket,
IN UINT8 HssiCardType,
OUT VOID **PxbConfig,
OUT VOID **ConfigDataPtr
);
} FPGA_CONFIG_PROTOCOL;
// ---------------------------------------------------------------------------
// Global Variables (from .data / .bss)
// ---------------------------------------------------------------------------
extern EFI_SYSTEM_TABLE *gST; ///< 0x6920
extern EFI_BOOT_SERVICES *gBS; ///< 0x6928
extern EFI_HANDLE gImageHandle; ///< 0x6930
extern EFI_RUNTIME_SERVICES *gRT; ///< 0x6938
extern VOID *mDebugProtocol; ///< 0x6940 - cached DebugLib protocol
extern VOID *mHobList; ///< 0x6948 - cached HOB list pointer
extern UINT8 mCmosDebugLevel; ///< 0x6950 - cached CMOS debug level
///
/// FPGA configuration data array, one entry per socket (4 sockets).
/// Populated from HOB or UEFI variable "FpgaSocketConfig".
///
extern FPGA_CONFIG_DATA mFpgaConfigData; ///< 0x6960
// ---------------------------------------------------------------------------
// Function Declarations
// ---------------------------------------------------------------------------
/**
UEFI module entry point. Called by the DXE dispatcher.
Initializes gImageHandle, gST, gBS, gRT with standard UefiBootServicesTableLib
assertions. Then calls sub_870 to locate the HOB list, and sub_51C to perform
the FPGA configuration data setup.
@param[in] ImageHandle Handle for this driver image.
@param[in] SystemTable Pointer to the UEFI system table.
@return EFI_STATUS from sub_51C.
**/
EFI_STATUS
EFIAPI
_ModuleEntryPoint(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
/**
Queries FPGA configuration data for a given socket and HSSI card type.
Looks up the (Socket, CardType) pair in mHssiCardConfigTable. If found,
returns the PXB configuration data pointer and the config data callback pointer.
@param[in] Socket Socket index (0-based).
@param[in] HssiCardType HSSI card type (see HSSI_CARD_TYPE_*).
@param[out] PxbConfig Receives PXB config data pointer.
@param[out] ConfigDataPtr Receives config data pointer.
@retval EFI_SUCCESS Lookup succeeded.
@retval EFI_INVALID_PARAMETER PxbConfig or ConfigDataPtr is NULL.
@retval EFI_NOT_FOUND No matching table entry.
@retval EFI_UNSUPPORTED Unsupported HSSI card type (value 3, 5, etc.).
**/
EFI_STATUS
EFIAPI
GetFpgaConfigData(
IN UINT8 Socket,
IN UINT8 HssiCardType,
OUT VOID **PxbConfig,
OUT VOID **ConfigDataPtr
);
/**
Main FPGA configuration data entry function.
Extracts configuration from the FPGA_CONFIG_DATA HOB (located by sub_9A0),
populates mFpgaConfigData, and installs the FPGA_CONFIG_PROTOCOL.
@param[in] ImageHandle Image handle for protocol installation.
@param[in] Buffer Pointer to the HOB data buffer from sub_9A0.
@return EFI_SUCCESS on success, error code otherwise.
**/
EFI_STATUS
EFIAPI
FpgaConfigDataEntry(
IN EFI_HANDLE ImageHandle,
IN VOID *Buffer
);
/**
Initializes FPGA configuration data from HOB or UEFI variable.
Locates the FPGA configuration HOB by scanning the HOB list for the
paired GUID sequence (gFpgaConfigProtocolGuid + gHobSentinelGuid).
If not found in HOB, creates a new HOB and initializes it from the
"FpgaSocketConfig" UEFI variable.
@param[out] ConfigData Receives pointer to the FPGA configuration data.
@retval EFI_SUCCESS HOB located or created.
@retval EFI_NOT_FOUND HOB not found and creation failed.
**/
EFI_STATUS
EFIAPI
InitializeFpgaConfigData(
OUT VOID **ConfigData
);
// ---------------------------------------------------------------------------
// Internal Helper Functions
// ---------------------------------------------------------------------------
/**
Locates the HOB list from the system configuration table.
Scans SystemTable->ConfigurationTable[] for EFI_HOB_LIST_GUID
(7739F24C-93D7-11D4-9A3A-0090273FC14D). Caches result in mHobList.
@return Pointer to the HOB list, or NULL if not found.
**/
VOID *
EFIAPI
GetHobList(
VOID
);
/**
Scans the HOB list for a FPGA configuration HOB.
Walks the HOB list starting from mHobList, looking for a HOB whose
GUID matches the paired sequence (gFpgaConfigProtocolGuid +
gHobSentinelGuid). If found, returns a pointer to the HOB payload.
If no suitable HOB is found, creates a new FPGA configuration HOB
and initializes it from the "FpgaSocketConfig" UEFI variable (if
available) or with default zero values.
@param[out] Buffer Receives pointer to FPGA configuration data.
@retval EFI_SUCCESS FPGA config data pointer returned successfully.
**/
EFI_STATUS
EFIAPI
GetFpgaConfigHob(
OUT VOID **Buffer
);
/**
Determines the debug output level by reading CMOS register 0x4B.
Reads CMOS register 0x4B via RTC ports 0x70/0x71. If the register
value is 0, falls back to reading MMIO at 0xFDAF0490 (bit 1).
@return Debug level: 1 (normal), 2, 3, or 4 (verbose).
**/
UINT8
EFIAPI
GetCmosDebugLevel(
VOID
);
/**
Debug print function with level filtering.
Compares the ErrorLevel parameter against the CMOS debug level.
Only prints if the level is permitted.
@param[in] ErrorLevel DEBUG_* error level mask.
@param[in] Format Print format string.
@param[in] ... Additional format arguments.
**/
VOID
EFIAPI
DebugPrint(
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
);
/**
ASSERT handler -- calls DebugLib protocol assertion.
@param[in] FileName Source file name string.
@param[in] LineNumber Line number of the assertion.
@param[in] Description Assertion description string.
**/
VOID
EFIAPI
DebugAssert(
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
);
/**
Lazily resolves and caches the DebugLib protocol.
Uses gBS->LocateProtocol() to find the DebugLib protocol interface.
Caches in mDebugProtocol.
@return Pointer to DebugLib protocol interface, or NULL if not found.
**/
VOID *
EFIAPI
GetDebugProtocol(
VOID
);
/**
Compares two GUIDs by comparing their two 8-byte halves.
@param[in] Guid1 Pointer to first GUID.
@param[in] Guid2 Pointer to second GUID.
@return TRUE if the GUIDs match.
**/
BOOLEAN
EFIAPI
CompareGuid(
IN EFI_GUID *Guid1,
IN EFI_GUID *Guid2
);
/**
Reads a UINT64 from an unaligned pointer with NULL check.
@param[in] Buffer Pointer to the UINT64 value.
@return The UINT64 value at Buffer.
**/
UINT64
EFIAPI
ReadUnaligned64(
IN CONST UINT64 *Buffer
);
/**
Allocates pool memory of the given type and size.
Calls gBS->AllocatePool().
@param[in] PoolType Type of pool to allocate.
@param[in] Size Number of bytes to allocate.
@param[out] Buffer Receives the allocated buffer pointer.
@return EFI_STATUS from gBS->AllocatePool().
**/
VOID *
EFIAPI
AllocatePool(
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size
);
/**
Frees pool memory previously allocated by AllocatePool.
Calls gBS->FreePool().
@param[in] Buffer Pointer to memory to free.
**/
VOID
EFIAPI
FreePool(
IN VOID *Buffer
);
/**
Zeroes a memory buffer.
@param[in] Buffer Pointer to memory to zero.
@param[in] Size Number of bytes to zero.
@return Buffer.
**/
VOID *
EFIAPI
ZeroMem(
IN VOID *Buffer,
IN UINTN Size
);
#endif // FPGA_CONFIG_DATA_DXE_NEON_CITY_FPGA_H