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