CpuBist.c 10 KB

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