diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/ACPI/mptable.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/ACPI/mptable.c')
-rw-r--r-- | Core/EM/ACPI/mptable.c | 1553 |
1 files changed, 1553 insertions, 0 deletions
diff --git a/Core/EM/ACPI/mptable.c b/Core/EM/ACPI/mptable.c new file mode 100644 index 0000000..66fe0d4 --- /dev/null +++ b/Core/EM/ACPI/mptable.c @@ -0,0 +1,1553 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/BIN/Modules/ACPI/Template/Core/mptable.c 31 12/13/12 12:01p Oleksiyy $ +// +// $Revision: 31 $ +// +// $Date: 12/13/12 12:01p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Modules/ACPI/Template/Core/mptable.c $ +// +// 31 12/13/12 12:01p Oleksiyy +// [TAG] EIP109290 +// [Category] Improvement +// [Description] Issues found by CppCheck in ACPI eModule +// [Files] AcpiCore.c, mptable.c, AmlString.c, BootScriptSave.c and +// BootScriptExecuter.c +// +// 30 1/12/12 4:51p Oleksiyy +// [TAG] EIP80870 +// [Category] Improvement +// [Description] MP table entry has a zero sized Address Length. +// [Files] mptable.c +// +// 29 1/12/12 4:15p Oleksiyy +// [TAG] EIP79240 +// [Category] Improvement +// [Description] Added Variable to handle the situation when MP table +// created multiple times. +// [Files] mptable.c +// +// 28 11/29/11 12:20p Oleksiyy +// [TAG] EIP76814 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] MP_TABLE_LEGACY_REGION_LOCATION = 0 causes build error +// [RootCause] Unreferenced variable: LegacyBiosProtocol +// [Solution] Variable declared only if MP_TABLE_LEGACY_REGION_LOCATION +// != 0 +// [Files] mptable.c +// +// 27 7/19/11 11:31a Oleksiyy +// [TAG] EIP64108 +// [Category] Improvement +// [Description] ACPI, convert or update all eModules to be compliant +// with PI 1.2, and UEFI 2.3.1 specifications. +// [Files] AcpiCore.c, mptable.c, AcpiS3Save.c, S3Resume.dxs, +// S3Resume.c, AcpiPeiS3Func.c, BootScriptExecuter.c and DxeIpl.c +// +// 26 5/25/10 5:07p Yakovlevs +// Fixed Issue when with Multiple IO APICs, upper IOAPIC's INT_IN 0 was +// excluded from the table. +// +// 25 9/28/09 3:59p Yakovlevs +// +// 24 5/27/09 5:41p Yakovlevs +// CSM Protocol definition moved in #if scope +// +// 23 5/18/09 10:11a Yakovlevs +// Added support of IOAPIC discovery tokens. Some project don't want +// certain algorithms to be used. +// +// 22 5/15/09 12:49p Yakovlevs +// Fixed logic in IOAPIC discovery ordering. +// +// 21 5/14/09 5:39p Yakovlevs +// Added code to use "USE_BOARD_INFO_APIC_DATA" token +// +// 20 5/08/09 1:16p Yakovlevs +// Made ACPI Driver use AMI Board Info Protocol if available without +// breaking compatibility. +// +// 19 5/07/09 5:46p Markw +// Use #ifdef ACPI_INFO2_PROTOCOL_PUBLISHED to exclude code that uses ACPI +// INFO 2 for CPUs that provide the header files. +// +// 18 5/04/09 5:49p Markw +// EIP #17903 If AmiCpuInfo2 Protocol available, MP tables will use this +// instead of hobs. +// +// 17 3/26/09 4:51p Oleksiyy +// New ACPI Core implementation - improves logic, execution time and +// memory usage of ACPI module. +// +// 16 2/06/09 4:52p Yakovlevs +// Added Creating EFI Config Table Entry for MPS 14. +// +// 15 10/06/08 3:07p Yakovlevs +// Restored accidentally removed fixes. +// +// 14 9/25/08 4:14p Artems +// Solve problem with non-consecutive IO APIC IDs +// +// 13 7/14/08 3:26p Markw +// In for loop count total number of local apics (hyper-threading) not +// just number of cores. Code already correctly skips hyper-treading in +// for loop. +// +// 12 7/07/08 5:06p Artems +// Fixed bug in PCI IOAPIC detection +// +// 11 6/11/08 5:58p Markw +// Update MpsTableAddCpuEntry function to multiple cores and threads to +// get total CPUs instead just cores. +// +// 10 4/15/08 9:16p Yakovlevs +// Functions Headers added +// +// 9 4/11/07 5:44p Artems +// Multi processor detection added +// +// 8 3/28/07 10:42a Artems +// Fixed bug - added System memory map entry for legacy video +// +// 7 3/19/07 12:19p Felixp +// Clean up +// +// 6 3/13/07 6:40p Yakovlevs +// +// 5 3/13/07 5:41p Artems +// MPS 1.4 TABLE SUPPORT added +// +// 3 2/06/07 5:38p Artems +// +// 2 2/06/07 5:25p Artems +// +// 1 2/06/07 4:54p Artems +// + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: mptable.c +// +// Description: MPS table builder functions implementation +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <Token.h> + +//------------------------ Include files ------------------------------ + +#include <AmiDxeLib.h> +#include <AmiHobs.h> + +#include <Protocol/LegacyBios.h> +#include <Protocol/AmiCpuInfo.h> + +#ifdef ACPI_INFO2_PROTOCOL_PUBLISHED +#include <Protocol\AmiCpuInfo2.h> +#endif + + +#include "acpicore.h" +#include "mptable.h" + + +#include <Protocol\AmiBoardInfo.h> +extern AMI_BOARD_INFO_PROTOCOL *gAmiBoardInfoProtocol; + +//------------------------ Global variables --------------------------- + +static EFI_GUID gMpsTableGuid = MPS_TABLE_GUID; +static EFI_GUID EfiLegacyBiosProtocolGuid = EFI_LEGACY_BIOS_PROTOCOL_GUID; +AMI_CPU_INFO_PROTOCOL *AmiCpuInfoProtocol = NULL; +static EFI_GUID AmiCpuInfoProtocolGuid = AMI_CPU_INFO_PROTOCOL_GUID; +static EFI_EVENT MpsTableReadyToBootEvent = 0; +static MP_FLOATING_POINTER MpsTableFloatingPointer; +static VOID *MpsTablePointer = NULL; +static VOID *MpsTableCurrentPointer = NULL; +static VOID *MpsExTablePointer = NULL; +static VOID *MpsExTableCurrentPointer = NULL; +static UINT16 BaseTableLength = 0; +static UINT16 BaseTableEntryCount = 0; +static UINT16 ExtendedTableLength = 0; +static UINT8 OemId[8] = CONVERT_TO_STRING(T_ACPI_OEM_TBL_ID); //{ 0,1,2,3,4,5,6,7 }; +static UINT8 ProductId[12] = CONVERT_TO_STRING(T_ACPI_OEM_ID); //{ 0,1,2,3,4,5,6,7,8,9,0xA, 0xB }; + +static BUS_INFO BusEntry[MP_TABLE_MAX_BUS_ENTRIES]; +static UINT8 MaxBusId = 0; +static UINT8 CurrentBusEntry = 0; +static UINT8 IsaBusId = 0; +static UINT8 *BusTypeString[] = {"CBUS ", "CBUSII", "EISA ", "FUTURE", "INTERN", "ISA ", + "MBI ", "MBII ", "MCA ", "MPI ", "MPSA ", "NUBUS ", + "PCI ", "PCMCIA", "TC ", "VL ", "VME ", "XPRESS" }; +static UINT8 BridgeBusTypes[] = { 12, 5, 2, 8, 12, 13, 11 }; //each number represents corresponding + //number in BusTypeString array, i.e. + //bridge subclass 0 - PCI host has number + //12 in array, subclass 1 - ISA bridge - + //number 5 etc. +static IO_APIC_INFO IoApicEntry[MP_TABLE_MAX_IO_APIC_ENTRIES]; +static UINT8 CurrentIoApicEntry = 0; + +#ifdef ACPI_INFO2_PROTOCOL_PUBLISHED +extern AMI_CPU_INFO_2_PROTOCOL* gAmiCpu2Info; +#endif + + +extern ISO_PARAMETER_TABLE IsoTbl[]; +EFI_STATUS MpsTableCreateStatus = EFI_NO_RESPONSE; +EFI_STATUS MpsTableFloatPointerModifyStatus = EFI_NO_RESPONSE; +BOOLEAN MpsTableWasCreated = FALSE; +//------------------------ Functions ---------------------------------- + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableBuilderInit +// +// Description: MPS table builder entry point +// +// Input: +// IN EFI_HANDLE ImageHandle - MPS table builder image handle +// IN EFI_SYSTEM_TABLE *SystemTaple - pointer to system table +// +// Output: +// EFI_SUCCESS - Initialization completed successfully +// EFI_ERROR - Initialization failed +// +// Modified: MpsTableReadyToBootEvent +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS MpsTableBuilderInit( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + + InitAmiLib(ImageHandle,SystemTable); + + Status = CreateReadyToBootEvent(TPL_CALLBACK, + MpsTableReadyToBootNotify, + NULL, + &MpsTableReadyToBootEvent); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableReadyToBootNotify +// +// Description: MPS table builder ReadyToBoot notification function +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to calling context +// +// Output: +// VOID +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID MpsTableReadyToBootNotify( + IN EFI_EVENT Event, + IN VOID *Context) +{ + EFI_STATUS Status; + + if(EFI_ERROR(MpsTableCreateStatus)) + { + MpsTableCreateStatus = MpsTableCreate(); + if(EFI_ERROR(MpsTableCreateStatus)) + return; + } + if(EFI_ERROR(MpsTableFloatPointerModifyStatus)) + MpsTableFloatPointerModifyStatus = MpsTableFloatPointerModify(); + + //Install a Configuration table Entry + Status=pBS->InstallConfigurationTable(&gMpsTableGuid,MpsTablePointer); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) return; + //After we did everything needed + pBS->CloseEvent(Event); + + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableFloatPointerModify +// +// Description: Fills MP_FLOATING_POINTER structure with actual data +// and places it into F000 segment +// +// Input: +// VOID +// +// Output: +// EFI_SUCCESS - Pointer created and placed successfully +// EFI_ERROR - Some error occurs +// +// Modified: MpsTableFloatingPointer +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS MpsTableFloatPointerModify(VOID) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBiosProtocol; + VOID *LegacyRegionAddress; + + MpsTableFloatingPointer.Signature = MP_FLOATING_POINTER_SIGNATURE; + +//at this point we have address of MPS table + MpsTableFloatingPointer.PhysicalAddresPointer = (UINT32) MpsTablePointer; + +//length in 16-byte paragraphs + MpsTableFloatingPointer.Length = sizeof(MP_FLOATING_POINTER)/16; + +//here must be token + MpsTableFloatingPointer.VersionNumber = MP_TABLE_VERSION_1_4; + +//force checksum to zero before calculate actual checksum + MpsTableFloatingPointer.CheckSum = 0; + +//here must be token + MpsTableFloatingPointer.DefaultConfiguration = 0; + +//here must be token + MpsTableFloatingPointer.IMCRflag = 0; + + MpsTableFloatingPointer.Reserved[0] = 0; + MpsTableFloatingPointer.Reserved[1] = 0; + MpsTableFloatingPointer.Reserved[2] = 0; + +//now we are ready to calculate checksum + MpsTableFloatingPointer.CheckSum = ChsumTbl((UINT8 *)&MpsTableFloatingPointer, + sizeof(MP_FLOATING_POINTER)); + + Status = pBS->LocateProtocol(&EfiLegacyBiosProtocolGuid, + NULL, + &LegacyBiosProtocol); + if(EFI_ERROR(Status)) + return Status; + + Status = LegacyBiosProtocol->GetLegacyRegion(LegacyBiosProtocol, + (UINTN)sizeof(MP_FLOATING_POINTER), + F0000_BIT, + 0x10, + &LegacyRegionAddress); + if(EFI_ERROR(Status)) + return Status; + + Status = LegacyBiosProtocol->CopyLegacyRegion(LegacyBiosProtocol, + (UINTN) sizeof(MP_FLOATING_POINTER), + LegacyRegionAddress, + (VOID *) &MpsTableFloatingPointer); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableCreate +// +// Description: Allocates space and creates MPS table +// +// Input: +// VOID +// +// Output: +// EFI_SUCCESS - function executed successfully +// EFI_ERROR - some error occured +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS MpsTableCreate(VOID) +{ + EFI_STATUS Status; + UINT16 EntryCount; + + if (MpsTableWasCreated) + return MpsTableAddHeader(); + + Status = pBS->AllocatePool(EfiBootServicesData, + MP_TBL_TMP_BUFFER_SIZE, + &MpsTablePointer); + if(EFI_ERROR(Status)) + return Status; + + MpsTableCurrentPointer = MpsTablePointer; + +//split buffer onto two parts for base and extended tables + MpsExTablePointer = MpsTablePointer; + (UINT8 *)MpsExTablePointer += ((MP_TBL_TMP_BUFFER_SIZE)/2); + MpsExTableCurrentPointer = MpsExTablePointer; + +//Leave placeholder for header + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_CONFIGURATION_TABLE_HEADER); + BaseTableLength += sizeof(MP_CONFIGURATION_TABLE_HEADER); + +//add CPU Entry + EntryCount = MpsTableAddCpuEntry(); + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_TABLE_CPU_ENTRY) * EntryCount; + BaseTableLength += sizeof(MP_TABLE_CPU_ENTRY) * EntryCount; + BaseTableEntryCount += EntryCount; + +//add Bus Entry + EntryCount = MpsTableAddBusEntry(); + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_TABLE_BUS_ENTRY) * EntryCount; + BaseTableLength += sizeof(MP_TABLE_BUS_ENTRY) * EntryCount; + BaseTableEntryCount += EntryCount; + +//add IO Apic Entry + EntryCount = MpsTableAddIoApicEntry(); + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_TABLE_IO_APIC_ENTRY) * EntryCount; + BaseTableLength += sizeof(MP_TABLE_IO_APIC_ENTRY) * EntryCount; + BaseTableEntryCount += EntryCount; + +//add Interrupt assignment Entry + EntryCount = MpsTableAddIntAssignEntry(); + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_TABLE_INT_ASSIGN_ENTRY) * EntryCount; + BaseTableLength += sizeof(MP_TABLE_INT_ASSIGN_ENTRY) * EntryCount; + BaseTableEntryCount += EntryCount; + +//add Local interrupt assignment Entry + EntryCount = MpsTableAddLocalIntAssignEntry(); + (UINT8 *)MpsTableCurrentPointer += sizeof(MP_TABLE_LOCAL_INT_ASSIGN_ENTRY) * EntryCount; + BaseTableLength += sizeof(MP_TABLE_LOCAL_INT_ASSIGN_ENTRY) * EntryCount; + BaseTableEntryCount += EntryCount; + + MpsTableAddExtendedTable(); + + MpsTableWasCreated = TRUE; + + return MpsTableAddHeader(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddHeader +// +// Description: Creates MPS table header, allocates space and copies entire +// table into RuntimeServicesData memory +// +// Input: +// VOID +// +// Output: +// EFI_SUCCESS - function executed successfully +// +// Modified: MpsTablePointer +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS MpsTableAddHeader(VOID) +{ + EFI_STATUS Status; + MP_CONFIGURATION_TABLE_HEADER *HeaderPointer; + VOID *AllocationPointer; +#if MP_TABLE_LEGACY_REGION_LOCATION != 0 + EFI_LEGACY_BIOS_PROTOCOL *LegacyBiosProtocol; +#endif + HeaderPointer = (MP_CONFIGURATION_TABLE_HEADER *) MpsTablePointer; + + HeaderPointer->Signature = MP_CONFIGURATION_TABLE_SIGNATURE; + HeaderPointer->BaseTableLength = BaseTableLength; + HeaderPointer->VersionNumber = MP_TABLE_VERSION_1_4; + HeaderPointer->CheckSum = 0; //force checksum to zero before calculating + + MemCpy((VOID *)HeaderPointer->OemId, (VOID *)OemId, 8); + MemCpy((VOID *)HeaderPointer->ProductId, (VOID *)ProductId, 12); + + HeaderPointer->OemTablePointer = 0; + HeaderPointer->OemTableSize = 0; + HeaderPointer->BaseTableEntryCount = BaseTableEntryCount; + HeaderPointer->LocalApicAddress = LOCAL_APIC_BASE; //sdl token + HeaderPointer->ExtendedTableLength = ExtendedTableLength; + HeaderPointer->ExtendedCheckSum = 0; + HeaderPointer->Reserved = 0; + + HeaderPointer->ExtendedCheckSum = ChsumTbl(MpsExTablePointer, ExtendedTableLength); + HeaderPointer->CheckSum = ChsumTbl(MpsTablePointer, BaseTableLength); + +#if MP_TABLE_LEGACY_REGION_LOCATION == 0 + +//publish table in high memory + Status = pBS->AllocatePool(EfiRuntimeServicesData, + BaseTableLength + ExtendedTableLength, + &AllocationPointer); + + if(EFI_ERROR(Status)) + return Status; + MemCpy(AllocationPointer, //memory allocated - copy MPS table to new location + MpsTablePointer, + (UINTN) (BaseTableLength + ExtendedTableLength)); + +#else + +//publish table in F0000 segment + Status = pBS->LocateProtocol(&EfiLegacyBiosProtocolGuid, + NULL, + &LegacyBiosProtocol); + if(EFI_ERROR(Status)) + return Status; + + Status = LegacyBiosProtocol->GetLegacyRegion(LegacyBiosProtocol, + (UINTN)(BaseTableLength + ExtendedTableLength), + F0000_BIT, + 0x10, + &AllocationPointer); + if(EFI_ERROR(Status)) + return Status; + + Status = LegacyBiosProtocol->CopyLegacyRegion(LegacyBiosProtocol, + (UINTN) (BaseTableLength + ExtendedTableLength), + AllocationPointer, + MpsTablePointer); +#endif + + pBS->FreePool(MpsTablePointer); + MpsTablePointer = AllocationPointer; + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddCpuEntryByHob +// +// Description: Adds CPU entries to MPS table from HOB. +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 MpsTableAddCpuEntryByHob(VOID) +{ + MP_TABLE_CPU_ENTRY *EntryPointer; + UINT16 EntryCount = 0; + static EFI_GUID CpuInfoHobGuid = AMI_CPUINFO_HOB_GUID; + static EFI_GUID HobListGuid = HOB_LIST_GUID; + CPUINFO_HOB *pCpuInfoHob; + CPUINFO CpuInfo; + VOID *pHobList; + EFI_STATUS Status; + INTN i; + UINTN CpuIndex = 0; + UINT8 NumberOfCores; + UINT8 NumberOfThreads; + + + EntryPointer = (MP_TABLE_CPU_ENTRY *)MpsTableCurrentPointer; + + pHobList = GetEfiConfigurationTable(pST, &HobListGuid); + if(pHobList == NULL) + Status = EFI_NOT_FOUND; + else + Status = FindNextHobByGuid(&CpuInfoHobGuid, &pHobList); + + //If no CPU info available, we've got a UniProccessor System + if (EFI_ERROR(Status)) + { + EntryPointer->EntryType = MP_TABLE_CPU_ENTRY_TYPE; + EntryPointer->LocalApicId = 0; + EntryPointer->LocalApicVersion = 0; + EntryPointer->CpuFlags.CpuEnable = 1; + EntryPointer->CpuFlags.CpuBootStrap = 1; + EntryPointer->CpuFlags.Reserved = 0; + EntryPointer->CpuSignature = 0; + EntryPointer->FeatureFlags = 0; + EntryPointer->Reserved[0] = 0; + EntryPointer->Reserved[1] = 0; + + return 1; //just one CPU entry + } + + pCpuInfoHob = (CPUINFO_HOB *)pHobList; + + while(!EFI_ERROR(GetCpuInfo(CpuIndex, &NumberOfCores, &NumberOfThreads))) + { + for(i = 0; i < NumberOfCores * NumberOfThreads; i += NumberOfThreads) + { + CpuInfo = pCpuInfoHob->Cpuinfo[i + CpuIndex]; + + EntryPointer->EntryType = MP_TABLE_CPU_ENTRY_TYPE; + EntryPointer->LocalApicId = CpuInfo.ApicId; + EntryPointer->LocalApicVersion = CpuInfo.ApicVer; + EntryPointer->CpuFlags.CpuEnable = (CpuInfo.Disabled) ? 0 : 1; + EntryPointer->CpuFlags.CpuBootStrap = ((i + CpuIndex) == pCpuInfoHob->BspNo) ? 1 : 0; + EntryPointer->CpuFlags.Reserved = 0; + EntryPointer->CpuSignature = CpuInfo.CpuSignature; + EntryPointer->FeatureFlags = (UINT32) CpuInfo.CpuFeatureInfo; + EntryPointer->Reserved[0] = 0; + EntryPointer->Reserved[1] = 0; + + EntryPointer++; + EntryCount++; + } + CpuIndex += NumberOfCores * NumberOfThreads; + } + return EntryCount; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddCpuEntryByProtocol. +// +// Description: Adds CPU entries to MPS table from protocol. +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +#ifdef ACPI_INFO2_PROTOCOL_PUBLISHED +UINT16 MpsTableAddCpuEntryByProtocol(VOID) +{ + MP_TABLE_CPU_ENTRY *EntryPointer; + EFI_STATUS Status; + ACPI_PROCESSOR_INFO *AcpiProcInfo; + UINT32 NumEntries; + UINT32 EntryCount = 0; + UINT32 Index; + + if (gAmiCpu2Info->ProtocolVer < 1) return 0; + + Status = gAmiCpu2Info->GetAcpiInfo( + gAmiCpu2Info, (VOID**) &AcpiProcInfo, &NumEntries + ); + if (EFI_ERROR(Status)) return 0; + + EntryPointer = (MP_TABLE_CPU_ENTRY *)MpsTableCurrentPointer; + + for (Index = 0; Index < NumEntries; ++Index) { + //Note: Only some ACPI_PROCESSOR_INFO fields may only valid for some minimum ACPI_PROCESSOR_INFO.Length. + //The ACPI_PROCESSOR_INFO may have additional fields added in later version. Please see comments in + //AmiCpuInfo2.h file. + if (AcpiProcInfo->Type == ACPI_PROCESSOR_INFO_TYPE + && AcpiProcInfo->Thread == 0 + ) { + EntryPointer->EntryType = MP_TABLE_CPU_ENTRY_TYPE; + EntryPointer->LocalApicId = AcpiProcInfo->ApicId; + EntryPointer->LocalApicVersion = AcpiProcInfo->ApicVer; + EntryPointer->CpuFlags.CpuEnable = AcpiProcInfo->Enable; + EntryPointer->CpuFlags.CpuBootStrap = AcpiProcInfo->Bsp; + EntryPointer->CpuFlags.Reserved = 0; + EntryPointer->CpuSignature = AcpiProcInfo->CpuSignature; + EntryPointer->FeatureFlags = AcpiProcInfo->FeatureFlags; + EntryPointer->Reserved[0] = 0; + EntryPointer->Reserved[1] = 0; + EntryPointer++; + EntryCount++; + } + + AcpiProcInfo = (ACPI_PROCESSOR_INFO*)((UINT8*)AcpiProcInfo + AcpiProcInfo->Length); + } + + return (UINT16)EntryCount; +} +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddCpuEntry. +// +// Description: Adds CPU entries to MPS table. +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 MpsTableAddCpuEntry(VOID) +{ + UINT16 EntryCount = 0; + //First try to build Local APIC information from the protocol. +#ifdef ACPI_INFO2_PROTOCOL_PUBLISHED + if (gAmiCpu2Info != NULL) EntryCount = MpsTableAddCpuEntryByProtocol(); + //If protocol fails, try CPU INFO HOB. +#endif + if (!EntryCount) EntryCount = MpsTableAddCpuEntryByHob(); + return EntryCount; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddBusEntry +// +// Description: Adds Bus entries to MPS table +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 MpsTableAddBusEntry(VOID) +{ + MP_TABLE_BUS_ENTRY *EntryPointer; + UINT16 EntryCount = 0; + UINT16 i; + + EntryPointer = (MP_TABLE_BUS_ENTRY *)MpsTableCurrentPointer; + + QueryBusInfo(); + + for(i = 0; i < CurrentBusEntry; i++) + { + EntryPointer->EntryType = MP_TABLE_BUS_ENTRY_TYPE; + EntryPointer->BusId = BusEntry[i].BusId; + + MemCpy((VOID *)EntryPointer->BusTypeString, (VOID *)BusTypeString[(BusEntry[i].BusType)], 6); + + EntryPointer++; + EntryCount++; + } + return EntryCount; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddIoApicEntry +// +// Description: Adds IO Apic entries to MPS table +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 MpsTableAddIoApicEntry(VOID) +{ + MP_TABLE_IO_APIC_ENTRY *EntryPointer; + UINT16 EntryCount = 0; + UINT8 i=0; +#if FEC00000_APIC_AUTODETECT == 1 + UINT64 SearchAddress=0; +#endif + EntryPointer = (MP_TABLE_IO_APIC_ENTRY *)MpsTableCurrentPointer; + +#if FEC00000_APIC_AUTODETECT == 1 +//first we detect IO APICS mapped into default address range + for(SearchAddress = IO_APIC_BASE_ADDRESS_BOTTOM; + SearchAddress < IO_APIC_BASE_ADDRESS_TOP; + SearchAddress += IO_APIC_SEARCH_STEP) + + if(*((UINT8 *)SearchAddress) != 0xFF) //we have something + CollectIoApicInfo(NULL, (UINT32)SearchAddress); + +//second we arrange IO APIC in their ID ascending order (if there more than one) +#endif + + +//Check also SDL ceated Structures they might address very none standard IOAPICS. +//------------------------------------------------------------------------------------------- + +#if USE_BOARD_INFO_APIC_DATA == 1 +{ + AMI_APIC_INFO *BrdApicInfo; + BOOLEAN Present; + UINTN j; + //----------------- + for(i=0; i<(gAmiBoardInfoProtocol->ApicInfoLength/sizeof(AMI_APIC_INFO)); i++){ + BrdApicInfo=&gAmiBoardInfoProtocol->ApicInfoTable[i]; + //This is a special case it could be a duplicate entries in MadtTblEntries[] + //if other options of IOAPIC/IOsAPIC detection was on. + //So check if IOAPIC/IOsAPIC entries with the same properties already present in DB. + for(j=0,Present=FALSE; j < CurrentIoApicEntry; j++){ + if(BrdApicInfo->ApicAddress.ADDRESS == IoApicEntry[j].IoApicAddress){ + Present = TRUE; + break; + } + } + //Entry with this address already present in IoApicEntry[] array + if(Present) continue; + + //Looks like it is a new IOAPIC/IOSAPIC entry! + //Check if something alive at this address + CollectIoApicInfo(NULL, BrdApicInfo->ApicAddress.ADDRESS); + } // for(...i<(gAmiBoardInfoProtocol->ApicInfoLength/sizeof(AMI_APIC_INFO)) +} +#endif //USE_BOARD_INFO_APIC_DATA ==1 + +//------------------------------------------------------------------------------------------- + + if(CurrentIoApicEntry > 1) + ArrangeIoApicEntries(); + + +//now we are ready to create MPS table IO APIC entries + for(i = 0; i < CurrentIoApicEntry; i++) + { + EntryPointer->EntryType = MP_TABLE_IO_APIC_ENTRY_TYPE; + EntryPointer->IoApicId = IoApicEntry[i].IoApicId; + EntryPointer->IoApicVersion = IoApicEntry[i].IoApicVersion; + EntryPointer->Flags = IoApicEntry[i].IoApicFlags; + EntryPointer->IoApicAddress = IoApicEntry[i].IoApicAddress; + + EntryPointer++; + EntryCount++; + } + return EntryCount; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddIntAssignEntry +// +// Description: Adds Interrupt assignment entries to MPS table +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 MpsTableAddIntAssignEntry(VOID) +{ + + MP_TABLE_INT_ASSIGN_ENTRY *EntryPointer; + UINT16 EntryCount = 0; + UINT16 Dummy; + PCI_IRQ_APIC_ROUTE *RouteTable; + UINT8 i, j; + + EntryPointer = (MP_TABLE_INT_ASSIGN_ENTRY *)MpsTableCurrentPointer; + +//First assign ISA IRQ interrupts + AmiIsaIrqMask(&Dummy, TRUE); + + for(i = 0; i < 16; i++) + { + if((Dummy & 1) && (i != 2)) //create entry only if IRQ is used + { //and it isn't IRQ2 + EntryPointer->EntryType = MP_TABLE_INT_ASSIGN_ENTRY_TYPE; + EntryPointer->InterruptType = INT_TYPE_INT; + EntryPointer->Flags = (UINT16)IsoTbl[i].Flags; + EntryPointer->SourceBusId = IsaBusId; + EntryPointer->SourceBusIrq.IsaBusIrq = i; +//define Apic ID and Itin depends of GLobal sys vector + GetIoApicId(IsoTbl[i].ApicInt, + &EntryPointer->DestIoApicId, + &EntryPointer->DestIoApicItin); + + EntryPointer++; + EntryCount++; + } + Dummy >>= 1; + } + +//Second assign PCI IRQ Entries + + Dummy = (UINT16)gAmiBoardInfoProtocol->ApicRoutLength/sizeof(PCI_IRQ_APIC_ROUTE); + RouteTable = gAmiBoardInfoProtocol->ApicRoutTable; + + for(i = 0; i < Dummy; i++) + { +//define runtime bus number from build bus number + + for(j = 0; j < 4; j++) + { + if((RouteTable[i].Intn[j].IoApicItin != 0) || (RouteTable[i].Intn[j].IoApicId != 0)) + { + EntryPointer->EntryType = MP_TABLE_INT_ASSIGN_ENTRY_TYPE; + EntryPointer->InterruptType = INT_TYPE_INT; + EntryPointer->Flags = 0; //always conforms PCI bus specs + EntryPointer->SourceBusId = RouteTable[i].PciBusNumber; + EntryPointer->SourceBusIrq.PciBusIrq.PciIntSignal = j; + EntryPointer->SourceBusIrq.PciBusIrq.PciDeviceNumber = RouteTable[i].DeviceNumber; + EntryPointer->SourceBusIrq.PciBusIrq.Reserved = 0; + EntryPointer->DestIoApicId = RouteTable[i].Intn[j].IoApicId; + EntryPointer->DestIoApicItin = RouteTable[i].Intn[j].IoApicItin; + + EntryPointer++; + EntryCount++; + } + } + } + + return EntryCount; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddLocalIntAssignEntry +// +// Description: Adds Local interrupt assignment entries to MPS table +// +// Input: +// VOID +// +// Output: +// UINT16 - Number of entries added +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 MpsTableAddLocalIntAssignEntry(VOID) +{ + MP_TABLE_LOCAL_INT_ASSIGN_ENTRY *EntryPointer; + UINT16 EntryCount = 0; + + EntryPointer = (MP_TABLE_LOCAL_INT_ASSIGN_ENTRY *)MpsTableCurrentPointer; + + EntryPointer->EntryType = MP_TABLE_LOCAL_INT_ASSIGN_ENTRY_TYPE; + EntryPointer->InterruptType = INT_TYPE_EXT_INT; + EntryPointer->InterruptSignal.Polarity = POLARITY_CONFORM_SPEC; + EntryPointer->InterruptSignal.TriggerMode = TRIGGER_MODE_CONFORM_SPEC; + EntryPointer->InterruptSignal.Reserved = 0; + EntryPointer->SourceBusId = 0; + EntryPointer->SourceBusIrq = 0; + EntryPointer->DestLocalApicId = 0xFF; + EntryPointer->DestLocalApicItin = 0; + + EntryPointer++; + EntryCount++; + + EntryPointer->EntryType = MP_TABLE_LOCAL_INT_ASSIGN_ENTRY_TYPE; + EntryPointer->InterruptType = INT_TYPE_NMI; + EntryPointer->InterruptSignal.Polarity = POLARITY_CONFORM_SPEC; + EntryPointer->InterruptSignal.TriggerMode = TRIGGER_MODE_CONFORM_SPEC; + EntryPointer->InterruptSignal.Reserved = 0; + EntryPointer->SourceBusId = 0; + EntryPointer->SourceBusIrq = 0; + EntryPointer->DestLocalApicId = 0xFF; + EntryPointer->DestLocalApicItin = 1; + + EntryPointer++; + EntryCount++; + + return EntryCount; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsTableAddExtendedTable +// +// Description: Adds Extended table entries to base table +// +// Input: +// VOID +// +// Output: +// VOID +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MpsTableAddExtendedTable(VOID) +{ + MemCpy(MpsTableCurrentPointer, MpsExTablePointer, ExtendedTableLength); + MpsExTablePointer = MpsTableCurrentPointer; + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsExTableAddSysAddressMapEntry +// +// Description: Creates Extended MPS table system address space map entryies +// +// Input: +// IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *pPciRootBridgeIoProtocol +// IN UINT8 BusId - PCI bus number +// IN UINT8 BusAttributes - PCI bus attributes +// +// Output: +// VOID +// +// Modified: MpsExTableCurrentPointer +// ExtendedTableLength +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MpsExTableAddSysAddressMapEntry( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *pPciRootBridgeIoProtocol, + IN UINT8 BusId, + IN UINT8 BusAttributes) +{ + MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY *EntryPointer; + ACPI_ADDRESS_SPACE_DESC *Resources; + BOOLEAN VgaMemoryAdded = FALSE; + + EntryPointer = (MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY *)MpsExTableCurrentPointer; + + pPciRootBridgeIoProtocol->Configuration(pPciRootBridgeIoProtocol, &Resources); + +//add entries to ISA decode + if(BusAttributes & 0x3) //support ISA I/O space + { + EntryPointer->EntryType = MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + EntryPointer->BusId = BusId; + EntryPointer->AddressType = 0; //IO descriptor + EntryPointer->AddressBase = 0; + EntryPointer->AddressLength = 0x1000; + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + } + + while(Resources->Signature == 0x8A) + { + if(Resources->ResourceType != 2 && Resources->AddressLength) + { + if(Resources->ResourceType == 1) //IO descriptor + EntryPointer->AddressType = 0; + else if(Resources->TypeSpecificFlags & 6) //bits 1 and 2 set + EntryPointer->AddressType = 2; //memory prefetch address + else + EntryPointer->AddressType = 1; //memory descriptor + +// VGA region should be at the beginning of Memory range + if ((EntryPointer->AddressType == 1) && (BusAttributes & 0x1C) && (!(VgaMemoryAdded))) { + EntryPointer->EntryType = MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + EntryPointer->BusId = BusId; + EntryPointer->AddressType = 1; //memory descriptor + EntryPointer->AddressBase = 0xA0000; + EntryPointer->AddressLength = 0x20000; + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + VgaMemoryAdded = TRUE; + EntryPointer->AddressType = 1; //memory descriptor + } + + EntryPointer->EntryType = MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + EntryPointer->BusId = BusId; + EntryPointer->AddressBase = Resources->AddressRangeMin; + EntryPointer->AddressLength = Resources->AddressLength; + + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_SYS_ADDRESS_MAP_ENTRY); + } + Resources++; + } + + MpsExTableCurrentPointer = (VOID *)EntryPointer; + + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsExTableAddBusHierarchyEntry +// +// Description: Creates Extended MPS table bus hierarchy entryies +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: MpsExTableCurrentPointer +// ExtendedTableLength +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MpsExTableAddBusHierarchyEntry(VOID) +{ + MP_EX_TABLE_BUS_HIERARCHY_ENTRY *EntryPointer; + UINT8 i; + + EntryPointer = (MP_EX_TABLE_BUS_HIERARCHY_ENTRY *)MpsExTableCurrentPointer; + + for(i = 0; i < CurrentBusEntry; i++) + { + if(BusEntry[i].ParentBusId != 0xFF && BusEntry[i].BusType != 12) //skip root bridge and P2P bridge + { + EntryPointer->EntryType = MP_EX_TABLE_BUS_HIERARCHY_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_BUS_HIERARCHY_ENTRY); + EntryPointer->BusId = BusEntry[i].BusId; + EntryPointer->BusInfo = BusEntry[i].Flags; + EntryPointer->ParentBusId = BusEntry[i].ParentBusId; + EntryPointer->Reserved[0] = 0; + EntryPointer->Reserved[1] = 0; + EntryPointer->Reserved[2] = 0; + + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_BUS_HIERARCHY_ENTRY); + } + } + MpsExTableCurrentPointer = (VOID *)EntryPointer; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: MpsExTableAddCompatBusAddressModifierEntry +// +// Description: Creates Extended MPS table compatibility bus address space +// modifier entryies +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: MpsExTableCurrentPointer +// ExtendedTableLength +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MpsExTableAddCompatBusAddressModifierEntry(VOID) +{ + MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY *EntryPointer; + UINT8 i; + + EntryPointer = (MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY *)MpsExTableCurrentPointer; + + for(i = 0; i < CurrentBusEntry; i++) + { + if(BusEntry[i].ParentBusId == 0xFF) + { + //add/subtract ISA predefined range + EntryPointer->EntryType = MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY); + EntryPointer->BusId = BusEntry[i].BusId; + EntryPointer->RangeList = 0; //isa range list + EntryPointer->AddressModifier = (BusEntry[i].Flags & 0x3) ? 0 : 1; + + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY); + + //add/subtract VGA predefined range + EntryPointer->EntryType = MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY_TYPE; + EntryPointer->EntryLength = sizeof(MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY); + EntryPointer->BusId = BusEntry[i].BusId; + EntryPointer->RangeList = 1; //vga range list + EntryPointer->AddressModifier = (BusEntry[i].Flags & 0x1C) ? 0 : 1; + + EntryPointer++; + ExtendedTableLength += sizeof(MP_EX_TABLE_COMPAT_BUS_ADDRESS_MODIFIER_ENTRY); + } + } + MpsExTableCurrentPointer = (VOID *)EntryPointer; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: QueryBusInfo +// +// Description: Retreive system info about buses and bus ierarchy and fills +// BUS_INFO structure. Also creates MPS table extended entries +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: BusEntry +// MaxBusId +// CurrentBusEntry +// IsaBusId +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID QueryBusInfo(VOID) +{ + EFI_STATUS Status; + EFI_HANDLE *pHandleBuffer; + UINTN NumberOfHandles; + UINTN i; + + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *pPciRootBridgeIoProtocol; + static EFI_GUID PciRootBridgeIoProtocolGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; + ACPI_ADDRESS_SPACE_DESC *pAddressDescriptor; + + EFI_PCI_IO_PROTOCOL *pPciIoProtocol; + static EFI_GUID PciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID; + UINT8 PciData[4]; + UINTN BusNumber; + UINTN dummy[3]; + UINT64 SupportedAttributes; + +//First detect and retreive bus Id for PCI host (root) buses + Status = pBS->LocateHandleBuffer(ByProtocol, &PciRootBridgeIoProtocolGuid, + NULL, &NumberOfHandles, &pHandleBuffer); + if(EFI_ERROR(Status)) + return; + + for(i = 0; i < NumberOfHandles; i++) + { + Status = pBS->HandleProtocol(pHandleBuffer[i], &PciRootBridgeIoProtocolGuid, + (VOID**)&pPciRootBridgeIoProtocol); + ASSERT_EFI_ERROR(Status); + Status = pPciRootBridgeIoProtocol->Configuration(pPciRootBridgeIoProtocol, + &pAddressDescriptor); + ASSERT_EFI_ERROR(Status); + Status = pPciRootBridgeIoProtocol->GetAttributes(pPciRootBridgeIoProtocol, + &SupportedAttributes, + NULL); + ASSERT_EFI_ERROR(Status); +//find bus range decoding - the min will be host PCI bus Id + while((pAddressDescriptor->Signature == 0x8A) && \ + (pAddressDescriptor->ResourceType != 2)) + pAddressDescriptor++; + + BusEntry[CurrentBusEntry].BusId = (UINT8)pAddressDescriptor->AddressRangeMin; + BusEntry[CurrentBusEntry].ParentBusId = 0xFF; //host bus has no parent + BusEntry[CurrentBusEntry].BusType = BridgeBusTypes[0]; + BusEntry[CurrentBusEntry].Flags = (UINT8)SupportedAttributes; //for host we save ISA/VGA support values + + MaxBusId = (MaxBusId > BusEntry[CurrentBusEntry].BusId) ? \ + MaxBusId : BusEntry[CurrentBusEntry].BusId; + + MpsExTableAddSysAddressMapEntry(pPciRootBridgeIoProtocol, + BusEntry[CurrentBusEntry].BusId, + BusEntry[CurrentBusEntry].Flags); + CurrentBusEntry++; + } + pBS->FreePool(pHandleBuffer); + +//Second detect all other buses via PCI bridges + Status = pBS->LocateHandleBuffer(ByProtocol, &PciIoProtocolGuid, + NULL, &NumberOfHandles, &pHandleBuffer); + if(EFI_ERROR(Status)) + return; + + for(i = 0; i < NumberOfHandles; i++) + { + Status = pBS->HandleProtocol(pHandleBuffer[i], &PciIoProtocolGuid, + (VOID**)&pPciIoProtocol); + if(EFI_ERROR(Status)) + continue; + + //read class code information at 0x8 offset in PCI header + Status = pPciIoProtocol->Pci.Read(pPciIoProtocol, EfiPciIoWidthUint32, + 0x8, 1, (VOID*)PciData); + if(EFI_ERROR(Status)) //problem + continue; +#if PCI_BUS_APIC_AUTODETECT == 1 +//if IO APIC device collect info, we will need it later + if((PciData[3] == 0x8) && (PciData[2] == 0) && (PciData[1] >= 0x10)) + { + UINT64 Attr=0, OldAttr=0; + //---------------------- + //1. make sure it is Enabled and Decoding it's resources + Status=pPciIoProtocol->Attributes(pPciIoProtocol,EfiPciIoAttributeOperationGet, Attr, &OldAttr); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) continue; + + Status=pPciIoProtocol->Attributes(pPciIoProtocol,EfiPciIoAttributeOperationSupported, 0, &Attr); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) continue; + + Status=pPciIoProtocol->Attributes(pPciIoProtocol,EfiPciIoAttributeOperationSet, Attr&(EFI_PCI_DEVICE_ENABLE), NULL); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) continue; + + CollectIoApicInfo(pPciIoProtocol, NULL); + +#if PCI_BUS_APIC_LEAVE_ENABLE != 0 + //Restore attributes of the device + Status=pPciIoProtocol->Attributes(pPciIoProtocol,EfiPciIoAttributeOperationSet, OldAttr, NULL); + ASSERT_EFI_ERROR(Status); + if(EFI_ERROR(Status)) continue; +#endif//PCI_BUS_APIC_LEAVE_ENABLE + + continue; + } +#endif//PCI_BUS_APIC_AUTODETECT + + if(PciData[3] != 0x6) //not bridge device + continue; + + if((PciData[2] == 0) || (PciData[2] > 6)) //PCI host bridge we already know, so skip it + continue; //or unknown bridge - skip it also + + BusEntry[CurrentBusEntry].BusType = BridgeBusTypes[(PciData[2])]; + + if(PciData[2] == 4) // PCI to PCI bridge + { + BusEntry[CurrentBusEntry].Flags = PciData[1]; + //read primary and secondary bus numbers + Status = pPciIoProtocol->Pci.Read(pPciIoProtocol, EfiPciIoWidthUint32, + 0x18, 1, (VOID*)PciData); + + BusEntry[CurrentBusEntry].BusId = PciData[1]; //bus Id prodused by this bridge + BusEntry[CurrentBusEntry].ParentBusId = PciData[0]; + MaxBusId = (MaxBusId > BusEntry[CurrentBusEntry].BusId) ? \ + MaxBusId : BusEntry[CurrentBusEntry].BusId; + } + else //any other bridge + { + BusEntry[CurrentBusEntry].Flags = 1; //all other buses has this feature + BusEntry[CurrentBusEntry].BusId = 0xFF; //we will assign Id after enumerating PCI buses + //get bridge location to determine parent bus Id + Status = pPciIoProtocol->GetLocation(pPciIoProtocol, &dummy[0], &BusNumber, + &dummy[1], &dummy[2]); + + BusEntry[CurrentBusEntry].ParentBusId = (UINT8)BusNumber; + } + CurrentBusEntry++; + } + pBS->FreePool(pHandleBuffer); + +// Third enumerate all other buses + for(i = 0; i < CurrentBusEntry; i++) + { + if(BusEntry[i].BusId == 0xFF) + { + BusEntry[i].BusId = MaxBusId + 1; + MaxBusId++; + if(BusEntry[i].BusType == BUS_TYPE_ISA) //save ISA bus Id for interrupt assign procedure + IsaBusId = MaxBusId; + } + } + MpsExTableAddBusHierarchyEntry(); + MpsExTableAddCompatBusAddressModifierEntry(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CollectIoApicInfo +// +// Description: Retreive system info about IO APIC +// +// Input: +// IN OPTIONAL EFI_PCI_IO_PROTOCOL *pPciIoProtocol +// IN OPTIONAL UINT32 BaseAddress - base address of IO APIC +// +// Output: +// VOID +// +// Modified: IoApicEntry +// CurrentIoApicEntry +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CollectIoApicInfo( + IN EFI_PCI_IO_PROTOCOL *pPciIoProtocol OPTIONAL, + IN UINT32 BaseAddress OPTIONAL) +{ + UINT32 IoApicAddress; + EFI_STATUS Status; + UINT32 volatile *IoApicMemory32; + UINT8 volatile *IoApicMemory8; + UINT32 data; + + if(BaseAddress == NULL) //IO APIC visible as PCI device + { + Status = pPciIoProtocol->Pci.Read(pPciIoProtocol, EfiPciIoWidthUint32, + 0x10, 1, (VOID*)&IoApicAddress); + if(EFI_ERROR(Status) || (IoApicAddress == 0)) //problem or mapped to default address range + return; + } + else // IO APIC mapped to default range + IoApicAddress = BaseAddress; + + IoApicMemory32 = (UINT32 *)IoApicAddress; + IoApicMemory8 = (UINT8 *)IoApicAddress; + + IoApicMemory8[IO_APIC_INDEX_REG] = IO_APIC_MAP_ID_REG; + data = IoApicMemory32[IO_APIC_DATA_REG]; + + IoApicEntry[CurrentIoApicEntry].IoApicId = (UINT8)((data & 0x0F000000) >> 24); + + IoApicMemory8[IO_APIC_INDEX_REG] = IO_APIC_MAP_VERSION_REG; + data = IoApicMemory32[IO_APIC_DATA_REG]; + + IoApicEntry[CurrentIoApicEntry].IoApicVersion = (UINT8)(data & 0xFF); + IoApicEntry[CurrentIoApicEntry].MaxRedirectionEntries = (UINT8)((data & 0x00FF0000) >> 16); + IoApicEntry[CurrentIoApicEntry].IoApicFlags = 1; + IoApicEntry[CurrentIoApicEntry].IoApicAddress = IoApicAddress; + + CurrentIoApicEntry++; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ArrangeIoApicEntries +// +// Description: Arranges IO APIC Entries in their ID ascending order +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: IoApicEntry +// CurrentIoApicEntry +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ArrangeIoApicEntries(VOID) +{ + UINT8 i; + BOOLEAN Swap = TRUE; + IO_APIC_INFO Temp; + + while(Swap) + { + Swap = FALSE; + for(i = 0; i < CurrentIoApicEntry - 1; i++) + { + if(IoApicEntry[i].IoApicId > IoApicEntry[i+1].IoApicId) + { + Swap = TRUE; + MemCpy(&Temp, &IoApicEntry[i], sizeof(IO_APIC_INFO)); + MemCpy(&IoApicEntry[i], &IoApicEntry[i+1], sizeof(IO_APIC_INFO)); + MemCpy(&IoApicEntry[i+1], &Temp, sizeof(IO_APIC_INFO)); + } + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetIoApicId +// +// Description: Returns IO APIC ID and Pin number assosiated with given SysVectorNumber +// +// Input: +// IN UINT16 SysVectorNumber - system interrupt vector number +// OUT UINT8 *IoApicId - Id of IO APIC which handles that vector +// OUT UINT8 *IoApicItin - IO APIC Pin number associated with given vector number +// +// Output: +// VOID +// +// Modified: IoApicEntry +// CurrentIoApicEntry +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID GetIoApicId( + IN UINT16 SysVectorNumber, + OUT UINT8 *IoApicId, + OUT UINT8 *IoApicItin) +{ + UINT8 i; + + for(i = 0; i < CurrentIoApicEntry; i++) + { + if(SysVectorNumber < IoApicEntry[i].MaxRedirectionEntries) //this is Apic we need + { + *IoApicId = IoApicEntry[i].IoApicId; + *IoApicItin = (UINT8)SysVectorNumber; + return; + } + SysVectorNumber -= IoApicEntry[i].MaxRedirectionEntries; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GetCpuInfo +// +// Description: Returns number of cores and threads of given CPU +// +// Input: +// IN UINTN Cpu - Cpu number +// OUT UINT8 *Cores - number of cores in given Cpu +// OUT UINT8 *Threads - number of threads in given Cpu +// +// Output: +// EFI_SUCCESS - function executed successfully +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetCpuInfo( + IN UINTN Cpu, + OUT UINT8 *Cores, + OUT UINT8 *Threads) +{ + EFI_STATUS Status; + AMI_CPU_INFO *Info; + +//find AMICpuInfo protocol + if(AmiCpuInfoProtocol == NULL) + { + Status = pBS->LocateProtocol(&AmiCpuInfoProtocolGuid, + NULL, + &AmiCpuInfoProtocol); + if(EFI_ERROR(Status)) + return Status; + } + + Status = AmiCpuInfoProtocol->GetCpuInfo(AmiCpuInfoProtocol, Cpu, &Info); + if(EFI_ERROR(Status)) + return Status; + + *Cores = Info->NumCores; + *Threads = (Info->NumHts == 0) ? 1 : Info->NumHts; + + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file |