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