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