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