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 
10 #include <PiPei.h>
11 
12 #include <Guid/TpmInstance.h>
13 
14 #include <Library/BaseLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/PeiServicesLib.h>
19 #include <Library/PcdLib.h>
20 
21 #include <Ppi/ReadOnlyVariable2.h>
22 #include <Ppi/TpmInitialized.h>
23 #include <Protocol/Tcg2Protocol.h>
24 
25 #include "Tcg2ConfigNvData.h"
26 
27 TPM_INSTANCE_ID  mTpmInstanceId[] = TPM_INSTANCE_ID_LIST;
28 
29 CONST EFI_PEI_PPI_DESCRIPTOR gTpmSelectedPpi = {
30   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
31   &gEfiTpmDeviceSelectedGuid,
32   NULL
33 };
34 
35 EFI_PEI_PPI_DESCRIPTOR  mTpmInitializationDonePpiList = {
36   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
37   &gPeiTpmInitializationDonePpiGuid,
38   NULL
39 };
40 
41 /**
42   This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
43 
44   @param  SetupTpmDevice  TpmDevice configuration in setup driver
45 
46   @return TpmDevice configuration
47 **/
48 UINT8
49 DetectTpmDevice (
50   IN UINT8 SetupTpmDevice
51   );
52 
53 /**
54   The entry point for Tcg2 configuration driver.
55 
56   @param  FileHandle  Handle of the file being invoked.
57   @param  PeiServices Describes the list of possible PEI Services.
58 
59   @retval EFI_SUCCES             Convert variable to PCD successfully.
60   @retval Others                 Fail to convert variable to PCD.
61 **/
62 EFI_STATUS
63 EFIAPI
Tcg2ConfigPeimEntryPoint(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)64 Tcg2ConfigPeimEntryPoint (
65   IN       EFI_PEI_FILE_HANDLE  FileHandle,
66   IN CONST EFI_PEI_SERVICES     **PeiServices
67   )
68 {
69   UINTN                           Size;
70   EFI_STATUS                      Status;
71   EFI_STATUS                      Status2;
72   EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariablePpi;
73   TCG2_CONFIGURATION              Tcg2Configuration;
74   UINTN                           Index;
75   UINT8                           TpmDevice;
76 
77   Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi);
78   ASSERT_EFI_ERROR (Status);
79 
80   Size = sizeof(Tcg2Configuration);
81   Status = VariablePpi->GetVariable (
82                           VariablePpi,
83                           TCG2_STORAGE_NAME,
84                           &gTcg2ConfigFormSetGuid,
85                           NULL,
86                           &Size,
87                           &Tcg2Configuration
88                           );
89   if (EFI_ERROR (Status)) {
90     //
91     // Variable not ready, set default value
92     //
93     Tcg2Configuration.TpmDevice           = TPM_DEVICE_DEFAULT;
94   }
95 
96   //
97   // Validation
98   //
99   if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) {
100     Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT;
101   }
102 
103   //
104   // Although we have SetupVariable info, we still need detect TPM device manually.
105   //
106   DEBUG ((EFI_D_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice));
107 
108   if (PcdGetBool (PcdTpmAutoDetection)) {
109     TpmDevice = DetectTpmDevice (Tcg2Configuration.TpmDevice);
110     DEBUG ((EFI_D_INFO, "TpmDevice final: %x\n", TpmDevice));
111     if (TpmDevice != TPM_DEVICE_NULL) {
112       Tcg2Configuration.TpmDevice = TpmDevice;
113     }
114   } else {
115     TpmDevice = Tcg2Configuration.TpmDevice;
116   }
117 
118   //
119   // Convert variable to PCD.
120   // This is work-around because there is no gurantee DynamicHiiPcd can return correct value in DXE phase.
121   // Using DynamicPcd instead.
122   //
123   // NOTE: Tcg2Configuration variable contains the desired TpmDevice type,
124   // while PcdTpmInstanceGuid PCD contains the real detected TpmDevice type
125   //
126   for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) {
127     if (TpmDevice == mTpmInstanceId[Index].TpmDevice) {
128       Size = sizeof(mTpmInstanceId[Index].TpmInstanceGuid);
129       Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid);
130       ASSERT_EFI_ERROR (Status);
131       DEBUG ((EFI_D_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid));
132       break;
133     }
134   }
135 
136   //
137   // Selection done
138   //
139   Status = PeiServicesInstallPpi (&gTpmSelectedPpi);
140   ASSERT_EFI_ERROR (Status);
141 
142   //
143   // Even if no TPM is selected or detected, we still need intall TpmInitializationDonePpi.
144   // Because TcgPei or Tcg2Pei will not run, but we still need a way to notify other driver.
145   // Other driver can know TPM initialization state by TpmInitializedPpi.
146   //
147   if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid)) {
148     Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
149     ASSERT_EFI_ERROR (Status2);
150   }
151 
152   return Status;
153 }
154