1 /** @file
2   HII Config Access protocol implementation of TCG configuration module.
3 
4 Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "TcgConfigImpl.h"
10 
11 CHAR16                          mTcgStorageName[] = L"TCG_CONFIGURATION";
12 
13 TCG_CONFIG_PRIVATE_DATA         mTcgConfigPrivateDateTemplate = {
14   TCG_CONFIG_PRIVATE_DATA_SIGNATURE,
15   {
16     TcgExtractConfig,
17     TcgRouteConfig,
18     TcgCallback
19   }
20 };
21 
22 HII_VENDOR_DEVICE_PATH          mTcgHiiVendorDevicePath = {
23   {
24     {
25       HARDWARE_DEVICE_PATH,
26       HW_VENDOR_DP,
27       {
28         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
29         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
30       }
31     },
32     TCG_CONFIG_FORM_SET_GUID
33   },
34   {
35     END_DEVICE_PATH_TYPE,
36     END_ENTIRE_DEVICE_PATH_SUBTYPE,
37     {
38       (UINT8) (END_DEVICE_PATH_LENGTH),
39       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
40     }
41   }
42 };
43 
44 /**
45   Get current state of TPM device.
46 
47   @param[in]   TcgProtocol          Point to EFI_TCG_PROTOCOL instance.
48   @param[out]  TpmEnable            Flag to indicate TPM is enabled or not.
49   @param[out]  TpmActivate          Flag to indicate TPM is activated or not.
50 
51   @retval EFI_SUCCESS               State is successfully returned.
52   @retval EFI_DEVICE_ERROR          Failed to get TPM response.
53   @retval Others                    Other errors as indicated.
54 
55 **/
56 EFI_STATUS
GetTpmState(IN EFI_TCG_PROTOCOL * TcgProtocol,OUT BOOLEAN * TpmEnable,OPTIONAL OUT BOOLEAN * TpmActivate OPTIONAL)57 GetTpmState (
58   IN  EFI_TCG_PROTOCOL          *TcgProtocol,
59   OUT BOOLEAN                   *TpmEnable,  OPTIONAL
60   OUT BOOLEAN                   *TpmActivate OPTIONAL
61   )
62 {
63   EFI_STATUS                    Status;
64   TPM_RSP_COMMAND_HDR           *TpmRsp;
65   UINT32                        TpmSendSize;
66   TPM_PERMANENT_FLAGS           *TpmPermanentFlags;
67   UINT8                         CmdBuf[64];
68 
69   ASSERT (TcgProtocol != NULL);
70 
71   //
72   // Get TPM Permanent flags (TpmEnable, TpmActivate)
73   //
74   if ((TpmEnable != NULL) || (TpmActivate != NULL)) {
75     TpmSendSize           = sizeof (TPM_RQU_COMMAND_HDR) + sizeof (UINT32) * 3;
76     *(UINT16*)&CmdBuf[0]  = SwapBytes16 (TPM_TAG_RQU_COMMAND);
77     *(UINT32*)&CmdBuf[2]  = SwapBytes32 (TpmSendSize);
78     *(UINT32*)&CmdBuf[6]  = SwapBytes32 (TPM_ORD_GetCapability);
79 
80     *(UINT32*)&CmdBuf[10] = SwapBytes32 (TPM_CAP_FLAG);
81     *(UINT32*)&CmdBuf[14] = SwapBytes32 (sizeof (TPM_CAP_FLAG_PERMANENT));
82     *(UINT32*)&CmdBuf[18] = SwapBytes32 (TPM_CAP_FLAG_PERMANENT);
83 
84     Status = TcgProtocol->PassThroughToTpm (
85                             TcgProtocol,
86                             TpmSendSize,
87                             CmdBuf,
88                             sizeof (CmdBuf),
89                             CmdBuf
90                             );
91     TpmRsp = (TPM_RSP_COMMAND_HDR *) &CmdBuf[0];
92     if (EFI_ERROR (Status) || (TpmRsp->tag != SwapBytes16 (TPM_TAG_RSP_COMMAND)) || (TpmRsp->returnCode != 0)) {
93       return EFI_DEVICE_ERROR;
94     }
95 
96     TpmPermanentFlags = (TPM_PERMANENT_FLAGS *) &CmdBuf[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];
97 
98     if (TpmEnable != NULL) {
99       *TpmEnable = (BOOLEAN) !TpmPermanentFlags->disable;
100     }
101 
102     if (TpmActivate != NULL) {
103       *TpmActivate = (BOOLEAN) !TpmPermanentFlags->deactivated;
104     }
105   }
106 
107   return EFI_SUCCESS;
108 }
109 
110 /**
111   This function allows a caller to extract the current configuration for one
112   or more named elements from the target driver.
113 
114   @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
115   @param[in]   Request           A null-terminated Unicode string in
116                                  <ConfigRequest> format.
117   @param[out]  Progress          On return, points to a character in the Request
118                                  string. Points to the string's null terminator if
119                                  request was successful. Points to the most recent
120                                  '&' before the first failing name/value pair (or
121                                  the beginning of the string if the failure is in
122                                  the first name/value pair) if the request was not
123                                  successful.
124   @param[out]  Results           A null-terminated Unicode string in
125                                  <ConfigAltResp> format which has all values filled
126                                  in for the names in the Request string. String to
127                                  be allocated by the called function.
128 
129   @retval EFI_SUCCESS            The Results is filled with the requested values.
130   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
131   @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
132   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
133                                  driver.
134 
135 **/
136 EFI_STATUS
137 EFIAPI
TcgExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)138 TcgExtractConfig (
139   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,
140   IN CONST EFI_STRING                            Request,
141        OUT EFI_STRING                            *Progress,
142        OUT EFI_STRING                            *Results
143   )
144 {
145   EFI_STATUS                 Status;
146   TCG_CONFIG_PRIVATE_DATA    *PrivateData;
147   EFI_STRING                 ConfigRequestHdr;
148   EFI_STRING                 ConfigRequest;
149   BOOLEAN                    AllocatedRequest;
150   UINTN                      Size;
151   BOOLEAN                    TpmEnable;
152   BOOLEAN                    TpmActivate;
153 
154   if (Progress == NULL || Results == NULL) {
155     return EFI_INVALID_PARAMETER;
156   }
157 
158   *Progress = Request;
159   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTcgConfigFormSetGuid, mTcgStorageName)) {
160     return EFI_NOT_FOUND;
161   }
162 
163   ConfigRequestHdr = NULL;
164   ConfigRequest    = NULL;
165   AllocatedRequest = FALSE;
166   Size             = 0;
167 
168   PrivateData = TCG_CONFIG_PRIVATE_DATA_FROM_THIS (This);
169 
170   //
171   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
172   //
173   PrivateData->Configuration->TpmOperation = PHYSICAL_PRESENCE_NO_ACTION;
174 
175   //
176   // Get current TPM state.
177   //
178   if (PrivateData->TcgProtocol != NULL) {
179     Status = GetTpmState (PrivateData->TcgProtocol, &TpmEnable, &TpmActivate);
180     if (EFI_ERROR (Status)) {
181       return Status;
182     }
183 
184     PrivateData->Configuration->TpmEnable   = TpmEnable;
185     PrivateData->Configuration->TpmActivate = TpmActivate;
186   }
187 
188   ConfigRequest = Request;
189   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
190     //
191     // Request has no request element, construct full request string.
192     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
193     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
194     //
195     ConfigRequestHdr = HiiConstructConfigHdr (&gTcgConfigFormSetGuid, mTcgStorageName, PrivateData->DriverHandle);
196     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
197     ConfigRequest = AllocateZeroPool (Size);
198     ASSERT (ConfigRequest != NULL);
199     AllocatedRequest = TRUE;
200     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof (TCG_CONFIGURATION));
201     FreePool (ConfigRequestHdr);
202   }
203 
204   Status = gHiiConfigRouting->BlockToConfig (
205                                 gHiiConfigRouting,
206                                 ConfigRequest,
207                                 (UINT8 *) PrivateData->Configuration,
208                                 sizeof (TCG_CONFIGURATION),
209                                 Results,
210                                 Progress
211                                 );
212   //
213   // Free the allocated config request string.
214   //
215   if (AllocatedRequest) {
216     FreePool (ConfigRequest);
217   }
218   //
219   // Set Progress string to the original request string.
220   //
221   if (Request == NULL) {
222     *Progress = NULL;
223   } else if (StrStr (Request, L"OFFSET") == NULL) {
224     *Progress = Request + StrLen (Request);
225   }
226 
227   return Status;
228 }
229 
230 /**
231   This function processes the results of changes in configuration.
232 
233   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
234   @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>
235                                  format.
236   @param[out] Progress           A pointer to a string filled in with the offset of
237                                  the most recent '&' before the first failing
238                                  name/value pair (or the beginning of the string if
239                                  the failure is in the first name/value pair) or
240                                  the terminating NULL if all was successful.
241 
242   @retval EFI_SUCCESS            The Results is processed successfully.
243   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
244   @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this
245                                  driver.
246 
247 **/
248 EFI_STATUS
249 EFIAPI
TcgRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)250 TcgRouteConfig (
251   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
252   IN CONST EFI_STRING                          Configuration,
253        OUT EFI_STRING                          *Progress
254   )
255 {
256   EFI_STATUS                       Status;
257   UINTN                            BufferSize;
258   TCG_CONFIGURATION                TcgConfiguration;
259 
260   if (Configuration == NULL || Progress == NULL) {
261     return EFI_INVALID_PARAMETER;
262   }
263 
264   *Progress = Configuration;
265   if (!HiiIsConfigHdrMatch (Configuration, &gTcgConfigFormSetGuid, mTcgStorageName)) {
266     return EFI_NOT_FOUND;
267   }
268 
269   //
270   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
271   //
272   BufferSize = sizeof (TCG_CONFIGURATION);
273   Status = gHiiConfigRouting->ConfigToBlock (
274                                 gHiiConfigRouting,
275                                 Configuration,
276                                 (UINT8 *) &TcgConfiguration,
277                                 &BufferSize,
278                                 Progress
279                                 );
280   if (EFI_ERROR (Status)) {
281     return Status;
282   }
283 
284   return EFI_SUCCESS;
285 }
286 
287 /**
288   Save TPM request to variable space.
289 
290   @param[in] PpRequest             Physical Presence request command.
291 
292   @retval    EFI_SUCCESS           The operation is finished successfully.
293   @retval    Others                Other errors as indicated.
294 
295 **/
296 EFI_STATUS
SavePpRequest(IN UINT8 PpRequest)297 SavePpRequest (
298   IN UINT8                         PpRequest
299   )
300 {
301   EFI_STATUS                       Status;
302   UINTN                            DataSize;
303   EFI_PHYSICAL_PRESENCE            PpData;
304 
305   //
306   // Save TPM command to variable.
307   //
308   DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
309   Status = gRT->GetVariable (
310                   PHYSICAL_PRESENCE_VARIABLE,
311                   &gEfiPhysicalPresenceGuid,
312                   NULL,
313                   &DataSize,
314                   &PpData
315                   );
316   if (EFI_ERROR (Status)) {
317     return Status;
318   }
319 
320   PpData.PPRequest = PpRequest;
321   Status = gRT->SetVariable (
322                   PHYSICAL_PRESENCE_VARIABLE,
323                   &gEfiPhysicalPresenceGuid,
324                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
325                   DataSize,
326                   &PpData
327                   );
328   if (EFI_ERROR(Status)) {
329     return Status;
330   }
331 
332   return EFI_SUCCESS;
333 }
334 
335 /**
336   This function processes the results of changes in configuration.
337 
338   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
339   @param[in]  Action             Specifies the type of action taken by the browser.
340   @param[in]  QuestionId         A unique value which is sent to the original
341                                  exporting driver so that it can identify the type
342                                  of data to expect.
343   @param[in]  Type               The type of value for the question.
344   @param[in]  Value              A pointer to the data being sent to the original
345                                  exporting driver.
346   @param[out] ActionRequest      On return, points to the action requested by the
347                                  callback function.
348 
349   @retval EFI_SUCCESS            The callback successfully handled the action.
350   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
351                                  variable and its data.
352   @retval EFI_DEVICE_ERROR       The variable could not be saved.
353   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
354                                  callback.
355 
356 **/
357 EFI_STATUS
358 EFIAPI
TcgCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)359 TcgCallback (
360   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
361   IN     EFI_BROWSER_ACTION                    Action,
362   IN     EFI_QUESTION_ID                       QuestionId,
363   IN     UINT8                                 Type,
364   IN     EFI_IFR_TYPE_VALUE                    *Value,
365      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest
366   )
367 {
368   TCG_CONFIG_PRIVATE_DATA    *PrivateData;
369   CHAR16                     State[32];
370 
371   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
372     return EFI_INVALID_PARAMETER;
373   }
374 
375   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
376     if (QuestionId == KEY_TPM_ACTION) {
377 
378       PrivateData = TCG_CONFIG_PRIVATE_DATA_FROM_THIS (This);
379       UnicodeSPrint (
380         State,
381         sizeof (State),
382         L"%s, and %s",
383         PrivateData->Configuration->TpmEnable   ? L"Enabled"   : L"Disabled",
384         PrivateData->Configuration->TpmActivate ? L"Activated" : L"Deactivated"
385         );
386       HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM_STATE_CONTENT), State, NULL);
387     }
388     return EFI_SUCCESS;
389   }
390 
391   if ((Action != EFI_BROWSER_ACTION_CHANGED) || (QuestionId != KEY_TPM_ACTION)) {
392     return EFI_UNSUPPORTED;
393   }
394 
395   SavePpRequest (Value->u8);
396   *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
397 
398   return EFI_SUCCESS;
399 }
400 
401 /**
402   This function publish the TCG configuration Form for TPM device.
403 
404   @param[in, out]  PrivateData   Points to TCG configuration private data.
405 
406   @retval EFI_SUCCESS            HII Form is installed for this network device.
407   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.
408   @retval Others                 Other errors as indicated.
409 
410 **/
411 EFI_STATUS
InstallTcgConfigForm(IN OUT TCG_CONFIG_PRIVATE_DATA * PrivateData)412 InstallTcgConfigForm (
413   IN OUT TCG_CONFIG_PRIVATE_DATA  *PrivateData
414   )
415 {
416   EFI_STATUS                      Status;
417   EFI_HII_HANDLE                  HiiHandle;
418   EFI_HANDLE                      DriverHandle;
419   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
420 
421   DriverHandle = NULL;
422   ConfigAccess = &PrivateData->ConfigAccess;
423   Status = gBS->InstallMultipleProtocolInterfaces (
424                   &DriverHandle,
425                   &gEfiDevicePathProtocolGuid,
426                   &mTcgHiiVendorDevicePath,
427                   &gEfiHiiConfigAccessProtocolGuid,
428                   ConfigAccess,
429                   NULL
430                   );
431   if (EFI_ERROR (Status)) {
432     return Status;
433   }
434 
435   PrivateData->DriverHandle = DriverHandle;
436 
437   //
438   // Publish the HII package list
439   //
440   HiiHandle = HiiAddPackages (
441                 &gTcgConfigFormSetGuid,
442                 DriverHandle,
443                 TcgConfigDxeStrings,
444                 TcgConfigBin,
445                 NULL
446                 );
447   if (HiiHandle == NULL) {
448     gBS->UninstallMultipleProtocolInterfaces (
449            DriverHandle,
450            &gEfiDevicePathProtocolGuid,
451            &mTcgHiiVendorDevicePath,
452            &gEfiHiiConfigAccessProtocolGuid,
453            ConfigAccess,
454            NULL
455            );
456 
457     return EFI_OUT_OF_RESOURCES;
458   }
459 
460   PrivateData->HiiHandle = HiiHandle;
461 
462   return EFI_SUCCESS;
463 }
464 
465 /**
466   This function removes TCG configuration Form.
467 
468   @param[in, out]  PrivateData   Points to TCG configuration private data.
469 
470 **/
471 VOID
UninstallTcgConfigForm(IN OUT TCG_CONFIG_PRIVATE_DATA * PrivateData)472 UninstallTcgConfigForm (
473   IN OUT TCG_CONFIG_PRIVATE_DATA    *PrivateData
474   )
475 {
476   //
477   // Uninstall HII package list
478   //
479   if (PrivateData->HiiHandle != NULL) {
480     HiiRemovePackages (PrivateData->HiiHandle);
481     PrivateData->HiiHandle = NULL;
482   }
483 
484   //
485   // Uninstall HII Config Access Protocol
486   //
487   if (PrivateData->DriverHandle != NULL) {
488     gBS->UninstallMultipleProtocolInterfaces (
489            PrivateData->DriverHandle,
490            &gEfiDevicePathProtocolGuid,
491            &mTcgHiiVendorDevicePath,
492            &gEfiHiiConfigAccessProtocolGuid,
493            &PrivateData->ConfigAccess,
494            NULL
495            );
496     PrivateData->DriverHandle = NULL;
497   }
498 
499   if (PrivateData->Configuration != NULL) {
500     FreePool(PrivateData->Configuration);
501   }
502   FreePool (PrivateData);
503 }
504