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