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