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 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.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 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 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 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 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 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