2 The logic to process capsule.
4 Caution: This module requires additional review when modified.
5 This driver will have external input - capsule image.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 CapsuleDataCoalesce() will do basic validation before coalesce capsule data
12 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
13 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
14 SPDX-License-Identifier: BSD-2-Clause-Patent
21 #include <Guid/CapsuleVendor.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/PrintLib.h>
26 #include <Library/BaseLib.h>
28 #include "CommonHeader.h"
30 #define MIN_COALESCE_ADDR (1024 * 1024)
33 Given a pointer to the capsule block list, info on the available system
34 memory, and the size of a buffer, find a free block of memory where a
35 buffer of the given size can be copied to safely.
37 @param BlockList Pointer to head of capsule block descriptors
38 @param MemBase Pointer to the base of memory in which we want to find free space
39 @param MemSize The size of the block of memory pointed to by MemBase
40 @param DataSize How big a free block we want to find
42 @return A pointer to a memory block of at least DataSize that lies somewhere
43 between MemBase and (MemBase + MemSize). The memory pointed to does not
44 contain any of the capsule block descriptors or capsule blocks pointed to
50 EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
,
57 The capsule block descriptors may be fragmented and spread all over memory.
58 To simplify the coalescing of capsule blocks, first coalesce all the
59 capsule block descriptors low in memory.
61 The descriptors passed in can be fragmented throughout memory. Here
62 they are relocated into memory to turn them into a contiguous (null
65 @param PeiServices pointer to PEI services table
66 @param BlockList pointer to the capsule block descriptors
67 @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
68 @param MemBase base of system memory in which we can work
69 @param MemSize size of the system memory pointed to by MemBase
71 @retval NULL could not relocate the descriptors
72 @retval Pointer to the base of the successfully-relocated block descriptors.
75 EFI_CAPSULE_BLOCK_DESCRIPTOR
*
76 RelocateBlockDescriptors (
77 IN EFI_PEI_SERVICES
**PeiServices
,
78 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
,
79 IN UINTN NumDescriptors
,
85 Check every capsule header.
87 @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
89 @retval FALSE Capsule is OK
90 @retval TRUE Capsule is corrupted
95 IN EFI_CAPSULE_HEADER
*CapsuleHeader
99 Determine if two buffers overlap in memory.
101 @param Buff1 pointer to first buffer
102 @param Size1 size of Buff1
103 @param Buff2 pointer to second buffer
104 @param Size2 size of Buff2
106 @retval TRUE Buffers overlap in memory.
107 @retval FALSE Buffer doesn't overlap.
119 Given a pointer to a capsule block descriptor, traverse the list to figure
120 out how many legitimate descriptors there are, and how big the capsule it
123 @param Desc Pointer to the capsule block descriptors
124 @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
125 @param CapsuleSize Optional pointer to where to return the capsule image size
126 @param CapsuleNumber Optional pointer to where to return the number of capsule
128 @retval EFI_NOT_FOUND No descriptors containing data in the list
129 @retval EFI_SUCCESS Return data is valid
134 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*Desc
,
135 IN OUT UINTN
*NumDescriptors OPTIONAL
,
136 IN OUT UINTN
*CapsuleSize OPTIONAL
,
137 IN OUT UINTN
*CapsuleNumber OPTIONAL
141 Given a pointer to the capsule block list, info on the available system
142 memory, and the size of a buffer, find a free block of memory where a
143 buffer of the given size can be copied to safely.
145 @param BlockList Pointer to head of capsule block descriptors
146 @param MemBase Pointer to the base of memory in which we want to find free space
147 @param MemSize The size of the block of memory pointed to by MemBase
148 @param DataSize How big a free block we want to find
150 @return A pointer to a memory block of at least DataSize that lies somewhere
151 between MemBase and (MemBase + MemSize). The memory pointed to does not
152 contain any of the capsule block descriptors or capsule blocks pointed to
158 EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
,
165 EFI_CAPSULE_BLOCK_DESCRIPTOR
*CurrDesc
;
166 EFI_CAPSULE_BLOCK_DESCRIPTOR
*TempDesc
;
171 // Need at least enough to copy the data to at the end of the buffer, so
172 // say the end is less the data size for easy comparisons here.
174 MemEnd
= MemBase
+ MemSize
- DataSize
;
175 CurrDesc
= BlockList
;
177 // Go through all the descriptor blocks and see if any obstruct the range
179 while (CurrDesc
!= NULL
) {
181 // Get the size of this block list and see if it's in the way
185 Size
= sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
186 while (TempDesc
->Length
!= 0) {
187 Size
+= sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
191 if (IsOverlapped (MemBase
, DataSize
, (UINT8
*) CurrDesc
, Size
)) {
193 // Set our new base to the end of this block list and start all over
195 MemBase
= (UINT8
*) CurrDesc
+ Size
;
196 CurrDesc
= BlockList
;
197 if (MemBase
> MemEnd
) {
204 // Now go through all the blocks and make sure none are in the way
206 while ((CurrDesc
->Length
!= 0) && (!Failed
)) {
207 if (IsOverlapped (MemBase
, DataSize
, (UINT8
*) (UINTN
) CurrDesc
->Union
.DataBlock
, (UINTN
) CurrDesc
->Length
)) {
209 // Set our new base to the end of this block and start all over
212 MemBase
= (UINT8
*) ((UINTN
) CurrDesc
->Union
.DataBlock
) + CurrDesc
->Length
;
213 CurrDesc
= BlockList
;
214 if (MemBase
> MemEnd
) {
221 // Normal continuation -- jump to next block descriptor list
224 CurrDesc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) CurrDesc
->Union
.ContinuationPointer
;
231 Validate capsule by MemoryResource.
233 @param MemoryResource Pointer to the buffer of memory resource descriptor.
234 @param Address Address to be validated.
235 @param Size Size to be validated.
237 @retval TRUE No memory resource descriptor reported in HOB list before capsule Coalesce,
238 or it is valid in one MemoryResource.
239 FALSE It is not in any MemoryResource.
243 ValidateCapsuleByMemoryResource (
244 IN MEMORY_RESOURCE_DESCRIPTOR
*MemoryResource
,
245 IN EFI_PHYSICAL_ADDRESS Address
,
254 if (Size
> MAX_ADDRESS
) {
255 DEBUG ((DEBUG_ERROR
, "ERROR: Size(0x%lx) > MAX_ADDRESS\n", Size
));
262 if (Address
> (MAX_ADDRESS
- Size
)) {
263 DEBUG ((DEBUG_ERROR
, "ERROR: Address(0x%lx) > (MAX_ADDRESS - Size(0x%lx))\n", Address
, Size
));
267 if (MemoryResource
== NULL
) {
269 // No memory resource descriptor reported in HOB list before capsule Coalesce.
274 for (Index
= 0; MemoryResource
[Index
].ResourceLength
!= 0; Index
++) {
275 if ((Address
>= MemoryResource
[Index
].PhysicalStart
) &&
276 ((Address
+ Size
) <= (MemoryResource
[Index
].PhysicalStart
+ MemoryResource
[Index
].ResourceLength
))) {
277 DEBUG ((DEBUG_INFO
, "Address(0x%lx) Size(0x%lx) in MemoryResource[0x%x] - Start(0x%lx) Length(0x%lx)\n",
279 Index
, MemoryResource
[Index
].PhysicalStart
, MemoryResource
[Index
].ResourceLength
));
284 DEBUG ((DEBUG_ERROR
, "ERROR: Address(0x%lx) Size(0x%lx) not in any MemoryResource\n", Address
, Size
));
289 Check the integrity of the capsule descriptors.
291 @param BlockList Pointer to the capsule descriptors
292 @param MemoryResource Pointer to the buffer of memory resource descriptor.
294 @retval NULL BlockList is not valid.
295 @retval LastBlockDesc Last one Block in BlockList
298 EFI_CAPSULE_BLOCK_DESCRIPTOR
*
299 ValidateCapsuleIntegrity (
300 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
,
301 IN MEMORY_RESOURCE_DESCRIPTOR
*MemoryResource
304 EFI_CAPSULE_HEADER
*CapsuleHeader
;
307 EFI_CAPSULE_BLOCK_DESCRIPTOR
*Ptr
;
309 DEBUG ((DEBUG_INFO
, "ValidateCapsuleIntegrity\n"));
312 // Go through the list to look for inconsistencies. Check for:
313 // * misaligned block descriptors.
314 // * The first capsule header guid
315 // * The first capsule header flag
316 // * The first capsule header HeaderSize
317 // * Below check will be done in ValidateCapsuleByMemoryResource()
318 // Length > MAX_ADDRESS
319 // Ptr + sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR) > MAX_ADDRESS
320 // DataBlock + Length > MAX_ADDRESS
326 if (!ValidateCapsuleByMemoryResource (MemoryResource
, (EFI_PHYSICAL_ADDRESS
) (UINTN
) Ptr
, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
))) {
330 DEBUG ((DEBUG_INFO
, "Ptr - 0x%x\n", Ptr
));
331 DEBUG ((DEBUG_INFO
, "Ptr->Length - 0x%x\n", Ptr
->Length
));
332 DEBUG ((DEBUG_INFO
, "Ptr->Union - 0x%x\n", Ptr
->Union
.ContinuationPointer
));
333 while ((Ptr
->Length
!= 0) || (Ptr
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
335 // Make sure the descriptor is aligned at UINT64 in memory
337 if ((UINTN
) Ptr
& (sizeof(UINT64
) - 1)) {
338 DEBUG ((DEBUG_ERROR
, "ERROR: BlockList address failed alignment check\n"));
342 if (Ptr
->Length
== 0) {
344 // Descriptor points to another list of block descriptors somewhere
347 Ptr
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) Ptr
->Union
.ContinuationPointer
;
348 if (!ValidateCapsuleByMemoryResource (MemoryResource
, (EFI_PHYSICAL_ADDRESS
) (UINTN
) Ptr
, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
))) {
351 DEBUG ((DEBUG_INFO
, "Ptr(C) - 0x%x\n", Ptr
));
352 DEBUG ((DEBUG_INFO
, "Ptr->Length - 0x%x\n", Ptr
->Length
));
353 DEBUG ((DEBUG_INFO
, "Ptr->Union - 0x%x\n", Ptr
->Union
.ContinuationPointer
));
355 if (!ValidateCapsuleByMemoryResource (MemoryResource
, Ptr
->Union
.DataBlock
, Ptr
->Length
)) {
360 //To enhance the reliability of check-up, the first capsule's header is checked here.
361 //More reliabilities check-up will do later.
363 if (CapsuleSize
== 0) {
365 //Move to the first capsule to check its header.
367 CapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINTN
)Ptr
->Union
.DataBlock
);
371 if (Ptr
->Length
< sizeof(EFI_CAPSULE_HEADER
)) {
372 DEBUG ((DEBUG_ERROR
, "ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr
->Length
));
376 // Make sure HeaderSize field is valid
378 if (CapsuleHeader
->HeaderSize
> CapsuleHeader
->CapsuleImageSize
) {
379 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader
->HeaderSize
, CapsuleHeader
->CapsuleImageSize
));
382 if (IsCapsuleCorrupted (CapsuleHeader
)) {
386 CapsuleSize
= CapsuleHeader
->CapsuleImageSize
;
389 if (CapsuleSize
>= Ptr
->Length
) {
390 CapsuleSize
= CapsuleSize
- Ptr
->Length
;
392 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize
, Ptr
->Length
));
400 // Move to next BLOCK descriptor
403 if (!ValidateCapsuleByMemoryResource (MemoryResource
, (EFI_PHYSICAL_ADDRESS
) (UINTN
) Ptr
, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
))) {
406 DEBUG ((DEBUG_INFO
, "Ptr(B) - 0x%x\n", Ptr
));
407 DEBUG ((DEBUG_INFO
, "Ptr->Length - 0x%x\n", Ptr
->Length
));
408 DEBUG ((DEBUG_INFO
, "Ptr->Union - 0x%x\n", Ptr
->Union
.ContinuationPointer
));
412 if (CapsuleCount
== 0) {
414 // No any capsule is found in BlockList
416 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount
));
420 if (CapsuleSize
!= 0) {
422 // Capsule data is incomplete.
424 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize
));
432 The capsule block descriptors may be fragmented and spread all over memory.
433 To simplify the coalescing of capsule blocks, first coalesce all the
434 capsule block descriptors low in memory.
436 The descriptors passed in can be fragmented throughout memory. Here
437 they are relocated into memory to turn them into a contiguous (null
440 @param PeiServices pointer to PEI services table
441 @param BlockList pointer to the capsule block descriptors
442 @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
443 @param MemBase base of system memory in which we can work
444 @param MemSize size of the system memory pointed to by MemBase
446 @retval NULL could not relocate the descriptors
447 @retval Pointer to the base of the successfully-relocated block descriptors.
450 EFI_CAPSULE_BLOCK_DESCRIPTOR
*
451 RelocateBlockDescriptors (
452 IN EFI_PEI_SERVICES
**PeiServices
,
453 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
,
454 IN UINTN NumDescriptors
,
459 EFI_CAPSULE_BLOCK_DESCRIPTOR
*NewBlockList
;
460 EFI_CAPSULE_BLOCK_DESCRIPTOR
*CurrBlockDescHead
;
461 EFI_CAPSULE_BLOCK_DESCRIPTOR
*TempBlockDesc
;
462 EFI_CAPSULE_BLOCK_DESCRIPTOR
*PrevBlockDescTail
;
468 // Get the info on the blocks and descriptors. Since we're going to move
469 // the descriptors low in memory, adjust the base/size values accordingly here.
470 // NumDescriptors is the number of legit data descriptors, so add one for
471 // a terminator. (Already done by caller, no check is needed.)
474 BufferSize
= NumDescriptors
* sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
475 NewBlockList
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) MemBase
;
476 if (MemSize
< BufferSize
) {
480 MemSize
-= BufferSize
;
481 MemBase
+= BufferSize
;
483 // Go through all the blocks and make sure none are in the way
485 TempBlockDesc
= BlockList
;
486 while (TempBlockDesc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
) {
487 if (TempBlockDesc
->Length
== 0) {
489 // Next block of descriptors
491 TempBlockDesc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) TempBlockDesc
->Union
.ContinuationPointer
;
494 // If the capsule data pointed to by this descriptor is in the way,
498 (UINT8
*) NewBlockList
,
500 (UINT8
*) (UINTN
) TempBlockDesc
->Union
.DataBlock
,
501 (UINTN
) TempBlockDesc
->Length
504 // Relocate the block
506 RelocBuffer
= FindFreeMem (BlockList
, MemBase
, MemSize
, (UINTN
) TempBlockDesc
->Length
);
507 if (RelocBuffer
== NULL
) {
511 CopyMem ((VOID
*) RelocBuffer
, (VOID
*) (UINTN
) TempBlockDesc
->Union
.DataBlock
, (UINTN
) TempBlockDesc
->Length
);
512 DEBUG ((DEBUG_INFO
, "Capsule relocate descriptors from/to/size 0x%lX 0x%lX 0x%lX\n", TempBlockDesc
->Union
.DataBlock
, (UINT64
)(UINTN
)RelocBuffer
, TempBlockDesc
->Length
));
513 TempBlockDesc
->Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) RelocBuffer
;
519 // Now go through all the block descriptors to make sure that they're not
520 // in the memory region we want to copy them to.
522 CurrBlockDescHead
= BlockList
;
523 PrevBlockDescTail
= NULL
;
524 while ((CurrBlockDescHead
!= NULL
) && (CurrBlockDescHead
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
526 // Get the size of this list then see if it overlaps our low region
528 TempBlockDesc
= CurrBlockDescHead
;
529 BlockListSize
= sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
530 while (TempBlockDesc
->Length
!= 0) {
531 BlockListSize
+= sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
536 (UINT8
*) NewBlockList
,
538 (UINT8
*) CurrBlockDescHead
,
542 // Overlaps, so move it out of the way
544 RelocBuffer
= FindFreeMem (BlockList
, MemBase
, MemSize
, BlockListSize
);
545 if (RelocBuffer
== NULL
) {
548 CopyMem ((VOID
*) RelocBuffer
, (VOID
*) CurrBlockDescHead
, BlockListSize
);
549 DEBUG ((DEBUG_INFO
, "Capsule reloc descriptor block #2\n"));
551 // Point the previous block's next point to this copied version. If
552 // the tail pointer is null, then this is the first descriptor block.
554 if (PrevBlockDescTail
== NULL
) {
555 BlockList
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) RelocBuffer
;
557 PrevBlockDescTail
->Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) RelocBuffer
;
561 // Save our new tail and jump to the next block list
563 PrevBlockDescTail
= TempBlockDesc
;
564 CurrBlockDescHead
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) TempBlockDesc
->Union
.ContinuationPointer
;
567 // Cleared out low memory. Now copy the descriptors down there.
569 TempBlockDesc
= BlockList
;
570 CurrBlockDescHead
= NewBlockList
;
571 while ((TempBlockDesc
!= NULL
) && (TempBlockDesc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
572 if (TempBlockDesc
->Length
!= 0) {
573 CurrBlockDescHead
->Union
.DataBlock
= TempBlockDesc
->Union
.DataBlock
;
574 CurrBlockDescHead
->Length
= TempBlockDesc
->Length
;
578 TempBlockDesc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) TempBlockDesc
->Union
.ContinuationPointer
;
584 CurrBlockDescHead
->Union
.ContinuationPointer
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
;
585 CurrBlockDescHead
->Length
= 0;
590 Determine if two buffers overlap in memory.
592 @param Buff1 pointer to first buffer
593 @param Size1 size of Buff1
594 @param Buff2 pointer to second buffer
595 @param Size2 size of Buff2
597 @retval TRUE Buffers overlap in memory.
598 @retval FALSE Buffer doesn't overlap.
610 // If buff1's end is less than the start of buff2, then it's ok.
611 // Also, if buff1's start is beyond buff2's end, then it's ok.
613 if (((Buff1
+ Size1
) <= Buff2
) || (Buff1
>= (Buff2
+ Size2
))) {
621 Given a pointer to a capsule block descriptor, traverse the list to figure
622 out how many legitimate descriptors there are, and how big the capsule it
625 @param Desc Pointer to the capsule block descriptors
626 @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
627 @param CapsuleSize Optional pointer to where to return the capsule image size
628 @param CapsuleNumber Optional pointer to where to return the number of capsule
630 @retval EFI_NOT_FOUND No descriptors containing data in the list
631 @retval EFI_SUCCESS Return data is valid
636 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*Desc
,
637 IN OUT UINTN
*NumDescriptors OPTIONAL
,
638 IN OUT UINTN
*CapsuleSize OPTIONAL
,
639 IN OUT UINTN
*CapsuleNumber OPTIONAL
645 UINTN ThisCapsuleImageSize
;
646 EFI_CAPSULE_HEADER
*CapsuleHeader
;
648 DEBUG ((DEBUG_INFO
, "GetCapsuleInfo enter\n"));
650 ASSERT (Desc
!= NULL
);
655 ThisCapsuleImageSize
= 0;
657 while (Desc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
) {
658 if (Desc
->Length
== 0) {
660 // Descriptor points to another list of block descriptors somewhere
662 Desc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) Desc
->Union
.ContinuationPointer
;
666 // It is needed, because ValidateCapsuleIntegrity() only validate one individual capsule Size.
667 // While here we need check all capsules size.
669 if (Desc
->Length
>= (MAX_ADDRESS
- Size
)) {
670 DEBUG ((DEBUG_ERROR
, "ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc
->Length
, Size
));
671 return EFI_OUT_OF_RESOURCES
;
673 Size
+= (UINTN
) Desc
->Length
;
677 // See if this is first capsule's header
679 if (ThisCapsuleImageSize
== 0) {
680 CapsuleHeader
= (EFI_CAPSULE_HEADER
*)((UINTN
)Desc
->Union
.DataBlock
);
682 // This has been checked in ValidateCapsuleIntegrity()
685 ThisCapsuleImageSize
= CapsuleHeader
->CapsuleImageSize
;
689 // This has been checked in ValidateCapsuleIntegrity()
691 ASSERT (ThisCapsuleImageSize
>= Desc
->Length
);
692 ThisCapsuleImageSize
= (UINTN
)(ThisCapsuleImageSize
- Desc
->Length
);
701 // If no descriptors, then fail
704 DEBUG ((DEBUG_ERROR
, "ERROR: Count == 0\n"));
705 return EFI_NOT_FOUND
;
709 // checked in ValidateCapsuleIntegrity()
711 ASSERT (ThisCapsuleImageSize
== 0);
713 if (NumDescriptors
!= NULL
) {
714 *NumDescriptors
= Count
;
717 if (CapsuleSize
!= NULL
) {
721 if (CapsuleNumber
!= NULL
) {
722 *CapsuleNumber
= Number
;
729 Check every capsule header.
731 @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
733 @retval FALSE Capsule is OK
734 @retval TRUE Capsule is corrupted
739 IN EFI_CAPSULE_HEADER
*CapsuleHeader
743 //A capsule to be updated across a system reset should contain CAPSULE_FLAGS_PERSIST_ACROSS_RESET.
745 if ((CapsuleHeader
->Flags
& CAPSULE_FLAGS_PERSIST_ACROSS_RESET
) == 0) {
749 //Make sure the flags combination is supported by the platform.
751 if ((CapsuleHeader
->Flags
& (CAPSULE_FLAGS_PERSIST_ACROSS_RESET
| CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
) {
754 if ((CapsuleHeader
->Flags
& (CAPSULE_FLAGS_PERSIST_ACROSS_RESET
| CAPSULE_FLAGS_INITIATE_RESET
)) == CAPSULE_FLAGS_INITIATE_RESET
) {
762 Try to verify the integrity of a capsule test pattern before the
763 capsule gets coalesced. This can be useful in narrowing down
764 where capsule data corruption occurs.
766 The test pattern mode fills in memory with a counting UINT32 value.
767 If the capsule is not divided up in a multiple of 4-byte blocks, then
768 things get messy doing the check. Therefore there are some cases
769 here where we just give up and skip the pre-coalesce check.
771 @param PeiServices PEI services table
772 @param Desc Pointer to capsule descriptors
775 CapsuleTestPatternPreCoalesce (
776 IN EFI_PEI_SERVICES
**PeiServices
,
777 IN EFI_CAPSULE_BLOCK_DESCRIPTOR
*Desc
784 DEBUG ((DEBUG_INFO
, "CapsuleTestPatternPreCoalesce\n"));
787 // Find first data descriptor
789 while ((Desc
->Length
== 0) && (Desc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
790 Desc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) Desc
->Union
.ContinuationPointer
;
793 if (Desc
->Union
.ContinuationPointer
== 0) {
797 // First one better be long enough to at least hold the test signature
799 if (Desc
->Length
< sizeof (UINT32
)) {
800 DEBUG ((DEBUG_INFO
, "Capsule test pattern pre-coalesce punted #1\n"));
804 TestPtr
= (UINT32
*) (UINTN
) Desc
->Union
.DataBlock
;
808 if (*TestPtr
!= 0x54534554) {
813 TestSize
= (UINT32
) Desc
->Length
- 2 * sizeof (UINT32
);
815 // Skip over the signature and the size fields in the pattern data header
819 if ((TestSize
& 0x03) != 0) {
820 DEBUG ((DEBUG_INFO
, "Capsule test pattern pre-coalesce punted #2\n"));
824 while (TestSize
> 0) {
825 if (*TestPtr
!= TestCounter
) {
826 DEBUG ((DEBUG_INFO
, "Capsule test pattern pre-coalesce failed data corruption check\n"));
830 TestSize
-= sizeof (UINT32
);
835 while ((Desc
->Length
== 0) && (Desc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
836 Desc
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*) (UINTN
) Desc
->Union
.ContinuationPointer
;
839 if (Desc
->Union
.ContinuationPointer
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
) {
842 TestSize
= (UINT32
) Desc
->Length
;
843 TestPtr
= (UINT32
*) (UINTN
) Desc
->Union
.DataBlock
;
848 Checks for the presence of capsule descriptors.
849 Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
851 @param BlockListBuffer Pointer to the buffer of capsule descriptors variables
852 @param MemoryResource Pointer to the buffer of memory resource descriptor.
853 @param BlockDescriptorList Pointer to the capsule descriptors list
855 @retval EFI_SUCCESS a valid capsule is present
856 @retval EFI_NOT_FOUND if a valid capsule is not present
859 BuildCapsuleDescriptors (
860 IN EFI_PHYSICAL_ADDRESS
*BlockListBuffer
,
861 IN MEMORY_RESOURCE_DESCRIPTOR
*MemoryResource
,
862 OUT EFI_CAPSULE_BLOCK_DESCRIPTOR
**BlockDescriptorList
866 EFI_CAPSULE_BLOCK_DESCRIPTOR
*LastBlock
;
867 EFI_CAPSULE_BLOCK_DESCRIPTOR
*TempBlock
;
868 EFI_CAPSULE_BLOCK_DESCRIPTOR
*HeadBlock
;
870 DEBUG ((DEBUG_INFO
, "BuildCapsuleDescriptors enter\n"));
877 while (BlockListBuffer
[Index
] != 0) {
879 // Test integrity of descriptors.
881 if (BlockListBuffer
[Index
] < MAX_ADDRESS
) {
882 TempBlock
= ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR
*)(UINTN
)BlockListBuffer
[Index
], MemoryResource
);
883 if (TempBlock
!= NULL
) {
884 if (LastBlock
== NULL
) {
885 LastBlock
= TempBlock
;
888 // Return the base of the block descriptors
890 HeadBlock
= (EFI_CAPSULE_BLOCK_DESCRIPTOR
*)(UINTN
)BlockListBuffer
[Index
];
893 // Combine the different BlockList into single BlockList.
895 LastBlock
->Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)BlockListBuffer
[Index
];
896 LastBlock
->Length
= 0;
897 LastBlock
= TempBlock
;
901 DEBUG ((DEBUG_ERROR
, "ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer
[Index
]));
906 if (HeadBlock
!= NULL
) {
907 *BlockDescriptorList
= HeadBlock
;
910 return EFI_NOT_FOUND
;
914 The function to coalesce a fragmented capsule in memory.
916 Memory Map for coalesced capsule:
917 MemBase + ---->+---------------------------+<-----------+
918 MemSize | ------------------------- | |
919 | | Capsule [Num-1] | | |
920 | ------------------------- | |
921 | | ................ | | |
922 | ------------------------- | |
923 | | Capsule [1] | | |
924 | ------------------------- | |
925 | | Capsule [0] | | |
926 | ------------------------- | |
928 CapsuleImageBase-->+---------------------------+
929 | ------------------------- | |
930 | | CapsuleOffset[Num-1] | | |
931 | ------------------------- | |
932 | | ................ | | CapsuleSize
933 | ------------------------- | |
934 | | CapsuleOffset[1] | | |
935 | ------------------------- | |
936 | | CapsuleOffset[0] | | |
937 |---------------------------| |
938 | | CapsuleNumber | | |
939 | ------------------------- | |
940 | | CapsuleAllImageSize | | |
941 | ------------------------- | |
943 DestPtr ---->+---------------------------+<-----------+
945 | FreeMem | FreeMemSize
947 FreeMemBase --->+---------------------------+<-----------+
949 +---------------------------+
950 | BlockDescriptor n |
951 +---------------------------+
952 | ................. |
953 +---------------------------+
954 | BlockDescriptor 1 |
955 +---------------------------+
956 | BlockDescriptor 0 |
957 +---------------------------+
958 | PrivateDataDesc 0 |
959 MemBase ---->+---------------------------+<----- BlockList
961 Caution: This function may receive untrusted input.
962 The capsule data is external input, so this routine will do basic validation before
963 coalesce capsule data into memory.
965 @param PeiServices General purpose services available to every PEIM.
966 @param BlockListBuffer Pointer to the buffer of Capsule Descriptor Variables.
967 @param MemoryResource Pointer to the buffer of memory resource descriptor.
968 @param MemoryBase Pointer to the base of a block of memory that we can walk
969 all over while trying to coalesce our buffers.
970 On output, this variable will hold the base address of
972 @param MemorySize Size of the memory region pointed to by MemoryBase.
973 On output, this variable will contain the size of the
976 @retval EFI_NOT_FOUND If we could not find the capsule descriptors.
978 @retval EFI_BUFFER_TOO_SMALL
979 If we could not coalesce the capsule in the memory
980 region provided to us.
982 @retval EFI_SUCCESS Processed the capsule successfully.
986 CapsuleDataCoalesce (
987 IN EFI_PEI_SERVICES
**PeiServices
,
988 IN EFI_PHYSICAL_ADDRESS
*BlockListBuffer
,
989 IN MEMORY_RESOURCE_DESCRIPTOR
*MemoryResource
,
990 IN OUT VOID
**MemoryBase
,
991 IN OUT UINTN
*MemorySize
994 VOID
*NewCapsuleBase
;
995 VOID
*CapsuleImageBase
;
1003 UINT64 CapsuleImageSize
;
1005 UINTN CapsuleNumber
;
1006 UINTN DescriptorsSize
;
1008 UINTN NumDescriptors
;
1009 BOOLEAN CapsuleBeginFlag
;
1011 EFI_CAPSULE_HEADER
*CapsuleHeader
;
1012 EFI_CAPSULE_PEIM_PRIVATE_DATA PrivateData
;
1013 EFI_CAPSULE_PEIM_PRIVATE_DATA
*PrivateDataPtr
;
1014 EFI_CAPSULE_BLOCK_DESCRIPTOR
*BlockList
;
1015 EFI_CAPSULE_BLOCK_DESCRIPTOR
*CurrentBlockDesc
;
1016 EFI_CAPSULE_BLOCK_DESCRIPTOR
*TempBlockDesc
;
1017 EFI_CAPSULE_BLOCK_DESCRIPTOR PrivateDataDesc
[2];
1019 DEBUG ((DEBUG_INFO
, "CapsuleDataCoalesce enter\n"));
1024 CapsuleImageSize
= 0;
1025 PrivateDataPtr
= NULL
;
1026 CapsuleHeader
= NULL
;
1027 CapsuleBeginFlag
= TRUE
;
1032 // Build capsule descriptors list
1034 Status
= BuildCapsuleDescriptors (BlockListBuffer
, MemoryResource
, &BlockList
);
1035 if (EFI_ERROR (Status
)) {
1040 CapsuleTestPatternPreCoalesce (PeiServices
, BlockList
);
1044 // Get the size of our descriptors and the capsule size. GetCapsuleInfo()
1045 // returns the number of descriptors that actually point to data, so add
1046 // one for a terminator. Do that below.
1048 Status
= GetCapsuleInfo (BlockList
, &NumDescriptors
, &CapsuleSize
, &CapsuleNumber
);
1049 if (EFI_ERROR (Status
)) {
1052 DEBUG ((DEBUG_INFO
, "CapsuleSize - 0x%x\n", CapsuleSize
));
1053 DEBUG ((DEBUG_INFO
, "CapsuleNumber - 0x%x\n", CapsuleNumber
));
1054 DEBUG ((DEBUG_INFO
, "NumDescriptors - 0x%x\n", NumDescriptors
));
1055 if ((CapsuleSize
== 0) || (NumDescriptors
== 0) || (CapsuleNumber
== 0)) {
1056 return EFI_NOT_FOUND
;
1059 if (CapsuleNumber
- 1 >= (MAX_ADDRESS
- (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
) + sizeof(UINT64
))) / sizeof(UINT64
)) {
1060 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber
));
1061 return EFI_BUFFER_TOO_SMALL
;
1065 // Initialize our local copy of private data. When we're done, we'll create a
1066 // descriptor for it as well so that it can be put into free memory without
1067 // trashing anything.
1069 PrivateData
.Signature
= EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE
;
1070 PrivateData
.CapsuleAllImageSize
= (UINT64
) CapsuleSize
;
1071 PrivateData
.CapsuleNumber
= (UINT64
) CapsuleNumber
;
1072 PrivateData
.CapsuleOffset
[0] = 0;
1074 // NOTE: Only data in sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) is valid, CapsuleOffset field is uninitialized at this moment.
1075 // The code sets partial length here for Descriptor.Length check, but later it will use full length to reserve those PrivateData region.
1077 PrivateDataDesc
[0].Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &PrivateData
;
1078 PrivateDataDesc
[0].Length
= sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
);
1079 PrivateDataDesc
[1].Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) BlockList
;
1080 PrivateDataDesc
[1].Length
= 0;
1082 // Add PrivateDataDesc[0] in beginning, as it is new descriptor. PrivateDataDesc[1] is NOT needed.
1083 // In addition, one NULL terminator is added in the end. See RelocateBlockDescriptors().
1085 NumDescriptors
+= 2;
1089 if (CapsuleSize
>= (MAX_ADDRESS
- (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
) + (CapsuleNumber
- 1) * sizeof(UINT64
) + sizeof(UINT64
)))) {
1090 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleSize - 0x%x\n", CapsuleSize
));
1091 return EFI_BUFFER_TOO_SMALL
;
1094 // Need add sizeof(UINT64) for PrivateData alignment
1096 CapsuleSize
+= sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
) + (CapsuleNumber
- 1) * sizeof(UINT64
) + sizeof(UINT64
);
1097 BlockList
= PrivateDataDesc
;
1101 if (NumDescriptors
>= (MAX_ADDRESS
/ sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR
))) {
1102 DEBUG ((DEBUG_ERROR
, "ERROR: NumDescriptors - 0x%x\n", NumDescriptors
));
1103 return EFI_BUFFER_TOO_SMALL
;
1105 DescriptorsSize
= NumDescriptors
* sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR
);
1109 if (DescriptorsSize
>= (MAX_ADDRESS
- CapsuleSize
)) {
1110 DEBUG ((DEBUG_ERROR
, "ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64
)DescriptorsSize
, (UINT64
)CapsuleSize
));
1111 return EFI_BUFFER_TOO_SMALL
;
1115 // Don't go below some min address. If the base is below it,
1116 // then move it up and adjust the size accordingly.
1118 DEBUG ((DEBUG_INFO
, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN
) *MemoryBase
, (UINTN
)*MemoryBase
+ *MemorySize
));
1119 if ((UINTN
)*MemoryBase
< (UINTN
) MIN_COALESCE_ADDR
) {
1120 if (((UINTN
)*MemoryBase
+ *MemorySize
) < (UINTN
) MIN_COALESCE_ADDR
) {
1121 DEBUG ((DEBUG_ERROR
, "ERROR: *MemoryBase + *MemorySize - 0x%x\n", (UINTN
)*MemoryBase
+ *MemorySize
));
1122 return EFI_BUFFER_TOO_SMALL
;
1124 *MemorySize
= *MemorySize
- ((UINTN
) MIN_COALESCE_ADDR
- (UINTN
) *MemoryBase
);
1125 *MemoryBase
= (VOID
*) (UINTN
) MIN_COALESCE_ADDR
;
1129 if (*MemorySize
<= (CapsuleSize
+ DescriptorsSize
)) {
1130 DEBUG ((DEBUG_ERROR
, "ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize
+ DescriptorsSize
));
1131 return EFI_BUFFER_TOO_SMALL
;
1134 FreeMemBase
= *MemoryBase
;
1135 FreeMemSize
= *MemorySize
;
1136 DEBUG ((DEBUG_INFO
, "Capsule Free Memory from 0x%8X to 0x%8X\n", (UINTN
) FreeMemBase
, (UINTN
) FreeMemBase
+ FreeMemSize
));
1139 // Relocate all the block descriptors to low memory to make further
1140 // processing easier.
1142 BlockList
= RelocateBlockDescriptors (PeiServices
, BlockList
, NumDescriptors
, FreeMemBase
, FreeMemSize
);
1143 if (BlockList
== NULL
) {
1145 // Not enough room to relocate the descriptors
1147 return EFI_BUFFER_TOO_SMALL
;
1151 // Take the top of memory for the capsule. UINT64 align up.
1153 DestPtr
= FreeMemBase
+ FreeMemSize
- CapsuleSize
;
1154 DestPtr
= (UINT8
*) (((UINTN
)DestPtr
+ sizeof (UINT64
) - 1) & ~(sizeof (UINT64
) - 1));
1155 FreeMemBase
= (UINT8
*) BlockList
+ DescriptorsSize
;
1156 FreeMemSize
= (UINTN
) DestPtr
- (UINTN
) FreeMemBase
;
1157 NewCapsuleBase
= (VOID
*) DestPtr
;
1158 CapsuleImageBase
= (UINT8
*)NewCapsuleBase
+ sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA
) + (CapsuleNumber
- 1) * sizeof(UINT64
);
1160 PrivateDataPtr
= (EFI_CAPSULE_PEIM_PRIVATE_DATA
*) NewCapsuleBase
;
1163 // Move all the blocks to the top (high) of memory.
1164 // Relocate all the obstructing blocks. Note that the block descriptors
1165 // were coalesced when they were relocated, so we can just ++ the pointer.
1167 CurrentBlockDesc
= BlockList
;
1168 while ((CurrentBlockDesc
->Length
!= 0) || (CurrentBlockDesc
->Union
.ContinuationPointer
!= (EFI_PHYSICAL_ADDRESS
) (UINTN
) NULL
)) {
1169 if (CapsuleTimes
== 0) {
1171 // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1172 // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1174 ASSERT (CurrentBlockDesc
->Union
.DataBlock
== (UINT64
)(UINTN
)&PrivateData
);
1175 DestLength
= sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
) + (CapsuleNumber
- 1) * sizeof(UINT64
);
1177 DestLength
= (UINTN
)CurrentBlockDesc
->Length
;
1180 // See if any of the remaining capsule blocks are in the way
1182 TempBlockDesc
= CurrentBlockDesc
;
1183 while (TempBlockDesc
->Length
!= 0) {
1185 // Is this block in the way of where we want to copy the current descriptor to?
1190 (UINT8
*) (UINTN
) TempBlockDesc
->Union
.DataBlock
,
1191 (UINTN
) TempBlockDesc
->Length
1194 // Relocate the block
1196 RelocPtr
= FindFreeMem (BlockList
, FreeMemBase
, FreeMemSize
, (UINTN
) TempBlockDesc
->Length
);
1197 if (RelocPtr
== NULL
) {
1198 return EFI_BUFFER_TOO_SMALL
;
1201 CopyMem ((VOID
*) RelocPtr
, (VOID
*) (UINTN
) TempBlockDesc
->Union
.DataBlock
, (UINTN
) TempBlockDesc
->Length
);
1202 DEBUG ((DEBUG_INFO
, "Capsule reloc data block from 0x%8X to 0x%8X with size 0x%8X\n",
1203 (UINTN
) TempBlockDesc
->Union
.DataBlock
, (UINTN
) RelocPtr
, (UINTN
) TempBlockDesc
->Length
));
1205 TempBlockDesc
->Union
.DataBlock
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) RelocPtr
;
1213 // Ok, we made it through. Copy the block.
1214 // we just support greping one capsule from the lists of block descs list.
1218 //Skip the first block descriptor that filled with EFI_CAPSULE_PEIM_PRIVATE_DATA
1220 if (CapsuleTimes
> 1) {
1222 //For every capsule entry point, check its header to determine whether to relocate it.
1223 //If it is invalid, skip it and move on to the next capsule. If it is valid, relocate it.
1225 if (CapsuleBeginFlag
) {
1226 CapsuleBeginFlag
= FALSE
;
1227 CapsuleHeader
= (EFI_CAPSULE_HEADER
*)(UINTN
)CurrentBlockDesc
->Union
.DataBlock
;
1228 SizeLeft
= CapsuleHeader
->CapsuleImageSize
;
1231 // No more check here is needed, because IsCapsuleCorrupted() already in ValidateCapsuleIntegrity()
1233 ASSERT (CapsuleIndex
< CapsuleNumber
);
1236 // Relocate this capsule
1238 CapsuleImageSize
+= SizeLeft
;
1240 // Cache the begin offset of this capsule
1242 ASSERT (PrivateDataPtr
->Signature
== EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE
);
1243 ASSERT ((UINTN
)DestPtr
>= (UINTN
)CapsuleImageBase
);
1244 PrivateDataPtr
->CapsuleOffset
[CapsuleIndex
++] = (UINTN
)DestPtr
- (UINTN
)CapsuleImageBase
;
1248 // Below ASSERT is checked in ValidateCapsuleIntegrity()
1250 ASSERT (CurrentBlockDesc
->Length
<= SizeLeft
);
1252 CopyMem ((VOID
*) DestPtr
, (VOID
*) (UINTN
) (CurrentBlockDesc
->Union
.DataBlock
), (UINTN
)CurrentBlockDesc
->Length
);
1253 DEBUG ((DEBUG_INFO
, "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",(UINT64
)CapsuleTimes
,
1254 CurrentBlockDesc
->Union
.DataBlock
, (UINT64
)(UINTN
)DestPtr
, CurrentBlockDesc
->Length
));
1255 DestPtr
+= CurrentBlockDesc
->Length
;
1256 SizeLeft
-= CurrentBlockDesc
->Length
;
1258 if (SizeLeft
== 0) {
1260 //Here is the end of the current capsule image.
1262 CapsuleBeginFlag
= TRUE
;
1266 // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1267 // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1269 ASSERT (CurrentBlockDesc
->Length
== sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
));
1270 ASSERT ((UINTN
)DestPtr
== (UINTN
)NewCapsuleBase
);
1271 CopyMem ((VOID
*) DestPtr
, (VOID
*) (UINTN
) CurrentBlockDesc
->Union
.DataBlock
, (UINTN
) CurrentBlockDesc
->Length
);
1272 DestPtr
+= sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA
) + (CapsuleNumber
- 1) * sizeof(UINT64
);
1275 //Walk through the block descriptor list.
1280 // We return the base of memory we want reserved, and the size.
1281 // The memory peim should handle it appropriately from there.
1283 *MemorySize
= (UINTN
) CapsuleSize
;
1284 *MemoryBase
= (VOID
*) NewCapsuleBase
;
1286 ASSERT (PrivateDataPtr
->Signature
== EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE
);
1287 ASSERT (PrivateDataPtr
->CapsuleAllImageSize
== CapsuleImageSize
);
1288 ASSERT (PrivateDataPtr
->CapsuleNumber
== CapsuleIndex
);