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