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