• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
DumpUxCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)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
DumpImageAuthentication(IN VOID * Image,IN UINTN ImageSize)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
DumpFmpCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)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
IsNestedFmpCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)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
DumpCapsule(IN CHAR16 * CapsuleName)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
DmpCapsuleStatusVariable(VOID)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 *
FwTypeToString(IN UINT32 FwType)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 *
LastAttemptStatusToString(IN UINT32 LastAttemptStatus)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
DumpEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY * EsrtEntry)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
DumpEsrt(IN EFI_SYSTEM_RESOURCE_TABLE * Esrt)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
DumpEsrtData(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
DumpFmpImageInfo(IN UINTN ImageInfoSize,IN EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageInfo,IN UINT32 DescriptorVersion,IN UINT8 DescriptorCount,IN UINTN DescriptorSize,IN UINT32 PackageVersion,IN CHAR16 * PackageVersionName)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
DumpFmpPackageInfo(IN UINT32 PackageVersion,IN CHAR16 * PackageVersionName,IN UINT32 PackageVersionNameMaxLen,IN UINT64 AttributesSupported,IN UINT64 AttributesSetting)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
DumpFmpData(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
IsThisFmpImageInfo(IN EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageInfo,IN UINT8 DescriptorCount,IN UINTN DescriptorSize,IN EFI_GUID * ImageTypeId)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 *
FindFmpFromImageTypeId(IN EFI_GUID * ImageTypeId)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
DumpFmpImage(IN EFI_GUID * ImageTypeId,IN UINTN ImageIndex,IN CHAR16 * ImageName)908 DumpFmpImage (
909   IN EFI_GUID  *ImageTypeId,
910   IN UINTN     ImageIndex,
911   IN CHAR16    *ImageName
912   )
913 {
914   EFI_STATUS                                    Status;
915   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
916   VOID                                          *Image;
917   UINTN                                         ImageSize;
918 
919   Fmp = FindFmpFromImageTypeId (ImageTypeId);
920   if (Fmp == NULL) {
921     Print(L"No FMP include ImageTypeId %g\n", ImageTypeId);
922     return ;
923   }
924 
925   if (ImageIndex > 0xFF) {
926     Print(L"ImageIndex 0x%x too big\n", ImageIndex);
927     return ;
928   }
929 
930   Image = Fmp;
931   ImageSize = 0;
932   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
933   if (Status != EFI_BUFFER_TOO_SMALL) {
934     Print(L"Fmp->GetImage - %r\n", Status);
935     return ;
936   }
937 
938   Image = AllocatePool (ImageSize);
939   if (Image == NULL) {
940     Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
941     return ;
942   }
943 
944   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
945   if (EFI_ERROR(Status)) {
946     Print(L"Fmp->GetImage - %r\n", Status);
947     return ;
948   }
949 
950   Status = WriteFileFromBuffer(ImageName, ImageSize, Image);
951   Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
952 
953   return ;
954 }
955