]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/DxeTrEEPhysicalPresenceLib/DxeTrEEPhysicalPresenceLib.c
Add TPM Physical Presence >=128 operation value support.
[mirror_edk2.git] / SecurityPkg / Library / DxeTrEEPhysicalPresenceLib / DxeTrEEPhysicalPresenceLib.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Execute pending TPM2 requests from OS or BIOS.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This driver will have external input - variable.\r
6 This external input must be validated carefully to avoid security issue.\r
7\r
8 TrEEExecutePendingTpmRequest() will receive untrusted input and do validation.\r
9\r
4610b23a 10Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
c1d93242
JY
11This program and the accompanying materials \r
12are licensed and made available under the terms and conditions of the BSD License \r
13which accompanies this distribution. The full text of the license may be found at \r
14http://opensource.org/licenses/bsd-license.php\r
15\r
16THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
17WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
18\r
19**/\r
20\r
21#include <PiDxe.h>\r
22\r
23#include <Protocol/TrEEProtocol.h>\r
24#include <Protocol/VariableLock.h>\r
25#include <Library/DebugLib.h>\r
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/UefiRuntimeServicesTableLib.h>\r
28#include <Library/UefiDriverEntryPoint.h>\r
29#include <Library/UefiBootServicesTableLib.h>\r
30#include <Library/UefiLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
32#include <Library/PrintLib.h>\r
33#include <Library/HiiLib.h>\r
34#include <Guid/EventGroup.h>\r
35#include <Guid/TrEEPhysicalPresenceData.h>\r
36#include <Library/Tpm2CommandLib.h>\r
4610b23a 37#include <Library/TrEEPpVendorLib.h>\r
c1d93242
JY
38\r
39#define CONFIRM_BUFFER_SIZE 4096\r
40\r
41EFI_HII_HANDLE mTrEEPpStringPackHandle;\r
42\r
43/**\r
44 Get string by string id from HII Interface.\r
45\r
46 @param[in] Id String ID.\r
47\r
48 @retval CHAR16 * String from ID.\r
49 @retval NULL If error occurs.\r
50\r
51**/\r
52CHAR16 *\r
53TrEEPhysicalPresenceGetStringById (\r
54 IN EFI_STRING_ID Id\r
55 )\r
56{\r
57 return HiiGetString (mTrEEPpStringPackHandle, Id, NULL);\r
58}\r
59\r
60/**\r
61 Send ClearControl and Clear command to TPM.\r
62\r
63 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
64\r
65 @retval EFI_SUCCESS Operation completed successfully.\r
66 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
67 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
68 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
69\r
70**/\r
71EFI_STATUS\r
72EFIAPI\r
73TpmCommandClear (\r
74 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
75 )\r
76{\r
77 EFI_STATUS Status;\r
78 TPMS_AUTH_COMMAND *AuthSession;\r
79 TPMS_AUTH_COMMAND LocalAuthSession;\r
80\r
81 if (PlatformAuth == NULL) {\r
82 AuthSession = NULL;\r
83 } else {\r
84 AuthSession = &LocalAuthSession;\r
85 ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
86 LocalAuthSession.sessionHandle = TPM_RS_PW;\r
87 LocalAuthSession.hmac.size = PlatformAuth->size;\r
88 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
89 }\r
90\r
33985e3b 91 DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n"));\r
c1d93242 92 Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);\r
33985e3b 93 DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status));\r
c1d93242
JY
94 if (EFI_ERROR (Status)) {\r
95 goto Done;\r
96 }\r
33985e3b 97 DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n"));\r
c1d93242 98 Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);\r
33985e3b 99 DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status));\r
c1d93242
JY
100\r
101Done:\r
102 ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));\r
103 return Status;\r
104}\r
105\r
106/**\r
107 Execute physical presence operation requested by the OS.\r
108\r
109 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
110 @param[in] CommandCode Physical presence operation value.\r
111 @param[in, out] PpiFlags The physical presence interface flags.\r
112 \r
4610b23a
JY
113 @retval TREE_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation.\r
114 @retval TREE_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or \r
115 receiving response from TPM.\r
116 @retval Others Return code from the TPM device after command execution.\r
c1d93242 117**/\r
4610b23a 118UINT32\r
c1d93242 119TrEEExecutePhysicalPresence (\r
4610b23a
JY
120 IN TPM2B_AUTH *PlatformAuth, OPTIONAL\r
121 IN UINT32 CommandCode,\r
122 IN OUT EFI_TREE_PHYSICAL_PRESENCE_FLAGS *PpiFlags\r
c1d93242
JY
123 )\r
124{\r
125 EFI_STATUS Status;\r
126\r
127 switch (CommandCode) {\r
128 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
129 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
130 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
131 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
132 Status = TpmCommandClear (PlatformAuth);\r
133 if (EFI_ERROR (Status)) {\r
4610b23a 134 return TREE_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
c1d93242 135 } else {\r
4610b23a 136 return TREE_PP_OPERATION_RESPONSE_SUCCESS;\r
c1d93242
JY
137 }\r
138\r
139 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
4610b23a
JY
140 PpiFlags->PPFlags &= ~TREE_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR;\r
141 return TREE_PP_OPERATION_RESPONSE_SUCCESS;\r
c1d93242
JY
142\r
143 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
4610b23a
JY
144 PpiFlags->PPFlags |= TREE_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR;\r
145 return TREE_PP_OPERATION_RESPONSE_SUCCESS;\r
c1d93242
JY
146\r
147 default:\r
148 if (CommandCode <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
4610b23a 149 return TREE_PP_OPERATION_RESPONSE_SUCCESS;\r
c1d93242 150 } else {\r
4610b23a 151 return TREE_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
c1d93242
JY
152 }\r
153 }\r
154}\r
155\r
156\r
157/**\r
158 Read the specified key for user confirmation.\r
159\r
160 @param[in] CautionKey If true, F12 is used as confirm key;\r
161 If false, F10 is used as confirm key.\r
162\r
163 @retval TRUE User confirmed the changes by input.\r
164 @retval FALSE User discarded the changes.\r
165**/\r
166BOOLEAN\r
167TrEEReadUserKey (\r
168 IN BOOLEAN CautionKey\r
169 )\r
170{\r
171 EFI_STATUS Status;\r
172 EFI_INPUT_KEY Key;\r
173 UINT16 InputKey;\r
174 \r
175 InputKey = 0; \r
176 do {\r
177 Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
178 if (!EFI_ERROR (Status)) {\r
179 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
180 if (Key.ScanCode == SCAN_ESC) {\r
181 InputKey = Key.ScanCode;\r
182 }\r
183 if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
184 InputKey = Key.ScanCode;\r
185 }\r
186 if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
187 InputKey = Key.ScanCode;\r
188 }\r
189 } \r
190 } while (InputKey == 0);\r
191\r
192 if (InputKey != SCAN_ESC) {\r
193 return TRUE;\r
194 }\r
195 \r
196 return FALSE;\r
197}\r
198\r
199/**\r
200 The constructor function register UNI strings into imageHandle.\r
201 \r
202 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
203\r
204 @param ImageHandle The firmware allocated handle for the EFI image.\r
205 @param SystemTable A pointer to the EFI System Table.\r
206 \r
207 @retval EFI_SUCCESS The constructor successfully added string package.\r
208 @retval Other value The constructor can't add string package.\r
209**/\r
210EFI_STATUS\r
211EFIAPI\r
212TrEEPhysicalPresenceLibConstructor (\r
213 IN EFI_HANDLE ImageHandle,\r
214 IN EFI_SYSTEM_TABLE *SystemTable\r
215 )\r
216{\r
217 mTrEEPpStringPackHandle = HiiAddPackages (&gEfiTrEEPhysicalPresenceGuid, ImageHandle, DxeTrEEPhysicalPresenceLibStrings, NULL);\r
218 ASSERT (mTrEEPpStringPackHandle != NULL);\r
219\r
220 return EFI_SUCCESS;\r
221}\r
222\r
223/**\r
224 Display the confirm text and get user confirmation.\r
225\r
226 @param[in] TpmPpCommand The requested TPM physical presence command.\r
227\r
228 @retval TRUE The user has confirmed the changes.\r
229 @retval FALSE The user doesn't confirm the changes.\r
230**/\r
231BOOLEAN\r
232TrEEUserConfirm (\r
4610b23a 233 IN UINT32 TpmPpCommand\r
c1d93242
JY
234 )\r
235{\r
236 CHAR16 *ConfirmText;\r
237 CHAR16 *TmpStr1;\r
238 CHAR16 *TmpStr2; \r
239 UINTN BufSize;\r
240 BOOLEAN CautionKey;\r
241 UINT16 Index;\r
242 CHAR16 DstStr[81];\r
243 \r
244 TmpStr2 = NULL;\r
245 CautionKey = FALSE;\r
246 BufSize = CONFIRM_BUFFER_SIZE;\r
247 ConfirmText = AllocateZeroPool (BufSize);\r
248 ASSERT (ConfirmText != NULL);\r
249\r
250 switch (TpmPpCommand) {\r
251\r
252 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
253 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
254 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
255 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
256 CautionKey = TRUE;\r
257 TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
258\r
259 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
260 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
261 FreePool (TmpStr1);\r
262\r
263 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
4e684d3c
JY
264 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
265 StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
266 FreePool (TmpStr1); \r
267\r
268 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
4e684d3c 269 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
270 FreePool (TmpStr1);\r
271 break;\r
272\r
273 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
274 CautionKey = TRUE;\r
275 TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
276\r
277 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));\r
278 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
279 FreePool (TmpStr1);\r
280\r
281 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));\r
4e684d3c 282 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
283 FreePool (TmpStr1);\r
284\r
285 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
4e684d3c
JY
286 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
287 StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
288 FreePool (TmpStr1); \r
289\r
290 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
4e684d3c 291 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
292 FreePool (TmpStr1);\r
293\r
294 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));\r
4e684d3c 295 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
c1d93242
JY
296 FreePool (TmpStr1);\r
297 break;\r
298\r
299 default:\r
300 ;\r
301 }\r
302\r
303 if (TmpStr2 == NULL) {\r
304 FreePool (ConfirmText);\r
305 return FALSE;\r
306 }\r
307\r
308 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));\r
309 BufSize -= StrSize (ConfirmText);\r
310 UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);\r
311\r
312 DstStr[80] = L'\0';\r
313 for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {\r
314 StrnCpy(DstStr, ConfirmText + Index, 80); \r
315 Print (DstStr); \r
316 }\r
317 \r
318 FreePool (TmpStr1);\r
319 FreePool (TmpStr2);\r
320 FreePool (ConfirmText);\r
321\r
322 if (TrEEReadUserKey (CautionKey)) {\r
323 return TRUE;\r
324 }\r
325\r
326 return FALSE; \r
327}\r
328\r
329/**\r
330 Check if there is a valid physical presence command request. Also updates parameter value \r
331 to whether the requested physical presence command already confirmed by user\r
332 \r
333 @param[in] TcgPpData EFI TrEE Physical Presence request data. \r
334 @param[in] Flags The physical presence interface flags.\r
335 @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.\r
336 True, it indicates the command doesn't require user confirm, or already confirmed \r
337 in last boot cycle by user.\r
338 False, it indicates the command need user confirm from UI.\r
339\r
340 @retval TRUE Physical Presence operation command is valid.\r
341 @retval FALSE Physical Presence operation command is invalid.\r
342\r
343**/\r
344BOOLEAN\r
345TrEEHaveValidTpmRequest (\r
4610b23a
JY
346 IN EFI_TREE_PHYSICAL_PRESENCE *TcgPpData,\r
347 IN EFI_TREE_PHYSICAL_PRESENCE_FLAGS Flags,\r
348 OUT BOOLEAN *RequestConfirmed\r
c1d93242
JY
349 )\r
350{\r
4610b23a
JY
351 BOOLEAN IsRequestValid;\r
352\r
c1d93242
JY
353 *RequestConfirmed = FALSE;\r
354\r
355 switch (TcgPpData->PPRequest) {\r
356 case TREE_PHYSICAL_PRESENCE_NO_ACTION:\r
357 *RequestConfirmed = TRUE;\r
358 return TRUE;\r
359 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
360 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
361 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
362 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
4610b23a 363 if ((Flags.PPFlags & TREE_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0) {\r
c1d93242
JY
364 *RequestConfirmed = TRUE;\r
365 }\r
366 break;\r
367\r
368 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
369 *RequestConfirmed = TRUE;\r
370 break;\r
371\r
372 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
373 break;\r
374\r
375 default:\r
4610b23a
JY
376 if (TcgPpData->PPRequest >= TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
377 IsRequestValid = TrEEPpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);\r
378 if (!IsRequestValid) {\r
379 return FALSE;\r
380 } else {\r
381 break;\r
382 }\r
383 } else {\r
384 //\r
385 // Wrong Physical Presence command\r
386 //\r
387 return FALSE;\r
388 }\r
c1d93242
JY
389 }\r
390\r
4610b23a 391 if ((Flags.PPFlags & TREE_VENDOR_LIB_FLAG_RESET_TRACK) != 0) {\r
c1d93242
JY
392 //\r
393 // It had been confirmed in last boot, it doesn't need confirm again.\r
394 //\r
395 *RequestConfirmed = TRUE;\r
396 }\r
397\r
398 //\r
399 // Physical Presence command is correct\r
400 //\r
401 return TRUE;\r
402}\r
403\r
404\r
405/**\r
406 Check and execute the requested physical presence command.\r
407\r
408 Caution: This function may receive untrusted input.\r
409 TcgPpData variable is external input, so this function will validate\r
410 its data structure to be valid value.\r
411\r
412 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
413 @param[in] TcgPpData Point to the physical presence NV variable.\r
414 @param[in] Flags The physical presence interface flags.\r
415**/\r
416VOID\r
417TrEEExecutePendingTpmRequest (\r
4610b23a
JY
418 IN TPM2B_AUTH *PlatformAuth, OPTIONAL\r
419 IN EFI_TREE_PHYSICAL_PRESENCE *TcgPpData,\r
420 IN EFI_TREE_PHYSICAL_PRESENCE_FLAGS Flags\r
c1d93242
JY
421 )\r
422{\r
423 EFI_STATUS Status;\r
424 UINTN DataSize;\r
425 BOOLEAN RequestConfirmed;\r
4610b23a
JY
426 EFI_TREE_PHYSICAL_PRESENCE_FLAGS NewFlags;\r
427 BOOLEAN ResetRequired;\r
428 UINT32 NewPPFlags;\r
c1d93242
JY
429\r
430 if (TcgPpData->PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
431 //\r
432 // No operation request\r
433 //\r
434 return;\r
435 }\r
436\r
437 if (!TrEEHaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
438 //\r
439 // Invalid operation request.\r
440 //\r
441 if (TcgPpData->PPRequest <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
4610b23a 442 TcgPpData->PPResponse = TREE_PP_OPERATION_RESPONSE_SUCCESS;\r
c1d93242 443 } else {\r
4610b23a 444 TcgPpData->PPResponse = TREE_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
c1d93242
JY
445 }\r
446 TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
447 TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION;\r
448 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
449 Status = gRT->SetVariable (\r
450 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
451 &gEfiTrEEPhysicalPresenceGuid,\r
452 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
453 DataSize,\r
454 TcgPpData\r
455 );\r
456 return;\r
457 }\r
458\r
4610b23a
JY
459 ResetRequired = FALSE;\r
460 if (TcgPpData->PPRequest >= TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
461 NewFlags = Flags;\r
462 NewPPFlags = NewFlags.PPFlags;\r
463 TcgPpData->PPResponse = TrEEPpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);\r
464 NewFlags.PPFlags = (UINT8)NewPPFlags;\r
465 } else {\r
466 if (!RequestConfirmed) {\r
467 //\r
468 // Print confirm text and wait for approval. \r
469 //\r
470 RequestConfirmed = TrEEUserConfirm (TcgPpData->PPRequest\r
471 );\r
472 }\r
473\r
c1d93242 474 //\r
4610b23a 475 // Execute requested physical presence command\r
c1d93242 476 //\r
4610b23a
JY
477 TcgPpData->PPResponse = TREE_PP_OPERATION_RESPONSE_USER_ABORT;\r
478 NewFlags = Flags;\r
479 if (RequestConfirmed) {\r
480 TcgPpData->PPResponse = TrEEExecutePhysicalPresence (PlatformAuth, TcgPpData->PPRequest, \r
481 &NewFlags);\r
482 }\r
c1d93242
JY
483 }\r
484\r
485 //\r
486 // Save the flags if it is updated.\r
487 //\r
4610b23a 488 if (CompareMem (&Flags, &NewFlags, sizeof(EFI_TREE_PHYSICAL_PRESENCE_FLAGS)) != 0) {\r
c1d93242
JY
489 Status = gRT->SetVariable (\r
490 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
491 &gEfiTrEEPhysicalPresenceGuid,\r
492 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
4610b23a 493 sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS),\r
c1d93242
JY
494 &NewFlags\r
495 ); \r
496 }\r
497\r
498 //\r
499 // Clear request\r
500 //\r
4610b23a 501 if ((NewFlags.PPFlags & TREE_VENDOR_LIB_FLAG_RESET_TRACK) == 0) {\r
c1d93242
JY
502 TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
503 TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION; \r
504 }\r
505\r
506 //\r
507 // Save changes\r
508 //\r
509 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
510 Status = gRT->SetVariable (\r
511 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
512 &gEfiTrEEPhysicalPresenceGuid,\r
513 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
514 DataSize,\r
515 TcgPpData\r
516 );\r
517 if (EFI_ERROR (Status)) {\r
518 return;\r
519 }\r
520\r
4610b23a 521 if (TcgPpData->PPResponse == TREE_PP_OPERATION_RESPONSE_USER_ABORT) {\r
c1d93242
JY
522 return;\r
523 }\r
524\r
525 //\r
526 // Reset system to make new TPM settings in effect\r
527 //\r
528 switch (TcgPpData->LastPPRequest) {\r
529 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
530 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
531 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
532 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
533 break;\r
534 default:\r
4610b23a
JY
535 if (TcgPpData->LastPPRequest >= TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {\r
536 if (ResetRequired) {\r
537 break;\r
538 } else {\r
539 return ;\r
540 }\r
541 }\r
c1d93242
JY
542 if (TcgPpData->PPRequest != TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
543 break;\r
544 }\r
545 return;\r
546 }\r
547\r
548 Print (L"Rebooting system to make TPM2 settings in effect\n");\r
549 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
550 ASSERT (FALSE); \r
551}\r
552\r
553/**\r
554 Check and execute the pending TPM request.\r
555\r
556 The TPM request may come from OS or BIOS. This API will display request information and wait \r
557 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
558 the TPM request is confirmed, and one or more reset may be required to make TPM request to \r
559 take effect.\r
560 \r
561 This API should be invoked after console in and console out are all ready as they are required\r
562 to display request information and get user input to confirm the request. \r
563\r
564 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
565**/\r
566VOID\r
567EFIAPI\r
568TrEEPhysicalPresenceLibProcessRequest (\r
569 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
570 )\r
571{\r
572 EFI_STATUS Status;\r
573 UINTN DataSize;\r
574 EFI_TREE_PHYSICAL_PRESENCE TcgPpData;\r
575 EFI_TREE_PROTOCOL *TreeProtocol;\r
576 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;\r
4610b23a 577 EFI_TREE_PHYSICAL_PRESENCE_FLAGS PpiFlags;\r
c1d93242
JY
578\r
579 Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
580 if (EFI_ERROR (Status)) {\r
581 return ;\r
582 }\r
583\r
584 //\r
585 // Initialize physical presence flags.\r
586 //\r
4610b23a 587 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS);\r
c1d93242
JY
588 Status = gRT->GetVariable (\r
589 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
590 &gEfiTrEEPhysicalPresenceGuid,\r
591 NULL,\r
592 &DataSize,\r
593 &PpiFlags\r
594 );\r
595 if (EFI_ERROR (Status)) {\r
4610b23a 596 PpiFlags.PPFlags = 0;\r
8a8c6c96
DG
597 Status = gRT->SetVariable (\r
598 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
599 &gEfiTrEEPhysicalPresenceGuid,\r
600 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
4610b23a 601 sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS),\r
8a8c6c96
DG
602 &PpiFlags\r
603 );\r
604 if (EFI_ERROR (Status)) {\r
605 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));\r
606 return ;\r
c1d93242 607 }\r
c1d93242 608 }\r
4610b23a 609 DEBUG ((EFI_D_INFO, "[TPM2] PpiFlags = %x\n", PpiFlags.PPFlags));\r
c1d93242
JY
610\r
611 //\r
612 // This flags variable controls whether physical presence is required for TPM command. \r
613 // It should be protected from malicious software. We set it as read-only variable here.\r
614 //\r
615 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
616 if (!EFI_ERROR (Status)) {\r
617 Status = VariableLockProtocol->RequestToLock (\r
618 VariableLockProtocol,\r
619 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
620 &gEfiTrEEPhysicalPresenceGuid\r
621 );\r
622 if (EFI_ERROR (Status)) {\r
623 DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));\r
624 ASSERT_EFI_ERROR (Status);\r
625 }\r
626 }\r
627 \r
628 //\r
629 // Initialize physical presence variable.\r
630 //\r
631 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
632 Status = gRT->GetVariable (\r
633 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
634 &gEfiTrEEPhysicalPresenceGuid,\r
635 NULL,\r
636 &DataSize,\r
637 &TcgPpData\r
638 );\r
639 if (EFI_ERROR (Status)) {\r
8a8c6c96
DG
640 ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
641 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
642 Status = gRT->SetVariable (\r
643 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
644 &gEfiTrEEPhysicalPresenceGuid,\r
645 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
646 DataSize,\r
647 &TcgPpData\r
648 );\r
649 if (EFI_ERROR (Status)) {\r
650 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));\r
651 return ;\r
c1d93242 652 }\r
c1d93242
JY
653 }\r
654\r
4610b23a 655 DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));\r
c1d93242
JY
656\r
657 //\r
658 // Execute pending TPM request.\r
659 // \r
660 TrEEExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags);\r
4610b23a 661 DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));\r
c1d93242
JY
662\r
663}\r
664\r
665/**\r
666 Check if the pending TPM request needs user input to confirm.\r
667\r
668 The TPM request may come from OS. This API will check if TPM request exists and need user\r
669 input to confirmation.\r
670 \r
671 @retval TRUE TPM needs input to confirm user physical presence.\r
672 @retval FALSE TPM doesn't need input to confirm user physical presence.\r
673\r
674**/\r
675BOOLEAN\r
676EFIAPI\r
677TrEEPhysicalPresenceLibNeedUserConfirm(\r
678 VOID\r
679 )\r
680{\r
681 EFI_STATUS Status;\r
682 EFI_TREE_PHYSICAL_PRESENCE TcgPpData;\r
683 UINTN DataSize;\r
684 BOOLEAN RequestConfirmed;\r
685 EFI_TREE_PROTOCOL *TreeProtocol;\r
4610b23a 686 EFI_TREE_PHYSICAL_PRESENCE_FLAGS PpiFlags;\r
c1d93242
JY
687\r
688 Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
689 if (EFI_ERROR (Status)) {\r
690 return FALSE;\r
691 }\r
692\r
693 //\r
694 // Check Tpm requests\r
695 //\r
696 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
697 Status = gRT->GetVariable (\r
698 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
699 &gEfiTrEEPhysicalPresenceGuid,\r
700 NULL,\r
701 &DataSize,\r
702 &TcgPpData\r
703 );\r
704 if (EFI_ERROR (Status)) {\r
705 return FALSE;\r
706 }\r
707\r
4610b23a 708 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS);\r
c1d93242
JY
709 Status = gRT->GetVariable (\r
710 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
711 &gEfiTrEEPhysicalPresenceGuid,\r
712 NULL,\r
713 &DataSize,\r
714 &PpiFlags\r
715 );\r
716 if (EFI_ERROR (Status)) {\r
717 return FALSE;\r
718 }\r
719 \r
720 if (TcgPpData.PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
721 //\r
722 // No operation request\r
723 //\r
724 return FALSE;\r
725 }\r
726\r
727 if (!TrEEHaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
728 //\r
729 // Invalid operation request.\r
730 //\r
731 return FALSE;\r
732 }\r
733\r
734 if (!RequestConfirmed) {\r
735 //\r
736 // Need UI to confirm\r
737 //\r
738 return TRUE;\r
739 }\r
740\r
741 return FALSE;\r
742}\r
743\r