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