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