/** @file
Copyright (c) 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include "PcieAddress.h"
#if !defined(MINIBIOS_BUILD) && !defined(KTI_SW_SIMULATION) && !defined(SIM_BUILD)
#include
#endif
#ifdef _MSC_VER
#pragma optimize ("",off)
#endif //_MSC_VER
//////////////////////////////////////////////////////////////////////////
//
// Common Silicon Address Library
// This Lib provide the way use platform Library instance
//
//////////////////////////////////////////////////////////////////////////
PCIE_MMCFG_TABLE_TYPE mMmcfgTable =\
{
{
{'M', 'C', 'F', 'G'}, // Signature
0x00000090, // Length
0x01, // Revision
0x08, // The Maximum number of Segments
0x00FF, // Valid Segment Bit Map, LSB Bit0 for Seg0, bit1 for seg1 ...
{0x00,0x00,0x00,0x00} // Reserved
},
{{
0, //MMCFG_BASE_ADDRESS, // Base Address Low
0x00000000, // Base Address High
0x0000, // Segment 0
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
}}
};
//
// Segment 1 ~ 7
//
PCIE_MMCFG_BASE_ADDRESS_TYPE mMmcfgAddr[] = \
{
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0001, // Segment 1
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0002, // Segment 2
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0003, // Segment 3
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0004, // Segment 4
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0005, // Segment 5
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0006, // Segment 6
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
},
{
0x00000000, // Base Address Low
0x00000000, // Base Address High
0x0007, // Segment 7
0x00, // Start Bus
0xFF, // End Bus
{0x00,0x00,0x00,0x00} // Reserved
}
};
/**
This Lib is used for platfor to set platform specific Pcie MMCFG Table
@param MmcfgTable: A pointer of the MMCFG Table structure for PCIE_MMCFG_TABLE_TYPE type.
@param NumOfSeg: Sumber of Segments in the table.
@retval <>NULL The function completed successfully.
@retval NULL Returen Error
**/
UINTN
SetSocketMmcfgTable (
IN UINT8 SocketLastBus[],
IN UINT8 SocketFirstBus[],
IN UINT8 segmentSocket[],
IN UINT32 mmCfgBaseH[],
IN UINT32 mmCfgBaseL[],
IN UINT8 NumOfSocket
)
{
#if !defined(MINIBIOS_BUILD) && !defined(KTI_SW_SIMULATION) && !defined(SIM_BUILD)
UINT32 MmcfgTableSize;
PCIE_MMCFG_TABLE_TYPE *HobMmcfgTable;
UINT8 i, *Dest, *Source;
union {
UINT64 D64;
UINT32 D32[2];
} Data;
MmcfgTableSize = sizeof(PCIE_MMCFG_HEADER_TYPE) + (NumOfSocket * sizeof(PCIE_MMCFG_BASE_ADDRESS_TYPE));
HobMmcfgTable = (PCIE_MMCFG_TABLE_TYPE *) PcdGetPtr (PcdPcieMmcfgTablePtr);
ASSERT (MmcfgTableSize < PcdGetSize (PcdPcieMmcfgTablePtr));
Data.D64 = PcdGet64 (PcdPciExpressBaseAddress);
mMmcfgTable.MmcfgBase[0].BaseAddressL = Data.D32[0];
mMmcfgTable.MmcfgBase[0].BaseAddressH = Data.D32[1];
//1. copy global variable mMcfgTable to HobMmcfgTable
// note that mMmcfgTable only has PCIE_MMCFG_BASE_ADDRESS_TYPE for segment 0 (for socket 0)
// need to copy base addresses for other segments corresponding to sockets 1 through NumOfSocket-1
Dest = (UINT8*)HobMmcfgTable;
Source = (UINT8*)&mMmcfgTable;
for(i=0; i 1){
Dest = (UINT8*)&HobMmcfgTable->MmcfgBase[1];
Source = (UINT8*)&mMmcfgAddr[0];//array of base addresses starting with segment 1 (max segment = 7)
for(i = 0; i< (MmcfgTableSize - sizeof(PCIE_MMCFG_TABLE_TYPE)); i++){
Dest[i] = Source[i];
}
}
HobMmcfgTable->Header.Length = MmcfgTableSize;
for(i=0; iMmcfgBase[i].StartBus = SocketFirstBus[i];
HobMmcfgTable->MmcfgBase[i].EndBus = SocketLastBus[i];
HobMmcfgTable->MmcfgBase[i].Segment = segmentSocket[i];
HobMmcfgTable->MmcfgBase[i].BaseAddressH = mmCfgBaseH[i];
HobMmcfgTable->MmcfgBase[i].BaseAddressL = mmCfgBaseL[i];
}
#endif
return 0;
};
/**
This Lib is used for platform to set platform specific Pcie MMCFG Table
@param MmcfgTable: A pointer of the MMCFG Table structure for PCIE_MMCFG_TABLE_TYPE type.
@param NumOfSeg: Sumber of Segments in the table.
@retval <>NULL The function completed successfully.
@retval NULL Returen Error
**/
UINTN
EFIAPI
SetPcieSegMmcfgTable (
IN PCIE_MMCFG_TABLE_TYPE *MmcfgTable,
IN UINT32 NumOfSeg
)
{
#if !defined(MINIBIOS_BUILD) && !defined(KTI_SW_SIMULATION) && !defined(SIM_BUILD)
UINT32 MmcfgTableSize;
PCIE_MMCFG_TABLE_TYPE *HobMmcfgTable;
union {
UINT64 D64;
UINT32 D32[2];
} Data;
Data.D32[0] = Data.D32[1] = 0;
MmcfgTableSize = sizeof(PCIE_MMCFG_HEADER_TYPE) + (NumOfSeg * sizeof(PCIE_MMCFG_BASE_ADDRESS_TYPE));
HobMmcfgTable = (PCIE_MMCFG_TABLE_TYPE *) PcdGetPtr (PcdPcieMmcfgTablePtr);
//ASSERT (MmcfgTableSize < PcdGetSize (PcdPcieMmcfgTablePtr));
//InternalMemCopyMem(HobMmcfgTable, MmcfgTable, PcdGetSize (PcdPcieMmcfgTablePtr));
MmcfgTable->Header.Length = MmcfgTableSize;
if((MmcfgTable->MmcfgBase[0].BaseAddressL == 0) && (MmcfgTable->MmcfgBase[0].BaseAddressH == 0))
{
//
// The first time default should be the PcdPciExpressBaseAddress
//
Data.D64 = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
HobMmcfgTable->MmcfgBase[0].BaseAddressL = Data.D32[0];
HobMmcfgTable->MmcfgBase[0].BaseAddressH = Data.D32[1];
};
#endif
return 0;
};
/**
This Lib return PCIE MMCFG Base Address
@param Address: A pointer of the address of the Common Address Structure for PCIE type.
@param Buffer: A pointer of buffer for the value read from platform.
@retval <>NULL The function completed successfully.
@retval NULL Returen Error
**/
UINTN
EFIAPI
GetPcieSegMmcfgBaseAddress (
IN USRA_ADDRESS *Address
)
{
UINT32 BaseAddressL=0; // Processor-relative Base Address (Lower 32-bit) for the Enhanced Configuration Access Mechanism
UINT32 BaseAddressH=0;
UINTN SegMmcfgBase;
#if !defined(MINIBIOS_BUILD) && !defined(KTI_SW_SIMULATION)
PCIE_MMCFG_TABLE_TYPE *MmcfgTable=NULL;
union {
UINTN D64;
UINT32 D32[2];
} Data;
#endif
#if !defined(MINIBIOS_BUILD) && !defined(KTI_SW_SIMULATION)
if(Address->Attribute.HostPtr == 0) {
MmcfgTable = (PCIE_MMCFG_TABLE_TYPE *) PcdGetPtr (PcdPcieMmcfgTablePtr);
if(MmcfgTable->Header.Length != 0)
{
BaseAddressH = MmcfgTable->MmcfgBase[Address->Pcie.Seg].BaseAddressH;
BaseAddressL = MmcfgTable->MmcfgBase[Address->Pcie.Seg].BaseAddressL;
} else {
//
// if it is not valid MMCFG pointer, initialize it to use the predefined default MMCFG Table
//
SetPcieSegMmcfgTable(&mMmcfgTable, PcdGet32 (PcdNumOfPcieSeg));
BaseAddressH = mMmcfgTable.MmcfgBase[Address->Pcie.Seg].BaseAddressH;
BaseAddressL = mMmcfgTable.MmcfgBase[Address->Pcie.Seg].BaseAddressL;
if((BaseAddressL == 0) && (BaseAddressH == 0)){
Data.D32[0] = Data.D32[1] = 0;
Data.D64 = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
BaseAddressL = Data.D32[0];
BaseAddressH = Data.D32[1];
}
}
}
else
#endif
{
BaseAddressH = 0;
BaseAddressL = 0;
}
if((BaseAddressL == 0) && (BaseAddressH == 0))
{
#if defined(MINIBIOS_BUILD) || defined(KTI_SW_SIMULATION)
BaseAddressL = 0x80000000;
BaseAddressH = 0;
#else
//
// The first time default should be the PcdPciExpressBaseAddress
//
Data.D32[0] = Data.D32[1] = 0;
Data.D64 = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
BaseAddressL = Data.D32[0];
BaseAddressH = Data.D32[1];
#endif
}
return SegMmcfgBase = BaseAddressL;
};