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