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