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