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