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