292 lines
9.9 KiB
C
292 lines
9.9 KiB
C
|
/** @file
|
||
|
Update and publish processors' BIST information.
|
||
|
|
||
|
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
|
||
|
**/
|
||
|
|
||
|
#include "CpuMpPei.h"
|
||
|
|
||
|
EFI_SEC_PLATFORM_INFORMATION2_PPI mSecPlatformInformation2Ppi = {
|
||
|
SecPlatformInformation2
|
||
|
};
|
||
|
|
||
|
EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation2Ppi = {
|
||
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
||
|
&gEfiSecPlatformInformation2PpiGuid,
|
||
|
&mSecPlatformInformation2Ppi
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.
|
||
|
|
||
|
@param PeiServices The pointer to the PEI Services Table.
|
||
|
@param StructureSize The pointer to the variable describing size of the input buffer.
|
||
|
@param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.
|
||
|
|
||
|
@retval EFI_SUCCESS The data was successfully returned.
|
||
|
@retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to
|
||
|
hold the record is returned in StructureSize.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SecPlatformInformation2 (
|
||
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||
|
IN OUT UINT64 *StructureSize,
|
||
|
OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
|
||
|
)
|
||
|
{
|
||
|
EFI_HOB_GUID_TYPE *GuidHob;
|
||
|
VOID *DataInHob;
|
||
|
UINTN DataSize;
|
||
|
|
||
|
GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);
|
||
|
if (GuidHob == NULL) {
|
||
|
*StructureSize = 0;
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
DataInHob = GET_GUID_HOB_DATA (GuidHob);
|
||
|
DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
|
||
|
|
||
|
//
|
||
|
// return the information from BistHob
|
||
|
//
|
||
|
if ((*StructureSize) < (UINT64) DataSize) {
|
||
|
*StructureSize = (UINT64) DataSize;
|
||
|
return EFI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
*StructureSize = (UINT64) DataSize;
|
||
|
CopyMem (PlatformInformationRecord2, DataInHob, DataSize);
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Worker function to get CPUs' BIST by calling SecPlatformInformationPpi
|
||
|
or SecPlatformInformation2Ppi.
|
||
|
|
||
|
@param PeiServices Pointer to PEI Services Table
|
||
|
@param Guid PPI Guid
|
||
|
@param PpiDescriptor Return a pointer to instance of the
|
||
|
EFI_PEI_PPI_DESCRIPTOR
|
||
|
@param BistInformationData Pointer to BIST information data
|
||
|
@param BistInformationSize Return the size in bytes of BIST information
|
||
|
|
||
|
@retval EFI_SUCCESS Retrieve of the BIST data successfully
|
||
|
@retval EFI_NOT_FOUND No sec platform information(2) ppi export
|
||
|
@retval EFI_DEVICE_ERROR Failed to get CPU Information
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
GetBistInfoFromPpi (
|
||
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||
|
IN CONST EFI_GUID *Guid,
|
||
|
OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
|
||
|
OUT VOID **BistInformationData,
|
||
|
OUT UINT64 *BistInformationSize OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EFI_SEC_PLATFORM_INFORMATION2_PPI *SecPlatformInformation2Ppi;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;
|
||
|
UINT64 InformationSize;
|
||
|
|
||
|
Status = PeiServicesLocatePpi (
|
||
|
Guid, // GUID
|
||
|
0, // INSTANCE
|
||
|
PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR
|
||
|
(VOID **)&SecPlatformInformation2Ppi // PPI
|
||
|
);
|
||
|
if (Status == EFI_NOT_FOUND) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
//
|
||
|
// Get the size of the sec platform information2(BSP/APs' BIST data)
|
||
|
//
|
||
|
InformationSize = 0;
|
||
|
SecPlatformInformation2 = NULL;
|
||
|
Status = SecPlatformInformation2Ppi->PlatformInformation2 (
|
||
|
PeiServices,
|
||
|
&InformationSize,
|
||
|
SecPlatformInformation2
|
||
|
);
|
||
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||
|
Status = PeiServicesAllocatePool (
|
||
|
(UINTN) InformationSize,
|
||
|
(VOID **) &SecPlatformInformation2
|
||
|
);
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
//
|
||
|
// Retrieve BIST data
|
||
|
//
|
||
|
Status = SecPlatformInformation2Ppi->PlatformInformation2 (
|
||
|
PeiServices,
|
||
|
&InformationSize,
|
||
|
SecPlatformInformation2
|
||
|
);
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
*BistInformationData = SecPlatformInformation2;
|
||
|
if (BistInformationSize != NULL) {
|
||
|
*BistInformationSize = InformationSize;
|
||
|
}
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Collects BIST data from PPI.
|
||
|
|
||
|
This function collects BIST data from Sec Platform Information2 PPI
|
||
|
or SEC Platform Information PPI.
|
||
|
|
||
|
@param PeiServices Pointer to PEI Services Table
|
||
|
|
||
|
**/
|
||
|
VOID
|
||
|
CollectBistDataFromPpi (
|
||
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EFI_PEI_PPI_DESCRIPTOR *SecInformationDescriptor;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;
|
||
|
UINTN NumberOfData;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;
|
||
|
UINTN ProcessorNumber;
|
||
|
UINTN CpuIndex;
|
||
|
EFI_PROCESSOR_INFORMATION ProcessorInfo;
|
||
|
EFI_HEALTH_FLAGS BistData;
|
||
|
UINTN NumberOfProcessors;
|
||
|
UINTN NumberOfEnabledProcessors;
|
||
|
UINTN BistInformationSize;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2;
|
||
|
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstanceInHob;
|
||
|
|
||
|
|
||
|
MpInitLibGetNumberOfProcessors(&NumberOfProcessors, &NumberOfEnabledProcessors);
|
||
|
|
||
|
BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) +
|
||
|
sizeof (EFI_SEC_PLATFORM_INFORMATION_CPU) * NumberOfProcessors;
|
||
|
Status = PeiServicesAllocatePool (
|
||
|
(UINTN) BistInformationSize,
|
||
|
(VOID **) &PlatformInformationRecord2
|
||
|
);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
PlatformInformationRecord2->NumberOfCpus = (UINT32)NumberOfProcessors;
|
||
|
|
||
|
SecPlatformInformation2 = NULL;
|
||
|
SecPlatformInformation = NULL;
|
||
|
NumberOfData = 0;
|
||
|
CpuInstance = NULL;
|
||
|
//
|
||
|
// Get BIST information from Sec Platform Information2 Ppi firstly
|
||
|
//
|
||
|
Status = GetBistInfoFromPpi (
|
||
|
PeiServices,
|
||
|
&gEfiSecPlatformInformation2PpiGuid,
|
||
|
&SecInformationDescriptor,
|
||
|
(VOID *) &SecPlatformInformation2,
|
||
|
NULL
|
||
|
);
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
//
|
||
|
// Sec Platform Information2 PPI includes BSP/APs' BIST information
|
||
|
//
|
||
|
NumberOfData = SecPlatformInformation2->NumberOfCpus;
|
||
|
CpuInstance = SecPlatformInformation2->CpuInstance;
|
||
|
} else {
|
||
|
//
|
||
|
// Otherwise, get BIST information from Sec Platform Information Ppi
|
||
|
//
|
||
|
Status = GetBistInfoFromPpi (
|
||
|
PeiServices,
|
||
|
&gEfiSecPlatformInformationPpiGuid,
|
||
|
&SecInformationDescriptor,
|
||
|
(VOID *) &SecPlatformInformation,
|
||
|
NULL
|
||
|
);
|
||
|
if (Status == EFI_SUCCESS) {
|
||
|
NumberOfData = 1;
|
||
|
//
|
||
|
// SEC Platform Information only includes BSP's BIST information
|
||
|
// and does not have BSP's APIC ID
|
||
|
//
|
||
|
BspCpuInstance.CpuLocation = GetInitialApicId ();
|
||
|
BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;
|
||
|
CpuInstance = &BspCpuInstance;
|
||
|
} else {
|
||
|
DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n"));
|
||
|
}
|
||
|
}
|
||
|
for (ProcessorNumber = 0; ProcessorNumber < NumberOfProcessors; ProcessorNumber ++) {
|
||
|
MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);
|
||
|
for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) {
|
||
|
ASSERT (CpuInstance != NULL);
|
||
|
if (ProcessorInfo.ProcessorId == CpuInstance[CpuIndex].CpuLocation) {
|
||
|
//
|
||
|
// Update processor's BIST data if it is already stored before
|
||
|
//
|
||
|
BistData = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags;
|
||
|
}
|
||
|
}
|
||
|
if (BistData.Uint32 != 0) {
|
||
|
//
|
||
|
// Report Status Code that self test is failed
|
||
|
//
|
||
|
REPORT_STATUS_CODE (
|
||
|
EFI_ERROR_CODE | EFI_ERROR_MAJOR,
|
||
|
(EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
|
||
|
);
|
||
|
}
|
||
|
DEBUG ((EFI_D_INFO, " APICID - 0x%08x, BIST - 0x%08x\n",
|
||
|
(UINT32) ProcessorInfo.ProcessorId,
|
||
|
BistData
|
||
|
));
|
||
|
CpuInstanceInHob = PlatformInformationRecord2->CpuInstance;
|
||
|
CpuInstanceInHob[ProcessorNumber].CpuLocation = (UINT32) ProcessorInfo.ProcessorId;
|
||
|
CpuInstanceInHob[ProcessorNumber].InfoRecord.IA32HealthFlags = BistData;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Build SecPlatformInformation2 PPI GUIDed HOB that also could be consumed
|
||
|
// by CPU MP driver to get CPU BIST data
|
||
|
//
|
||
|
BuildGuidDataHob (
|
||
|
&gEfiSecPlatformInformation2PpiGuid,
|
||
|
PlatformInformationRecord2,
|
||
|
(UINTN) BistInformationSize
|
||
|
);
|
||
|
|
||
|
if (SecPlatformInformation2 != NULL) {
|
||
|
if (NumberOfData < NumberOfProcessors) {
|
||
|
//
|
||
|
// Reinstall SecPlatformInformation2 PPI to include new BIST information
|
||
|
//
|
||
|
Status = PeiServicesReInstallPpi (
|
||
|
SecInformationDescriptor,
|
||
|
&mPeiSecPlatformInformation2Ppi
|
||
|
);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// Install SecPlatformInformation2 PPI
|
||
|
//
|
||
|
Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi);
|
||
|
ASSERT_EFI_ERROR(Status);
|
||
|
}
|
||
|
}
|
||
|
|