1 /** @file
2   Dump Capsule image information.
3 
4   Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "CapsuleApp.h"
10 
11 /**
12   Validate if it is valid capsule header
13 
14   This function assumes the caller provided correct CapsuleHeader pointer
15   and CapsuleSize.
16 
17   This function validates the fields in EFI_CAPSULE_HEADER.
18 
19   @param[in] CapsuleHeader  Points to a capsule header.
20   @param[in] CapsuleSize    Size of the whole capsule image.
21 
22 **/
23 BOOLEAN
24 IsValidCapsuleHeader (
25   IN EFI_CAPSULE_HEADER     *CapsuleHeader,
26   IN UINT64                 CapsuleSize
27   );
28 
29 /**
30   Dump UX capsule information.
31 
32   @param[in] CapsuleHeader      The UX capsule header
33 **/
34 VOID
DumpUxCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)35 DumpUxCapsule (
36   IN EFI_CAPSULE_HEADER  *CapsuleHeader
37   )
38 {
39   EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
40   DisplayCapsule = (EFI_DISPLAY_CAPSULE *)CapsuleHeader;
41   Print(L"[UxCapsule]\n");
42   Print(L"CapsuleHeader:\n");
43   Print(L"  CapsuleGuid      - %g\n", &DisplayCapsule->CapsuleHeader.CapsuleGuid);
44   Print(L"  HeaderSize       - 0x%x\n", DisplayCapsule->CapsuleHeader.HeaderSize);
45   Print(L"  Flags            - 0x%x\n", DisplayCapsule->CapsuleHeader.Flags);
46   Print(L"  CapsuleImageSize - 0x%x\n", DisplayCapsule->CapsuleHeader.CapsuleImageSize);
47   Print(L"ImagePayload:\n");
48   Print(L"  Version          - 0x%x\n", DisplayCapsule->ImagePayload.Version);
49   Print(L"  Checksum         - 0x%x\n", DisplayCapsule->ImagePayload.Checksum);
50   Print(L"  ImageType        - 0x%x\n", DisplayCapsule->ImagePayload.ImageType);
51   Print(L"  Mode             - 0x%x\n", DisplayCapsule->ImagePayload.Mode);
52   Print(L"  OffsetX          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetX);
53   Print(L"  OffsetY          - 0x%x\n", DisplayCapsule->ImagePayload.OffsetY);
54 }
55 
56 
57 /**
58   Dump a non-nested FMP capsule.
59 
60   @param[in]  CapsuleHeader  A pointer to CapsuleHeader
61 **/
62 VOID
DumpFmpCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)63 DumpFmpCapsule (
64   IN EFI_CAPSULE_HEADER  *CapsuleHeader
65   )
66 {
67   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
68   UINT64                                        *ItemOffsetList;
69   UINTN                                         Index;
70   UINTN                                         Count;
71   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *FmpImageHeader;
72 
73   Print(L"[FmpCapsule]\n");
74   Print(L"CapsuleHeader:\n");
75   Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
76   Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
77   Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
78   Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
79 
80   FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
81   ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
82   Print(L"FmpHeader:\n");
83   Print(L"  Version             - 0x%x\n", FmpCapsuleHeader->Version);
84   Print(L"  EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount);
85   Print(L"  PayloadItemCount    - 0x%x\n", FmpCapsuleHeader->PayloadItemCount);
86   Count = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
87   for (Index = 0; Index < Count; Index++) {
88     Print(L"  Offset[%d]           - 0x%x\n", Index, ItemOffsetList[Index]);
89   }
90 
91   for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < Count; Index++) {
92     Print(L"FmpPayload[%d] ImageHeader:\n", Index);
93     FmpImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
94     Print(L"  Version                - 0x%x\n", FmpImageHeader->Version);
95     Print(L"  UpdateImageTypeId      - %g\n", &FmpImageHeader->UpdateImageTypeId);
96     Print(L"  UpdateImageIndex       - 0x%x\n", FmpImageHeader->UpdateImageIndex);
97     Print(L"  UpdateImageSize        - 0x%x\n", FmpImageHeader->UpdateImageSize);
98     Print(L"  UpdateVendorCodeSize   - 0x%x\n", FmpImageHeader->UpdateVendorCodeSize);
99     if (FmpImageHeader->Version >= 2) {
100       Print(L"  UpdateHardwareInstance - 0x%lx\n", FmpImageHeader->UpdateHardwareInstance);
101       if (FmpImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
102         Print(L"  ImageCapsuleSupport    - 0x%lx\n", FmpImageHeader->ImageCapsuleSupport);
103       }
104     }
105   }
106 }
107 
108 /**
109   Return if there is a FMP header below capsule header.
110 
111   @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
112 
113   @retval TRUE  There is a FMP header below capsule header.
114   @retval FALSE There is not a FMP header below capsule header
115 **/
116 BOOLEAN
IsNestedFmpCapsule(IN EFI_CAPSULE_HEADER * CapsuleHeader)117 IsNestedFmpCapsule (
118   IN EFI_CAPSULE_HEADER         *CapsuleHeader
119   )
120 {
121   EFI_STATUS                 Status;
122   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
123   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
124   UINTN                      Index;
125   BOOLEAN                    EsrtGuidFound;
126   EFI_CAPSULE_HEADER         *NestedCapsuleHeader;
127   UINTN                      NestedCapsuleSize;
128 
129   //
130   // Check ESRT
131   //
132   EsrtGuidFound = FALSE;
133   Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
134   if (!EFI_ERROR(Status)) {
135     ASSERT (Esrt != NULL);
136     EsrtEntry = (VOID *)(Esrt + 1);
137     for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
138       if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
139         EsrtGuidFound = TRUE;
140         break;
141       }
142     }
143   }
144 
145   if (!EsrtGuidFound) {
146     return FALSE;
147   }
148 
149   //
150   // Check nested capsule header
151   // FMP GUID after ESRT one
152   //
153   NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
154   NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize- (UINTN)NestedCapsuleHeader;
155   if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
156     return FALSE;
157   }
158   if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
159     return FALSE;
160   }
161   return TRUE;
162 }
163 
164 /**
165   Dump capsule information
166 
167   @param[in] CapsuleName  The name of the capsule image.
168 
169   @retval EFI_SUCCESS            The capsule information is dumped.
170   @retval EFI_UNSUPPORTED        Input parameter is not valid.
171 **/
172 EFI_STATUS
DumpCapsule(IN CHAR16 * CapsuleName)173 DumpCapsule (
174   IN CHAR16                                        *CapsuleName
175   )
176 {
177   VOID                                          *Buffer;
178   UINTN                                         FileSize;
179   EFI_CAPSULE_HEADER                            *CapsuleHeader;
180   EFI_STATUS                                    Status;
181 
182   Buffer = NULL;
183   Status = ReadFileToBuffer(CapsuleName, &FileSize, &Buffer);
184   if (EFI_ERROR(Status)) {
185     Print(L"CapsuleApp: Capsule (%s) is not found.\n", CapsuleName);
186     goto Done;
187   }
188   if (!IsValidCapsuleHeader (Buffer, FileSize)) {
189     Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
190     Status = EFI_INVALID_PARAMETER;
191     goto Done;
192   }
193 
194   CapsuleHeader = Buffer;
195   if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
196     DumpUxCapsule(CapsuleHeader);
197     Status = EFI_SUCCESS;
198     goto Done;
199   }
200 
201   if (CompareGuid(&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
202     DumpFmpCapsule(CapsuleHeader);
203   }
204   if (IsNestedFmpCapsule(CapsuleHeader)) {
205     Print(L"[NestedCapsule]\n");
206     Print(L"CapsuleHeader:\n");
207     Print(L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
208     Print(L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
209     Print(L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
210     Print(L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
211     DumpFmpCapsule((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
212   }
213 
214 Done:
215   if (Buffer != NULL) {
216     FreePool(Buffer);
217   }
218   return Status;
219 }
220 
221 /**
222   Dump capsule status variable.
223 
224   @retval EFI_SUCCESS            The capsule status variable is dumped.
225   @retval EFI_UNSUPPORTED        Input parameter is not valid.
226 **/
227 EFI_STATUS
DumpCapsuleStatusVariable(VOID)228 DumpCapsuleStatusVariable (
229   VOID
230   )
231 {
232   EFI_STATUS                          Status;
233   UINT32                              Index;
234   CHAR16                              CapsuleVarName[20];
235   CHAR16                              *TempVarName;
236   EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResult;
237   EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultFmp;
238   UINTN                               CapsuleFileNameSize;
239   CHAR16                              CapsuleIndexData[12];
240   CHAR16                              *CapsuleIndex;
241   CHAR16                              *CapsuleFileName;
242   CHAR16                              *CapsuleTarget;
243 
244   Status = GetVariable2(
245              L"CapsuleMax",
246              &gEfiCapsuleReportGuid,
247              (VOID **)&CapsuleIndex,
248              NULL
249              );
250   if (!EFI_ERROR(Status)) {
251     ASSERT (CapsuleIndex != NULL);
252     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
253     CapsuleIndexData[11] = 0;
254     Print(L"CapsuleMax - %s\n", CapsuleIndexData);
255     FreePool(CapsuleIndex);
256   }
257   Status = GetVariable2(
258              L"CapsuleLast",
259              &gEfiCapsuleReportGuid,
260              (VOID **)&CapsuleIndex,
261              NULL
262              );
263   if (!EFI_ERROR(Status)) {
264     ASSERT (CapsuleIndex != NULL);
265     CopyMem(CapsuleIndexData, CapsuleIndex, 11 * sizeof(CHAR16));
266     CapsuleIndexData[11] = 0;
267     Print(L"CapsuleLast - %s\n", CapsuleIndexData);
268     FreePool(CapsuleIndex);
269   }
270 
271 
272   StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");
273   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
274   Index = 0;
275 
276   while (TRUE) {
277     UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
278 
279     Status = GetVariable2 (
280                CapsuleVarName,
281                &gEfiCapsuleReportGuid,
282                (VOID **) &CapsuleResult,
283                NULL
284                );
285     if (Status == EFI_NOT_FOUND) {
286       break;
287     } else if (EFI_ERROR(Status)) {
288       continue;
289     }
290     ASSERT (CapsuleResult != NULL);
291 
292     //
293     // display capsule process status
294     //
295     if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
296       Print (L"CapsuleName: %s\n", CapsuleVarName);
297       Print (L"  Capsule Guid: %g\n", &CapsuleResult->CapsuleGuid);
298       Print (L"  Capsule ProcessedTime: %t\n", &CapsuleResult->CapsuleProcessed);
299       Print (L"  Capsule Status: %r\n", CapsuleResult->CapsuleStatus);
300     }
301 
302     if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
303       if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) {
304         CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
305         Print(L"  Capsule FMP Version: 0x%x\n", CapsuleResultFmp->Version);
306         Print(L"  Capsule FMP PayloadIndex: 0x%x\n", CapsuleResultFmp->PayloadIndex);
307         Print(L"  Capsule FMP UpdateImageIndex: 0x%x\n", CapsuleResultFmp->UpdateImageIndex);
308         Print(L"  Capsule FMP UpdateImageTypeId: %g\n", &CapsuleResultFmp->UpdateImageTypeId);
309         CapsuleFileName = (CHAR16 *)(CapsuleResultFmp + 1);
310         Print(L"  Capsule FMP CapsuleFileName: \"%s\"\n", CapsuleFileName);
311         CapsuleFileNameSize = StrSize(CapsuleFileName);
312         CapsuleTarget = (CHAR16 *)((UINTN)CapsuleFileName + CapsuleFileNameSize);
313         Print(L"  Capsule FMP CapsuleTarget: \"%s\"\n", CapsuleTarget);
314       }
315     }
316 
317     FreePool(CapsuleResult);
318 
319     Index++;
320     if (Index > 0xFFFF) {
321       break;
322     }
323   }
324 
325   return EFI_SUCCESS;
326 }
327 
328 CHAR8 *mFwTypeString[] = {
329   "Unknown",
330   "SystemFirmware",
331   "DeviceFirmware",
332   "UefiDriver",
333 };
334 
335 CHAR8 *mLastAttemptStatusString[] = {
336   "Success",
337   "Error: Unsuccessful",
338   "Error: Insufficient Resources",
339   "Error: Incorrect Version",
340   "Error: Invalid Format",
341   "Error: Auth Error",
342   "Error: Power Event AC",
343   "Error: Power Event Battery",
344   "Error: Unsatisfied Dependencies",
345 };
346 
347 /**
348   Convert FwType to a string.
349 
350   @param[in] FwType  FwType in ESRT
351 
352   @return a string for FwType.
353 **/
354 CHAR8 *
FwTypeToString(IN UINT32 FwType)355 FwTypeToString (
356   IN UINT32  FwType
357   )
358 {
359   if (FwType < sizeof(mFwTypeString) / sizeof(mFwTypeString[0])) {
360     return mFwTypeString[FwType];
361   } else {
362     return "Invalid";
363   }
364 }
365 
366 /**
367   Convert LastAttemptStatus to a string.
368 
369   @param[in] LastAttemptStatus  LastAttemptStatus in FMP or ESRT
370 
371   @return a string for LastAttemptStatus.
372 **/
373 CHAR8 *
LastAttemptStatusToString(IN UINT32 LastAttemptStatus)374 LastAttemptStatusToString (
375   IN UINT32  LastAttemptStatus
376   )
377 {
378   if (LastAttemptStatus < sizeof(mLastAttemptStatusString) / sizeof(mLastAttemptStatusString[0])) {
379     return mLastAttemptStatusString[LastAttemptStatus];
380   } else {
381     return "Error: Unknown";
382   }
383 }
384 
385 /**
386   Dump ESRT entry.
387 
388   @param[in] EsrtEntry  ESRT entry
389 **/
390 VOID
DumpEsrtEntry(IN EFI_SYSTEM_RESOURCE_ENTRY * EsrtEntry)391 DumpEsrtEntry (
392   IN EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry
393   )
394 {
395   Print(L"  FwClass                  - %g\n", &EsrtEntry->FwClass);
396   Print(L"  FwType                   - 0x%x (%a)\n", EsrtEntry->FwType, FwTypeToString(EsrtEntry->FwType));
397   Print(L"  FwVersion                - 0x%x\n", EsrtEntry->FwVersion);
398   Print(L"  LowestSupportedFwVersion - 0x%x\n", EsrtEntry->LowestSupportedFwVersion);
399   Print(L"  CapsuleFlags             - 0x%x\n", EsrtEntry->CapsuleFlags);
400   Print(L"  LastAttemptVersion       - 0x%x\n", EsrtEntry->LastAttemptVersion);
401   Print(L"  LastAttemptStatus        - 0x%x (%a)\n", EsrtEntry->LastAttemptStatus, LastAttemptStatusToString(EsrtEntry->LastAttemptStatus));
402 }
403 
404 /**
405   Dump ESRT table.
406 
407   @param[in] Esrt  ESRT table
408 **/
409 VOID
DumpEsrt(IN EFI_SYSTEM_RESOURCE_TABLE * Esrt)410 DumpEsrt (
411   IN EFI_SYSTEM_RESOURCE_TABLE  *Esrt
412   )
413 {
414   UINTN                      Index;
415   EFI_SYSTEM_RESOURCE_ENTRY  *EsrtEntry;
416 
417   if (Esrt == NULL) {
418     return ;
419   }
420 
421   Print(L"EFI_SYSTEM_RESOURCE_TABLE:\n");
422   Print(L"FwResourceCount    - 0x%x\n", Esrt->FwResourceCount);
423   Print(L"FwResourceCountMax - 0x%x\n", Esrt->FwResourceCountMax);
424   Print(L"FwResourceVersion  - 0x%lx\n", Esrt->FwResourceVersion);
425 
426   EsrtEntry = (VOID *)(Esrt + 1);
427   for (Index = 0; Index < Esrt->FwResourceCount; Index++) {
428     Print(L"EFI_SYSTEM_RESOURCE_ENTRY (%d):\n", Index);
429     DumpEsrtEntry(EsrtEntry);
430     EsrtEntry++;
431   }
432 }
433 
434 /**
435   Dump ESRT info.
436 **/
437 VOID
DumpEsrtData(VOID)438 DumpEsrtData (
439   VOID
440   )
441 {
442   EFI_STATUS                 Status;
443   EFI_SYSTEM_RESOURCE_TABLE  *Esrt;
444 
445   Print(L"##############\n");
446   Print(L"# ESRT TABLE #\n");
447   Print(L"##############\n");
448 
449   Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
450   if (EFI_ERROR(Status)) {
451     Print(L"ESRT - %r\n", Status);
452     return;
453   }
454   DumpEsrt(Esrt);
455   Print(L"\n");
456 }
457 
458 
459 /**
460   Dump capsule information from CapsuleHeader
461 
462   @param[in] CapsuleHeader       The CapsuleHeader of the capsule image.
463 
464   @retval EFI_SUCCESS            The capsule information is dumped.
465 
466 **/
467 EFI_STATUS
DumpCapsuleFromBuffer(IN EFI_CAPSULE_HEADER * CapsuleHeader)468 DumpCapsuleFromBuffer (
469   IN EFI_CAPSULE_HEADER                         *CapsuleHeader
470   )
471 {
472   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
473     DumpUxCapsule (CapsuleHeader);
474     return EFI_SUCCESS;
475   }
476 
477   if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
478     DumpFmpCapsule (CapsuleHeader);
479   }
480   if (IsNestedFmpCapsule (CapsuleHeader)) {
481     Print (L"[NestedCapusule]\n");
482     Print (L"CapsuleHeader:\n");
483     Print (L"  CapsuleGuid      - %g\n", &CapsuleHeader->CapsuleGuid);
484     Print (L"  HeaderSize       - 0x%x\n", CapsuleHeader->HeaderSize);
485     Print (L"  Flags            - 0x%x\n", CapsuleHeader->Flags);
486     Print (L"  CapsuleImageSize - 0x%x\n", CapsuleHeader->CapsuleImageSize);
487     DumpFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
488   }
489 
490   return EFI_SUCCESS;
491 }
492 
493 /**
494   This routine is called to upper case given unicode string.
495 
496   @param[in]   Str              String to upper case
497 
498   @retval upper cased string after process
499 
500 **/
501 STATIC
502 CHAR16 *
UpperCaseString(IN CHAR16 * Str)503 UpperCaseString (
504   IN CHAR16 *Str
505   )
506 {
507   CHAR16  *Cptr;
508 
509   for (Cptr = Str; *Cptr != L'\0'; Cptr++) {
510     if (L'a' <= *Cptr && *Cptr <= L'z') {
511       *Cptr = *Cptr - L'a' + L'A';
512     }
513   }
514 
515   return Str;
516 }
517 
518 /**
519   This routine is used to return substring before period '.' or '\0'
520   Caller should respsonsible of substr space allocation & free
521 
522   @param[in]   Str              String to check
523   @param[out]  SubStr           First part of string before period or '\0'
524   @param[out]  SubStrLen        Length of first part of string
525 
526 **/
527 STATIC
528 VOID
GetSubStringBeforePeriod(IN CHAR16 * Str,OUT CHAR16 * SubStr,OUT UINTN * SubStrLen)529 GetSubStringBeforePeriod (
530   IN  CHAR16 *Str,
531   OUT CHAR16 *SubStr,
532   OUT UINTN  *SubStrLen
533   )
534 {
535   UINTN Index;
536   for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
537     SubStr[Index] = Str[Index];
538   }
539 
540   SubStr[Index] = L'\0';
541   *SubStrLen = Index;
542 }
543 
544 /**
545   This routine pad the string in tail with input character.
546 
547   @param[in]   StrBuf            Str buffer to be padded, should be enough room for
548   @param[in]   PadLen            Expected padding length
549   @param[in]   Character         Character used to pad
550 
551 **/
552 STATIC
553 VOID
PadStrInTail(IN CHAR16 * StrBuf,IN UINTN PadLen,IN CHAR16 Character)554 PadStrInTail (
555   IN CHAR16   *StrBuf,
556   IN UINTN    PadLen,
557   IN CHAR16   Character
558   )
559 {
560   UINTN Index;
561 
562   for (Index = 0; StrBuf[Index] != L'\0'; Index++);
563 
564   while(PadLen != 0) {
565     StrBuf[Index] = Character;
566     Index++;
567     PadLen--;
568   }
569 
570   StrBuf[Index] = L'\0';
571 }
572 
573 /**
574   This routine find the offset of the last period '.' of string. if No period exists
575   function FileNameExtension is set to L'\0'
576 
577   @param[in]   FileName           File name to split between last period
578   @param[out]  FileNameFirst      First FileName before last period
579   @param[out]  FileNameExtension  FileName after last period
580 
581 **/
582 STATIC
583 VOID
SplitFileNameExtension(IN CHAR16 * FileName,OUT CHAR16 * FileNameFirst,OUT CHAR16 * FileNameExtension)584 SplitFileNameExtension (
585   IN  CHAR16  *FileName,
586   OUT CHAR16  *FileNameFirst,
587   OUT CHAR16  *FileNameExtension
588   )
589 {
590   UINTN Index;
591   UINTN StringLen;
592 
593   StringLen = StrLen(FileName);
594   for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--);
595 
596   //
597   // No period exists. No FileName Extension
598   //
599   if (Index == 0 && FileName[Index] != L'.') {
600     FileNameExtension[0] = L'\0';
601     Index = StringLen;
602   } else {
603     StrCpyS (FileNameExtension, MAX_FILE_NAME_LEN, &FileName[Index+1]);
604   }
605 
606   //
607   // Copy First file name
608   //
609   StrnCpyS (FileNameFirst, MAX_FILE_NAME_LEN, FileName, Index);
610   FileNameFirst[Index] = L'\0';
611 }
612 
613 /**
614   The function is called by PerformQuickSort to sort file name in alphabet.
615 
616   @param[in] Left            The pointer to first buffer.
617   @param[in] Right           The pointer to second buffer.
618 
619   @retval 0                  Buffer1 equal to Buffer2.
620   @return <0                 Buffer1 is less than Buffer2.
621   @return >0                 Buffer1 is greater than Buffer2.
622 
623 **/
624 INTN
CompareFileNameInAlphabet(IN VOID * Left,IN VOID * Right)625 CompareFileNameInAlphabet (
626   IN VOID                         *Left,
627   IN VOID                         *Right
628   )
629 {
630   EFI_FILE_INFO  *FileInfo1;
631   EFI_FILE_INFO  *FileInfo2;
632   CHAR16         FileName1[MAX_FILE_NAME_SIZE];
633   CHAR16         FileExtension1[MAX_FILE_NAME_SIZE];
634   CHAR16         FileName2[MAX_FILE_NAME_SIZE];
635   CHAR16         FileExtension2[MAX_FILE_NAME_SIZE];
636   CHAR16         TempSubStr1[MAX_FILE_NAME_SIZE];
637   CHAR16         TempSubStr2[MAX_FILE_NAME_SIZE];
638   UINTN          SubStrLen1;
639   UINTN          SubStrLen2;
640   INTN           SubStrCmpResult;
641 
642   FileInfo1 = (EFI_FILE_INFO *) (*(UINTN *)Left);
643   FileInfo2 = (EFI_FILE_INFO *) (*(UINTN *)Right);
644 
645   SplitFileNameExtension (FileInfo1->FileName, FileName1, FileExtension1);
646   SplitFileNameExtension (FileInfo2->FileName, FileName2, FileExtension2);
647 
648   UpperCaseString (FileName1);
649   UpperCaseString (FileName2);
650 
651   GetSubStringBeforePeriod (FileName1, TempSubStr1, &SubStrLen1);
652   GetSubStringBeforePeriod (FileName2, TempSubStr2, &SubStrLen2);
653 
654   if (SubStrLen1 > SubStrLen2) {
655     //
656     // Substr in NewFileName is longer.  Pad tail with SPACE
657     //
658     PadStrInTail (TempSubStr2, SubStrLen1 - SubStrLen2, L' ');
659   } else if (SubStrLen1 < SubStrLen2){
660     //
661     // Substr in ListedFileName is longer. Pad tail with SPACE
662     //
663     PadStrInTail (TempSubStr1, SubStrLen2 - SubStrLen1, L' ');
664   }
665 
666   SubStrCmpResult = StrnCmp (TempSubStr1, TempSubStr2, MAX_FILE_NAME_LEN);
667   if (SubStrCmpResult != 0) {
668     return SubStrCmpResult;
669   }
670 
671   UpperCaseString (FileExtension1);
672   UpperCaseString (FileExtension2);
673 
674   return StrnCmp (FileExtension1, FileExtension2, MAX_FILE_NAME_LEN);
675 }
676 
677 /**
678   Dump capsule information from disk.
679 
680   @param[in] Fs                  The device path of disk.
681   @param[in] DumpCapsuleInfo     The flag to indicate whether to dump the capsule inforomation.
682 
683   @retval EFI_SUCCESS            The capsule information is dumped.
684 
685 **/
686 EFI_STATUS
DumpCapsuleFromDisk(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * Fs,IN BOOLEAN DumpCapsuleInfo)687 DumpCapsuleFromDisk (
688   IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL            *Fs,
689   IN BOOLEAN                                    DumpCapsuleInfo
690   )
691 {
692   EFI_STATUS                                    Status;
693   EFI_FILE                                      *Root;
694   EFI_FILE                                      *DirHandle;
695   EFI_FILE                                      *FileHandle;
696   UINTN                                         Index;
697   UINTN                                         FileSize;
698   VOID                                          *FileBuffer;
699   EFI_FILE_INFO                                 **FileInfoBuffer;
700   EFI_FILE_INFO                                 *FileInfo;
701   UINTN                                         FileCount;
702   BOOLEAN                                       NoFile;
703 
704   DirHandle       = NULL;
705   FileHandle      = NULL;
706   Index           = 0;
707   FileInfoBuffer  = NULL;
708   FileInfo        = NULL;
709   FileCount       = 0;
710   NoFile          = FALSE;
711 
712   Status = Fs->OpenVolume (Fs, &Root);
713   if (EFI_ERROR (Status)) {
714     Print (L"Cannot open volume. Status = %r\n", Status);
715     goto Done;
716   }
717 
718   Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE , 0);
719   if (EFI_ERROR (Status)) {
720     Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status);
721     goto Done;
722   }
723 
724   //
725   // Get file count first
726   //
727   Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
728   do {
729     if (EFI_ERROR (Status) || FileInfo == NULL) {
730       Print (L"Get File Info Fail. Status = %r\n", Status);
731       goto Done;
732     }
733 
734     if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
735       FileCount++;
736     }
737 
738     Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
739     if (EFI_ERROR (Status)) {
740       Print (L"Get Next File Fail. Status = %r\n", Status);
741       goto Done;
742     }
743   } while (!NoFile);
744 
745   if (FileCount == 0) {
746     Print (L"Error: No capsule file found!\n");
747     Status = EFI_NOT_FOUND;
748     goto Done;
749   }
750 
751   FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount);
752   if (FileInfoBuffer == NULL) {
753     Status = EFI_OUT_OF_RESOURCES;
754     goto Done;
755   }
756   NoFile = FALSE;
757 
758   //
759   // Get all file info
760   //
761   Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
762   do {
763     if (EFI_ERROR (Status) || FileInfo == NULL) {
764       Print (L"Get File Info Fail. Status = %r\n", Status);
765       goto Done;
766     }
767 
768     if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) {
769       FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo);
770     }
771 
772     Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile);
773     if (EFI_ERROR (Status)) {
774       Print (L"Get Next File Fail. Status = %r\n", Status);
775       goto Done;
776     }
777   } while (!NoFile);
778 
779   //
780   // Sort FileInfoBuffer by alphabet order
781   //
782   PerformQuickSort (
783     FileInfoBuffer,
784     FileCount,
785     sizeof (FileInfo),
786     (SORT_COMPARE) CompareFileNameInAlphabet
787     );
788 
789   Print (L"The capsules will be performed by following order:\n");
790 
791   for (Index = 0; Index < FileCount; Index++) {
792     Print (L"  %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName);
793   }
794 
795   if (!DumpCapsuleInfo) {
796     Status = EFI_SUCCESS;
797     goto Done;
798   }
799 
800   Print(L"The infomation of the capsules:\n");
801 
802   for (Index = 0; Index < FileCount; Index++) {
803     FileHandle = NULL;
804     Status = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0);
805     if (EFI_ERROR (Status)) {
806       goto Done;
807     }
808 
809     Status = FileHandleGetSize (FileHandle, (UINT64 *) &FileSize);
810     if (EFI_ERROR (Status)) {
811       Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
812       FileHandleClose (FileHandle);
813       goto Done;
814     }
815 
816     FileBuffer = AllocatePool (FileSize);
817     if (FileBuffer == NULL) {
818       Status = EFI_OUT_OF_RESOURCES;
819       goto Done;
820     }
821 
822     Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
823     if (EFI_ERROR (Status)) {
824       Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status);
825       FileHandleClose (FileHandle);
826       FreePool (FileBuffer);
827       goto Done;
828     }
829 
830     Print (L"**************************\n");
831     Print (L"  %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName);
832     Print (L"**************************\n");
833     DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *) FileBuffer);
834     FileHandleClose (FileHandle);
835     FreePool (FileBuffer);
836   }
837 
838 Done:
839   if (FileInfoBuffer != NULL) {
840     for (Index = 0; Index < FileCount; Index++) {
841       if (FileInfoBuffer[Index] != NULL) {
842         FreePool (FileInfoBuffer[Index]);
843       }
844     }
845     FreePool (FileInfoBuffer);
846   }
847 
848   return Status;
849 }
850 
851 /**
852   Dump capsule inforomation form Gather list.
853 
854   @param[in]  BlockDescriptors The block descriptors for the capsule images
855   @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.
856 
857 **/
858 VOID
DumpBlockDescriptors(IN EFI_CAPSULE_BLOCK_DESCRIPTOR * BlockDescriptors,IN BOOLEAN DumpCapsuleInfo)859 DumpBlockDescriptors (
860   IN EFI_CAPSULE_BLOCK_DESCRIPTOR   *BlockDescriptors,
861   IN BOOLEAN                        DumpCapsuleInfo
862   )
863 {
864   EFI_CAPSULE_BLOCK_DESCRIPTOR      *TempBlockPtr;
865 
866   TempBlockPtr = BlockDescriptors;
867 
868   while (TRUE) {
869     if (TempBlockPtr->Length != 0) {
870       if (DumpCapsuleInfo) {
871         Print(L"******************************************************\n");
872       }
873       Print(L"Capsule data starts at 0x%08x with size 0x%08x\n", TempBlockPtr->Union.DataBlock, TempBlockPtr->Length);
874       if (DumpCapsuleInfo) {
875         Print(L"******************************************************\n");
876         DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *) (UINTN) TempBlockPtr->Union.DataBlock);
877       }
878       TempBlockPtr += 1;
879     } else {
880       if (TempBlockPtr->Union.ContinuationPointer == (UINTN)NULL) {
881         break;
882       } else {
883         TempBlockPtr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockPtr->Union.ContinuationPointer;
884       }
885     }
886   }
887 }
888 
889 /**
890   Dump Provisioned Capsule.
891 
892   @param[in]  DumpCapsuleInfo  The flag to indicate whether to dump the capsule inforomation.
893 
894 **/
895 VOID
DumpProvisionedCapsule(IN BOOLEAN DumpCapsuleInfo)896 DumpProvisionedCapsule (
897   IN BOOLEAN                      DumpCapsuleInfo
898   )
899 {
900   EFI_STATUS                      Status;
901   CHAR16                          CapsuleVarName[30];
902   CHAR16                          *TempVarName;
903   UINTN                           Index;
904   EFI_PHYSICAL_ADDRESS            *CapsuleDataPtr64;
905   UINT16                          *BootNext;
906   CHAR16                          BootOptionName[20];
907   EFI_BOOT_MANAGER_LOAD_OPTION    BootNextOptionEntry;
908   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
909   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
910   EFI_SHELL_PROTOCOL              *ShellProtocol;
911 
912   Index             = 0;
913   CapsuleDataPtr64  = NULL;
914   BootNext          = NULL;
915 
916   ShellProtocol = GetShellProtocol ();
917   if (ShellProtocol == NULL) {
918     Print (L"Get Shell Protocol Fail\n");
919     return ;
920   }
921 
922   //
923   // Dump capsule provisioned on Memory
924   //
925   Print (L"#########################\n");
926   Print (L"### Capsule on Memory ###\n");
927   Print (L"#########################\n");
928   StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CHAR16), EFI_CAPSULE_VARIABLE_NAME);
929   TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
930   while (TRUE) {
931     if (Index > 0) {
932       UnicodeValueToStringS (
933         TempVarName,
934         sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
935         0,
936         Index,
937         0
938         );
939     }
940 
941     Status = GetVariable2 (
942               CapsuleVarName,
943               &gEfiCapsuleVendorGuid,
944               (VOID **) &CapsuleDataPtr64,
945               NULL
946               );
947     if (EFI_ERROR (Status) || CapsuleDataPtr64 == NULL) {
948       if (Index == 0) {
949         Print (L"No data.\n");
950       }
951       break;
952     }
953 
954     Index++;
955     Print (L"Capsule Description at 0x%08x\n", *CapsuleDataPtr64);
956     DumpBlockDescriptors ((EFI_CAPSULE_BLOCK_DESCRIPTOR*) (UINTN) *CapsuleDataPtr64, DumpCapsuleInfo);
957   }
958 
959   //
960   // Dump capsule provisioned on Disk
961   //
962   Print (L"#########################\n");
963   Print (L"### Capsule on Disk #####\n");
964   Print (L"#########################\n");
965   Status = GetVariable2 (
966              L"BootNext",
967              &gEfiGlobalVariableGuid,
968              (VOID **) &BootNext,
969              NULL
970             );
971   if (EFI_ERROR (Status) || BootNext == NULL) {
972     Print (L"Get BootNext Variable Fail. Status = %r\n", Status);
973   } else {
974     UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", *BootNext);
975     Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);
976     if (!EFI_ERROR (Status)) {
977       //
978       // Display description and device path
979       //
980       GetEfiSysPartitionFromBootOptionFilePath (BootNextOptionEntry.FilePath, &DevicePath, &Fs);
981       if(!EFI_ERROR (Status)) {
982         Print (L"Capsules are provisioned on BootOption: %s\n", BootNextOptionEntry.Description);
983         Print (L"    %s %s\n", ShellProtocol->GetMapFromDevicePath (&DevicePath), ConvertDevicePathToText(DevicePath, TRUE, TRUE));
984         DumpCapsuleFromDisk (Fs, DumpCapsuleInfo);
985       }
986     }
987   }
988 }
989 
990 /**
991   Dump FMP information.
992 
993   @param[in] ImageInfoSize       The size of ImageInfo, in bytes.
994   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
995   @param[in] DescriptorVersion   The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
996   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
997   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
998   @param[in] PackageVersion      The version of package.
999   @param[in] PackageVersionName  The version name of package.
1000 **/
1001 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)1002 DumpFmpImageInfo (
1003   IN UINTN                           ImageInfoSize,
1004   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
1005   IN UINT32                          DescriptorVersion,
1006   IN UINT8                           DescriptorCount,
1007   IN UINTN                           DescriptorSize,
1008   IN UINT32                          PackageVersion,
1009   IN CHAR16                          *PackageVersionName
1010   )
1011 {
1012   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
1013   UINTN                                         Index;
1014   UINTN                                         Index2;
1015 
1016   Print(L"  DescriptorVersion  - 0x%x\n", DescriptorVersion);
1017   Print(L"  DescriptorCount    - 0x%x\n", DescriptorCount);
1018   Print(L"  DescriptorSize     - 0x%x\n", DescriptorSize);
1019   Print(L"  PackageVersion     - 0x%x\n", PackageVersion);
1020   Print(L"  PackageVersionName - \"%s\"\n", PackageVersionName);
1021   CurrentImageInfo = ImageInfo;
1022   for (Index = 0; Index < DescriptorCount; Index++) {
1023     Print(L"  ImageDescriptor (%d)\n", Index);
1024     Print(L"    ImageIndex                  - 0x%x\n", CurrentImageInfo->ImageIndex);
1025     Print(L"    ImageTypeId                 - %g\n", &CurrentImageInfo->ImageTypeId);
1026     Print(L"    ImageId                     - 0x%lx\n", CurrentImageInfo->ImageId);
1027     Print(L"    ImageIdName                 - \"%s\"\n", CurrentImageInfo->ImageIdName);
1028     Print(L"    Version                     - 0x%x\n", CurrentImageInfo->Version);
1029     Print(L"    VersionName                 - \"%s\"\n", CurrentImageInfo->VersionName);
1030     Print(L"    Size                        - 0x%x\n", CurrentImageInfo->Size);
1031     Print(L"    AttributesSupported         - 0x%lx\n", CurrentImageInfo->AttributesSupported);
1032     Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
1033     Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
1034     Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
1035     Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE);
1036     Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_UEFI_IMAGE);
1037     Print(L"    AttributesSetting           - 0x%lx\n", CurrentImageInfo->AttributesSetting);
1038     Print(L"      IMAGE_UPDATABLE           - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
1039     Print(L"      RESET_REQUIRED            - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
1040     Print(L"      AUTHENTICATION_REQUIRED   - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
1041     Print(L"      IN_USE                    - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE);
1042     Print(L"      UEFI_IMAGE                - 0x%lx\n", CurrentImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE);
1043     Print(L"    Compatibilities             - 0x%lx\n", CurrentImageInfo->Compatibilities);
1044     Print(L"      COMPATIB_CHECK_SUPPORTED  - 0x%lx\n", CurrentImageInfo->Compatibilities & IMAGE_COMPATIBILITY_CHECK_SUPPORTED);
1045     if (DescriptorVersion > 1) {
1046       Print(L"    LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion);
1047       if (DescriptorVersion > 2) {
1048         Print(L"    LastAttemptVersion          - 0x%x\n", CurrentImageInfo->LastAttemptVersion);
1049         Print(L"    LastAttemptStatus           - 0x%x (%a)\n", CurrentImageInfo->LastAttemptStatus, LastAttemptStatusToString(CurrentImageInfo->LastAttemptStatus));
1050         Print(L"    HardwareInstance            - 0x%lx\n", CurrentImageInfo->HardwareInstance);
1051         if (DescriptorVersion > 3) {
1052           Print(L"    Dependencies                - ");
1053           if (CurrentImageInfo->Dependencies == NULL) {
1054             Print(L"NULL\n");
1055           } else {
1056             Index2 = 0;
1057             do {
1058               Print(L"%02x ", CurrentImageInfo->Dependencies->Dependencies[Index2]);
1059             } while (CurrentImageInfo->Dependencies->Dependencies[Index2 ++] != EFI_FMP_DEP_END);
1060             Print(L"\n");
1061           }
1062         }
1063       }
1064     }
1065     //
1066     // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
1067     //
1068     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
1069   }
1070 }
1071 
1072 /**
1073   Dump FMP package information.
1074 
1075   @param[in] PackageVersion             The version of package.
1076   @param[in] PackageVersionName         The version name of package.
1077   @param[in] PackageVersionNameMaxLen   The maximum length of PackageVersionName.
1078   @param[in] AttributesSupported        Package attributes that are supported by this device.
1079   @param[in] AttributesSetting          Package attributes.
1080 **/
1081 VOID
DumpFmpPackageInfo(IN UINT32 PackageVersion,IN CHAR16 * PackageVersionName,IN UINT32 PackageVersionNameMaxLen,IN UINT64 AttributesSupported,IN UINT64 AttributesSetting)1082 DumpFmpPackageInfo (
1083   IN UINT32                           PackageVersion,
1084   IN CHAR16                           *PackageVersionName,
1085   IN UINT32                           PackageVersionNameMaxLen,
1086   IN UINT64                           AttributesSupported,
1087   IN UINT64                           AttributesSetting
1088   )
1089 {
1090   Print(L"  PackageVersion              - 0x%x\n", PackageVersion);
1091   Print(L"  PackageVersionName          - \"%s\"\n", PackageVersionName);
1092   Print(L"  PackageVersionNameMaxLen    - 0x%x\n", PackageVersionNameMaxLen);
1093   Print(L"  AttributesSupported         - 0x%lx\n", AttributesSupported);
1094   Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
1095   Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED);
1096   Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSupported & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
1097   Print(L"  AttributesSetting           - 0x%lx\n", AttributesSetting);
1098   Print(L"    IMAGE_UPDATABLE           - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE);
1099   Print(L"    RESET_REQUIRED            - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED);
1100   Print(L"    AUTHENTICATION_REQUIRED   - 0x%lx\n", AttributesSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
1101 }
1102 
1103 /**
1104   Dump FMP protocol info.
1105 **/
1106 VOID
DumpFmpData(VOID)1107 DumpFmpData (
1108   VOID
1109   )
1110 {
1111   EFI_STATUS                                    Status;
1112   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
1113   EFI_HANDLE                                    *HandleBuffer;
1114   UINTN                                         NumberOfHandles;
1115   UINTN                                         Index;
1116   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
1117   UINTN                                         ImageInfoSize;
1118   UINT32                                        FmpImageInfoDescriptorVer;
1119   UINT8                                         FmpImageInfoCount;
1120   UINTN                                         DescriptorSize;
1121   UINT32                                        PackageVersion;
1122   CHAR16                                        *PackageVersionName;
1123   UINT32                                        PackageVersionNameMaxLen;
1124   UINT64                                        AttributesSupported;
1125   UINT64                                        AttributesSetting;
1126 
1127   Print(L"############\n");
1128   Print(L"# FMP DATA #\n");
1129   Print(L"############\n");
1130   Status = gBS->LocateHandleBuffer (
1131                   ByProtocol,
1132                   &gEfiFirmwareManagementProtocolGuid,
1133                   NULL,
1134                   &NumberOfHandles,
1135                   &HandleBuffer
1136                   );
1137   if (EFI_ERROR(Status)) {
1138     Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
1139     return;
1140   }
1141 
1142   for (Index = 0; Index < NumberOfHandles; Index++) {
1143     Status = gBS->HandleProtocol(
1144                     HandleBuffer[Index],
1145                     &gEfiFirmwareManagementProtocolGuid,
1146                     (VOID **)&Fmp
1147                     );
1148     if (EFI_ERROR(Status)) {
1149       continue;
1150     }
1151 
1152     ImageInfoSize = 0;
1153     Status = Fmp->GetImageInfo (
1154                     Fmp,
1155                     &ImageInfoSize,
1156                     NULL,
1157                     NULL,
1158                     NULL,
1159                     NULL,
1160                     NULL,
1161                     NULL
1162                     );
1163     if (Status != EFI_BUFFER_TOO_SMALL) {
1164       continue;
1165     }
1166 
1167     FmpImageInfoBuf = NULL;
1168     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
1169     if (FmpImageInfoBuf == NULL) {
1170       Status = EFI_OUT_OF_RESOURCES;
1171       goto EXIT;
1172     }
1173 
1174     PackageVersionName = NULL;
1175     Status = Fmp->GetImageInfo (
1176                     Fmp,
1177                     &ImageInfoSize,               // ImageInfoSize
1178                     FmpImageInfoBuf,              // ImageInfo
1179                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
1180                     &FmpImageInfoCount,           // DescriptorCount
1181                     &DescriptorSize,              // DescriptorSize
1182                     &PackageVersion,              // PackageVersion
1183                     &PackageVersionName           // PackageVersionName
1184                     );
1185 
1186     //
1187     // If FMP GetInformation interface failed, skip this resource
1188     //
1189     if (EFI_ERROR(Status)) {
1190       Print(L"FMP (%d) ImageInfo - %r\n", Index, Status);
1191       FreePool(FmpImageInfoBuf);
1192       continue;
1193     }
1194 
1195     Print(L"FMP (%d) ImageInfo:\n", Index);
1196     DumpFmpImageInfo(
1197       ImageInfoSize,               // ImageInfoSize
1198       FmpImageInfoBuf,             // ImageInfo
1199       FmpImageInfoDescriptorVer,   // DescriptorVersion
1200       FmpImageInfoCount,           // DescriptorCount
1201       DescriptorSize,              // DescriptorSize
1202       PackageVersion,              // PackageVersion
1203       PackageVersionName           // PackageVersionName
1204       );
1205 
1206     if (PackageVersionName != NULL) {
1207       FreePool(PackageVersionName);
1208     }
1209     FreePool(FmpImageInfoBuf);
1210 
1211     //
1212     // Get package info
1213     //
1214     PackageVersionName = NULL;
1215     Status = Fmp->GetPackageInfo (
1216                     Fmp,
1217                     &PackageVersion,              // PackageVersion
1218                     &PackageVersionName,          // PackageVersionName
1219                     &PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
1220                     &AttributesSupported,         // AttributesSupported
1221                     &AttributesSetting            // AttributesSetting
1222                     );
1223     if (EFI_ERROR(Status)) {
1224       Print(L"FMP (%d) PackageInfo - %r\n", Index, Status);
1225     } else {
1226       Print(L"FMP (%d) ImageInfo:\n", Index);
1227       DumpFmpPackageInfo(
1228         PackageVersion,              // PackageVersion
1229         PackageVersionName,          // PackageVersionName
1230         PackageVersionNameMaxLen,    // PackageVersionNameMaxLen
1231         AttributesSupported,         // AttributesSupported
1232         AttributesSetting            // AttributesSetting
1233         );
1234 
1235       if (PackageVersionName != NULL) {
1236         FreePool(PackageVersionName);
1237       }
1238     }
1239   }
1240   Print(L"\n");
1241 
1242 EXIT:
1243   FreePool(HandleBuffer);
1244 }
1245 
1246 /**
1247   Check if the ImageInfo includes the ImageTypeId.
1248 
1249   @param[in] ImageInfo           A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
1250   @param[in] DescriptorCount     The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
1251   @param[in] DescriptorSize      The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
1252   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
1253 
1254   @return TRUE  This ImageInfo includes the ImageTypeId
1255   @return FALSE This ImageInfo does not include the ImageTypeId
1256 **/
1257 BOOLEAN
IsThisFmpImageInfo(IN EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageInfo,IN UINT8 DescriptorCount,IN UINTN DescriptorSize,IN EFI_GUID * ImageTypeId)1258 IsThisFmpImageInfo (
1259   IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *ImageInfo,
1260   IN UINT8                           DescriptorCount,
1261   IN UINTN                           DescriptorSize,
1262   IN EFI_GUID                        *ImageTypeId
1263   )
1264 {
1265   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *CurrentImageInfo;
1266   UINTN                                         Index;
1267 
1268   CurrentImageInfo = ImageInfo;
1269   for (Index = 0; Index < DescriptorCount; Index++) {
1270     if (CompareGuid (&CurrentImageInfo->ImageTypeId, ImageTypeId)) {
1271       return TRUE;
1272     }
1273     CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
1274   }
1275   return FALSE;
1276 }
1277 
1278 /**
1279   return the FMP whoes ImageInfo includes the ImageTypeId.
1280 
1281   @param[in] ImageTypeId         A unique GUID identifying the firmware image type.
1282 
1283   @return The FMP whoes ImageInfo includes the ImageTypeId
1284 **/
1285 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *
FindFmpFromImageTypeId(IN EFI_GUID * ImageTypeId)1286 FindFmpFromImageTypeId (
1287   IN EFI_GUID  *ImageTypeId
1288   )
1289 {
1290   EFI_STATUS                                    Status;
1291   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
1292   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *TargetFmp;
1293   EFI_HANDLE                                    *HandleBuffer;
1294   UINTN                                         NumberOfHandles;
1295   UINTN                                         Index;
1296   EFI_FIRMWARE_IMAGE_DESCRIPTOR                 *FmpImageInfoBuf;
1297   UINTN                                         ImageInfoSize;
1298   UINT32                                        FmpImageInfoDescriptorVer;
1299   UINT8                                         FmpImageInfoCount;
1300   UINTN                                         DescriptorSize;
1301   UINT32                                        PackageVersion;
1302   CHAR16                                        *PackageVersionName;
1303 
1304   Status = gBS->LocateHandleBuffer (
1305                   ByProtocol,
1306                   &gEfiFirmwareManagementProtocolGuid,
1307                   NULL,
1308                   &NumberOfHandles,
1309                   &HandleBuffer
1310                   );
1311   if (EFI_ERROR(Status)) {
1312     Print(L"FMP protocol - %r\n", EFI_NOT_FOUND);
1313     return NULL;
1314   }
1315 
1316   TargetFmp = NULL;
1317   for (Index = 0; Index < NumberOfHandles; Index++) {
1318     Status = gBS->HandleProtocol(
1319                     HandleBuffer[Index],
1320                     &gEfiFirmwareManagementProtocolGuid,
1321                     (VOID **)&Fmp
1322                     );
1323     if (EFI_ERROR(Status)) {
1324       continue;
1325     }
1326 
1327     ImageInfoSize = 0;
1328     Status = Fmp->GetImageInfo (
1329                     Fmp,
1330                     &ImageInfoSize,
1331                     NULL,
1332                     NULL,
1333                     NULL,
1334                     NULL,
1335                     NULL,
1336                     NULL
1337                     );
1338     if (Status != EFI_BUFFER_TOO_SMALL) {
1339       continue;
1340     }
1341 
1342     FmpImageInfoBuf = NULL;
1343     FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
1344     if (FmpImageInfoBuf == NULL) {
1345       FreePool(HandleBuffer);
1346       Print(L"Out of resource\n");
1347       return NULL;
1348     }
1349 
1350     PackageVersionName = NULL;
1351     Status = Fmp->GetImageInfo (
1352                     Fmp,
1353                     &ImageInfoSize,               // ImageInfoSize
1354                     FmpImageInfoBuf,              // ImageInfo
1355                     &FmpImageInfoDescriptorVer,   // DescriptorVersion
1356                     &FmpImageInfoCount,           // DescriptorCount
1357                     &DescriptorSize,              // DescriptorSize
1358                     &PackageVersion,              // PackageVersion
1359                     &PackageVersionName           // PackageVersionName
1360                     );
1361 
1362     //
1363     // If FMP GetInformation interface failed, skip this resource
1364     //
1365     if (EFI_ERROR(Status)) {
1366       FreePool(FmpImageInfoBuf);
1367       continue;
1368     }
1369 
1370     if (PackageVersionName != NULL) {
1371       FreePool(PackageVersionName);
1372     }
1373 
1374     if (IsThisFmpImageInfo (FmpImageInfoBuf, FmpImageInfoCount, DescriptorSize, ImageTypeId)) {
1375       TargetFmp = Fmp;
1376     }
1377     FreePool(FmpImageInfoBuf);
1378     if (TargetFmp != NULL) {
1379       break;
1380     }
1381   }
1382   FreePool(HandleBuffer);
1383   return TargetFmp;
1384 }
1385 
1386 /**
1387   Dump FMP image data.
1388 
1389   @param[in]  ImageTypeId   The ImageTypeId of the FMP image.
1390                             It is used to identify the FMP protocol.
1391   @param[in]  ImageIndex    The ImageIndex of the FMP image.
1392                             It is the input parameter for FMP->GetImage().
1393   @param[in]  ImageName     The file name to hold the output FMP image.
1394 **/
1395 VOID
DumpFmpImage(IN EFI_GUID * ImageTypeId,IN UINTN ImageIndex,IN CHAR16 * ImageName)1396 DumpFmpImage (
1397   IN EFI_GUID  *ImageTypeId,
1398   IN UINTN     ImageIndex,
1399   IN CHAR16    *ImageName
1400   )
1401 {
1402   EFI_STATUS                                    Status;
1403   EFI_FIRMWARE_MANAGEMENT_PROTOCOL              *Fmp;
1404   VOID                                          *Image;
1405   UINTN                                         ImageSize;
1406 
1407   Fmp = FindFmpFromImageTypeId (ImageTypeId);
1408   if (Fmp == NULL) {
1409     Print(L"No FMP include ImageTypeId %g\n", ImageTypeId);
1410     return ;
1411   }
1412 
1413   if (ImageIndex > 0xFF) {
1414     Print(L"ImageIndex 0x%x too big\n", ImageIndex);
1415     return ;
1416   }
1417 
1418   Image = Fmp;
1419   ImageSize = 0;
1420   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
1421   if (Status != EFI_BUFFER_TOO_SMALL) {
1422     Print(L"Fmp->GetImage - %r\n", Status);
1423     return ;
1424   }
1425 
1426   Image = AllocatePool (ImageSize);
1427   if (Image == NULL) {
1428     Print(L"Allocate FmpImage 0x%x - %r\n", ImageSize, EFI_OUT_OF_RESOURCES);
1429     return ;
1430   }
1431 
1432   Status = Fmp->GetImage (Fmp, (UINT8)ImageIndex, Image, &ImageSize);
1433   if (EFI_ERROR(Status)) {
1434     Print(L"Fmp->GetImage - %r\n", Status);
1435     return ;
1436   }
1437 
1438   Status = WriteFileFromBuffer(ImageName, ImageSize, Image);
1439   Print(L"CapsuleApp: Dump %g ImageIndex (0x%x) to %s %r\n", ImageTypeId, ImageIndex, ImageName, Status);
1440 
1441   FreePool (Image);
1442 
1443   return ;
1444 }
1445