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