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