alder_lake_bios/Board/Oem/L05AlderLakeSMultiBoardPkg/Library/DxeOemSvcKernelLib/OemSvcGetHotplugBridgeInfo.c

1014 lines
47 KiB
C

/** @file
Provide OEM to get the HotPlugBridgeInfo table.
;******************************************************************************
;* Copyright (c) 2014 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include <Library/DxeOemSvcKernelLib.h>
#include <ChipsetSetupConfig.h>
#include <Protocol/SetupUtility.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <OemThunderbolt.h>
#include <PiDxe.h>
#include <Include/Guid/HobList.h>
#include <Include/Library/HobLib.h>
#include <Library/UefiLib.h>
#include <Library/VariableLib.h>
#include <ITbtInfoHob.h>
#include <DTbtInfoHob.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <SetupVariable.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/ITbtPolicy.h>
#include <Library/DebugLib.h>
#include <Library/TbtCommonLib.h>
#include <Library/PcdLib.h>
#include <Protocol/ITbtPolicy.h>
#include <Protocol/DxeDTbtPolicy.h>
//#include <Register/SaRegsItbtPcie.h>
#include <Library/PchInfoLib.h>
#include <Library/PchPcieRpLib.h>
#include <Library/CpuPcieInfoFruLib.h>
#include <Library/CpuPcieRpLib.h>
#include <PcieRegs.h>
#include <Register/CpuPcieRegs.h>
#include <Guid/H2OCp.h>
#include <Library/H2OCpLib.h>
#include <Library/PciSegmentLib.h>
#include <Library/PcieHelperLib.h>
#include <Library/DevicePathLib.h>
#define DTBT_CONTROLLER 0x00
#define ITBT_CONTROLLER 0x80
#define DTBT_TYPE_PCH 0x01
#define DTBT_TYPE_PEG 0x02
#define DTBT_SMI_HANDLER_NUMBER 0xF7
#define MAX_P2PB_OF_TBT_DAISY_CHAIN ((MAX_DTBT_CONTROLLER_NUMBER + MAX_ITBT_PCIE_PORT) * 64)
#define PCI_ROOT_0_STRING L"PciRoot(0x0)"
#define PCI_ROOT_1_STRING L"PciRoot(0x1)"
typedef struct {
EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath;
UINT64 HpcPciAddress; // Bit[15:8]:Function, Bit[23:16]:Device, Bit[31:24]:Bus, Bit[32]:Segment
UINT8 RsvdExtraBusNum;
UINT16 RsvdPcieMegaMem;
UINT8 PcieMemAddrRngMax;
UINT16 RsvdPciePMegaMem;
UINT8 PciePMemAddrRngMax;
UINT8 RsvdPcieKiloIo;
} P2PB_RESOURCE_RECORD;
typedef struct {
UINT8 P2pbSegNum;
UINT8 P2pbBusNum;
UINT8 P2pbLastDevNum;
UINT8 NumOfP2pbHotPlug;
UINT8 NumOfP2pbNonHotPlug;
} NUMBER_OF_HOTPLUG_BRIDGE;
GLOBAL_REMOVE_IF_UNREFERENCED P2PB_RESOURCE_RECORD mP2pbResourceRecord[MAX_P2PB_OF_TBT_DAISY_CHAIN];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mP2pbResourceRecordCount = 0;
// Record the number of HotPlug capability Bridge on the same Bus.
GLOBAL_REMOVE_IF_UNREFERENCED NUMBER_OF_HOTPLUG_BRIDGE mNumOfHotPlugBridge[MAX_P2PB_OF_TBT_DAISY_CHAIN];
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mRemainderBus = 0;
BOOLEAN mEnableAbove4GBMmio = FALSE;
//TBT_INFO_HOB *gTbtInfoHob;
//
// Please base on your project to fill this table.
// 1. If your Pcie devices/slots do not support Hotplug, Please disable it by setup variable PcieRootPortHPE[Index]
// 2. Alderlake S support Port1-Port28
// Alderlake P support Port1-Port12
// Alderlake M support Port1-Port10
// 3. Current CRB BIOS set PcieRootPortHPE[0] - PcieRootPortHPE[20] disabled as default
//
HOT_PLUG_BRIDGE_INFO HotPlugBridgeInfo [] = {
// NodeUID, DevNum, FuncNum, ReservedBusCount, ReservedIoRange, ReservedNonPrefetchableMmio, AlignemntOfReservedNonPrefetchableMmio, ReservedPrefetchableMmio, AlignemntOfReservedPrefetchableMmio
{ 0x00, 0x1C, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F0 PCIe Root Port #1
{ 0x00, 0x1C, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F1 PCIe Root Port #2
{ 0x00, 0x1C, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F2 PCIe Root Port #3
{ 0x00, 0x1C, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F3 PCIe Root Port #4
{ 0x00, 0x1C, 4, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F4 PCIe Root Port #5
{ 0x00, 0x1C, 5, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F5 PCIe Root Port #6
{ 0x00, 0x1C, 6, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F6 PCIe Root Port #7
{ 0x00, 0x1C, 7, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F7 PCIe Root Port #8
{ 0x00, 0x1D, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F0 PCIe* Root Port #9
{ 0x00, 0x1D, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F1 PCIe Root Port #10
{ 0x00, 0x1D, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F2 PCIe Root Port #11
{ 0x00, 0x1D, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F3 PCIe Root Port #12
{ 0x00, 0x1D, 4, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F4 PCIe Root Port #13
{ 0x00, 0x1D, 5, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F5 PCIe Root Port #14
{ 0x00, 0x1D, 6, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F6 PCIe Root Port #15
{ 0x00, 0x1D, 7, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F7 PCIe Root Port #16
{ 0x00, 0x1B, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F0 PCIe Root Port #17
{ 0x00, 0x1B, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F1 PCIe Root Port #18
{ 0x00, 0x1B, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F2 PCIe Root Port #19
{ 0x00, 0x1B, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F3 PCIe Root Port #20
{ 0x00, 0x1B, 4, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F4 PCIe Root Port #21
{ 0x00, 0x1B, 5, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F5 PCIe Root Port #22
{ 0x00, 0x1B, 6, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F6 PCIe Root Port #23
{ 0x00, 0x1B, 7, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D27/F7 PCIe Root Port #24
{ 0x00, 0x1A, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D26/F0 PCIe Root Port #25
{ 0x00, 0x1A, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D26/F1 PCIe Root Port #26
{ 0x00, 0x1A, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D26/F2 PCIe Root Port #27
{ 0x00, 0x1A, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D26/F3 PCIe Root Port #28
{ 0x00, 0x01, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D01/F0 PCIe RC 010 G5
{ 0x00, 0x01, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D01/F1 PCIe RC 011 G5
{ 0x00, 0x06, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D06/F0 PCIe RC 060 (x4) G4
{ END_OF_TABLE, 0, 0, 0, 0, 0, 0, 0, 0}, //End of Table, Cannot be removed.
};
/**
Get resource padding information from record.
@param[in] Event A pointer to the Event that triggered the callback.
@param[in] Handle Checkpoint handle.
**/
VOID
EFIAPI
PciHpcGetResourcePaddingCallback (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
);
/**
Dump HotPlugBridgeInfo table for debug purpose.
**/
VOID
DumpHotPlugBridgeInfo (
VOID
)
{
UINT16 Index;
DEBUG ((DEBUG_INFO, "\nDump HotPlugBridgeInfo table:\n"));
DEBUG ((DEBUG_INFO, "NodeUID DevNum FuncNum BusCount IoRange NonPrefetchableMmio AlignemntOfNonPrefetchableMmio PrefetchableMmio AlignemntOfPrefetchableMmio\n"));
for (Index = 0; HotPlugBridgeInfo[Index].NodeUID != END_OF_TABLE; Index++) {
DEBUG ((DEBUG_INFO, "0x%02X 0x%02X 0x%02X 0x%02X 0x%04X",\
HotPlugBridgeInfo[Index].NodeUID,\
HotPlugBridgeInfo[Index].DevNum,\
HotPlugBridgeInfo[Index].FuncNum,\
HotPlugBridgeInfo[Index].ReservedBusCount,\
HotPlugBridgeInfo[Index].ReservedIoRange));
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].ReservedNonPrefetchableMmio));
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].AlignemntOfReservedNonPrefetchableMmio));
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].ReservedPrefetchableMmio));
DEBUG ((DEBUG_INFO, " 0x%016llX\n", HotPlugBridgeInfo[Index].AlignemntOfReservedPrefetchableMmio));
}
}
/**
Provide OEM to get the HotPlugBridgeInfo table.
This table contains the hot plug bridge address info and defines reserved BUS, I/O and memory range for bridge device.
@param[out] *HotPlugBridgeInfoTable Point to HOT_PLUG_BRIDGE_INFO Table
@retval EFI_MEDIA_CHANGED Get hot plug bridge info success.
@retval Others Depends on customization.
**/
EFI_STATUS
OemSvcGetHotplugBridgeInfo (
OUT HOT_PLUG_BRIDGE_INFO **HotPlugBridgeInfoTable
)
{
EFI_STATUS Status;
SETUP_DATA *SystemConfiguration = NULL;
CHIPSET_CONFIGURATION *ChipsetConfiguration = NULL;
UINT8 Index;
PCH_SETUP *PchSetup = NULL;
SA_SETUP SaSetup;
UINTN VariableSize;
UINTN SaVariableSize;
UINTN RpDevice;
UINTN RpFunction;
DTBT_INFO_HOB *DTbtInfoHob = NULL;
UINT8 Rootportselected = 0;
ITBT_POLICY_PROTOCOL *ITbtPolicy;
DXE_ITBT_CONFIG *DxeITbtConfig;
DXE_DTBT_POLICY_PROTOCOL *DxeDTbtConfig;
UINT64 RpBase;
H2O_CP_HANDLE CpGetResourcePaddingHandle;
ITbtPolicy = NULL;
DxeITbtConfig = NULL;
DxeDTbtConfig = NULL;
RpBase = 0;
if (PcdGetBool(PcdITbtEnable)) {
Status = gBS->LocateProtocol (&gITbtPolicyProtocolGuid, NULL, (VOID **) &ITbtPolicy);
ASSERT_EFI_ERROR (Status);
Status = GetConfigBlock ((VOID *) ITbtPolicy, &gDxeITbtConfigGuid, (VOID *)&DxeITbtConfig);
ASSERT_EFI_ERROR (Status);
}
VariableSize = sizeof (PCH_SETUP);
PchSetup = AllocateZeroPool (VariableSize);
if (PchSetup == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (PcdGetBool(PcdDTbtEnable)) {
Status = gBS->LocateProtocol (
&gDxeDTbtPolicyProtocolGuid,
NULL,
(VOID **) &DxeDTbtConfig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, " gDxeDTbtPolicyProtocolGuid Not installed!!!\n"));
return Status;
}
}
Status = gRT->GetVariable (
PCH_SETUP_VARIABLE_NAME,
&gPchSetupVariableGuid,
NULL,
&VariableSize,
PchSetup
);
if (EFI_ERROR (Status)) {
FreePool (PchSetup);
return Status;
}
SaVariableSize = sizeof (SA_SETUP);
Status = gRT->GetVariable (
SA_SETUP_VARIABLE_NAME,
&gSaSetupVariableGuid,
NULL,
&SaVariableSize,
&SaSetup
);
if (EFI_ERROR (Status)) {
FreePool (PchSetup);
return Status;
}
mEnableAbove4GBMmio = SaSetup.EnableAbove4GBMmio;
if (PcdGetBool (PcdH2ODxeCpPciHpcGetResourcePaddingSupported)) {
Status = H2OCpRegisterHandler (
&gH2ODxeCpPciHpcGetResourcePaddingGuid,
PciHpcGetResourcePaddingCallback,
H2O_CP_MEDIUM_HIGH,
&CpGetResourcePaddingHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2ODxeCpPciHpcGetResourcePaddingGuid, Status));
}
DEBUG ((EFI_D_INFO, "Checkpoint Registered: %g (%r)\n", &gH2ODxeCpPciHpcGetResourcePaddingGuid, Status));
}
//
// Get NVRAM data
//
SystemConfiguration = CommonGetVariableData (PLATFORM_SETUP_VARIABLE_NAME, &gSetupVariableGuid);
ChipsetConfiguration = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
if ((SystemConfiguration != NULL) && (ChipsetConfiguration != NULL)) {
for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
//
// The max number of PCH root ports will different by PCH type.
// PCH_P : 12
// PCH_M : 10
// PCH_S : 28
//
if (Index >= GetPchMaxPciePortNum ()) {
continue;
}
//
// Get correct Device and Function number for root port.
//
Status = GetPchPcieRpDevFun (Index, &RpDevice, &RpFunction);
ASSERT_EFI_ERROR (Status);
//
// Update Device and Function number to HotPlugBridgeInfo table.
//
HotPlugBridgeInfo[Index].DevNum = (UINT8)RpDevice;
HotPlugBridgeInfo[Index].FuncNum = (UINT8)RpFunction;
//
// PCH Rootports Hotplug Capability Check.
//
RpBase = PchPcieBase (Index);
if (((PciSegmentRead32 (RpBase + R_PCIE_SLCAP) >> 6) & BIT0) != 1) {
HotPlugBridgeInfo[Index].NodeUID = IGNORE_DEVICE;
}
}
//
// CPU Rootports.
//
for (Index = 0; Index < GetMaxCpuPciePortNum (); Index++) {
if (Index >= GetMaxCpuPciePortNum ()) {
continue;
}
//
// Get correct Device and Function number for root port.
//
Status = GetCpuPcieRpDevFun (Index, &RpDevice, &RpFunction);
//
// Update Device and Function number to HotPlugBridgeInfo table.
//
Rootportselected = GetPchMaxPciePortNum () + Index;
HotPlugBridgeInfo[Rootportselected].DevNum = (UINT8)RpDevice;
HotPlugBridgeInfo[Rootportselected].FuncNum = (UINT8)RpFunction;
//
// CPU Rootports Hotplug Capability Check.
//
RpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, (UINT32)RpDevice, (UINT32)RpFunction, 0);
if (((PciSegmentRead32 (RpBase + R_PCIE_CLIST + R_PCIE_SLCAP_OFFSET) >> 6) & BIT0) != 1) {
HotPlugBridgeInfo[Rootportselected].NodeUID = IGNORE_DEVICE;
}
}
//
// iTBT Rootports Resource Update
//
if (PcdGetBool(PcdITbtEnable)) {
if (SystemConfiguration->IntegratedTbtSupport == 1) {
for (Index = 0; Index < MAX_ITBT_PCIE_PORT; Index++) {
//
// Check if Controller is set to AUTO and Enabled by default.
//
Rootportselected = GetPchMaxPciePortNum () + GetMaxCpuPciePortNum () + Index;
if (SystemConfiguration->ITbtRootPort[Index] == 0x01) {
//
// Get the Exact Root port number corresponding to the Controller Selected
//
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieExtraBusRsvd;
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = LShiftU64 (DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieMemRsvd, 20);
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = LShiftU64 (DxeITbtConfig->ITbtResourceConfig[Index].TbtPciePMemRsvd, 20);
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = LShiftU64 (1, DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieMemAddrRngMax);
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = LShiftU64 (1, DxeITbtConfig->ITbtResourceConfig[Index].TbtPciePMemAddrRngMax);
} else {
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = 0;
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = 0;
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = 0;
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = 0;
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = 0;
}
} // for loop
}
}
//[-start-190611-IB16990047-add]//
//
// dTBT Rootports Resource Update
//
if (PcdGetBool(PcdDTbtEnable)) {
if (SystemConfiguration->DiscreteTbtSupport == 1) {
DTbtInfoHob = (DTBT_INFO_HOB *) GetFirstGuidHob (&gDTbtInfoHobGuid);
if (DTbtInfoHob == NULL) {
DEBUG ((DEBUG_INFO, "TbtInfoHob not found\n"));
ASSERT (FALSE);
} else {
for (Index = 0; Index < MAX_DTBT_CONTROLLER_NUMBER; Index++) {
if (DTbtInfoHob->DTbtControllerConfig[Index].DTbtControllerEn == 0x01) {
//
// Check if Root Index is for PCH PCIe or PEG
//
if (DTbtInfoHob->DTbtControllerConfig[Index].Type == (DTBT_CONTROLLER + DTBT_TYPE_PCH)) {
//
// Get the Exact Root port number corresponding to the Controller Selected
//
Rootportselected = (DTbtInfoHob->DTbtControllerConfig[Index].PcieRpNumber - 1);
} else if (DTbtInfoHob->DTbtControllerConfig[Index].Type == (DTBT_CONTROLLER + DTBT_TYPE_PEG)) {
Rootportselected = GetPchMaxPciePortNum () + Index;
} else {
continue;
}// Type
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieExtraBusRsvd;
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = LShiftU64 (DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieMemRsvd, 20);
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = LShiftU64 (DxeDTbtConfig->DTbtResourceConfig[Index].TbtPciePMemRsvd, 20);
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = LShiftU64 (1, DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieMemAddrRngMax);
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = LShiftU64 (1, DxeDTbtConfig->DTbtResourceConfig[Index].TbtPciePMemAddrRngMax);
}
} // for loop
}
}
}
//[-end-190611-IB16990047-add]//
gBS->FreePool (SystemConfiguration);
gBS->FreePool (ChipsetConfiguration);
}
#ifdef EFI_DEBUG
//
// Dump HotPlugBridgeInfo table for debug purpose.
//
DumpHotPlugBridgeInfo ();
#endif
*HotPlugBridgeInfoTable = HotPlugBridgeInfo;
if (PchSetup != NULL) {
FreePool (PchSetup);
}
return EFI_MEDIA_CHANGED;
}
/**
Get the Parent Pci Address
@param[in] Segment Segment Number
@param[in] CurrentRpBus P2P Bridge Bus Number
@retval ParentP2PBridgeBase Parent Pci Address
**/
UINT64
GetParentPciAddress (
IN UINT8 Segment,
IN UINT64 CurrentRpBus
)
{
UINT16 ParentRpBus;
UINT8 ParentRpDev;
UINT8 ParentRpFunc;
UINT64 ParentP2PBridgeBase;
UINT8 BaseClass;
UINT8 SubClass;
UINT8 CapHeaderOffset;
PCI_REG_PCIE_CAPABILITY PcieCap;
ParentRpBus = 0;
ParentRpDev = 0;
ParentRpFunc = 0;
for (ParentRpBus = 0; ParentRpBus <= 0xFF; ++ParentRpBus) {
for (ParentRpDev = 0; ParentRpDev <= PCI_MAX_DEVICE; ++ParentRpDev) {
for (ParentRpFunc = 0; ParentRpFunc <= PCI_MAX_FUNC; ++ParentRpFunc) {
ParentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, ParentRpBus, ParentRpDev, ParentRpFunc, 0);
if (PciSegmentRead16 (ParentP2PBridgeBase + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
if (ParentRpFunc == 0) {
//
// IF Fun is zero, stop enumerating other functions of the particular bridge
//
break;
}
continue;
}
BaseClass = PciSegmentRead8 (ParentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 2);
if (BaseClass == PCI_CLASS_BRIDGE) {
SubClass = PciSegmentRead8 (ParentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 1);
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
CapHeaderOffset = PcieFindCapId (Segment, (UINT8)ParentRpBus, ParentRpDev, ParentRpFunc, EFI_PCI_CAPABILITY_ID_PCIEXP);
PciSegmentReadBuffer (ParentP2PBridgeBase + CapHeaderOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability), sizeof (UINT16), &PcieCap);
if (PcieCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT) {
continue;
}
if (PciSegmentRead8 (ParentP2PBridgeBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET) == CurrentRpBus) {
if (PcieCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) {
//
// If the parent is a UPSTREAM_PORT, then it must inherit all resource from grand parent
// And since UPSTREAM_PORT is not a HotPlug P2PB, so check the resoruce from grand parent.
//
ParentP2PBridgeBase = GetParentPciAddress (Segment, ParentRpBus);
return ParentP2PBridgeBase;
}
goto Exit;
}
}
}
}
}
}
Exit:
DEBUG ((DEBUG_INFO, "Parent P2PB is Segment 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", Segment, ParentRpBus, ParentRpDev, ParentRpFunc));
DEBUG ((DEBUG_INFO, "PcieCap.Bits.DevicePortType = 0x%x \n", PcieCap.Bits.DevicePortType));
ParentP2PBridgeBase = (((UINT64)Segment << 32) | ((UINT64)ParentRpBus << 24) | ((UINT64)ParentRpDev << 16) | ((UINT64)ParentRpFunc << 8));
return ParentP2PBridgeBase;
}
/**
Get the Parent Resource
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
@param[out] ParentBusNum Parent Reserved Bus resource Number.
@param[out] ParentPcieMegaMem Parent Reserved Alignment of MEM resource.
@param[out] ParentPciePMegaMem Parent Reserved Alignment of PMEM resource.
@param[out] ParentPcieKiloIo Parent Reserved Pcie Kilo Io Number.
@retval EFI_SUCCESS.
**/
EFI_STATUS
GetParentResourceSize (
IN UINT64 HpcPciAddress,
OUT UINT8 *ParentBusNum,
OUT UINT16 *ParentPcieMegaMem,
OUT UINT16 *ParentPciePMegaMem,
OUT UINT8 *ParentPcieKiloIo
)
{
UINT16 Index;
UINTN RpBus;
UINTN RpDev;
UINTN RpFunc;
RpBus = (UINTN) ((HpcPciAddress >> 24) & 0xFF);
RpDev = (UINTN) ((HpcPciAddress >> 16) & 0xFF);
RpFunc = (UINTN) ((HpcPciAddress >> 8) & 0xFF);
DEBUG ((DEBUG_INFO, "[GetParentResourceSize] Segment 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", ((HpcPciAddress >> 32) & 0x01), RpBus, RpDev, RpFunc));
for (Index = 0; Index < MAX_P2PB_OF_TBT_DAISY_CHAIN; Index++) {
if (mP2pbResourceRecord[Index].HpcPciAddress == 0) {
continue;
}
if ((UINT64)HpcPciAddress == (UINT64)mP2pbResourceRecord[Index].HpcPciAddress) {
*ParentBusNum = mP2pbResourceRecord[Index].RsvdExtraBusNum;
*ParentPcieMegaMem = mP2pbResourceRecord[Index].RsvdPcieMegaMem;
*ParentPciePMegaMem = mP2pbResourceRecord[Index].RsvdPciePMegaMem;
*ParentPcieKiloIo = mP2pbResourceRecord[Index].RsvdPcieKiloIo;
break;
}
}
return EFI_SUCCESS;
}
/**
Check the HotPlug Capable of P2P bridge at the same Bus
@param[in] Segment Segment Number
@param[in] CurrentRpBus P2P Bridge Bus Number.
@param[out] *StrucIndex Indxe number of NUMBER_OF_HOTPLUG_BRIDGE struct.
@retval EFI_SUCCESS The function completed successfully
@retval EFI_INVALID_PARAMETER Invalid Bus number.
@retval EFI_ABORTED No matched P2P Bridge, exit without recorded.
**/
EFI_STATUS
GetCurrentBusP2pbHotPlug (
IN UINT8 Segment,
IN UINT8 CurrentRpBus,
OUT UINT8 *StrucIndex
)
{
UINT8 CurrentRpDev;
UINT8 CurrentRpFunc;
UINT64 CurrentP2PBridgeBase;
UINT8 BaseClass;
UINT8 SubClass;
UINT8 CapHeaderOffset;
UINT16 Index;
PCI_REG_PCIE_SLOT_CAPABILITY PcieSlotCap;
DEBUG ((DEBUG_INFO, "[GetCurrentBusP2pbHotPlug] Segment 0x%x, Bus 0x%x\n", Segment, CurrentRpBus));
if ((CurrentRpBus == 0) | (CurrentRpBus > 0xff)) {
DEBUG ((DEBUG_INFO, "Invalid Bus Number\n"));
return EFI_INVALID_PARAMETER;
}
for (Index = 0; Index <= 0xff; Index++) {
if (mNumOfHotPlugBridge[Index].P2pbBusNum == 0) {
for (CurrentRpDev = 0; CurrentRpDev <= PCI_MAX_DEVICE; ++CurrentRpDev) {
for (CurrentRpFunc = 0; CurrentRpFunc <= PCI_MAX_FUNC; ++CurrentRpFunc) {
CurrentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, CurrentRpBus, CurrentRpDev, CurrentRpFunc, 0);
if (PciSegmentRead16 (CurrentP2PBridgeBase + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
if (CurrentRpFunc == 0) {
//
// IF Fun is zero, stop enumerating other functions of the particular bridge
//
break;
}
continue;
}
BaseClass = PciSegmentRead8 (CurrentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 2);
if (BaseClass == PCI_CLASS_BRIDGE) {
SubClass = PciSegmentRead8 (CurrentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 1);
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
mNumOfHotPlugBridge[Index].P2pbSegNum = Segment;
mNumOfHotPlugBridge[Index].P2pbBusNum = CurrentRpBus;
// Check HotPlugCapable from PCI_CAPABILITY
CapHeaderOffset = PcieFindCapId (Segment, CurrentRpBus, CurrentRpDev, CurrentRpFunc, EFI_PCI_CAPABILITY_ID_PCIEXP);
PciSegmentReadBuffer (CurrentP2PBridgeBase + CapHeaderOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability), sizeof (UINT16), &PcieSlotCap);
if (PcieSlotCap.Bits.HotPlugCapable) {
mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug += 1;
mNumOfHotPlugBridge[Index].P2pbLastDevNum = CurrentRpDev; // Record the last device number in the same layer of Bus
} else {
mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug += 1;
}
*StrucIndex = (UINT8)Index;
}
}
}
}
DEBUG ((DEBUG_INFO, "Data structure Index: 0x%x, Number of P2PB with Hot-Plug: %x, Number of P2PB without Hot-Plug: %x\n", *StrucIndex, mNumOfHotPlugBridge[*StrucIndex].NumOfP2pbHotPlug, mNumOfHotPlugBridge[*StrucIndex].NumOfP2pbNonHotPlug));
return EFI_SUCCESS;
} else if ((mNumOfHotPlugBridge[Index].P2pbBusNum == CurrentRpBus) && (mNumOfHotPlugBridge[Index].P2pbSegNum == Segment)) {
*StrucIndex = (UINT8)Index;
DEBUG ((DEBUG_INFO, "The number of HotPlug Bridge of Bus already recorded in data structure Index: 0x%x\n", *StrucIndex));
return EFI_SUCCESS;
}
}
return EFI_ABORTED;
}
/**
Calculate the number of Bus consumed by Root port, Upstream port and Downstream port.
@param[in] ParentPciAddress The address of the Parent device.
@param[in] CurrentPciAddress The address of the Current device.
@param[in, out] *ConsumedBusNumber Consumed Bus number.
@retval None
**/
VOID
CalculateBusConsumptionBeforeAssign (
IN UINT64 ParentPciAddress,
IN UINT64 CurrentPciAddress,
IN OUT UINT8 *ConsumedBusNumber
)
{
UINTN UpBus;
UINTN DpBus;
UINT8 Segment;
UINTN ParentRpBus;
UINTN ParentRpDev;
UINTN ParentRpFunc;
UINT64 ParentP2PBridgeBase;
UpBus = 0;
DpBus = 0;
Segment = (UINT8) ((ParentPciAddress >> 32) & 0x01);
ParentRpBus = (UINTN) ((ParentPciAddress >> 24) & 0xFF);
ParentRpDev = (UINTN) ((ParentPciAddress >> 16) & 0xFF);
ParentRpFunc = (UINTN) ((ParentPciAddress >> 8) & 0xFF);
ParentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, ParentRpBus, ParentRpDev, ParentRpFunc, 0);
UpBus = PciSegmentRead8 (ParentP2PBridgeBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
DpBus = (UINTN) ((CurrentPciAddress >> 24) & 0xFF);
DEBUG ((DEBUG_INFO, "Upstream Port Bus 0x%x and Downstream Port Bus 0x%x consume 2 bus\n", UpBus, DpBus));
*ConsumedBusNumber = *ConsumedBusNumber + 2;
}
/**
Check if P2pb device is the last one in the same layer bus.
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
@retval TRUE This P2pb device is the last one.
@retval FALSE This P2pb device is not the last one.
**/
BOOLEAN
IsLastP2pbDevice (
IN UINT64 HpcPciAddress
)
{
UINT8 RpSeg;
UINTN RpBus;
UINTN RpDev;
UINT16 Index;
RpSeg = (UINT8)((HpcPciAddress >> 32) & 0x01);
RpBus = (UINTN)((HpcPciAddress >> 24) & 0xFF);
RpDev = (UINTN)((HpcPciAddress >> 16) & 0xFF);
for (Index = 0; Index <= 0xff; Index++) {
if (mNumOfHotPlugBridge[Index].P2pbBusNum != 0) {
if ((mNumOfHotPlugBridge[Index].P2pbSegNum == RpSeg) && (mNumOfHotPlugBridge[Index].P2pbBusNum == RpBus) && (mNumOfHotPlugBridge[Index].P2pbLastDevNum == RpDev)) {
return TRUE;
}
} else {
// if P2pbBusNum = 0, the record has ended.
return FALSE;
}
}
return FALSE;
}
/**
Update P2P Bridge Resource Record
@param[in] *HpcDevicePath The Device Path to the HPC that is being initialized.
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
@param[in] RsvdExtraBusNum Reserved Bus resource Number.
@param[in] RsvdPcieMegaMem Reserved Alignment of MEM resource.
@param[in] PcieMemAddrRngMax Alignment of MEM resource.
@param[in] RsvdPciePMegaMem Reserved Pcie Kilo Io Number.
@param[in] PciePMemAddrRngMax Alignment of PMEM resource.
@param[in] RsvdPcieKiloIo Reserved Pcie Kilo Io Number.
@retval EFI_SUCCESS.
**/
EFI_STATUS
UpdateP2pbResourceRecord (
IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
IN UINT64 HpcPciAddress,
IN UINT8 RsvdExtraBusNum,
IN UINT16 RsvdPcieMegaMem,
IN UINT8 PcieMemAddrRngMax,
IN UINT16 RsvdPciePMegaMem,
IN UINT8 PciePMemAddrRngMax,
IN UINT8 RsvdPcieKiloIo
)
{
UINT16 Index;
for (Index = 0; Index < MAX_P2PB_OF_TBT_DAISY_CHAIN; Index++) {
if (mP2pbResourceRecord[Index].HpcPciAddress == 0) {
continue;
}
if (mP2pbResourceRecord[Index].HpcPciAddress == HpcPciAddress) {
//
// Record already existed, so ignore it.
//
return EFI_ABORTED;
}
}
//
// Record the current HPC's resource assignment
//
mP2pbResourceRecord[mP2pbResourceRecordCount].HpcDevicePath = HpcDevicePath;
mP2pbResourceRecord[mP2pbResourceRecordCount].HpcPciAddress = HpcPciAddress;
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdExtraBusNum = RsvdExtraBusNum;
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieMegaMem = RsvdPcieMegaMem;
mP2pbResourceRecord[mP2pbResourceRecordCount].PcieMemAddrRngMax = PcieMemAddrRngMax;
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPciePMegaMem = RsvdPciePMegaMem;
mP2pbResourceRecord[mP2pbResourceRecordCount].PciePMemAddrRngMax = PciePMemAddrRngMax;
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieKiloIo = RsvdPcieKiloIo;
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].HpcDevicePath = %s \n", mP2pbResourceRecordCount, ConvertDevicePathToText (mP2pbResourceRecord[mP2pbResourceRecordCount].HpcDevicePath, TRUE, TRUE)));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].HpcPciAddress = %lx \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].HpcPciAddress));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdExtraBusNum = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdExtraBusNum));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPcieMegaMem = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieMegaMem));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].PcieMemAddrRngMax = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].PcieMemAddrRngMax));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPciePMegaMem = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPciePMegaMem));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].PciePMemAddrRngMax = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].PciePMemAddrRngMax));
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPcieKiloIo = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieKiloIo));
return EFI_SUCCESS;
}
/**
Handle the Resource Padding For Non-RootPort
@param[in] *HpcDevicePath The Device Path to the HPC that is being initialized.
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
@param[in] RsvdExtraBusNum Reserved Bus resource Number.
@param[in] RsvdPcieMegaMem Reserved Alignment of MEM resource.
@param[in] PcieMemAddrRngMax Alignment of MEM resource.
@param[in] RsvdPciePMegaMem Reserved Pcie Kilo Io Number.
@param[in] PciePMemAddrRngMax Alignment of PMEM resource.
@param[in] RsvdPcieKiloIo Reserved Pcie Kilo Io Number.
**/
VOID
HandleResourcePaddingForNonRootPort (
IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
IN UINT64 HpcPciAddress,
OUT UINT8 *RsvdExtraBusNum,
OUT UINT16 *RsvdPcieMegaMem,
OUT UINT8 *PcieMemAddrRngMax,
OUT UINT16 *RsvdPciePMegaMem,
OUT UINT8 *PciePMemAddrRngMax,
OUT UINT8 *RsvdPcieKiloIo
)
{
UINT8 RpSeg;
UINTN RpBus;
UINTN RpDev;
UINTN RpFunc;
UINT64 ParentPciAddress;
EFI_STATUS Status;
UINT8 Index;
UINT8 ConsumedBusNumber;
RpSeg = (UINT8) ((HpcPciAddress >> 32) & 0x01);
RpBus = (UINTN) ((HpcPciAddress >> 24) & 0xFF);
RpDev = (UINTN) ((HpcPciAddress >> 16) & 0xFF);
RpFunc = (UINTN) ((HpcPciAddress >> 8) & 0xFF);
// Non-Rootport
DEBUG ((DEBUG_INFO, "GetResourcePadding : Non-Rootport Seg 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", RpSeg, RpBus, RpDev, RpFunc));
*RsvdPcieKiloIo = 0;
ConsumedBusNumber = 0;
ParentPciAddress = GetParentPciAddress (RpSeg, RpBus);
GetParentResourceSize (ParentPciAddress, RsvdExtraBusNum, RsvdPcieMegaMem, RsvdPciePMegaMem, RsvdPcieKiloIo);
DEBUG ((DEBUG_INFO, "Parent's resource as below \n"));
DEBUG ((DEBUG_INFO, "BusNum = %x \n", *RsvdExtraBusNum));
DEBUG ((DEBUG_INFO, "PcieMegaMem = %x \n", *RsvdPcieMegaMem));
DEBUG ((DEBUG_INFO, "PciePMegaMem = %x \n", *RsvdPciePMegaMem));
DEBUG ((DEBUG_INFO, "PcieKiloIo = %x \n", *RsvdPcieKiloIo));
CalculateBusConsumptionBeforeAssign (ParentPciAddress, HpcPciAddress, &ConsumedBusNumber);
Index = 0;
Status = GetCurrentBusP2pbHotPlug(RpSeg, (UINT8)RpBus, &Index);
if (Status == EFI_SUCCESS) {
// RsvdExtraBusNum = (Reserved Bus - UpStream Bus - DownStream Bus - Tatal Non-HotPlug Bus) / Total HotPlug P2pb
if (mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug != 0) {
*RsvdExtraBusNum = (UINT8) DivU64x32Remainder ((UINT64)(*RsvdExtraBusNum - ConsumedBusNumber - mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug), (UINT32)mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug, &mRemainderBus);
}
// If mRemainderBus not equal zero, check this device is the last one or not.
if (mRemainderBus != 0) {
DEBUG((DEBUG_INFO, "Remainder Bus = %x in the Seg:%x Bus:%x layer\n", mRemainderBus, RpSeg, RpBus));
if (IsLastP2pbDevice(HpcPciAddress)) {
DEBUG((DEBUG_INFO, "This device is the last P2pb in the same layer, so we need to add Remainder Bus\n"));
*RsvdExtraBusNum = (UINT8)(*RsvdExtraBusNum + mRemainderBus);
}
}
*RsvdPcieMegaMem = (*RsvdPcieMegaMem - mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
*RsvdPciePMegaMem = (*RsvdPciePMegaMem)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
*RsvdPcieKiloIo = (*RsvdPcieKiloIo)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
DEBUG ((DEBUG_INFO, "Current resource as below \n"));
DEBUG ((DEBUG_INFO, "BusNum = %x \n", *RsvdExtraBusNum));
DEBUG ((DEBUG_INFO, "PcieMegaMem = %x \n", *RsvdPcieMegaMem));
DEBUG ((DEBUG_INFO, "PciePMegaMem = %x \n", *RsvdPciePMegaMem));
DEBUG ((DEBUG_INFO, "PcieKiloIo = %x \n", *RsvdPcieKiloIo));
} else {
DEBUG ((DEBUG_INFO, "GetCurrentBusP2pbHotPlug Status =%r\n", Status));
}
}
/**
Get resource padding information from record.
@param[in] Event A pointer to the Event that triggered the callback.
@param[in] Handle Checkpoint handle.
**/
VOID
EFIAPI
PciHpcGetResourcePaddingCallback (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
) {
EFI_STATUS Status;
H2O_DXE_CP_PCI_HPC_GET_RESOURCE_PADDING_DATA *PciHpcGetResourcePaddingData;
UINT8 RsvdExtraBusNum = 0;
UINT16 RsvdPcieMegaMem = 10;
UINT8 PcieMemAddrRngMax = 1;
UINT16 RsvdPciePMegaMem = 10;
UINT8 PciePMemAddrRngMax = 1;
UINT8 RsvdPcieKiloIo = 4;
UINTN RpBus;
CHAR16 *DevicePathStr;
UINT64 AlignmentTemp = 0;
Status = H2OCpLookup (Handle, (VOID **) &PciHpcGetResourcePaddingData, &gH2ODxeCpPciHpcGetResourcePaddingGuid);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Checkpoint Data Not Found: %x (%r)\n", Handle, Status));
DEBUG ((EFI_D_ERROR, " %a\n", __FUNCTION__));
return;
}
DEBUG ((DEBUG_INFO, "PciHpcGetResourcePaddingCallback start. \n"));
// Record the segment number in Bit[32] of HpcPciAddress.
DevicePathStr = ConvertDevicePathToText (PciHpcGetResourcePaddingData->PciDevicePath, TRUE, TRUE);
if (DevicePathStr != NULL) {
if (StrnCmp (DevicePathStr, PCI_ROOT_0_STRING, StrLen (PCI_ROOT_0_STRING)) == 0) {
DEBUG ((DEBUG_INFO, "Segment0 \n"));
PciHpcGetResourcePaddingData->PciAddress &= ~BIT32;
} else if (StrnCmp (DevicePathStr, PCI_ROOT_1_STRING, StrLen (PCI_ROOT_1_STRING)) == 0) {
DEBUG ((DEBUG_INFO, "Segment1 \n"));
PciHpcGetResourcePaddingData->PciAddress |= BIT32;
}
} else {
DEBUG ((DEBUG_ERROR, "Segment error. \n"));
}
RpBus = (UINTN) ((PciHpcGetResourcePaddingData->PciAddress >> 24) & 0xFF);
if (RpBus == 0x00) {
//
// Record RootPort resource
//
if (PciHpcGetResourcePaddingData->ResourcePaddingFound) {
//
// PciHotPlug driver had found resource,
// Just record it.
// Transform value to RC code record format.
//
RsvdExtraBusNum = PciHpcGetResourcePaddingData->ReservedBusCount;
RsvdPcieKiloIo = (UINT8)(PciHpcGetResourcePaddingData->ReservedIoRange / 0x400);
RsvdPcieMegaMem = (UINT16)(PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio / 0x100000);
AlignmentTemp = PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio;
//
// Change Alignment from value to shift bits.
//
if (AlignmentTemp != 0) {
AlignmentTemp = AlignmentTemp - 1;
while (AlignmentTemp > 1) {
AlignmentTemp = RShiftU64(AlignmentTemp, 1);
PcieMemAddrRngMax++;
}
}
RsvdPciePMegaMem = (UINT16)(PciHpcGetResourcePaddingData->ReservedPrefetchableMmio / 0x100000);
//
// Change Alignment from value to shift bits.
//
AlignmentTemp = PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio;
if (AlignmentTemp != 0) {
AlignmentTemp = AlignmentTemp - 1;
while (AlignmentTemp > 1) {
AlignmentTemp = RShiftU64(AlignmentTemp, 1);
PciePMemAddrRngMax++;
}
}
} else {
//
// PciHotPlug driver didn't find resource,
// Give default resource.
//
PciHpcGetResourcePaddingData->ReservedBusCount = RsvdExtraBusNum;
PciHpcGetResourcePaddingData->ReservedIoRange = RsvdPcieKiloIo * 0x400;
PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio = RsvdPcieMegaMem * 0x100000;
PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio = LShiftU64(1, PcieMemAddrRngMax);
PciHpcGetResourcePaddingData->ReservedPrefetchableMmio = RsvdPciePMegaMem * 0x100000;
PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio = LShiftU64(1, PciePMemAddrRngMax);
}
} else {
//
// Handle the GetResourcePadding for Non-RootPort
//
HandleResourcePaddingForNonRootPort (
PciHpcGetResourcePaddingData->PciDevicePath,
PciHpcGetResourcePaddingData->PciAddress,
&RsvdExtraBusNum,
&RsvdPcieMegaMem,
&PcieMemAddrRngMax,
&RsvdPciePMegaMem,
&PciePMemAddrRngMax,
&RsvdPcieKiloIo
);
}
//
// Record resource.
//
Status = UpdateP2pbResourceRecord (
PciHpcGetResourcePaddingData->PciDevicePath,
PciHpcGetResourcePaddingData->PciAddress,
RsvdExtraBusNum,
RsvdPcieMegaMem,
PcieMemAddrRngMax,
RsvdPciePMegaMem,
PciePMemAddrRngMax,
RsvdPcieKiloIo
);
if (Status == EFI_SUCCESS) {
mP2pbResourceRecordCount ++;
}
PciHpcGetResourcePaddingData->ResourcePaddingFound = TRUE;
PciHpcGetResourcePaddingData->Status = H2O_CP_TASK_UPDATE;
PciHpcGetResourcePaddingData->Above4GbMmioSupported = mEnableAbove4GBMmio;
//
// Return value with the format that PciHotPlugDxe used.
//
PciHpcGetResourcePaddingData->ReservedBusCount = RsvdExtraBusNum - 1;
PciHpcGetResourcePaddingData->ReservedIoRange = RsvdPcieKiloIo * 0x400;
PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio = RsvdPcieMegaMem * 0x100000;
PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio = LShiftU64(1, PcieMemAddrRngMax);
PciHpcGetResourcePaddingData->ReservedPrefetchableMmio = RsvdPciePMegaMem * 0x100000;
PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio = LShiftU64(1, PciePMemAddrRngMax);
DEBUG ((DEBUG_INFO, "Resource Padding infomation\n"));
DEBUG ((DEBUG_INFO, " Bus: 0x%x, Dev: 0x%x, Func: 0x%x\n", ((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 24) & 0xFF),
((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 16) & 0xFF),
((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 8) & 0xFF)));
DEBUG ((DEBUG_INFO, " ReservedBusCount : 0x%x\n", PciHpcGetResourcePaddingData->ReservedBusCount));
DEBUG ((DEBUG_INFO, " ReservedIoRange : 0x%x\n", PciHpcGetResourcePaddingData->ReservedIoRange));
DEBUG ((DEBUG_INFO, " ReservedNonPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio));
DEBUG ((DEBUG_INFO, " AlignmentOfReservedNonPrefetchableMmio: 0x%x\n", PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio - 1));
DEBUG ((DEBUG_INFO, " ReservedPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->ReservedPrefetchableMmio));
DEBUG ((DEBUG_INFO, " AlignmentOfReservedPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio - 1));
DEBUG ((DEBUG_INFO, " Above4GbMmioSupported : 0x%x\n", PciHpcGetResourcePaddingData->Above4GbMmioSupported));
return;
}