CapsuleDump.c 50 KB

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