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