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