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