1 /** @file
2   The module entry point for Tcg2 configuration module.
3 
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "Tcg2ConfigImpl.h"
10 
11 extern TPM_INSTANCE_ID  mTpmInstanceId[TPM_DEVICE_MAX + 1];
12 
13 /**
14   Update default PCR banks data.
15 
16   @param[in]  HiiPackage        HII Package.
17   @param[in]  HiiPackageSize    HII Package size.
18   @param[in]  PCRBanks          PCR Banks data.
19 
20 **/
21 VOID
UpdateDefaultPCRBanks(IN VOID * HiiPackage,IN UINTN HiiPackageSize,IN UINT32 PCRBanks)22 UpdateDefaultPCRBanks (
23   IN VOID                           *HiiPackage,
24   IN UINTN                          HiiPackageSize,
25   IN UINT32                         PCRBanks
26   )
27 {
28   EFI_HII_PACKAGE_HEADER        *HiiPackageHeader;
29   EFI_IFR_OP_HEADER             *IfrOpCodeHeader;
30   EFI_IFR_CHECKBOX              *IfrCheckBox;
31   EFI_IFR_DEFAULT               *IfrDefault;
32 
33   HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiPackage;
34 
35   switch (HiiPackageHeader->Type) {
36   case EFI_HII_PACKAGE_FORMS:
37     IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)(HiiPackageHeader + 1);
38     while ((UINTN)IfrOpCodeHeader < (UINTN)HiiPackageHeader + HiiPackageHeader->Length) {
39       switch (IfrOpCodeHeader->OpCode) {
40       case EFI_IFR_CHECKBOX_OP:
41         IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpCodeHeader;
42         if ((IfrCheckBox->Question.QuestionId >= KEY_TPM2_PCR_BANKS_REQUEST_0) && (IfrCheckBox->Question.QuestionId <= KEY_TPM2_PCR_BANKS_REQUEST_4)) {
43           IfrDefault = (EFI_IFR_DEFAULT *)(IfrCheckBox + 1);
44           ASSERT (IfrDefault->Header.OpCode == EFI_IFR_DEFAULT_OP);
45           ASSERT (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN);
46           IfrDefault->Value.b = (BOOLEAN)((PCRBanks >> (IfrCheckBox->Question.QuestionId - KEY_TPM2_PCR_BANKS_REQUEST_0)) & 0x1);
47         }
48         break;
49       }
50       IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)((UINTN)IfrOpCodeHeader + IfrOpCodeHeader->Length);
51     }
52     break;
53   }
54   return ;
55 }
56 
57 /**
58   Initialize TCG2 version information.
59 
60   This function will initialize efi varstore configuration data for
61   TCG2_VERSION_NAME variable, check the value of related PCD with
62   the variable value and set string for the version state content
63   according to the PCD value.
64 
65   @param[in] PrivateData    Points to TCG2 configuration private data.
66 
67 **/
68 VOID
InitializeTcg2VersionInfo(IN TCG2_CONFIG_PRIVATE_DATA * PrivateData)69 InitializeTcg2VersionInfo (
70   IN TCG2_CONFIG_PRIVATE_DATA   *PrivateData
71   )
72 {
73   EFI_STATUS                    Status;
74   EFI_STRING                    ConfigRequestHdr;
75   BOOLEAN                       ActionFlag;
76   TCG2_VERSION                  Tcg2Version;
77   UINTN                         DataSize;
78   UINT64                        PcdTcg2PpiVersion;
79   UINT8                         PcdTpm2AcpiTableRev;
80 
81   //
82   // Get the PCD value before initializing efi varstore configuration data.
83   //
84   PcdTcg2PpiVersion = 0;
85   CopyMem (
86     &PcdTcg2PpiVersion,
87     PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer),
88     AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer))
89     );
90 
91   PcdTpm2AcpiTableRev = PcdGet8 (PcdTpm2AcpiTableRev);
92 
93   //
94   // Initialize efi varstore configuration data.
95   //
96   ZeroMem (&Tcg2Version, sizeof (Tcg2Version));
97   ConfigRequestHdr = HiiConstructConfigHdr (
98                        &gTcg2ConfigFormSetGuid,
99                        TCG2_VERSION_NAME,
100                        PrivateData->DriverHandle
101                        );
102   ASSERT (ConfigRequestHdr != NULL);
103   DataSize = sizeof (Tcg2Version);
104   Status = gRT->GetVariable (
105                   TCG2_VERSION_NAME,
106                   &gTcg2ConfigFormSetGuid,
107                   NULL,
108                   &DataSize,
109                   &Tcg2Version
110                   );
111   if (!EFI_ERROR (Status)) {
112     //
113     // EFI variable does exist and validate current setting.
114     //
115     ActionFlag = HiiValidateSettings (ConfigRequestHdr);
116     if (!ActionFlag) {
117       //
118       // Current configuration is invalid, reset to defaults.
119       //
120       ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
121       ASSERT (ActionFlag);
122       //
123       // Get the default values from variable.
124       //
125       DataSize = sizeof (Tcg2Version);
126       Status = gRT->GetVariable (
127                       TCG2_VERSION_NAME,
128                       &gTcg2ConfigFormSetGuid,
129                       NULL,
130                       &DataSize,
131                       &Tcg2Version
132                       );
133       ASSERT_EFI_ERROR (Status);
134     }
135   } else {
136     //
137     // EFI variable doesn't exist or variable size is not expected.
138     //
139 
140     //
141     // Store zero data Buffer Storage to EFI variable.
142     //
143     Status = gRT->SetVariable (
144                     TCG2_VERSION_NAME,
145                     &gTcg2ConfigFormSetGuid,
146                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
147                     sizeof (Tcg2Version),
148                     &Tcg2Version
149                     );
150     if (EFI_ERROR (Status)) {
151       DEBUG ((DEBUG_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_VERSION_NAME\n"));
152       return;
153     } else {
154       //
155       // Build this variable based on default values stored in IFR.
156       //
157       ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
158       ASSERT (ActionFlag);
159       //
160       // Get the default values from variable.
161       //
162       DataSize = sizeof (Tcg2Version);
163       Status = gRT->GetVariable (
164                       TCG2_VERSION_NAME,
165                       &gTcg2ConfigFormSetGuid,
166                       NULL,
167                       &DataSize,
168                       &Tcg2Version
169                       );
170       ASSERT_EFI_ERROR (Status);
171       if (PcdTcg2PpiVersion != Tcg2Version.PpiVersion) {
172         DEBUG ((DEBUG_WARN, "WARNING: PcdTcgPhysicalPresenceInterfaceVer default value is not same with the default value in VFR\n"));
173         DEBUG ((DEBUG_WARN, "WARNING: The default value in VFR has be chosen\n"));
174       }
175       if (PcdTpm2AcpiTableRev != Tcg2Version.Tpm2AcpiTableRev) {
176         DEBUG ((DEBUG_WARN, "WARNING: PcdTpm2AcpiTableRev default value is not same with the default value in VFR\n"));
177         DEBUG ((DEBUG_WARN, "WARNING: The default value in VFR has be chosen\n"));
178       }
179     }
180   }
181   FreePool (ConfigRequestHdr);
182 
183   //
184   // Get the PCD value again.
185   // If the PCD value is not equal to the value in variable,
186   // the PCD is not DynamicHii type and does not map to the setup option.
187   //
188   PcdTcg2PpiVersion = 0;
189   CopyMem (
190     &PcdTcg2PpiVersion,
191     PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer),
192     AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer))
193     );
194   if (PcdTcg2PpiVersion != Tcg2Version.PpiVersion) {
195     DEBUG ((DEBUG_WARN, "WARNING: PcdTcgPhysicalPresenceInterfaceVer is not DynamicHii type and does not map to TCG2_VERSION.PpiVersion\n"));
196     DEBUG ((DEBUG_WARN, "WARNING: The TCG2 PPI version configuring from setup page will not work\n"));
197   }
198 
199   switch (PcdTcg2PpiVersion) {
200     case TCG2_PPI_VERSION_1_2:
201       HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_PPI_VERSION_STATE_CONTENT), L"1.2", NULL);
202       break;
203     case TCG2_PPI_VERSION_1_3:
204       HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_PPI_VERSION_STATE_CONTENT), L"1.3", NULL);
205       break;
206     default:
207       ASSERT (FALSE);
208       break;
209   }
210 
211   //
212   // Get the PcdTpm2AcpiTableRev value again.
213   // If the PCD value is not equal to the value in variable,
214   // the PCD is not DynamicHii type and does not map to TCG2_VERSION Variable.
215   //
216   PcdTpm2AcpiTableRev = PcdGet8 (PcdTpm2AcpiTableRev);
217   if (PcdTpm2AcpiTableRev != Tcg2Version.Tpm2AcpiTableRev) {
218     DEBUG ((DEBUG_WARN, "WARNING: PcdTpm2AcpiTableRev is not DynamicHii type and does not map to TCG2_VERSION.Tpm2AcpiTableRev\n"));
219     DEBUG ((DEBUG_WARN, "WARNING: The Tpm2 ACPI Revision configuring from setup page will not work\n"));
220   }
221 
222   switch (PcdTpm2AcpiTableRev) {
223     case EFI_TPM2_ACPI_TABLE_REVISION_3:
224       HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACPI_REVISION_STATE_CONTENT), L"Rev 3", NULL);
225       break;
226     case EFI_TPM2_ACPI_TABLE_REVISION_4:
227       HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACPI_REVISION_STATE_CONTENT), L"Rev 4", NULL);
228       break;
229     default:
230       ASSERT (FALSE);
231       break;
232   }
233 }
234 
235 /**
236   The entry point for Tcg2 configuration driver.
237 
238   @param[in]  ImageHandle        The image handle of the driver.
239   @param[in]  SystemTable        The system table.
240 
241   @retval EFI_ALREADY_STARTED    The driver already exists in system.
242   @retval EFI_OUT_OF_RESOURCES   Fail to execute entry point due to lack of resources.
243   @retval EFI_SUCCESS            All the related protocols are installed on the driver.
244   @retval Others                 Fail to install protocols as indicated.
245 
246 **/
247 EFI_STATUS
248 EFIAPI
Tcg2ConfigDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)249 Tcg2ConfigDriverEntryPoint (
250   IN EFI_HANDLE          ImageHandle,
251   IN EFI_SYSTEM_TABLE    *SystemTable
252   )
253 {
254   EFI_STATUS                    Status;
255   TCG2_CONFIG_PRIVATE_DATA      *PrivateData;
256   TCG2_CONFIGURATION            Tcg2Configuration;
257   TCG2_DEVICE_DETECTION         Tcg2DeviceDetection;
258   UINTN                         Index;
259   UINTN                         DataSize;
260   EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLockProtocol;
261   UINT32                        CurrentActivePCRBanks;
262 
263   Status = gBS->OpenProtocol (
264                   ImageHandle,
265                   &gEfiCallerIdGuid,
266                   NULL,
267                   ImageHandle,
268                   ImageHandle,
269                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
270                   );
271   if (!EFI_ERROR (Status)) {
272     return EFI_ALREADY_STARTED;
273   }
274 
275   //
276   // Create a private data structure.
277   //
278   PrivateData = AllocateCopyPool (sizeof (TCG2_CONFIG_PRIVATE_DATA), &mTcg2ConfigPrivateDateTemplate);
279   ASSERT (PrivateData != NULL);
280   mTcg2ConfigPrivateDate = PrivateData;
281   //
282   // Install private GUID.
283   //
284   Status = gBS->InstallMultipleProtocolInterfaces (
285                   &ImageHandle,
286                   &gEfiCallerIdGuid,
287                   PrivateData,
288                   NULL
289                   );
290   ASSERT_EFI_ERROR (Status);
291 
292   Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &PrivateData->Tcg2Protocol);
293   ASSERT_EFI_ERROR (Status);
294 
295   PrivateData->ProtocolCapability.Size = sizeof(PrivateData->ProtocolCapability);
296   Status = PrivateData->Tcg2Protocol->GetCapability (
297                                         PrivateData->Tcg2Protocol,
298                                         &PrivateData->ProtocolCapability
299                                         );
300   ASSERT_EFI_ERROR (Status);
301 
302   DataSize = sizeof(Tcg2Configuration);
303   Status = gRT->GetVariable (
304                   TCG2_STORAGE_NAME,
305                   &gTcg2ConfigFormSetGuid,
306                   NULL,
307                   &DataSize,
308                   &Tcg2Configuration
309                   );
310   if (EFI_ERROR (Status)) {
311     //
312     // Variable not ready, set default value
313     //
314     Tcg2Configuration.TpmDevice           = TPM_DEVICE_DEFAULT;
315   }
316 
317   //
318   // Validation
319   //
320   if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) {
321     Tcg2Configuration.TpmDevice   = TPM_DEVICE_DEFAULT;
322   }
323 
324   //
325   // Set value for Tcg2CurrentActivePCRBanks
326   // Search Tcg2ConfigBin[] and update default value there
327   //
328   Status = PrivateData->Tcg2Protocol->GetActivePcrBanks (PrivateData->Tcg2Protocol, &CurrentActivePCRBanks);
329   ASSERT_EFI_ERROR (Status);
330   PrivateData->PCRBanksDesired = CurrentActivePCRBanks;
331   UpdateDefaultPCRBanks (Tcg2ConfigBin + sizeof(UINT32), ReadUnaligned32((UINT32 *)Tcg2ConfigBin) - sizeof(UINT32), CurrentActivePCRBanks);
332 
333   //
334   // Sync data from PCD to variable, so that we do not need detect again in S3 phase.
335   //
336   Tcg2DeviceDetection.TpmDeviceDetected = TPM_DEVICE_NULL;
337   for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) {
338     if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &mTpmInstanceId[Index].TpmInstanceGuid)) {
339       Tcg2DeviceDetection.TpmDeviceDetected = mTpmInstanceId[Index].TpmDevice;
340       break;
341     }
342   }
343 
344   PrivateData->TpmDeviceDetected = Tcg2DeviceDetection.TpmDeviceDetected;
345   Tcg2Configuration.TpmDevice = Tcg2DeviceDetection.TpmDeviceDetected;
346 
347   //
348   // Save to variable so platform driver can get it.
349   //
350   Status = gRT->SetVariable (
351                   TCG2_DEVICE_DETECTION_NAME,
352                   &gTcg2ConfigFormSetGuid,
353                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
354                   sizeof(Tcg2DeviceDetection),
355                   &Tcg2DeviceDetection
356                   );
357   if (EFI_ERROR (Status)) {
358     DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_DEVICE_DETECTION_NAME\n"));
359     Status = gRT->SetVariable (
360                     TCG2_DEVICE_DETECTION_NAME,
361                     &gTcg2ConfigFormSetGuid,
362                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
363                     0,
364                     NULL
365                     );
366     ASSERT_EFI_ERROR (Status);
367   }
368 
369   //
370   // Save to variable so platform driver can get it.
371   //
372   Status = gRT->SetVariable (
373                   TCG2_STORAGE_NAME,
374                   &gTcg2ConfigFormSetGuid,
375                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
376                   sizeof(Tcg2Configuration),
377                   &Tcg2Configuration
378                   );
379   if (EFI_ERROR (Status)) {
380     DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_NAME\n"));
381   }
382 
383   //
384   // We should lock Tcg2DeviceDetection, because it contains information needed at S3.
385   //
386   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
387   if (!EFI_ERROR (Status)) {
388     Status = VariableLockProtocol->RequestToLock (
389                                      VariableLockProtocol,
390                                      TCG2_DEVICE_DETECTION_NAME,
391                                      &gTcg2ConfigFormSetGuid
392                                      );
393     ASSERT_EFI_ERROR (Status);
394   }
395 
396   //
397   // Install Tcg2 configuration form
398   //
399   Status = InstallTcg2ConfigForm (PrivateData);
400   if (EFI_ERROR (Status)) {
401     goto ErrorExit;
402   }
403 
404   InitializeTcg2VersionInfo (PrivateData);
405 
406   return EFI_SUCCESS;
407 
408 ErrorExit:
409   if (PrivateData != NULL) {
410     UninstallTcg2ConfigForm (PrivateData);
411   }
412 
413   return Status;
414 }
415 
416 /**
417   Unload the Tcg2 configuration form.
418 
419   @param[in]  ImageHandle         The driver's image handle.
420 
421   @retval     EFI_SUCCESS         The Tcg2 configuration form is unloaded.
422   @retval     Others              Failed to unload the form.
423 
424 **/
425 EFI_STATUS
426 EFIAPI
Tcg2ConfigDriverUnload(IN EFI_HANDLE ImageHandle)427 Tcg2ConfigDriverUnload (
428   IN EFI_HANDLE  ImageHandle
429   )
430 {
431   EFI_STATUS                  Status;
432   TCG2_CONFIG_PRIVATE_DATA    *PrivateData;
433 
434   Status = gBS->HandleProtocol (
435                   ImageHandle,
436                   &gEfiCallerIdGuid,
437                   (VOID **) &PrivateData
438                   );
439   if (EFI_ERROR (Status)) {
440     return Status;
441   }
442 
443   ASSERT (PrivateData->Signature == TCG2_CONFIG_PRIVATE_DATA_SIGNATURE);
444 
445   gBS->UninstallMultipleProtocolInterfaces (
446          ImageHandle,
447          &gEfiCallerIdGuid,
448          PrivateData,
449          NULL
450          );
451 
452   UninstallTcg2ConfigForm (PrivateData);
453 
454   return EFI_SUCCESS;
455 }
456