]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/CapsuleApp/CapsuleDump.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / CapsuleDump.c
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
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
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
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
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
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 *
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 *
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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 }