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