Fixes CodeQL alerts for CWE-457: https://cwe.mitre.org/data/definitions/457.html Cc: Eric Dong <eric.dong@intel.com> Cc: Erich McMillan <emcmillan@microsoft.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Michael Kubacki <mikuback@linux.microsoft.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Ray Ni <ray.ni@intel.com> Co-authored-by: Erich McMillan <emcmillan@microsoft.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Oliver Smith-Denny <osd@smith-denny.com>
		
			
				
	
	
		
			302 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			302 lines
		
	
	
		
			10 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;
 | 
						|
 | 
						|
  Status = MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    NumberOfProcessors        = 1;
 | 
						|
    NumberOfEnabledProcessors = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  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 ((DEBUG_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 ((
 | 
						|
      DEBUG_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);
 | 
						|
  }
 | 
						|
}
 |