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