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