1 /** @file
2   Get SEC platform information(2) PPI and reinstall it.
3 
4   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "SecMain.h"
10 
11 EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformation = {
12   SecPlatformInformationBist
13 };
14 
15 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation = {
16   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
17   &gEfiSecPlatformInformationPpiGuid,
18   &mSecPlatformInformation
19 };
20 
21 EFI_SEC_PLATFORM_INFORMATION2_PPI mSecPlatformInformation2 = {
22   SecPlatformInformation2Bist
23 };
24 
25 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformation2 = {
26   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
27   &gEfiSecPlatformInformation2PpiGuid,
28   &mSecPlatformInformation2
29 };
30 
31 /**
32   Worker function to parse CPU BIST information from Guided HOB.
33 
34   @param[in, out] StructureSize     Pointer to the variable describing size of the input buffer.
35   @param[in, out] StructureBuffer   Pointer to the buffer save CPU BIST information.
36 
37   @retval EFI_SUCCESS           The data was successfully returned.
38   @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.
39 
40 **/
41 EFI_STATUS
GetBistFromHob(IN OUT UINT64 * StructureSize,IN OUT VOID * StructureBuffer)42 GetBistFromHob (
43   IN OUT UINT64           *StructureSize,
44   IN OUT VOID             *StructureBuffer
45   )
46 {
47   EFI_HOB_GUID_TYPE       *GuidHob;
48   VOID                    *DataInHob;
49   UINTN                   DataSize;
50 
51   GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
52   if (GuidHob == NULL) {
53     *StructureSize = 0;
54     return EFI_SUCCESS;
55   }
56 
57   DataInHob = GET_GUID_HOB_DATA (GuidHob);
58   DataSize  = GET_GUID_HOB_DATA_SIZE (GuidHob);
59 
60   //
61   // return the information from BistHob
62   //
63   if ((*StructureSize) < (UINT64) DataSize) {
64     *StructureSize = (UINT64) DataSize;
65     return EFI_BUFFER_TOO_SMALL;
66   }
67 
68   *StructureSize = (UINT64) DataSize;
69   CopyMem (StructureBuffer, DataInHob, DataSize);
70   return EFI_SUCCESS;
71 }
72 
73 /**
74   Implementation of the PlatformInformation service in EFI_SEC_PLATFORM_INFORMATION_PPI.
75 
76   @param[in]      PeiServices                Pointer to the PEI Services Table.
77   @param[in, out] StructureSize              Pointer to the variable describing size of the input buffer.
78   @param[out]     PlatformInformationRecord  Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
79 
80   @retval EFI_SUCCESS                    The data was successfully returned.
81   @retval EFI_BUFFER_TOO_SMALL           The buffer was too small.
82 
83 **/
84 EFI_STATUS
85 EFIAPI
SecPlatformInformationBist(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT UINT64 * StructureSize,OUT EFI_SEC_PLATFORM_INFORMATION_RECORD * PlatformInformationRecord)86 SecPlatformInformationBist (
87   IN CONST EFI_PEI_SERVICES                  **PeiServices,
88   IN OUT UINT64                              *StructureSize,
89      OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
90   )
91 {
92   return GetBistFromHob (StructureSize, PlatformInformationRecord);
93 }
94 
95 /**
96   Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.
97 
98   @param[in]      PeiServices                The pointer to the PEI Services Table.
99   @param[in, out] StructureSize              The pointer to the variable describing size of the input buffer.
100   @param[out]     PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.
101 
102   @retval EFI_SUCCESS                    The data was successfully returned.
103   @retval EFI_BUFFER_TOO_SMALL           The buffer was too small. The current buffer size needed to
104                                          hold the record is returned in StructureSize.
105 
106 **/
107 EFI_STATUS
108 EFIAPI
SecPlatformInformation2Bist(IN CONST EFI_PEI_SERVICES ** PeiServices,IN OUT UINT64 * StructureSize,OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 * PlatformInformationRecord2)109 SecPlatformInformation2Bist (
110   IN CONST EFI_PEI_SERVICES                   **PeiServices,
111   IN OUT UINT64                               *StructureSize,
112      OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
113   )
114 {
115   return GetBistFromHob (StructureSize, PlatformInformationRecord2);
116 }
117 
118 /**
119   Worker function to get CPUs' BIST by calling SecPlatformInformationPpi
120   or SecPlatformInformation2Ppi.
121 
122   @param[in]  PeiServices         Pointer to PEI Services Table
123   @param[in]  Guid                PPI Guid
124   @param[out] PpiDescriptor       Return a pointer to instance of the
125                                   EFI_PEI_PPI_DESCRIPTOR
126   @param[out] BistInformationData Pointer to BIST information data
127   @param[out] BistInformationSize Return the size in bytes of BIST information
128 
129   @retval EFI_SUCCESS         Retrieve of the BIST data successfully
130   @retval EFI_NOT_FOUND       No sec platform information(2) ppi export
131   @retval EFI_DEVICE_ERROR    Failed to get CPU Information
132 
133 **/
134 EFI_STATUS
GetBistInfoFromPpi(IN CONST EFI_PEI_SERVICES ** PeiServices,IN CONST EFI_GUID * Guid,OUT EFI_PEI_PPI_DESCRIPTOR ** PpiDescriptor,OUT VOID ** BistInformationData,OUT UINT64 * BistInformationSize OPTIONAL)135 GetBistInfoFromPpi (
136   IN CONST EFI_PEI_SERVICES     **PeiServices,
137   IN CONST EFI_GUID             *Guid,
138      OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
139      OUT VOID                   **BistInformationData,
140      OUT UINT64                 *BistInformationSize OPTIONAL
141   )
142 {
143   EFI_STATUS                            Status;
144   EFI_SEC_PLATFORM_INFORMATION2_PPI     *SecPlatformInformation2Ppi;
145   EFI_SEC_PLATFORM_INFORMATION_RECORD2  *SecPlatformInformation2;
146   UINT64                                InformationSize;
147 
148   Status = PeiServicesLocatePpi (
149              Guid,                                // GUID
150              0,                                   // INSTANCE
151              PpiDescriptor,                       // EFI_PEI_PPI_DESCRIPTOR
152              (VOID **)&SecPlatformInformation2Ppi // PPI
153              );
154   if (Status == EFI_NOT_FOUND) {
155     return EFI_NOT_FOUND;
156   }
157 
158   if (Status == EFI_SUCCESS) {
159     //
160     // Get the size of the sec platform information2(BSP/APs' BIST data)
161     //
162     InformationSize         = 0;
163     SecPlatformInformation2 = NULL;
164     Status = SecPlatformInformation2Ppi->PlatformInformation2 (
165                                            PeiServices,
166                                            &InformationSize,
167                                            SecPlatformInformation2
168                                            );
169     if (Status == EFI_BUFFER_TOO_SMALL) {
170       Status = PeiServicesAllocatePool (
171                  (UINTN) InformationSize,
172                  (VOID **) &SecPlatformInformation2
173                  );
174       if (Status == EFI_SUCCESS) {
175         //
176         // Retrieve BIST data
177         //
178         Status = SecPlatformInformation2Ppi->PlatformInformation2 (
179                                                PeiServices,
180                                                &InformationSize,
181                                                SecPlatformInformation2
182                                                );
183         if (Status == EFI_SUCCESS) {
184           *BistInformationData = SecPlatformInformation2;
185           if (BistInformationSize != NULL) {
186             *BistInformationSize = InformationSize;
187           }
188           return EFI_SUCCESS;
189         }
190       }
191     }
192   }
193 
194   return EFI_DEVICE_ERROR;
195 }
196 
197 /**
198   Get CPUs' BIST by calling SecPlatformInformationPpi/SecPlatformInformation2Ppi.
199 
200 **/
201 VOID
RepublishSecPlatformInformationPpi(VOID)202 RepublishSecPlatformInformationPpi (
203   VOID
204   )
205 {
206   EFI_STATUS                            Status;
207   CONST EFI_PEI_SERVICES                **PeiServices;
208   UINT64                                BistInformationSize;
209   VOID                                  *BistInformationData;
210   EFI_PEI_PPI_DESCRIPTOR                *SecInformationDescriptor;
211 
212   PeiServices = GetPeiServicesTablePointer ();
213   Status = GetBistInfoFromPpi (
214              PeiServices,
215              &gEfiSecPlatformInformation2PpiGuid,
216              &SecInformationDescriptor,
217              &BistInformationData,
218              &BistInformationSize
219              );
220   if (Status == EFI_SUCCESS) {
221     BuildGuidDataHob (
222       &gEfiCallerIdGuid,
223       BistInformationData,
224       (UINTN) BistInformationSize
225       );
226     //
227     // The old SecPlatformInformation2 data is on temporary memory.
228     // After memory discovered, we should never get it from temporary memory,
229     // or the data will be crashed. So, we reinstall SecPlatformInformation2 PPI here.
230     //
231     Status = PeiServicesReInstallPpi (
232                SecInformationDescriptor,
233                &mPeiSecPlatformInformation2
234                );
235   } if (Status == EFI_NOT_FOUND) {
236     Status = GetBistInfoFromPpi (
237                PeiServices,
238                &gEfiSecPlatformInformationPpiGuid,
239                &SecInformationDescriptor,
240                &BistInformationData,
241                &BistInformationSize
242                );
243     if (Status == EFI_SUCCESS) {
244       BuildGuidDataHob (
245         &gEfiCallerIdGuid,
246         BistInformationData,
247         (UINTN) BistInformationSize
248         );
249       //
250       // The old SecPlatformInformation data is on temporary memory.
251       // After memory discovered, we should never get it from temporary memory,
252       // or the data will be crashed. So, we reinstall SecPlatformInformation PPI here.
253       //
254       Status = PeiServicesReInstallPpi (
255                  SecInformationDescriptor,
256                  &mPeiSecPlatformInformation
257                  );
258     } else if (Status == EFI_NOT_FOUND) {
259       return;
260     }
261   }
262 
263   ASSERT_EFI_ERROR(Status);
264 }
265