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   EFI_HOB_GUID_TYPE       *GuidHob;
     48   VOID                    *DataInHob;
     49   UINTN                   DataSize;
     50 
     51   GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);
     52   if (GuidHob == NULL) {
     53     *StructureSize = 0;
     54     return EFI_SUCCESS;
     55   }
     56 
     57   DataInHob = GET_GUID_HOB_DATA (GuidHob);
     58   DataSize  = GET_GUID_HOB_DATA_SIZE (GuidHob);
     59 
     60   //
     61   // return the information from BistHob
     62   //
     63   if ((*StructureSize) < (UINT64) DataSize) {
     64     *StructureSize = (UINT64) DataSize;
     65     return EFI_BUFFER_TOO_SMALL;
     66   }
     67 
     68   *StructureSize = (UINT64) DataSize;
     69   CopyMem (PlatformInformationRecord2, DataInHob, DataSize);
     70   return EFI_SUCCESS;
     71 }
     72 
     73 /**
     74   Worker function to get CPUs' BIST by calling SecPlatformInformationPpi
     75   or SecPlatformInformation2Ppi.
     76 
     77   @param  PeiServices         Pointer to PEI Services Table
     78   @param  Guid                PPI Guid
     79   @param  PpiDescriptor       Return a pointer to instance of the
     80                               EFI_PEI_PPI_DESCRIPTOR
     81   @param  BistInformationData Pointer to BIST information data
     82   @param  BistInformationSize Return the size in bytes of BIST information
     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      OUT UINT64                 *BistInformationSize OPTIONAL
     96   )
     97 {
     98   EFI_STATUS                            Status;
     99   EFI_SEC_PLATFORM_INFORMATION2_PPI     *SecPlatformInformation2Ppi;
    100   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *SecPlatformInformation2;
    101   UINT64                                InformationSize;
    102 
    103   Status = PeiServicesLocatePpi (
    104              Guid,                                // GUID
    105              0,                                   // INSTANCE
    106              PpiDescriptor,                       // EFI_PEI_PPI_DESCRIPTOR
    107              (VOID **)&SecPlatformInformation2Ppi // PPI
    108              );
    109   if (Status == EFI_NOT_FOUND) {
    110     return EFI_NOT_FOUND;
    111   }
    112 
    113   if (Status == EFI_SUCCESS) {
    114     //
    115     // Get the size of the sec platform information2(BSP/APs' BIST data)
    116     //
    117     InformationSize         = 0;
    118     SecPlatformInformation2 = NULL;
    119     Status = SecPlatformInformation2Ppi->PlatformInformation2 (
    120                                            PeiServices,
    121                                            &InformationSize,
    122                                            SecPlatformInformation2
    123                                            );
    124     if (Status == EFI_BUFFER_TOO_SMALL) {
    125       Status = PeiServicesAllocatePool (
    126                  (UINTN) InformationSize,
    127                  (VOID **) &SecPlatformInformation2
    128                  );
    129       if (Status == EFI_SUCCESS) {
    130         //
    131         // Retrieve BIST data
    132         //
    133         Status = SecPlatformInformation2Ppi->PlatformInformation2 (
    134                                                PeiServices,
    135                                                &InformationSize,
    136                                                SecPlatformInformation2
    137                                                );
    138         if (Status == EFI_SUCCESS) {
    139           *BistInformationData = SecPlatformInformation2;
    140           if (BistInformationSize != NULL) {
    141             *BistInformationSize = InformationSize;
    142           }
    143           return EFI_SUCCESS;
    144         }
    145       }
    146     }
    147   }
    148 
    149   return EFI_DEVICE_ERROR;
    150 }
    151 
    152 /**
    153   Collects BIST data from PPI.
    154 
    155   This function collects BIST data from Sec Platform Information2 PPI
    156   or SEC Platform Information PPI.
    157 
    158   @param PeiServices         Pointer to PEI Services Table
    159 
    160 **/
    161 VOID
    162 CollectBistDataFromPpi (
    163   IN CONST EFI_PEI_SERVICES             **PeiServices
    164   )
    165 {
    166   EFI_STATUS                            Status;
    167   EFI_PEI_PPI_DESCRIPTOR                *SecInformationDescriptor;
    168   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *SecPlatformInformation2;
    169   EFI_SEC_PLATFORM_INFORMATION_RECORD   *SecPlatformInformation;
    170   UINTN                                 NumberOfData;
    171   EFI_SEC_PLATFORM_INFORMATION_CPU      *CpuInstance;
    172   EFI_SEC_PLATFORM_INFORMATION_CPU      BspCpuInstance;
    173   UINTN                                 ProcessorNumber;
    174   UINTN                                 CpuIndex;
    175   EFI_PROCESSOR_INFORMATION             ProcessorInfo;
    176   EFI_HEALTH_FLAGS                      BistData;
    177   UINTN                                 NumberOfProcessors;
    178   UINTN                                 NumberOfEnabledProcessors;
    179   UINTN                                 BistInformationSize;
    180   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *PlatformInformationRecord2;
    181   EFI_SEC_PLATFORM_INFORMATION_CPU      *CpuInstanceInHob;
    182 
    183 
    184   MpInitLibGetNumberOfProcessors(&NumberOfProcessors, &NumberOfEnabledProcessors);
    185 
    186   BistInformationSize = sizeof (EFI_SEC_PLATFORM_INFORMATION_RECORD2) +
    187                         sizeof (EFI_SEC_PLATFORM_INFORMATION_CPU) * NumberOfProcessors;
    188   Status = PeiServicesAllocatePool (
    189              (UINTN) BistInformationSize,
    190              (VOID **) &PlatformInformationRecord2
    191              );
    192   ASSERT_EFI_ERROR (Status);
    193   PlatformInformationRecord2->NumberOfCpus = (UINT32)NumberOfProcessors;
    194 
    195   SecPlatformInformation2 = NULL;
    196   SecPlatformInformation  = NULL;
    197   NumberOfData            = 0;
    198   CpuInstance             = NULL;
    199   //
    200   // Get BIST information from Sec Platform Information2 Ppi firstly
    201   //
    202   Status = GetBistInfoFromPpi (
    203              PeiServices,
    204              &gEfiSecPlatformInformation2PpiGuid,
    205              &SecInformationDescriptor,
    206              (VOID *) &SecPlatformInformation2,
    207              NULL
    208              );
    209   if (Status == EFI_SUCCESS) {
    210     //
    211     // Sec Platform Information2 PPI includes BSP/APs' BIST information
    212     //
    213     NumberOfData = SecPlatformInformation2->NumberOfCpus;
    214     CpuInstance  = SecPlatformInformation2->CpuInstance;
    215   } else {
    216     //
    217     // Otherwise, get BIST information from Sec Platform Information Ppi
    218     //
    219     Status = GetBistInfoFromPpi (
    220                PeiServices,
    221                &gEfiSecPlatformInformationPpiGuid,
    222                &SecInformationDescriptor,
    223                (VOID *) &SecPlatformInformation,
    224                NULL
    225                );
    226     if (Status == EFI_SUCCESS) {
    227       NumberOfData = 1;
    228       //
    229       // SEC Platform Information only includes BSP's BIST information
    230       // and does not have BSP's APIC ID
    231       //
    232       BspCpuInstance.CpuLocation = GetInitialApicId ();
    233       BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32  = SecPlatformInformation->IA32HealthFlags.Uint32;
    234       CpuInstance = &BspCpuInstance;
    235     } else {
    236       DEBUG ((EFI_D_INFO, "Does not find any stored CPU BIST information from PPI!\n"));
    237     }
    238   }
    239   for (ProcessorNumber = 0; ProcessorNumber < NumberOfProcessors; ProcessorNumber ++) {
    240     MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);
    241     for (CpuIndex = 0; CpuIndex < NumberOfData; CpuIndex ++) {
    242       ASSERT (CpuInstance != NULL);
    243       if (ProcessorInfo.ProcessorId == CpuInstance[CpuIndex].CpuLocation) {
    244         //
    245         // Update processor's BIST data if it is already stored before
    246         //
    247         BistData = CpuInstance[CpuIndex].InfoRecord.IA32HealthFlags;
    248       }
    249     }
    250     if (BistData.Uint32 != 0) {
    251       //
    252       // Report Status Code that self test is failed
    253       //
    254       REPORT_STATUS_CODE (
    255         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
    256         (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
    257         );
    258     }
    259     DEBUG ((EFI_D_INFO, "  APICID - 0x%08x, BIST - 0x%08x\n",
    260             (UINT32) ProcessorInfo.ProcessorId,
    261             BistData
    262             ));
    263     CpuInstanceInHob = PlatformInformationRecord2->CpuInstance;
    264     CpuInstanceInHob[ProcessorNumber].CpuLocation = (UINT32) ProcessorInfo.ProcessorId;
    265     CpuInstanceInHob[ProcessorNumber].InfoRecord.IA32HealthFlags = BistData;
    266   }
    267 
    268   //
    269   // Build SecPlatformInformation2 PPI GUIDed HOB that also could be consumed
    270   // by CPU MP driver to get CPU BIST data
    271   //
    272   BuildGuidDataHob (
    273     &gEfiSecPlatformInformation2PpiGuid,
    274     PlatformInformationRecord2,
    275     (UINTN) BistInformationSize
    276     );
    277 
    278   if (SecPlatformInformation2 != NULL && NumberOfData < NumberOfProcessors) {
    279     //
    280     // Reinstall SecPlatformInformation2 PPI to include new BIST information
    281     //
    282     Status = PeiServicesReInstallPpi (
    283                SecInformationDescriptor,
    284                &mPeiSecPlatformInformation2Ppi
    285                );
    286     ASSERT_EFI_ERROR (Status);
    287   } else {
    288     //
    289     // Install SecPlatformInformation2 PPI to include new BIST information
    290     //
    291     Status = PeiServicesInstallPpi (&mPeiSecPlatformInformation2Ppi);
    292     ASSERT_EFI_ERROR(Status);
    293   }
    294 }
    295 
    296