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