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