Home | History | Annotate | Download | only in CpuMpPei
      1 /** @file
      2   Update and publish processors' BIST information.
      3 
      4   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "CpuMpPei.h"
     16 
     17 EFI_SEC_PLATFORM_INFORMATION2_PPI mSecPlatformInformation2Ppi = {
     18   SecPlatformInformation2
     19 };
     20 
     21 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation2Ppi = {
     22   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     23   &gEfiSecPlatformInformation2PpiGuid,
     24   &mSecPlatformInformation2Ppi
     25 };
     26 
     27 /**
     28   Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.
     29 
     30   @param  PeiServices                The pointer to the PEI Services Table.
     31   @param  StructureSize              The pointer to the variable describing size of the input buffer.
     32   @param  PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.
     33 
     34   @retval EFI_SUCCESS                The data was successfully returned.
     35   @retval EFI_BUFFER_TOO_SMALL       The buffer was too small. The current buffer size needed to
     36                                      hold the record is returned in StructureSize.
     37 
     38 **/
     39 EFI_STATUS
     40 EFIAPI
     41 SecPlatformInformation2 (
     42   IN CONST EFI_PEI_SERVICES                   **PeiServices,
     43   IN OUT UINT64                               *StructureSize,
     44      OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
     45   )
     46 {
     47   PEI_CPU_MP_DATA                      *PeiCpuMpData;
     48   UINTN                                BistInformationSize;
     49   UINTN                                CpuIndex;
     50   EFI_SEC_PLATFORM_INFORMATION_CPU     *CpuInstance;
     51 
     52   PeiCpuMpData = GetMpHobData ();
     53 
     54   BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) +
     55                         sizeof (EFI_SEC_PLATFORM_INFORMATION_CPU) * PeiCpuMpData->CpuCount;
     56   //
     57   // return the information size if input buffer size is too small
     58   //
     59   if ((*StructureSize) < (UINT64) BistInformationSize) {
     60     *StructureSize = (UINT64) BistInformationSize;
     61     return EFI_BUFFER_TOO_SMALL;
     62   }
     63 
     64   PlatformInformationRecord2->NumberOfCpus = PeiCpuMpData->CpuCount;
     65   CpuInstance = PlatformInformationRecord2->CpuInstance;
     66   for (CpuIndex = 0; CpuIndex < PeiCpuMpData->CpuCount; CpuIndex ++) {
     67     CpuInstance[CpuIndex].CpuLocation                = PeiCpuMpData->CpuData[CpuIndex].ApicId;
     68     CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags = PeiCpuMpData->CpuData[CpuIndex].Health;
     69   }
     70 
     71   return EFI_SUCCESS;
     72 }
     73 
     74 /**
     75   Worker function to get CPUs' BIST by calling SecPlatformInformationPpi
     76   or SecPlatformInformation2Ppi.
     77 
     78   @param  PeiServices         Pointer to PEI Services Table
     79   @param  Guid                PPI Guid
     80   @param  PpiDescriptor       Return a pointer to instance of the
     81                               EFI_PEI_PPI_DESCRIPTOR
     82   @param  BistInformationData Pointer to BIST information data
     83 
     84   @retval EFI_SUCCESS         Retrieve of the BIST data successfully
     85   @retval EFI_NOT_FOUND       No sec platform information(2) ppi export
     86   @retval EFI_DEVICE_ERROR    Failed to get CPU Information
     87 
     88 **/
     89 EFI_STATUS
     90 GetBistInfoFromPpi (
     91   IN CONST EFI_PEI_SERVICES     **PeiServices,
     92   IN CONST EFI_GUID             *Guid,
     93      OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
     94      OUT VOID                   **BistInformationData
     95   )
     96 {
     97   EFI_STATUS                            Status;
     98   EFI_SEC_PLATFORM_INFORMATION2_PPI     *SecPlatformInformation2Ppi;
     99   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *SecPlatformInformation2;
    100   UINT64                                InformationSize;
    101 
    102   Status = PeiServicesLocatePpi (
    103              Guid,                                // GUID
    104              0,                                   // INSTANCE
    105              PpiDescriptor,                       // EFI_PEI_PPI_DESCRIPTOR
    106              (VOID **)&SecPlatformInformation2Ppi // PPI
    107              );
    108   if (Status == EFI_NOT_FOUND) {
    109     return EFI_NOT_FOUND;
    110   }
    111 
    112   if (Status == EFI_SUCCESS) {
    113     //
    114     // Get the size of the sec platform information2(BSP/APs' BIST data)
    115     //
    116     InformationSize         = 0;
    117     SecPlatformInformation2 = NULL;
    118     Status = SecPlatformInformation2Ppi->PlatformInformation2 (
    119                                            PeiServices,
    120                                            &InformationSize,
    121                                            SecPlatformInformation2
    122                                            );
    123     if (Status == EFI_BUFFER_TOO_SMALL) {
    124       Status = PeiServicesAllocatePool (
    125                  (UINTN) InformationSize,
    126                  (VOID **) &SecPlatformInformation2
    127                  );
    128       if (Status == EFI_SUCCESS) {
    129         //
    130         // Retrieve BIST data
    131         //
    132         Status = SecPlatformInformation2Ppi->PlatformInformation2 (
    133                                                PeiServices,
    134                                                &InformationSize,
    135                                                SecPlatformInformation2
    136                                                );
    137         if (Status == EFI_SUCCESS) {
    138           *BistInformationData = SecPlatformInformation2;
    139           return EFI_SUCCESS;
    140         }
    141       }
    142     }
    143   }
    144 
    145   return EFI_DEVICE_ERROR;
    146 }
    147 
    148 /**
    149   Collects BIST data from PPI.
    150 
    151   This function collects BIST data from Sec Platform Information2 PPI
    152   or SEC Platform Information PPI.
    153 
    154   @param PeiServices         Pointer to PEI Services Table
    155   @param PeiCpuMpData        Pointer to PEI CPU MP Data
    156 
    157 **/
    158 VOID
    159 CollectBistDataFromPpi (
    160   IN CONST EFI_PEI_SERVICES             **PeiServices,
    161   IN PEI_CPU_MP_DATA                    *PeiCpuMpData
    162   )
    163 {
    164   EFI_STATUS                            Status;
    165   EFI_PEI_PPI_DESCRIPTOR                *SecInformationDescriptor;
    166   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *SecPlatformInformation2;
    167   EFI_SEC_PLATFORM_INFORMATION_RECORD   *SecPlatformInformation;
    168   UINTN                                 NumberOfData;
    169   EFI_SEC_PLATFORM_INFORMATION_CPU      *CpuInstance;
    170   EFI_SEC_PLATFORM_INFORMATION_CPU      BspCpuInstance;
    171   UINTN                                 ProcessorNumber;
    172   UINTN                                 CpuIndex;
    173   PEI_CPU_DATA                          *CpuData;
    174 
    175   SecPlatformInformation2 = NULL;
    176   SecPlatformInformation  = NULL;
    177   NumberOfData            = 0;
    178   CpuInstance             = NULL;
    179 
    180   //
    181   // Get BIST information from Sec Platform Information2 Ppi firstly
    182   //
    183   Status = GetBistInfoFromPpi (
    184              PeiServices,
    185              &gEfiSecPlatformInformation2PpiGuid,
    186              &SecInformationDescriptor,
    187              (VOID *) &SecPlatformInformation2
    188              );
    189   if (Status == EFI_SUCCESS) {
    190     //
    191     // Sec Platform Information2 PPI includes BSP/APs' BIST information
    192     //
    193     NumberOfData = SecPlatformInformation2->NumberOfCpus;
    194     CpuInstance  = SecPlatformInformation2->CpuInstance;
    195   } else {
    196     //
    197     // Otherwise, get BIST information from Sec Platform Information Ppi
    198     //
    199     Status = GetBistInfoFromPpi (
    200                PeiServices,
    201                &gEfiSecPlatformInformationPpiGuid,
    202                &SecInformationDescriptor,
    203                (VOID *) &SecPlatformInformation
    204                );
    205     if (Status == EFI_SUCCESS) {
    206       NumberOfData = 1;
    207       //
    208       // SEC Platform Information only includes BSP's BIST information
    209       // and does not have BSP's APIC ID
    210       //
    211       BspCpuInstance.CpuLocation = GetInitialApicId ();
    212       BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32  = SecPlatformInformation->IA32HealthFlags.Uint32;
    213       CpuInstance = &BspCpuInstance;
    214     } else {
    215       DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n"));
    216     }
    217   }
    218   for (ProcessorNumber = 0; ProcessorNumber < PeiCpuMpData->CpuCount; ProcessorNumber ++) {
    219     CpuData = &PeiCpuMpData->CpuData[ProcessorNumber];
    220     for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) {
    221       ASSERT (CpuInstance != NULL);
    222       if (CpuData->ApicId == CpuInstance[CpuIndex].CpuLocation) {
    223         //
    224         // Update processor's BIST data if it is already stored before
    225         //
    226         CpuData->Health = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags;
    227       }
    228     }
    229     if (CpuData->Health.Uint32 == 0) {
    230       CpuData->CpuHealthy = TRUE;
    231     } else {
    232       CpuData->CpuHealthy = FALSE;
    233       //
    234       // Report Status Code that self test is failed
    235       //
    236       REPORT_STATUS_CODE (
    237         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
    238         (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
    239         );
    240     }
    241     DEBUG ((EFI_D_INFO, "  APICID - 0x%08x, BIST - 0x%08x\n",
    242             PeiCpuMpData->CpuData[ProcessorNumber].ApicId,
    243             PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32
    244             ));
    245   }
    246 
    247   if (SecPlatformInformation2 != NULL && NumberOfData < PeiCpuMpData->CpuCount) {
    248     //
    249     // Reinstall SecPlatformInformation2 PPI to include new BIST inforamtion
    250     //
    251     Status = PeiServicesReInstallPpi (
    252                SecInformationDescriptor,
    253                &mPeiSecPlatformInformation2Ppi
    254                );
    255     ASSERT_EFI_ERROR (Status);
    256   } else {
    257     //
    258     // Install SecPlatformInformation2 PPI to include new BIST inforamtion
    259     //
    260     Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi);
    261     ASSERT_EFI_ERROR(Status);
    262   }
    263 }
    264