]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c
Fix system reboot automatically if changing the value of [TPM operation]
[mirror_edk2.git] / SecurityPkg / Tcg / TcgConfigDxe / TcgConfigImpl.c
1 /** @file
2 HII Config Access protocol implementation of TCG configuration module.
3
4 Copyright (c) 2011 - 2012, 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
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
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.MorState = PcdGetBool (PcdMorEnable);
185 Configuration.TpmOperation = PHYSICAL_PRESENCE_ENABLE;
186 Configuration.HideTpm = (BOOLEAN) (PcdGetBool (PcdHideTpmSupport) && PcdGetBool (PcdHideTpm));
187 //
188 // Read the original value of HideTpm from PrivateData which won't be changed by Setup in this boot.
189 //
190 Configuration.OriginalHideTpm = PrivateData->HideTpm;
191
192 //
193 // Display current TPM state.
194 //
195 if (PrivateData->TcgProtocol != NULL) {
196 Status = GetTpmState (PrivateData->TcgProtocol, &TpmEnable, &TpmActivate);
197 if (EFI_ERROR (Status)) {
198 return Status;
199 }
200
201 UnicodeSPrint (
202 State,
203 sizeof (State),
204 L"%s, and %s",
205 TpmEnable ? L"Enabled" : L"Disabled",
206 TpmActivate ? L"Activated" : L"Deactivated"
207 );
208 Configuration.TpmEnable = TpmEnable;
209 Configuration.TpmActivate = TpmActivate;
210
211 HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM_STATE_CONTENT), State, NULL);
212 }
213
214 BufferSize = sizeof (Configuration);
215 ConfigRequest = Request;
216 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
217 //
218 // Request has no request element, construct full request string.
219 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
220 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
221 //
222 ConfigRequestHdr = HiiConstructConfigHdr (&gTcgConfigFormSetGuid, mTcgStorageName, PrivateData->DriverHandle);
223 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
224 ConfigRequest = AllocateZeroPool (Size);
225 ASSERT (ConfigRequest != NULL);
226 AllocatedRequest = TRUE;
227 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64) BufferSize);
228 FreePool (ConfigRequestHdr);
229 }
230
231 Status = gHiiConfigRouting->BlockToConfig (
232 gHiiConfigRouting,
233 ConfigRequest,
234 (UINT8 *) &Configuration,
235 BufferSize,
236 Results,
237 Progress
238 );
239 //
240 // Free the allocated config request string.
241 //
242 if (AllocatedRequest) {
243 FreePool (ConfigRequest);
244 }
245 //
246 // Set Progress string to the original request string.
247 //
248 if (Request == NULL) {
249 *Progress = NULL;
250 } else if (StrStr (Request, L"OFFSET") == NULL) {
251 *Progress = Request + StrLen (Request);
252 }
253
254 return Status;
255 }
256
257 /**
258 This function processes the results of changes in configuration.
259
260 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
261 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
262 format.
263 @param[out] Progress A pointer to a string filled in with the offset of
264 the most recent '&' before the first failing
265 name/value pair (or the beginning of the string if
266 the failure is in the first name/value pair) or
267 the terminating NULL if all was successful.
268
269 @retval EFI_SUCCESS The Results is processed successfully.
270 @retval EFI_INVALID_PARAMETER Configuration is NULL.
271 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
272 driver.
273
274 **/
275 EFI_STATUS
276 EFIAPI
277 TcgRouteConfig (
278 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
279 IN CONST EFI_STRING Configuration,
280 OUT EFI_STRING *Progress
281 )
282 {
283 EFI_STATUS Status;
284 UINTN BufferSize;
285 TCG_CONFIGURATION TcgConfiguration;
286
287 if (Configuration == NULL || Progress == NULL) {
288 return EFI_INVALID_PARAMETER;
289 }
290
291 *Progress = Configuration;
292 if (!HiiIsConfigHdrMatch (Configuration, &gTcgConfigFormSetGuid, mTcgStorageName)) {
293 return EFI_NOT_FOUND;
294 }
295
296 //
297 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
298 //
299 BufferSize = sizeof (TCG_CONFIGURATION);
300 Status = gHiiConfigRouting->ConfigToBlock (
301 gHiiConfigRouting,
302 Configuration,
303 (UINT8 *) &TcgConfiguration,
304 &BufferSize,
305 Progress
306 );
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 PcdSetBool (PcdMorEnable, TcgConfiguration.MorState);
312 PcdSetBool (PcdHideTpm, TcgConfiguration.HideTpm);
313
314 return EFI_SUCCESS;
315 }
316
317 /**
318 Save TPM request to variable space.
319
320 @param[in] PpRequest Physical Presence request command.
321
322 @retval EFI_SUCCESS The operation is finished successfully.
323 @retval Others Other errors as indicated.
324
325 **/
326 EFI_STATUS
327 SavePpRequest (
328 IN UINT8 PpRequest
329 )
330 {
331 EFI_STATUS Status;
332 UINTN DataSize;
333 EFI_PHYSICAL_PRESENCE PpData;
334
335 //
336 // Save TPM command to variable.
337 //
338 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
339 Status = gRT->GetVariable (
340 PHYSICAL_PRESENCE_VARIABLE,
341 &gEfiPhysicalPresenceGuid,
342 NULL,
343 &DataSize,
344 &PpData
345 );
346 if (EFI_ERROR (Status)) {
347 return Status;
348 }
349
350 PpData.PPRequest = PpRequest;
351 Status = gRT->SetVariable (
352 PHYSICAL_PRESENCE_VARIABLE,
353 &gEfiPhysicalPresenceGuid,
354 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
355 DataSize,
356 &PpData
357 );
358 if (EFI_ERROR(Status)) {
359 return Status;
360 }
361
362 return EFI_SUCCESS;
363 }
364
365 /**
366 This function processes the results of changes in configuration.
367
368 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
369 @param[in] Action Specifies the type of action taken by the browser.
370 @param[in] QuestionId A unique value which is sent to the original
371 exporting driver so that it can identify the type
372 of data to expect.
373 @param[in] Type The type of value for the question.
374 @param[in] Value A pointer to the data being sent to the original
375 exporting driver.
376 @param[out] ActionRequest On return, points to the action requested by the
377 callback function.
378
379 @retval EFI_SUCCESS The callback successfully handled the action.
380 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
381 variable and its data.
382 @retval EFI_DEVICE_ERROR The variable could not be saved.
383 @retval EFI_UNSUPPORTED The specified Action is not supported by the
384 callback.
385
386 **/
387 EFI_STATUS
388 EFIAPI
389 TcgCallback (
390 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
391 IN EFI_BROWSER_ACTION Action,
392 IN EFI_QUESTION_ID QuestionId,
393 IN UINT8 Type,
394 IN EFI_IFR_TYPE_VALUE *Value,
395 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
396 )
397 {
398 if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
399 return EFI_INVALID_PARAMETER;
400 }
401
402 if ((Action != EFI_BROWSER_ACTION_CHANGED) || (QuestionId != KEY_TPM_ACTION)) {
403 return EFI_UNSUPPORTED;
404 }
405
406 SavePpRequest (Value->u8);
407 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
408
409 return EFI_SUCCESS;
410 }
411
412 /**
413 This function publish the TCG configuration Form for TPM device.
414
415 @param[in, out] PrivateData Points to TCG configuration private data.
416
417 @retval EFI_SUCCESS HII Form is installed for this network device.
418 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
419 @retval Others Other errors as indicated.
420
421 **/
422 EFI_STATUS
423 InstallTcgConfigForm (
424 IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
425 )
426 {
427 EFI_STATUS Status;
428 EFI_HII_HANDLE HiiHandle;
429 EFI_HANDLE DriverHandle;
430 VOID *StartOpCodeHandle;
431 VOID *EndOpCodeHandle;
432 EFI_IFR_GUID_LABEL *StartLabel;
433 EFI_IFR_GUID_LABEL *EndLabel;
434
435 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
436
437 DriverHandle = NULL;
438 ConfigAccess = &PrivateData->ConfigAccess;
439 Status = gBS->InstallMultipleProtocolInterfaces (
440 &DriverHandle,
441 &gEfiDevicePathProtocolGuid,
442 &mTcgHiiVendorDevicePath,
443 &gEfiHiiConfigAccessProtocolGuid,
444 ConfigAccess,
445 NULL
446 );
447 if (EFI_ERROR (Status)) {
448 return Status;
449 }
450
451 PrivateData->DriverHandle = DriverHandle;
452
453 //
454 // Publish the HII package list
455 //
456 HiiHandle = HiiAddPackages (
457 &gTcgConfigFormSetGuid,
458 DriverHandle,
459 TcgConfigDxeStrings,
460 TcgConfigBin,
461 NULL
462 );
463 if (HiiHandle == NULL) {
464 gBS->UninstallMultipleProtocolInterfaces (
465 DriverHandle,
466 &gEfiDevicePathProtocolGuid,
467 &mTcgHiiVendorDevicePath,
468 &gEfiHiiConfigAccessProtocolGuid,
469 ConfigAccess,
470 NULL
471 );
472
473 return EFI_OUT_OF_RESOURCES;
474 }
475
476 PrivateData->HiiHandle = HiiHandle;
477
478 //
479 // Remove the Hide TPM question from the IFR
480 //
481 if (!PcdGetBool (PcdHideTpmSupport)) {
482 //
483 // Allocate space for creation of UpdateData Buffer
484 //
485 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
486 ASSERT (StartOpCodeHandle != NULL);
487
488 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
489 ASSERT (EndOpCodeHandle != NULL);
490
491 //
492 // Create Hii Extend Label OpCode as the start opcode
493 //
494 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
495 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
496 StartLabel->Number = LABEL_TCG_CONFIGURATION_HIDETPM;
497
498 //
499 // Create Hii Extend Label OpCode as the end opcode
500 //
501 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
502 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
503 EndLabel->Number = LABEL_END;
504
505 HiiUpdateForm (HiiHandle, NULL, TCG_CONFIGURATION_FORM_ID, StartOpCodeHandle, EndOpCodeHandle);
506
507 HiiFreeOpCodeHandle (StartOpCodeHandle);
508 HiiFreeOpCodeHandle (EndOpCodeHandle);
509 }
510
511 return EFI_SUCCESS;
512 }
513
514 /**
515 This function removes TCG configuration Form.
516
517 @param[in, out] PrivateData Points to TCG configuration private data.
518
519 **/
520 VOID
521 UninstallTcgConfigForm (
522 IN OUT TCG_CONFIG_PRIVATE_DATA *PrivateData
523 )
524 {
525 //
526 // Uninstall HII package list
527 //
528 if (PrivateData->HiiHandle != NULL) {
529 HiiRemovePackages (PrivateData->HiiHandle);
530 PrivateData->HiiHandle = NULL;
531 }
532
533 //
534 // Uninstall HII Config Access Protocol
535 //
536 if (PrivateData->DriverHandle != NULL) {
537 gBS->UninstallMultipleProtocolInterfaces (
538 PrivateData->DriverHandle,
539 &gEfiDevicePathProtocolGuid,
540 &mTcgHiiVendorDevicePath,
541 &gEfiHiiConfigAccessProtocolGuid,
542 &PrivateData->ConfigAccess,
543 NULL
544 );
545 PrivateData->DriverHandle = NULL;
546 }
547
548 FreePool (PrivateData);
549 }