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