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