CapsuleApp.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. /** @file
  2. A shell application that triggers capsule update process.
  3. Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Uefi.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/BmpSupportLib.h>
  16. #include <Protocol/GraphicsOutput.h>
  17. #include <Guid/GlobalVariable.h>
  18. #include <Guid/CapsuleReport.h>
  19. #include <Guid/SystemResourceTable.h>
  20. #include <Guid/FmpCapsule.h>
  21. #include <IndustryStandard/WindowsUxCapsule.h>
  22. #define CAPSULE_HEADER_SIZE 0x20
  23. #define NESTED_CAPSULE_HEADER_SIZE SIZE_4KB
  24. #define SYSTEM_FIRMWARE_FLAG 0x50000
  25. #define DEVICE_FIRMWARE_FLAG 0x78010
  26. #define MAJOR_VERSION 1
  27. #define MINOR_VERSION 0
  28. #define MAX_CAPSULE_NUM 10
  29. extern UINTN Argc;
  30. extern CHAR16 **Argv;
  31. //
  32. // Define how many block descriptors we want to test with.
  33. //
  34. UINTN NumberOfDescriptors = 1;
  35. UINTN CapsuleFirstIndex;
  36. UINTN CapsuleLastIndex;
  37. /**
  38. Dump capsule information
  39. @param[in] CapsuleName The name of the capsule image.
  40. @retval EFI_SUCCESS The capsule information is dumped.
  41. @retval EFI_UNSUPPORTED Input parameter is not valid.
  42. **/
  43. EFI_STATUS
  44. DumpCapsule (
  45. IN CHAR16 *CapsuleName
  46. );
  47. /**
  48. Dump capsule status variable.
  49. @retval EFI_SUCCESS The capsule status variable is dumped.
  50. @retval EFI_UNSUPPORTED Input parameter is not valid.
  51. **/
  52. EFI_STATUS
  53. DumpCapsuleStatusVariable (
  54. VOID
  55. );
  56. /**
  57. Dump FMP protocol info.
  58. **/
  59. VOID
  60. DumpFmpData (
  61. VOID
  62. );
  63. /**
  64. Dump FMP image data.
  65. @param[in] ImageTypeId The ImageTypeId of the FMP image.
  66. It is used to identify the FMP protocol.
  67. @param[in] ImageIndex The ImageIndex of the FMP image.
  68. It is the input parameter for FMP->GetImage().
  69. @param[in] ImageName The file name to hold the output FMP image.
  70. **/
  71. VOID
  72. DumpFmpImage (
  73. IN EFI_GUID *ImageTypeId,
  74. IN UINTN ImageIndex,
  75. IN CHAR16 *ImageName
  76. );
  77. /**
  78. Dump ESRT info.
  79. **/
  80. VOID
  81. DumpEsrtData (
  82. VOID
  83. );
  84. /**
  85. Dump Provisioned Capsule.
  86. @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation.
  87. **/
  88. VOID
  89. DumpProvisionedCapsule (
  90. IN BOOLEAN DumpCapsuleInfo
  91. );
  92. /**
  93. Dump all EFI System Partition.
  94. **/
  95. VOID
  96. DumpAllEfiSysPartition (
  97. VOID
  98. );
  99. /**
  100. Process Capsule On Disk.
  101. @param[in] CapsuleBuffer An array of pointer to capsule images
  102. @param[in] CapsuleBufferSize An array of UINTN to capsule images size
  103. @param[in] FilePath An array of capsule images file path
  104. @param[in] Map File system mapping string
  105. @param[in] CapsuleNum The count of capsule images
  106. @retval EFI_SUCCESS Capsule on disk success.
  107. @retval others Capsule on disk fail.
  108. **/
  109. EFI_STATUS
  110. ProcessCapsuleOnDisk (
  111. IN VOID **CapsuleBuffer,
  112. IN UINTN *CapsuleBufferSize,
  113. IN CHAR16 **FilePath,
  114. IN CHAR16 *Map,
  115. IN UINTN CapsuleNum
  116. );
  117. /**
  118. Read a file.
  119. @param[in] FileName The file to be read.
  120. @param[out] BufferSize The file buffer size
  121. @param[out] Buffer The file buffer
  122. @retval EFI_SUCCESS Read file successfully
  123. @retval EFI_NOT_FOUND Shell protocol or file not found
  124. @retval others Read file failed
  125. **/
  126. EFI_STATUS
  127. ReadFileToBuffer (
  128. IN CHAR16 *FileName,
  129. OUT UINTN *BufferSize,
  130. OUT VOID **Buffer
  131. );
  132. /**
  133. Write a file.
  134. @param[in] FileName The file to be written.
  135. @param[in] BufferSize The file buffer size
  136. @param[in] Buffer The file buffer
  137. @retval EFI_SUCCESS Write file successfully
  138. @retval EFI_NOT_FOUND Shell protocol not found
  139. @retval others Write file failed
  140. **/
  141. EFI_STATUS
  142. WriteFileFromBuffer (
  143. IN CHAR16 *FileName,
  144. IN UINTN BufferSize,
  145. IN VOID *Buffer
  146. );
  147. /**
  148. This function parse application ARG.
  149. @return Status
  150. **/
  151. EFI_STATUS
  152. GetArg (
  153. VOID
  154. );
  155. /**
  156. Create UX capsule.
  157. @retval EFI_SUCCESS The capsule header is appended.
  158. @retval EFI_UNSUPPORTED Input parameter is not valid.
  159. @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule.
  160. **/
  161. EFI_STATUS
  162. CreateBmpFmp (
  163. VOID
  164. )
  165. {
  166. CHAR16 *OutputCapsuleName;
  167. VOID *BmpBuffer;
  168. UINTN FileSize;
  169. CHAR16 *BmpName;
  170. UINT8 *FullCapsuleBuffer;
  171. UINTN FullCapsuleBufferSize;
  172. EFI_DISPLAY_CAPSULE *DisplayCapsule;
  173. EFI_STATUS Status;
  174. EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
  175. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
  176. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt;
  177. UINTN GopBltSize;
  178. UINTN Height;
  179. UINTN Width;
  180. Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
  181. if (EFI_ERROR(Status)) {
  182. Print(L"CapsuleApp: NO GOP is found.\n");
  183. return EFI_UNSUPPORTED;
  184. }
  185. Info = Gop->Mode->Info;
  186. Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
  187. Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution);
  188. Print(L"VerticalResolution - %d\n", Info->VerticalResolution);
  189. // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
  190. // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight
  191. if (Argc != 5) {
  192. Print(L"CapsuleApp: Incorrect parameter count.\n");
  193. return EFI_UNSUPPORTED;
  194. }
  195. if (StrCmp(Argv[3], L"-O") != 0) {
  196. Print(L"CapsuleApp: NO output capsule name.\n");
  197. return EFI_UNSUPPORTED;
  198. }
  199. OutputCapsuleName = Argv[4];
  200. BmpBuffer = NULL;
  201. FileSize = 0;
  202. FullCapsuleBuffer = NULL;
  203. BmpName = Argv[2];
  204. Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
  205. if (EFI_ERROR(Status)) {
  206. Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
  207. goto Done;
  208. }
  209. GopBlt = NULL;
  210. Status = TranslateBmpToGopBlt (
  211. BmpBuffer,
  212. FileSize,
  213. &GopBlt,
  214. &GopBltSize,
  215. &Height,
  216. &Width
  217. );
  218. if (EFI_ERROR(Status)) {
  219. Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName);
  220. goto Done;
  221. }
  222. if (GopBlt != NULL) {
  223. FreePool (GopBlt);
  224. }
  225. Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height);
  226. if (Height > Info->VerticalResolution) {
  227. Status = EFI_INVALID_PARAMETER;
  228. Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName);
  229. goto Done;
  230. }
  231. if (Width > Info->HorizontalResolution) {
  232. Status = EFI_INVALID_PARAMETER;
  233. Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName);
  234. goto Done;
  235. }
  236. FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
  237. FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
  238. if (FullCapsuleBuffer == NULL) {
  239. Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
  240. Status = EFI_OUT_OF_RESOURCES;
  241. goto Done;
  242. }
  243. DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
  244. CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
  245. DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
  246. DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
  247. DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
  248. DisplayCapsule->ImagePayload.Version = 1;
  249. DisplayCapsule->ImagePayload.Checksum = 0;
  250. DisplayCapsule->ImagePayload.ImageType = 0; // BMP
  251. DisplayCapsule->ImagePayload.Reserved = 0;
  252. DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;
  253. //
  254. // Center the bitmap horizontally
  255. //
  256. DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2);
  257. //
  258. // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom
  259. // of bitmap at bottom of display.
  260. //
  261. DisplayCapsule->ImagePayload.OffsetY =
  262. MIN (
  263. (UINT32)(Info->VerticalResolution - Height),
  264. (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4)
  265. );
  266. Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n",
  267. BmpName,
  268. DisplayCapsule->ImagePayload.OffsetX,
  269. DisplayCapsule->ImagePayload.OffsetY
  270. );
  271. CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);
  272. DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize);
  273. Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
  274. Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
  275. Done:
  276. if (BmpBuffer != NULL) {
  277. FreePool(BmpBuffer);
  278. }
  279. if (FullCapsuleBuffer != NULL) {
  280. FreePool(FullCapsuleBuffer);
  281. }
  282. return Status;
  283. }
  284. /**
  285. Get ImageTypeId in the FMP capsule header.
  286. @param[in] CapsuleHeader The FMP capsule image header.
  287. @return ImageTypeId
  288. **/
  289. EFI_GUID *
  290. GetCapsuleImageTypeId (
  291. IN EFI_CAPSULE_HEADER *CapsuleHeader
  292. )
  293. {
  294. EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
  295. UINT64 *ItemOffsetList;
  296. EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
  297. FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
  298. ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
  299. if (FmpCapsuleHeader->PayloadItemCount == 0) {
  300. return NULL;
  301. }
  302. ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[FmpCapsuleHeader->EmbeddedDriverCount]);
  303. return &ImageHeader->UpdateImageTypeId;
  304. }
  305. /**
  306. Get ESRT FwType according to ImageTypeId
  307. @param[in] ImageTypeId ImageTypeId of an FMP capsule.
  308. @return ESRT FwType
  309. **/
  310. UINT32
  311. GetEsrtFwType (
  312. IN EFI_GUID *ImageTypeId
  313. )
  314. {
  315. EFI_STATUS Status;
  316. EFI_SYSTEM_RESOURCE_TABLE *Esrt;
  317. EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
  318. UINTN Index;
  319. //
  320. // Check ESRT
  321. //
  322. Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
  323. if (!EFI_ERROR(Status)) {
  324. ASSERT(Esrt != NULL);
  325. EsrtEntry = (VOID *)(Esrt + 1);
  326. for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
  327. if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) {
  328. return EsrtEntry->FwType;
  329. }
  330. }
  331. }
  332. return ESRT_FW_TYPE_UNKNOWN;
  333. }
  334. /**
  335. Validate if it is valid capsule header
  336. This function assumes the caller provided correct CapsuleHeader pointer
  337. and CapsuleSize.
  338. This function validates the fields in EFI_CAPSULE_HEADER.
  339. @param[in] CapsuleHeader Points to a capsule header.
  340. @param[in] CapsuleSize Size of the whole capsule image.
  341. **/
  342. BOOLEAN
  343. IsValidCapsuleHeader (
  344. IN EFI_CAPSULE_HEADER *CapsuleHeader,
  345. IN UINT64 CapsuleSize
  346. )
  347. {
  348. if (CapsuleSize < sizeof (EFI_CAPSULE_HEADER)) {
  349. return FALSE;
  350. }
  351. if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
  352. return FALSE;
  353. }
  354. if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
  355. return FALSE;
  356. }
  357. if (CapsuleHeader->HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {
  358. return FALSE;
  359. }
  360. return TRUE;
  361. }
  362. /**
  363. Return if this CapsuleGuid is a FMP capsule GUID or not.
  364. @param[in] CapsuleGuid A pointer to EFI_GUID
  365. @retval TRUE It is a FMP capsule GUID.
  366. @retval FALSE It is not a FMP capsule GUID.
  367. **/
  368. BOOLEAN
  369. IsFmpCapsuleGuid (
  370. IN EFI_GUID *CapsuleGuid
  371. )
  372. {
  373. if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
  374. return TRUE;
  375. }
  376. return FALSE;
  377. }
  378. /**
  379. Append a capsule header on top of current image.
  380. This function follows Windows UEFI Firmware Update Platform document.
  381. @retval EFI_SUCCESS The capsule header is appended.
  382. @retval EFI_UNSUPPORTED Input parameter is not valid.
  383. @retval EFI_OUT_OF_RESOURCES No enough resource to append capsule header.
  384. **/
  385. EFI_STATUS
  386. CreateNestedFmp (
  387. VOID
  388. )
  389. {
  390. CHAR16 *OutputCapsuleName;
  391. VOID *CapsuleBuffer;
  392. UINTN FileSize;
  393. CHAR16 *CapsuleName;
  394. UINT8 *FullCapsuleBuffer;
  395. UINTN FullCapsuleBufferSize;
  396. EFI_CAPSULE_HEADER *NestedCapsuleHeader;
  397. EFI_GUID *ImageTypeId;
  398. UINT32 FwType;
  399. EFI_STATUS Status;
  400. if (Argc != 5) {
  401. Print(L"CapsuleApp: Incorrect parameter count.\n");
  402. return EFI_UNSUPPORTED;
  403. }
  404. if (StrCmp(Argv[3], L"-O") != 0) {
  405. Print(L"CapsuleApp: NO output capsule name.\n");
  406. return EFI_UNSUPPORTED;
  407. }
  408. OutputCapsuleName = Argv[4];
  409. CapsuleBuffer = NULL;
  410. FileSize = 0;
  411. FullCapsuleBuffer = NULL;
  412. CapsuleName = Argv[2];
  413. Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
  414. if (EFI_ERROR(Status)) {
  415. Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
  416. goto Done;
  417. }
  418. if (!IsValidCapsuleHeader (CapsuleBuffer, FileSize)) {
  419. Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
  420. Status = EFI_INVALID_PARAMETER;
  421. goto Done;
  422. }
  423. if (!IsFmpCapsuleGuid (&((EFI_CAPSULE_HEADER *) CapsuleBuffer)->CapsuleGuid)) {
  424. Print(L"CapsuleApp: Capsule image (%s) is not a FMP capsule.\n", CapsuleName);
  425. Status = EFI_INVALID_PARAMETER;
  426. goto Done;
  427. }
  428. ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
  429. if (ImageTypeId == NULL) {
  430. Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
  431. Status = EFI_INVALID_PARAMETER;
  432. goto Done;
  433. }
  434. FwType = GetEsrtFwType(ImageTypeId);
  435. if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
  436. Print(L"CapsuleApp: Capsule FwType is invalid.\n");
  437. Status = EFI_INVALID_PARAMETER;
  438. goto Done;
  439. }
  440. FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
  441. FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
  442. if (FullCapsuleBuffer == NULL) {
  443. Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
  444. Status = EFI_OUT_OF_RESOURCES;
  445. goto Done;
  446. }
  447. NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
  448. ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
  449. CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
  450. NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
  451. NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
  452. NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;
  453. CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);
  454. Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
  455. Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);
  456. Done:
  457. if (CapsuleBuffer != NULL) {
  458. FreePool(CapsuleBuffer);
  459. }
  460. if (FullCapsuleBuffer != NULL) {
  461. FreePool(FullCapsuleBuffer);
  462. }
  463. return Status;
  464. }
  465. /**
  466. Clear capsule status variable.
  467. @retval EFI_SUCCESS The capsule status variable is cleared.
  468. **/
  469. EFI_STATUS
  470. ClearCapsuleStatusVariable (
  471. VOID
  472. )
  473. {
  474. EFI_STATUS Status;
  475. UINT32 Index;
  476. CHAR16 CapsuleVarName[20];
  477. CHAR16 *TempVarName;
  478. BOOLEAN Found;
  479. StrCpyS (CapsuleVarName, sizeof(CapsuleVarName)/sizeof(CapsuleVarName[0]), L"Capsule");
  480. TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
  481. Index = 0;
  482. Found = FALSE;
  483. while (TRUE) {
  484. UnicodeSPrint (TempVarName, 5 * sizeof(CHAR16), L"%04x", Index);
  485. Status = gRT->SetVariable (
  486. CapsuleVarName,
  487. &gEfiCapsuleReportGuid,
  488. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  489. 0,
  490. (VOID *)NULL
  491. );
  492. if (Status == EFI_NOT_FOUND) {
  493. //
  494. // There is no more capsule variables, quit
  495. //
  496. break;
  497. }
  498. Found = TRUE;
  499. Print (L"Clear %s %r\n", CapsuleVarName, Status);
  500. Index++;
  501. if (Index > 0xFFFF) {
  502. break;
  503. }
  504. }
  505. if (!Found) {
  506. Print (L"No any Capsule#### variable found\n");
  507. }
  508. return EFI_SUCCESS;
  509. }
  510. /**
  511. Build Gather list for a list of capsule images.
  512. @param[in] CapsuleBuffer An array of pointer to capsule images
  513. @param[in] FileSize An array of UINTN to capsule images size
  514. @param[in] CapsuleNum The count of capsule images
  515. @param[out] BlockDescriptors The block descriptors for the capsule images
  516. @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
  517. **/
  518. EFI_STATUS
  519. BuildGatherList (
  520. IN VOID **CapsuleBuffer,
  521. IN UINTN *FileSize,
  522. IN UINTN CapsuleNum,
  523. OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
  524. )
  525. {
  526. EFI_STATUS Status;
  527. EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1;
  528. EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors2;
  529. EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorPre;
  530. EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorsHeader;
  531. EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
  532. UINT8 *TempDataPtr;
  533. UINTN SizeLeft;
  534. UINTN Size;
  535. INT32 Count;
  536. INT32 Number;
  537. UINTN Index;
  538. TempBlockPtr = NULL;
  539. BlockDescriptors1 = NULL;
  540. BlockDescriptors2 = NULL;
  541. BlockDescriptorPre = NULL;
  542. BlockDescriptorsHeader = NULL;
  543. for (Index = 0; Index < CapsuleNum; Index++) {
  544. //
  545. // Allocate memory for the descriptors.
  546. //
  547. if (NumberOfDescriptors == 1) {
  548. Count = 2;
  549. } else {
  550. Count = (INT32)(NumberOfDescriptors + 2) / 2;
  551. }
  552. Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
  553. BlockDescriptors1 = AllocateRuntimeZeroPool (Size);
  554. if (BlockDescriptors1 == NULL) {
  555. Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
  556. Status = EFI_OUT_OF_RESOURCES;
  557. goto ERREXIT;
  558. } else {
  559. Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1);
  560. Print (L"CapsuleApp: capsule data starts at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer[Index], FileSize[Index]);
  561. }
  562. //
  563. // Record descirptor header
  564. //
  565. if (Index == 0) {
  566. BlockDescriptorsHeader = BlockDescriptors1;
  567. }
  568. if (BlockDescriptorPre != NULL) {
  569. BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
  570. BlockDescriptorPre->Length = 0;
  571. }
  572. //
  573. // Fill them in
  574. //
  575. TempBlockPtr = BlockDescriptors1;
  576. TempDataPtr = CapsuleBuffer[Index];
  577. SizeLeft = FileSize[Index];
  578. for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
  579. //
  580. // Divide remaining data in half
  581. //
  582. if (NumberOfDescriptors != 1) {
  583. if (SizeLeft == 1) {
  584. Size = 1;
  585. } else {
  586. Size = SizeLeft / 2;
  587. }
  588. } else {
  589. Size = SizeLeft;
  590. }
  591. TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
  592. TempBlockPtr->Length = Size;
  593. Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
  594. SizeLeft -= Size;
  595. TempDataPtr += Size;
  596. TempBlockPtr++;
  597. }
  598. //
  599. // Allocate the second list, point the first block's last entry to point
  600. // to this one, and fill this one in. Worst case is that the previous
  601. // list only had one element that pointed here, so we need at least two
  602. // elements -- one to point to all the data, another to terminate the list.
  603. //
  604. if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
  605. Count = (INT32)(NumberOfDescriptors + 2) - Count;
  606. if (Count == 1) {
  607. Count++;
  608. }
  609. Size = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
  610. BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
  611. if (BlockDescriptors2 == NULL) {
  612. Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
  613. Status = EFI_OUT_OF_RESOURCES;
  614. goto ERREXIT;
  615. }
  616. //
  617. // Point the first list's last element to point to this second list.
  618. //
  619. TempBlockPtr->Union.ContinuationPointer = (UINTN) BlockDescriptors2;
  620. TempBlockPtr->Length = 0;
  621. TempBlockPtr = BlockDescriptors2;
  622. for (Number = 0; Number < Count - 1; Number++) {
  623. //
  624. // If second-to-last one, then dump rest to this element
  625. //
  626. if (Number == (Count - 2)) {
  627. Size = SizeLeft;
  628. } else {
  629. //
  630. // Divide remaining data in half
  631. //
  632. if (SizeLeft == 1) {
  633. Size = 1;
  634. } else {
  635. Size = SizeLeft / 2;
  636. }
  637. }
  638. TempBlockPtr->Union.DataBlock = (UINTN)TempDataPtr;
  639. TempBlockPtr->Length = Size;
  640. Print (L"CapsuleApp: capsule block/size 0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
  641. SizeLeft -= Size;
  642. TempDataPtr += Size;
  643. TempBlockPtr++;
  644. if (SizeLeft == 0) {
  645. break;
  646. }
  647. }
  648. }
  649. BlockDescriptorPre = TempBlockPtr;
  650. BlockDescriptors1 = NULL;
  651. }
  652. //
  653. // Null-terminate.
  654. //
  655. if (TempBlockPtr != NULL) {
  656. TempBlockPtr->Union.ContinuationPointer = (UINTN)NULL;
  657. TempBlockPtr->Length = 0;
  658. *BlockDescriptors = BlockDescriptorsHeader;
  659. }
  660. return EFI_SUCCESS;
  661. ERREXIT:
  662. if (BlockDescriptors1 != NULL) {
  663. FreePool(BlockDescriptors1);
  664. }
  665. if (BlockDescriptors2 != NULL) {
  666. FreePool(BlockDescriptors2);
  667. }
  668. return Status;
  669. }
  670. /**
  671. Clear the Gather list for a list of capsule images.
  672. @param[in] BlockDescriptors The block descriptors for the capsule images
  673. @param[in] CapsuleNum The count of capsule images
  674. **/
  675. VOID
  676. CleanGatherList (
  677. IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors,
  678. IN UINTN CapsuleNum
  679. )
  680. {
  681. EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr;
  682. EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr1;
  683. EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockPtr2;
  684. UINTN Index;
  685. if (BlockDescriptors != NULL) {
  686. TempBlockPtr1 = BlockDescriptors;
  687. while (1){
  688. TempBlockPtr = TempBlockPtr1;
  689. for (Index = 0; Index < CapsuleNum; Index++) {
  690. if (TempBlockPtr[Index].Length == 0) {
  691. break;
  692. }
  693. }
  694. if (TempBlockPtr[Index].Union.ContinuationPointer == (UINTN)NULL) {
  695. break;
  696. }
  697. TempBlockPtr2 = (VOID *) ((UINTN) TempBlockPtr[Index].Union.ContinuationPointer);
  698. FreePool(TempBlockPtr1);
  699. TempBlockPtr1 = TempBlockPtr2;
  700. }
  701. }
  702. }
  703. /**
  704. Print APP usage.
  705. **/
  706. VOID
  707. PrintUsage (
  708. VOID
  709. )
  710. {
  711. Print(L"CapsuleApp: usage\n");
  712. Print(L" CapsuleApp <Capsule...> [-NR] [-OD [FSx]]\n");
  713. Print(L" CapsuleApp -S\n");
  714. Print(L" CapsuleApp -C\n");
  715. Print(L" CapsuleApp -P\n");
  716. Print(L" CapsuleApp -E\n");
  717. Print(L" CapsuleApp -L\n");
  718. Print(L" CapsuleApp -L INFO\n");
  719. Print(L" CapsuleApp -F\n");
  720. Print(L" CapsuleApp -G <BMP> -O <Capsule>\n");
  721. Print(L" CapsuleApp -N <Capsule> -O <NestedCapsule>\n");
  722. Print(L" CapsuleApp -D <Capsule>\n");
  723. Print(L" CapsuleApp -P GET <ImageTypeId> <Index> -O <FileName>\n");
  724. Print(L"Parameter:\n");
  725. Print(L" -NR: No reset will be triggered for the capsule\n");
  726. Print(L" with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET.\n");
  727. Print(L" -OD: Delivery of Capsules via file on Mass Storage device.");
  728. Print(L" -S: Dump capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
  729. Print(L" which is defined in UEFI specification.\n");
  730. Print(L" -C: Clear capsule report variable (EFI_CAPSULE_REPORT_GUID),\n");
  731. Print(L" which is defined in UEFI specification.\n");
  732. Print(L" -P: Dump UEFI FMP protocol info, or get image with specified\n");
  733. Print(L" ImageTypeId and Index (decimal format) to a file if 'GET'\n");
  734. Print(L" option is used.\n");
  735. Print(L" -E: Dump UEFI ESRT table info.\n");
  736. Print(L" -L: Dump provisioned capsule image information.\n");
  737. Print(L" -F: Dump all EFI System Partition.\n");
  738. Print(L" -G: Convert a BMP file to be an UX capsule,\n");
  739. Print(L" according to Windows Firmware Update document\n");
  740. Print(L" -N: Append a Capsule Header to an existing FMP capsule image\n");
  741. Print(L" with its ImageTypeId supported by the system,\n");
  742. Print(L" according to Windows Firmware Update document\n");
  743. Print(L" -O: Output new Capsule file name\n");
  744. Print(L" -D: Dump Capsule image header information, image payload\n");
  745. Print(L" information if it is an UX capsule and FMP header\n");
  746. Print(L" information if it is a FMP capsule.\n");
  747. }
  748. /**
  749. Update Capsule image.
  750. @param[in] ImageHandle The image handle.
  751. @param[in] SystemTable The system table.
  752. @retval EFI_SUCCESS Command completed successfully.
  753. @retval EFI_UNSUPPORTED Command usage unsupported.
  754. @retval EFI_INVALID_PARAMETER Command usage invalid.
  755. @retval EFI_NOT_FOUND The input file can't be found.
  756. **/
  757. EFI_STATUS
  758. EFIAPI
  759. UefiMain (
  760. IN EFI_HANDLE ImageHandle,
  761. IN EFI_SYSTEM_TABLE *SystemTable
  762. )
  763. {
  764. EFI_STATUS Status;
  765. RETURN_STATUS RStatus;
  766. UINTN CapsuleBufferSize[MAX_CAPSULE_NUM];
  767. VOID *CapsuleBuffer[MAX_CAPSULE_NUM];
  768. EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors;
  769. EFI_CAPSULE_HEADER *CapsuleHeaderArray[MAX_CAPSULE_NUM + 1];
  770. UINT64 MaxCapsuleSize;
  771. EFI_RESET_TYPE ResetType;
  772. BOOLEAN NeedReset;
  773. BOOLEAN NoReset;
  774. BOOLEAN CapsuleOnDisk;
  775. CHAR16 *CapsuleName;
  776. CHAR16 *CapsuleNames[MAX_CAPSULE_NUM];
  777. CHAR16 *MapFsStr;
  778. UINTN CapsuleNum;
  779. UINTN Index;
  780. UINTN ParaOdIndex;
  781. UINTN ParaNrIndex;
  782. EFI_GUID ImageTypeId;
  783. UINTN ImageIndex;
  784. BlockDescriptors = NULL;
  785. MapFsStr = NULL;
  786. CapsuleNum = 0;
  787. Status = GetArg();
  788. if (EFI_ERROR(Status)) {
  789. Print(L"Please use UEFI SHELL to run this application!\n", Status);
  790. return Status;
  791. }
  792. if (Argc < 2) {
  793. PrintUsage();
  794. return EFI_UNSUPPORTED;
  795. }
  796. if (StrCmp(Argv[1], L"-D") == 0) {
  797. if (Argc != 3) {
  798. Print(L"CapsuleApp: Incorrect parameter count.\n");
  799. return EFI_UNSUPPORTED;
  800. }
  801. Status = DumpCapsule(Argv[2]);
  802. return Status;
  803. }
  804. if (StrCmp(Argv[1], L"-G") == 0) {
  805. Status = CreateBmpFmp();
  806. return Status;
  807. }
  808. if (StrCmp(Argv[1], L"-N") == 0) {
  809. Status = CreateNestedFmp();
  810. return Status;
  811. }
  812. if (StrCmp(Argv[1], L"-S") == 0) {
  813. Status = DumpCapsuleStatusVariable();
  814. return EFI_SUCCESS;
  815. }
  816. if (StrCmp(Argv[1], L"-C") == 0) {
  817. Status = ClearCapsuleStatusVariable();
  818. return Status;
  819. }
  820. if (StrCmp(Argv[1], L"-P") == 0) {
  821. if (Argc == 2) {
  822. DumpFmpData();
  823. }
  824. if (Argc >= 3) {
  825. if (StrCmp(Argv[2], L"GET") != 0) {
  826. Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[2]);
  827. return EFI_UNSUPPORTED;
  828. } else {
  829. if (Argc != 7) {
  830. Print(L"CapsuleApp: Incorrect parameter count.\n");
  831. return EFI_UNSUPPORTED;
  832. }
  833. //
  834. // FMP->GetImage()
  835. //
  836. RStatus = StrToGuid (Argv[3], &ImageTypeId);
  837. if (RETURN_ERROR (RStatus) || (Argv[3][GUID_STRING_LENGTH] != L'\0')) {
  838. Print (L"Invalid ImageTypeId - %s\n", Argv[3]);
  839. return EFI_INVALID_PARAMETER;
  840. }
  841. ImageIndex = StrDecimalToUintn(Argv[4]);
  842. if (StrCmp(Argv[5], L"-O") != 0) {
  843. Print(L"CapsuleApp: NO output file name.\n");
  844. return EFI_UNSUPPORTED;
  845. }
  846. DumpFmpImage(&ImageTypeId, ImageIndex, Argv[6]);
  847. }
  848. }
  849. return EFI_SUCCESS;
  850. }
  851. if (StrCmp(Argv[1], L"-E") == 0) {
  852. DumpEsrtData();
  853. return EFI_SUCCESS;
  854. }
  855. if (StrCmp(Argv[1], L"-L") == 0) {
  856. if (Argc >= 3 && StrCmp(Argv[2], L"INFO") == 0) {
  857. DumpProvisionedCapsule(TRUE);
  858. } else {
  859. DumpProvisionedCapsule(FALSE);
  860. }
  861. return EFI_SUCCESS;
  862. }
  863. if (StrCmp(Argv[1], L"-F") == 0) {
  864. DumpAllEfiSysPartition();
  865. return EFI_SUCCESS;
  866. }
  867. if (Argv[1][0] == L'-') {
  868. Print(L"CapsuleApp: Unrecognized option(%s).\n", Argv[1]);
  869. return EFI_UNSUPPORTED;
  870. }
  871. CapsuleFirstIndex = 1;
  872. NoReset = FALSE;
  873. CapsuleOnDisk = FALSE;
  874. ParaOdIndex = 0;
  875. ParaNrIndex = 0;
  876. for (Index = 1; Index < Argc; Index++) {
  877. if (StrCmp(Argv[Index], L"-OD") == 0) {
  878. ParaOdIndex = Index;
  879. CapsuleOnDisk = TRUE;
  880. } else if (StrCmp(Argv[Index], L"-NR") == 0) {
  881. ParaNrIndex = Index;
  882. NoReset = TRUE;
  883. }
  884. }
  885. if (ParaOdIndex != 0) {
  886. if (ParaOdIndex == Argc - 1) {
  887. MapFsStr = NULL;
  888. } else if (ParaOdIndex == Argc - 2) {
  889. MapFsStr = Argv[Argc-1];
  890. } else {
  891. Print (L"CapsuleApp: Invalid Position for -OD Options\n");
  892. Status = EFI_INVALID_PARAMETER;
  893. goto Done;
  894. }
  895. if (ParaNrIndex != 0) {
  896. if (ParaNrIndex + 1 == ParaOdIndex) {
  897. CapsuleLastIndex = ParaNrIndex - 1;
  898. } else {
  899. Print (L"CapsuleApp: Invalid Position for -NR Options\n");
  900. Status = EFI_INVALID_PARAMETER;
  901. goto Done;
  902. }
  903. } else {
  904. CapsuleLastIndex = ParaOdIndex - 1;
  905. }
  906. } else {
  907. if (ParaNrIndex != 0) {
  908. if (ParaNrIndex == Argc -1) {
  909. CapsuleLastIndex = ParaNrIndex - 1;
  910. } else {
  911. Print (L"CapsuleApp: Invalid Position for -NR Options\n");
  912. Status = EFI_INVALID_PARAMETER;
  913. goto Done;
  914. }
  915. } else {
  916. CapsuleLastIndex = Argc - 1;
  917. }
  918. }
  919. CapsuleNum = CapsuleLastIndex - CapsuleFirstIndex + 1;
  920. if (CapsuleFirstIndex > CapsuleLastIndex) {
  921. Print(L"CapsuleApp: NO capsule image.\n");
  922. return EFI_UNSUPPORTED;
  923. }
  924. if (CapsuleNum > MAX_CAPSULE_NUM) {
  925. Print(L"CapsuleApp: Too many capsule images.\n");
  926. return EFI_UNSUPPORTED;
  927. }
  928. ZeroMem(&CapsuleBuffer, sizeof(CapsuleBuffer));
  929. ZeroMem(&CapsuleBufferSize, sizeof(CapsuleBufferSize));
  930. BlockDescriptors = NULL;
  931. for (Index = 0; Index < CapsuleNum; Index++) {
  932. CapsuleName = Argv[CapsuleFirstIndex + Index];
  933. Status = ReadFileToBuffer(CapsuleName, &CapsuleBufferSize[Index], &CapsuleBuffer[Index]);
  934. if (EFI_ERROR(Status)) {
  935. Print(L"CapsuleApp: capsule image (%s) is not found.\n", CapsuleName);
  936. goto Done;
  937. }
  938. if (!IsValidCapsuleHeader (CapsuleBuffer[Index], CapsuleBufferSize[Index])) {
  939. Print(L"CapsuleApp: Capsule image (%s) is not a valid capsule.\n", CapsuleName);
  940. return EFI_INVALID_PARAMETER;
  941. }
  942. CapsuleNames[Index] = CapsuleName;
  943. }
  944. //
  945. // Every capsule use 2 descriptor 1 for data 1 for end
  946. //
  947. Status = BuildGatherList(CapsuleBuffer, CapsuleBufferSize, CapsuleNum, &BlockDescriptors);
  948. if (EFI_ERROR(Status)) {
  949. goto Done;
  950. }
  951. //
  952. // Call the runtime service capsule.
  953. //
  954. NeedReset = FALSE;
  955. for (Index = 0; Index < CapsuleNum; Index++) {
  956. CapsuleHeaderArray[Index] = (EFI_CAPSULE_HEADER *) CapsuleBuffer[Index];
  957. if ((CapsuleHeaderArray[Index]->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
  958. NeedReset = TRUE;
  959. }
  960. }
  961. CapsuleHeaderArray[CapsuleNum] = NULL;
  962. //
  963. // Inquire platform capability of UpdateCapsule.
  964. //
  965. Status = gRT->QueryCapsuleCapabilities (CapsuleHeaderArray, CapsuleNum, &MaxCapsuleSize, &ResetType);
  966. if (EFI_ERROR(Status)) {
  967. Print (L"CapsuleApp: failed to query capsule capability - %r\n", Status);
  968. goto Done;
  969. }
  970. for (Index = 0; Index < CapsuleNum; Index++) {
  971. if (CapsuleBufferSize[Index] > MaxCapsuleSize) {
  972. Print (L"CapsuleApp: capsule is too large to update, %ld is allowed\n", MaxCapsuleSize);
  973. Status = EFI_UNSUPPORTED;
  974. goto Done;
  975. }
  976. }
  977. //
  978. // Check whether is capsule on disk.
  979. //
  980. if (CapsuleOnDisk) {
  981. Status = ProcessCapsuleOnDisk (CapsuleBuffer, CapsuleBufferSize, CapsuleNames, MapFsStr, CapsuleNum);
  982. if (Status != EFI_SUCCESS) {
  983. Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
  984. goto Done;
  985. } else {
  986. if (!NoReset) {
  987. gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
  988. } else {
  989. goto Done;
  990. }
  991. }
  992. }
  993. //
  994. // Check whether the input capsule image has the flag of persist across system reset.
  995. //
  996. if (NeedReset) {
  997. Status = gRT->UpdateCapsule(CapsuleHeaderArray,CapsuleNum,(UINTN) BlockDescriptors);
  998. if (Status != EFI_SUCCESS) {
  999. Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
  1000. goto Done;
  1001. }
  1002. //
  1003. // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET + CAPSULE_FLAGS_INITIATE_RESET,
  1004. // a system reset should have been triggered by gRT->UpdateCapsule() calling above.
  1005. //
  1006. // For capsule with CAPSULE_FLAGS_PERSIST_ACROSS_RESET and without CAPSULE_FLAGS_INITIATE_RESET,
  1007. // check if -NR (no-reset) has been specified or not.
  1008. //
  1009. if (!NoReset) {
  1010. //
  1011. // For capsule who has reset flag and no -NR (no-reset) has been specified, after calling UpdateCapsule service,
  1012. // trigger a system reset to process capsule persist across a system reset.
  1013. //
  1014. gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
  1015. }
  1016. } else {
  1017. //
  1018. // For capsule who has no reset flag, only call UpdateCapsule Service without a
  1019. // system reset. The service will process the capsule immediately.
  1020. //
  1021. Status = gRT->UpdateCapsule (CapsuleHeaderArray,CapsuleNum,(UINTN) BlockDescriptors);
  1022. if (Status != EFI_SUCCESS) {
  1023. Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
  1024. }
  1025. }
  1026. Status = EFI_SUCCESS;
  1027. Done:
  1028. for (Index = 0; Index < CapsuleNum; Index++) {
  1029. if (CapsuleBuffer[Index] != NULL) {
  1030. FreePool (CapsuleBuffer[Index]);
  1031. }
  1032. }
  1033. CleanGatherList(BlockDescriptors, CapsuleNum);
  1034. return Status;
  1035. }