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