1 /** @file 2 Dump Capsule image information. 3 4 Copyright (c) 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 <PiDxe.h> 16 #include <Library/BaseLib.h> 17 #include <Library/DebugLib.h> 18 #include <Library/BaseMemoryLib.h> 19 #include <Library/MemoryAllocationLib.h> 20 #include <Library/UefiBootServicesTableLib.h> 21 #include <Library/UefiRuntimeServicesTableLib.h> 22 #include <Library/UefiLib.h> 23 #include <Library/PrintLib.h> 24 #include <Protocol/FirmwareManagement.h> 25 #include <Guid/ImageAuthentication.h> 26 #include <Guid/CapsuleReport.h> 27 #include <Guid/SystemResourceTable.h> 28 #include <Guid/FmpCapsule.h> 29 #include <IndustryStandard/WindowsUxCapsule.h> 30 31 /** 32 Read a file. 33 34 @param[in] FileName The file to be read. 35 @param[out] BufferSize The file buffer size 36 @param[out] Buffer The file buffer 37 38 @retval EFI_SUCCESS Read file successfully 39 @retval EFI_NOT_FOUND File not found 40 **/ 41 EFI_STATUS 42 ReadFileToBuffer ( 43 IN CHAR16 *FileName, 44 OUT UINTN *BufferSize, 45 OUT VOID **Buffer 46 ); 47 48 /** 49 Write a file. 50 51 @param[in] FileName The file to be written. 52 @param[in] BufferSize The file buffer size 53 @param[in] Buffer The file buffer 54 55 @retval EFI_SUCCESS Write file successfully 56 **/ 57 EFI_STATUS 58 WriteFileFromBuffer ( 59 IN CHAR16 *FileName, 60 IN UINTN BufferSize, 61 IN VOID *Buffer 62 ); 63 64 /** 65 Dump UX capsule information. 66 67 @param[in] CapsuleHeader The UX capsule header 68 **/ 69 VOID 70 DumpUxCapsule ( 71 IN EFI_CAPSULE_HEADER *CapsuleHeader 72 ) 73 { 74 EFI_DISPLAY_CAPSULE *DisplayCapsule; 75 DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader; 76 Print(L"[UxCapusule]\n"); 77 Print(L"CapsuleHeader:\n"); 78 Print(L" CapsuleGuid - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid); 79 Print(L" HeaderSize - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize); 80 Print(L" Flags - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags); 81 Print(L" CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize); 82 Print(L"ImagePayload:\n"); 83 Print(L" Version - 0x%x\n", DisplayCapsule->ImagePayload.Version); 84 Print(L" Checksum - 0x%x\n", DisplayCapsule->ImagePayload.Checksum); 85 Print(L" ImageType - 0x%x\n", DisplayCapsule->ImagePayload.ImageType); 86 Print(L" Mode - 0x%x\n", DisplayCapsule->ImagePayload.Mode); 87 Print(L" OffsetX - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX); 88 Print(L" OffsetY - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY); 89 } 90 91 /** 92 Dump FMP image authentication information. 93 94 @param[in] Image The FMP capsule image 95 @param[in] ImageSize The size of the FMP capsule image in bytes. 96 97 @return the size of FMP authentication. 98 **/ 99 UINTN 100 DumpImageAuthentication ( 101 IN VOID *Image, 102 IN UINTN ImageSize 103 ) 104 { 105 EFI_FIRMWARE_IMAGE_AUTHENTICATION *ImageAuthentication; 106 107 ImageAuthentication = Image; 108 if (CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertPkcs7Guid) || 109 CompareGuid(&ImageAuthentication->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)) { 110 Print(L"[ImageAuthentication]\n"); 111 Print(L" MonotonicCount - 0x%lx\n", ImageAuthentication->MonotonicCount); 112 Print(L"WIN_CERTIFICATE:\n"); 113 Print(L" dwLength - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.dwLength); 114 Print(L" wRevision - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wRevision); 115 Print(L" wCertificateType - 0x%x\n", ImageAuthentication->AuthInfo.Hdr.wCertificateType); 116 Print(L" CertType - %g\n", &ImageAuthentication->AuthInfo.CertType); 117 return sizeof(ImageAuthentication->MonotonicCount) + ImageAuthentication->AuthInfo.Hdr.dwLength; 118 } else { 119 return 0; 120 } 121 } 122 123 /** 124 Dump a non-nested FMP capsule. 125 126 @param[in] CapsuleHeader A pointer to CapsuleHeader 127 **/ 128 VOID 129 DumpFmpCapsule ( 130 IN EFI_CAPSULE_HEADER *CapsuleHeader 131 ) 132 { 133 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; 134 UINT64 *ItemOffsetList; 135 UINTN Index; 136 UINTN Count; 137 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *FmpImageHeader; 138 139 Print(L"[FmpCapusule]\n"); 140 Print(L"CapsuleHeader:\n"); 141 Print(L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid); 142 Print(L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize); 143 Print(L" Flags - 0x%x\n", CapsuleHeader->Flags); 144 Print(L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize); 145 146 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize); 147 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1); 148 Print(L"FmpHeader:\n"); 149 Print(L" Version - 0x%x\n", FmpCapsuleHeader->Version); 150 Print(L" EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount); 151 Print(L" PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount); 152 Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; 153 for (Index = 0; Index < Count; Index++) { 154 Print(L" Offset[%d] - 0x%x\n", Index, ItemOffsetList[Index]); 155 } 156 157 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) { 158 Print(L"FmpPayload[%d] ImageHeader:\n", Index); 159 FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]); 160 Print(L" Version - 0x%x\n", FmpImageHeader->Version); 161 Print(L" UpdateImageTypeId - %g\n", &FmpImageHeader->UpdateImageTypeId); 162 Print(L" UpdateImageIndex - 0x%x\n", FmpImageHeader->UpdateImageIndex); 163 Print(L" UpdateImageSize - 0x%x\n", FmpImageHeader->UpdateImageSize); 164 Print(L" UpdateVendorCodeSize - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize); 165 if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) { 166 Print(L" UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance); 167 } 168 } 169 } 170 171 /** 172 Return if there is a FMP header below capsule header. 173 174 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER 175 176 @retval TRUE There is a FMP header below capsule header. 177 @retval FALSE There is not a FMP header below capsule header 178 **/ 179 BOOLEAN 180 IsNestedFmpCapsule ( 181 IN EFI_CAPSULE_HEADER *CapsuleHeader 182 ) 183 { 184 EFI_STATUS Status; 185 EFI_SYSTEM_RESOURCE_TABLE *Esrt; 186 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry; 187 UINTN Index; 188 BOOLEAN EsrtGuidFound; 189 EFI_CAPSULE_HEADER *NestedCapsuleHeader; 190 UINTN NestedCapsuleSize; 191 192 // 193 // Check ESRT 194 // 195 EsrtGuidFound = FALSE; 196 Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt); 197 if (!EFI_ERROR(Status)) { 198 ASSERT (Esrt != NULL); 199 EsrtEntry = (VOID *)(Esrt + 1); 200 for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) { 201 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) { 202 EsrtGuidFound = TRUE; 203 break; 204 } 205 } 206 } 207 208 if (!EsrtGuidFound) { 209 return FALSE; 210 } 211 212 // 213 // Check nested capsule header 214 // FMP GUID after ESRT one 215 // 216 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize); 217 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader; 218 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) { 219 return FALSE; 220 } 221 if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) { 222 return FALSE; 223 } 224 return TRUE; 225 } 226 227 /** 228 Dump capsule information 229 230 @param[in] CapsuleName The name of the capsule image. 231 232 @retval EFI_SUCCESS The capsule information is dumped. 233 @retval EFI_UNSUPPORTED Input parameter is not valid. 234 **/ 235 EFI_STATUS 236 DumpCapsule ( 237 IN CHAR16 *CapsuleName 238 ) 239 { 240 VOID *Buffer; 241 UINTN FileSize; 242 EFI_CAPSULE_HEADER *CapsuleHeader; 243 EFI_STATUS Status; 244 245 Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer); 246 if (EFI_ERROR(Status)) { 247 Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName); 248 goto Done; 249 } 250 251 CapsuleHeader = Buffer; 252 if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) { 253 DumpUxCapsule(CapsuleHeader); 254 Status = EFI_SUCCESS; 255 goto Done; 256 } 257 258 if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) { 259 DumpFmpCapsule(CapsuleHeader); 260 } 261 if (IsNestedFmpCapsule(CapsuleHeader)) { 262 Print(L"[NestedCapusule]\n"); 263 Print(L"CapsuleHeader:\n"); 264 Print(L" CapsuleGuid - %g\n", &CapsuleHeader->CapsuleGuid); 265 Print(L" HeaderSize - 0x%x\n", CapsuleHeader->HeaderSize); 266 Print(L" Flags - 0x%x\n", CapsuleHeader->Flags); 267 Print(L" CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize); 268 DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize)); 269 } 270 271 Done: 272 FreePool(Buffer); 273 return Status; 274 } 275 276 /** 277 Dump capsule status variable. 278 279 @retval EFI_SUCCESS The capsule status variable is dumped. 280 @retval EFI_UNSUPPORTED Input parameter is not valid. 281 **/ 282 EFI_STATUS 283 DmpCapsuleStatusVariable ( 284 VOID 285 ) 286 { 287 EFI_STATUS Status; 288 UINT32 Index; 289 CHAR16 CapsuleVarName[20]; 290 CHAR16 *TempVarName; 291 EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult; 292 EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp; 293 UINTN CapsuleFileNameSize; 294 CHAR16 CapsuleIndexData[12]; 295 CHAR16 *CapsuleIndex; 296 CHAR16 *CapsuleFileName; 297 CHAR16 *CapsuleTarget; 298 299 Status = GetVariable2( 300 L"CapsuleMax", 301 &gEfiCapsuleReportGuid, 302 (VOID **)&CapsuleIndex, 303 NULL 304 ); 305 if (!EFI_ERROR(Status)) { 306 ASSERT (CapsuleIndex != NULL); 307 CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16)); 308 CapsuleIndexData[11] = 0; 309 Print(L"CapsuleMax - %s\n", CapsuleIndexData); 310 FreePool(CapsuleIndex); 311 } 312 Status = GetVariable2( 313 L"CapsuleLast", 314 &gEfiCapsuleReportGuid, 315 (VOID **)&CapsuleIndex, 316 NULL 317 ); 318 if (!EFI_ERROR(Status)) { 319 ASSERT (CapsuleIndex != NULL); 320 CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16)); 321 CapsuleIndexData[11] = 0; 322 Print(L"CapsuleLast - %s\n", CapsuleIndexData); 323 FreePool(CapsuleIndex); 324 } 325 326 327 StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule"); 328 TempVarName = CapsuleVarName + StrLen (CapsuleVarName); 329 Index = 0; 330 331 while (TRUE) { 332 UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index); 333 334 Status = GetVariable2 ( 335 CapsuleVarName, 336 &gEfiCapsuleReportGuid, 337 (VOID **) &CapsuleResult, 338 NULL 339 ); 340 if (Status == EFI_NOT_FOUND) { 341 break; 342 } else if (EFI_ERROR(Status)) { 343 continue; 344 } 345 ASSERT (CapsuleResult != NULL); 346 347 // 348 // display capsule process status 349 // 350 if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) { 351 Print (L"CapsuleName: %s\n", CapsuleVarName); 352 Print (L" Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid); 353 Print (L" Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed); 354 Print (L" Capsule Status: %r\n", CapsuleResult->CapsuleStatus); 355 } 356 357 if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) { 358 if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) { 359 CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1); 360 Print(L" Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version); 361 Print(L" Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex); 362 Print(L" Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex); 363 Print(L" Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId); 364 CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1); 365 Print(L" Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName); 366 CapsuleFileNameSize = StrSize(CapsuleFileName); 367 CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize); 368 Print(L" Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget); 369 } 370 } 371 372 FreePool(CapsuleResult); 373 374 Index++; 375 if (Index > 0xFFFF) { 376 break; 377 } 378 } 379 380 return EFI_SUCCESS; 381 } 382 383 CHAR8 *mFwTypeString[] = { 384 "Unknown", 385 "SystemFirmware", 386 "DeviceFirmware", 387 "UefiDriver", 388 }; 389 390 CHAR8 *mLastAttemptStatusString[] = { 391 "Success", 392 "Error: Unsuccessful", 393 "Error: Insufficient Resources", 394 "Error: Incorrect Version", 395 "Error: Invalid Format", 396 "Error: Auth Error", 397 "Error: Power Event AC", 398 "Error: Power Event Battery", 399 }; 400 401 /** 402 Convert FwType to a string. 403 404 @param[in] FwType FwType in ESRT 405 406 @return a string for FwType. 407 **/ 408 CHAR8 * 409 FwTypeToString ( 410 IN UINT32 FwType 411 ) 412 { 413 if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) { 414 return mFwTypeString[FwType]; 415 } else { 416 return "Invalid"; 417 } 418 } 419 420 /** 421 Convert LastAttemptStatus to a string. 422 423 @param[in] LastAttemptStatus LastAttemptStatus in FMP or ESRT 424 425 @return a string for LastAttemptStatus. 426 **/ 427 CHAR8 * 428 LastAttemptStatusToString ( 429 IN UINT32 LastAttemptStatus 430 ) 431 { 432 if (LastAttemptStatus < sizeof(mLastAttemptStatusString) / sizeof(mLastAttemptStatusString[0])) { 433 return mLastAttemptStatusString[LastAttemptStatus]; 434 } else { 435 return "Error: Unknown"; 436 } 437 } 438 439 /** 440 Dump ESRT entry. 441 442 @param[in] EsrtEntry ESRT entry 443 **/ 444 VOID 445 DumpEsrtEntry ( 446 IN EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry 447 ) 448 { 449 Print(L" FwClass - %g\n", &EsrtEntry->FwClass); 450 Print(L" FwType - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString(EsrtEntry->FwType)); 451 Print(L" FwVersion - 0x%x\n", EsrtEntry->FwVersion); 452 Print(L" LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion); 453 Print(L" CapsuleFlags - 0x%x\n", EsrtEntry->CapsuleFlags); 454 Print(L" PERSIST_ACROSS_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET); 455 Print(L" POPULATE_SYSTEM_TABLE - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE); 456 Print(L" INITIATE_RESET - 0x%x\n", EsrtEntry->CapsuleFlags & CAPSULE_FLAGS_INITIATE_RESET); 457 Print(L" LastAttemptVersion - 0x%x\n", EsrtEntry->LastAttemptVersion); 458 Print(L" LastAttemptStatus - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus)); 459 } 460 461 /** 462 Dump ESRT table. 463 464 @param[in] Esrt ESRT table 465 **/ 466 VOID 467 DumpEsrt ( 468 IN EFI_SYSTEM_RESOURCE_TABLE *Esrt 469 ) 470 { 471 UINTN Index; 472 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry; 473 474 if (Esrt == NULL) { 475 return ; 476 } 477 478 Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n"); 479 Print(L"FwResourceCount - 0x%x\n", Esrt->FwResourceCount); 480 Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax); 481 Print(L"FwResourceVersion - 0x%lx\n", Esrt->FwResourceVersion); 482 483 EsrtEntry = (VOID *)(Esrt + 1); 484 for (Index = 0; Index < Esrt->FwResourceCount; Index++) { 485 Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index); 486 DumpEsrtEntry(EsrtEntry); 487 EsrtEntry++; 488 } 489 } 490 491 /** 492 Dump ESRT info. 493 **/ 494 VOID 495 DumpEsrtData ( 496 VOID 497 ) 498 { 499 EFI_STATUS Status; 500 EFI_SYSTEM_RESOURCE_TABLE *Esrt; 501 502 Print(L"##############\n"); 503 Print(L"# ESRT TABLE #\n"); 504 Print(L"##############\n"); 505 506 Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt); 507 if (EFI_ERROR(Status)) { 508 Print(L"ESRT - %r\n", Status); 509 return; 510 } 511 DumpEsrt(Esrt); 512 Print(L"\n"); 513 } 514 515 /** 516 Dump FMP information. 517 518 @param[in] ImageInfoSize The size of ImageInfo, in bytes. 519 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR. 520 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR. 521 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR. 522 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes. 523 @param[in] PackageVersion The version of package. 524 @param[in] PackageVersionName The version name of package. 525 **/ 526 VOID 527 DumpFmpImageInfo ( 528 IN UINTN ImageInfoSize, 529 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, 530 IN UINT32 DescriptorVersion, 531 IN UINT8 DescriptorCount, 532 IN UINTN DescriptorSize, 533 IN UINT32 PackageVersion, 534 IN CHAR16 *PackageVersionName 535 ) 536 { 537 EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo; 538 UINTN Index; 539 540 Print(L" DescriptorVersion - 0x%x\n", DescriptorVersion); 541 Print(L" DescriptorCount - 0x%x\n", DescriptorCount); 542 Print(L" DescriptorSize - 0x%x\n", DescriptorSize); 543 Print(L" PackageVersion - 0x%x\n", PackageVersion); 544 Print(L" PackageVersionName - \"%s\"\n", PackageVersionName); 545 CurrentImageInfo = ImageInfo; 546 for (Index = 0; Index < DescriptorCount; Index++) { 547 Print(L" ImageDescriptor (%d)\n", Index); 548 Print(L" ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex); 549 Print(L" ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId); 550 Print(L" ImageId - 0x%lx\n", CurrentImageInfo->ImageId); 551 Print(L" ImageIdName - \"%s\"\n", CurrentImageInfo->ImageIdName); 552 Print(L" Version - 0x%x\n", CurrentImageInfo->Version); 553 Print(L" VersionName - \"%s\"\n", CurrentImageInfo->VersionName); 554 Print(L" Size - 0x%x\n", CurrentImageInfo->Size); 555 Print(L" AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported); 556 Print(L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE); 557 Print(L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED); 558 Print(L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); 559 Print(L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE); 560 Print(L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE); 561 Print(L" AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting); 562 Print(L" IMAGE_UPDATABLE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE); 563 Print(L" RESET_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED); 564 Print(L" AUTHENTICATION_REQUIRED - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); 565 Print(L" IN_USE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE); 566 Print(L" UEFI_IMAGE - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE); 567 Print(L" Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities); 568 Print(L" COMPATIB_CHECK_SUPPORTED - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED); 569 if (DescriptorVersion > 1) { 570 Print(L" LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion); 571 if (DescriptorVersion > 2) { 572 Print(L" LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion); 573 Print(L" LastAttemptStatus - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus)); 574 Print(L" HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance); 575 } 576 } 577 // 578 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version 579 // 580 CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize); 581 } 582 } 583 584 /** 585 Dump FMP package information. 586 587 @param[in] PackageVersion The version of package. 588 @param[in] PackageVersionName The version name of package. 589 @param[in] PackageVersionNameMaxLen The maximum length of PackageVersionName. 590 @param[in] AttributesSupported Package attributes that are supported by this device. 591 @param[in] AttributesSetting Package attributes. 592 **/ 593 VOID 594 DumpFmpPackageInfo ( 595 IN UINT32 PackageVersion, 596 IN CHAR16 *PackageVersionName, 597 IN UINT32 PackageVersionNameMaxLen, 598 IN UINT64 AttributesSupported, 599 IN UINT64 AttributesSetting 600 ) 601 { 602 Print(L" PackageVersion - 0x%x\n", PackageVersion); 603 Print(L" PackageVersionName - \"%s\"\n", PackageVersionName); 604 Print(L" PackageVersionNameMaxLen - 0x%x\n", PackageVersionNameMaxLen); 605 Print(L" AttributesSupported - 0x%lx\n", AttributesSupported); 606 Print(L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE); 607 Print(L" RESET_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED); 608 Print(L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); 609 Print(L" AttributesSetting - 0x%lx\n", AttributesSetting); 610 Print(L" IMAGE_UPDATABLE - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE); 611 Print(L" RESET_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED); 612 Print(L" AUTHENTICATION_REQUIRED - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED); 613 } 614 615 /** 616 Dump FMP protocol info. 617 **/ 618 VOID 619 DumpFmpData ( 620 VOID 621 ) 622 { 623 EFI_STATUS Status; 624 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; 625 EFI_HANDLE *HandleBuffer; 626 UINTN NumberOfHandles; 627 UINTN Index; 628 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; 629 UINTN ImageInfoSize; 630 UINT32 FmpImageInfoDescriptorVer; 631 UINT8 FmpImageInfoCount; 632 UINTN DescriptorSize; 633 UINT32 PackageVersion; 634 CHAR16 *PackageVersionName; 635 UINT32 PackageVersionNameMaxLen; 636 UINT64 AttributesSupported; 637 UINT64 AttributesSetting; 638 639 Print(L"############\n"); 640 Print(L"# FMP DATA #\n"); 641 Print(L"############\n"); 642 Status = gBS->LocateHandleBuffer ( 643 ByProtocol, 644 &gEfiFirmwareManagementProtocolGuid, 645 NULL, 646 &NumberOfHandles, 647 &HandleBuffer 648 ); 649 if (EFI_ERROR(Status)) { 650 Print(L"FMP protocol - %r\n", EFI_NOT_FOUND); 651 return; 652 } 653 654 for (Index = 0; Index < NumberOfHandles; Index++) { 655 Status = gBS->HandleProtocol( 656 HandleBuffer[Index], 657 &gEfiFirmwareManagementProtocolGuid, 658 (VOID **)&Fmp 659 ); 660 if (EFI_ERROR(Status)) { 661 continue; 662 } 663 664 ImageInfoSize = 0; 665 Status = Fmp->GetImageInfo ( 666 Fmp, 667 &ImageInfoSize, 668 NULL, 669 NULL, 670 NULL, 671 NULL, 672 NULL, 673 NULL 674 ); 675 if (Status != EFI_BUFFER_TOO_SMALL) { 676 continue; 677 } 678 679 FmpImageInfoBuf = NULL; 680 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); 681 if (FmpImageInfoBuf == NULL) { 682 Status = EFI_OUT_OF_RESOURCES; 683 goto EXIT; 684 } 685 686 PackageVersionName = NULL; 687 Status = Fmp->GetImageInfo ( 688 Fmp, 689 &ImageInfoSize, // ImageInfoSize 690 FmpImageInfoBuf, // ImageInfo 691 &FmpImageInfoDescriptorVer, // DescriptorVersion 692 &FmpImageInfoCount, // DescriptorCount 693 &DescriptorSize, // DescriptorSize 694 &PackageVersion, // PackageVersion 695 &PackageVersionName // PackageVersionName 696 ); 697 698 // 699 // If FMP GetInformation interface failed, skip this resource 700 // 701 if (EFI_ERROR(Status)) { 702 Print(L"FMP (%d) ImageInfo - %r\n", Index, Status); 703 FreePool(FmpImageInfoBuf); 704 continue; 705 } 706 707 Print(L"FMP (%d) ImageInfo:\n", Index); 708 DumpFmpImageInfo( 709 ImageInfoSize, // ImageInfoSize 710 FmpImageInfoBuf, // ImageInfo 711 FmpImageInfoDescriptorVer, // DescriptorVersion 712 FmpImageInfoCount, // DescriptorCount 713 DescriptorSize, // DescriptorSize 714 PackageVersion, // PackageVersion 715 PackageVersionName // PackageVersionName 716 ); 717 718 if (PackageVersionName != NULL) { 719 FreePool(PackageVersionName); 720 } 721 FreePool(FmpImageInfoBuf); 722 723 // 724 // Get package info 725 // 726 PackageVersionName = NULL; 727 Status = Fmp->GetPackageInfo ( 728 Fmp, 729 &PackageVersion, // PackageVersion 730 &PackageVersionName, // PackageVersionName 731 &PackageVersionNameMaxLen, // PackageVersionNameMaxLen 732 &AttributesSupported, // AttributesSupported 733 &AttributesSetting // AttributesSetting 734 ); 735 if (EFI_ERROR(Status)) { 736 Print(L"FMP (%d) PackageInfo - %r\n", Index, Status); 737 } else { 738 Print(L"FMP (%d) ImageInfo:\n", Index); 739 DumpFmpPackageInfo( 740 PackageVersion, // PackageVersion 741 PackageVersionName, // PackageVersionName 742 PackageVersionNameMaxLen, // PackageVersionNameMaxLen 743 AttributesSupported, // AttributesSupported 744 AttributesSetting // AttributesSetting 745 ); 746 747 if (PackageVersionName != NULL) { 748 FreePool(PackageVersionName); 749 } 750 } 751 } 752 Print(L"\n"); 753 754 EXIT: 755 FreePool(HandleBuffer); 756 } 757 758 /** 759 Check if the ImageInfo includes the ImageTypeId. 760 761 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR. 762 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR. 763 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes. 764 @param[in] ImageTypeId A unique GUID identifying the firmware image type. 765 766 @return TRUE This ImageInfo includes the ImageTypeId 767 @return FALSE This ImageInfo does not include the ImageTypeId 768 **/ 769 BOOLEAN 770 IsThisFmpImageInfo ( 771 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, 772 IN UINT8 DescriptorCount, 773 IN UINTN DescriptorSize, 774 IN EFI_GUID *ImageTypeId 775 ) 776 { 777 EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo; 778 UINTN Index; 779 780 CurrentImageInfo = ImageInfo; 781 for (Index = 0; Index < DescriptorCount; Index++) { 782 if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) { 783 return TRUE; 784 } 785 CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize); 786 } 787 return FALSE; 788 } 789 790 /** 791 return the FMP whoes ImageInfo includes the ImageTypeId. 792 793 @param[in] ImageTypeId A unique GUID identifying the firmware image type. 794 795 @return The FMP whoes ImageInfo includes the ImageTypeId 796 **/ 797 EFI_FIRMWARE_MANAGEMENT_PROTOCOL * 798 FindFmpFromImageTypeId ( 799 IN EFI_GUID *ImageTypeId 800 ) 801 { 802 EFI_STATUS Status; 803 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; 804 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *TargetFmp; 805 EFI_HANDLE *HandleBuffer; 806 UINTN NumberOfHandles; 807 UINTN Index; 808 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; 809 UINTN ImageInfoSize; 810 UINT32 FmpImageInfoDescriptorVer; 811 UINT8 FmpImageInfoCount; 812 UINTN DescriptorSize; 813 UINT32 PackageVersion; 814 CHAR16 *PackageVersionName; 815 816 Status = gBS->LocateHandleBuffer ( 817 ByProtocol, 818 &gEfiFirmwareManagementProtocolGuid, 819 NULL, 820 &NumberOfHandles, 821 &HandleBuffer 822 ); 823 if (EFI_ERROR(Status)) { 824 Print(L"FMP protocol - %r\n", EFI_NOT_FOUND); 825 return NULL; 826 } 827 828 TargetFmp = NULL; 829 for (Index = 0; Index < NumberOfHandles; Index++) { 830 Status = gBS->HandleProtocol( 831 HandleBuffer[Index], 832 &gEfiFirmwareManagementProtocolGuid, 833 (VOID **)&Fmp 834 ); 835 if (EFI_ERROR(Status)) { 836 continue; 837 } 838 839 ImageInfoSize = 0; 840 Status = Fmp->GetImageInfo ( 841 Fmp, 842 &ImageInfoSize, 843 NULL, 844 NULL, 845 NULL, 846 NULL, 847 NULL, 848 NULL 849 ); 850 if (Status != EFI_BUFFER_TOO_SMALL) { 851 continue; 852 } 853 854 FmpImageInfoBuf = NULL; 855 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize); 856 if (FmpImageInfoBuf == NULL) { 857 FreePool(HandleBuffer); 858 Print(L"Out of resource\n"); 859 return NULL; 860 } 861 862 PackageVersionName = NULL; 863 Status = Fmp->GetImageInfo ( 864 Fmp, 865 &ImageInfoSize, // ImageInfoSize 866 FmpImageInfoBuf, // ImageInfo 867 &FmpImageInfoDescriptorVer, // DescriptorVersion 868 &FmpImageInfoCount, // DescriptorCount 869 &DescriptorSize, // DescriptorSize 870 &PackageVersion, // PackageVersion 871 &PackageVersionName // PackageVersionName 872 ); 873 874 // 875 // If FMP GetInformation interface failed, skip this resource 876 // 877 if (EFI_ERROR(Status)) { 878 FreePool(FmpImageInfoBuf); 879 continue; 880 } 881 882 if (PackageVersionName != NULL) { 883 FreePool(PackageVersionName); 884 } 885 886 if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) { 887 TargetFmp = Fmp; 888 } 889 FreePool(FmpImageInfoBuf); 890 if (TargetFmp != NULL) { 891 break; 892 } 893 } 894 FreePool(HandleBuffer); 895 return TargetFmp; 896 } 897 898 /** 899 Dump FMP image data. 900 901 @param[in] ImageTypeId The ImageTypeId of the FMP image. 902 It is used to identify the FMP protocol. 903 @param[in] ImageIndex The ImageIndex of the FMP image. 904 It is the input parameter for FMP->GetImage(). 905 @param[in] ImageName The file name to hold the output FMP image. 906 **/ 907 VOID 908 DumpFmpImage ( 909 IN EFI_GUID *ImageTypeId, 910 IN UINTN ImageIndex, 911 IN CHAR16 *ImageName 912 ) 913 { 914 EFI_STATUS Status; 915 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; 916 VOID *Image; 917 UINTN ImageSize; 918 919 Fmp = FindFmpFromImageTypeId (ImageTypeId); 920 if (Fmp == NULL) { 921 Print(L"No FMP include ImageTypeId %g\n", ImageTypeId); 922 return ; 923 } 924 925 if (ImageIndex > 0xFF) { 926 Print(L"ImageIndex 0x%x too big\n", ImageIndex); 927 return ; 928 } 929 930 Image = Fmp; 931 ImageSize = 0; 932 Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize); 933 if (Status != EFI_BUFFER_TOO_SMALL) { 934 Print(L"Fmp->GetImage - %r\n", Status); 935 return ; 936 } 937 938 Image = AllocatePool (ImageSize); 939 if (Image == NULL) { 940 Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES); 941 return ; 942 } 943 944 Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize); 945 if (EFI_ERROR(Status)) { 946 Print(L"Fmp->GetImage - %r\n", Status); 947 return ; 948 } 949 950 Status = WriteFileFromBuffer(ImageName, ImageSize, Image); 951 Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status); 952 953 return ; 954 } 955