2bb5f1f02cf427888055b285afe84c38709f67b5
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
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 }