30#define MIN_COALESCE_ADDR (1024 * 1024)
174 MemEnd = MemBase + MemSize - DataSize;
175 CurrDesc = BlockList;
179 while (CurrDesc !=
NULL) {
186 while (TempDesc->
Length != 0) {
191 if (
IsOverlapped (MemBase, DataSize, (UINT8 *)CurrDesc, Size)) {
195 MemBase = (UINT8 *)CurrDesc + Size;
196 CurrDesc = BlockList;
197 if (MemBase > MemEnd) {
207 while ((CurrDesc->
Length != 0) && (!Failed)) {
214 CurrDesc = BlockList;
215 if (MemBase > MemEnd) {
259 DEBUG ((DEBUG_ERROR,
"ERROR: Size(0x%lx) > MAX_ADDRESS\n", Size));
267 DEBUG ((DEBUG_ERROR,
"ERROR: Address(0x%lx) > (MAX_ADDRESS - Size(0x%lx))\n", Address, Size));
271 if (MemoryResource ==
NULL) {
278 for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {
279 if ((Address >= MemoryResource[Index].PhysicalStart) &&
280 ((Address + Size) <= (MemoryResource[Index].PhysicalStart + MemoryResource[Index].ResourceLength)))
284 "Address(0x%lx) Size(0x%lx) in MemoryResource[0x%x] - Start(0x%lx) Length(0x%lx)\n",
288 MemoryResource[Index].PhysicalStart,
289 MemoryResource[Index].ResourceLength
295 DEBUG ((DEBUG_ERROR,
"ERROR: Address(0x%lx) Size(0x%lx) not in any MemoryResource\n", Address, Size));
320 DEBUG ((DEBUG_INFO,
"ValidateCapsuleIntegrity\n"));
341 DEBUG ((DEBUG_INFO,
"Ptr - 0x%p\n", Ptr));
342 DEBUG ((DEBUG_INFO,
"Ptr->Length - 0x%lx\n", Ptr->
Length));
348 if ((
UINTN)Ptr & (
sizeof (UINT64) - 1)) {
349 DEBUG ((DEBUG_ERROR,
"ERROR: BlockList address failed alignment check\n"));
363 DEBUG ((DEBUG_INFO,
"Ptr(C) - 0x%p\n", Ptr));
364 DEBUG ((DEBUG_INFO,
"Ptr->Length - 0x%lx\n", Ptr->Length));
365 DEBUG ((DEBUG_INFO,
"Ptr->Union - 0x%lx\n", Ptr->Union.ContinuationPointer));
375 if (CapsuleSize == 0) {
384 DEBUG ((DEBUG_ERROR,
"ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr->
Length));
392 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader->
HeaderSize, CapsuleHeader->
CapsuleImageSize));
404 if (CapsuleSize >= Ptr->
Length) {
405 CapsuleSize = CapsuleSize - Ptr->
Length;
407 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize, Ptr->
Length));
422 DEBUG ((DEBUG_INFO,
"Ptr(B) - 0x%p\n", Ptr));
423 DEBUG ((DEBUG_INFO,
"Ptr->Length - 0x%lx\n", Ptr->Length));
424 DEBUG ((DEBUG_INFO,
"Ptr->Union - 0x%lx\n", Ptr->Union.ContinuationPointer));
428 if (CapsuleCount == 0) {
432 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount));
436 if (CapsuleSize != 0) {
440 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize));
492 if (MemSize < BufferSize) {
496 MemSize -= BufferSize;
497 MemBase += BufferSize;
501 TempBlockDesc = BlockList;
503 if (TempBlockDesc->
Length == 0) {
514 (UINT8 *)NewBlockList,
524 if (RelocBuffer ==
NULL) {
529 DEBUG ((DEBUG_INFO,
"Capsule relocate descriptors from/to/size 0x%lX 0x%lX 0x%lX\n", TempBlockDesc->Union.
DataBlock, (UINT64)(
UINTN)RelocBuffer, TempBlockDesc->
Length));
541 CurrBlockDescHead = BlockList;
542 PrevBlockDescTail =
NULL;
547 TempBlockDesc = CurrBlockDescHead;
549 while (TempBlockDesc->
Length != 0) {
555 (UINT8 *)NewBlockList,
557 (UINT8 *)CurrBlockDescHead,
564 RelocBuffer =
FindFreeMem (BlockList, MemBase, MemSize, BlockListSize);
565 if (RelocBuffer ==
NULL) {
569 CopyMem ((VOID *)RelocBuffer, (VOID *)CurrBlockDescHead, BlockListSize);
570 DEBUG ((DEBUG_INFO,
"Capsule reloc descriptor block #2\n"));
575 if (PrevBlockDescTail ==
NULL) {
585 PrevBlockDescTail = TempBlockDesc;
592 TempBlockDesc = BlockList;
593 CurrBlockDescHead = NewBlockList;
595 if (TempBlockDesc->
Length != 0) {
609 CurrBlockDescHead->
Length = 0;
637 if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
669 UINTN ThisCapsuleImageSize;
672 DEBUG ((DEBUG_INFO,
"GetCapsuleInfo enter\n"));
674 ASSERT (Desc !=
NULL);
679 ThisCapsuleImageSize = 0;
682 if (Desc->Length == 0) {
694 DEBUG ((DEBUG_ERROR,
"ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc->Length, Size));
695 return EFI_OUT_OF_RESOURCES;
698 Size += (
UINTN)Desc->Length;
704 if (ThisCapsuleImageSize == 0) {
716 ASSERT (ThisCapsuleImageSize >= Desc->Length);
717 ThisCapsuleImageSize = (
UINTN)(ThisCapsuleImageSize - Desc->Length);
730 DEBUG ((DEBUG_ERROR,
"ERROR: Count == 0\n"));
731 return EFI_NOT_FOUND;
737 ASSERT (ThisCapsuleImageSize == 0);
739 if (NumDescriptors !=
NULL) {
740 *NumDescriptors = Count;
743 if (CapsuleSize !=
NULL) {
747 if (CapsuleNumber !=
NULL) {
748 *CapsuleNumber = Number;
771 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
778 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
782 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
812 DEBUG ((DEBUG_INFO,
"CapsuleTestPatternPreCoalesce\n"));
821 if (Desc->Union.ContinuationPointer == 0) {
828 if (Desc->Length < sizeof (UINT32)) {
829 DEBUG ((DEBUG_INFO,
"Capsule test pattern pre-coalesce punted #1\n"));
833 TestPtr = (UINT32 *)(
UINTN)Desc->Union.DataBlock;
837 if (*TestPtr != 0x54534554) {
842 TestSize = (UINT32)Desc->Length - 2 * sizeof (UINT32);
848 if ((TestSize & 0x03) != 0) {
849 DEBUG ((DEBUG_INFO,
"Capsule test pattern pre-coalesce punted #2\n"));
853 while (TestSize > 0) {
854 if (*TestPtr != TestCounter) {
855 DEBUG ((DEBUG_INFO,
"Capsule test pattern pre-coalesce failed data corruption check\n"));
859 TestSize -=
sizeof (UINT32);
873 TestSize = (UINT32)Desc->Length;
874 TestPtr = (UINT32 *)(
UINTN)Desc->Union.DataBlock;
901 DEBUG ((DEBUG_INFO,
"BuildCapsuleDescriptors enter\n"));
908 while (BlockListBuffer[Index] != 0) {
914 if (TempBlock !=
NULL) {
915 if (LastBlock ==
NULL) {
916 LastBlock = TempBlock;
928 LastBlock = TempBlock;
932 DEBUG ((DEBUG_ERROR,
"ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer[Index]));
938 if (HeadBlock !=
NULL) {
939 *BlockDescriptorList = HeadBlock;
943 return EFI_NOT_FOUND;
1023 IN OUT VOID **MemoryBase,
1027 VOID *NewCapsuleBase;
1028 VOID *CapsuleImageBase;
1036 UINT64 CapsuleImageSize;
1038 UINTN CapsuleNumber;
1039 UINTN DescriptorsSize;
1041 UINTN NumDescriptors;
1042 BOOLEAN CapsuleBeginFlag;
1052 DEBUG ((DEBUG_INFO,
"CapsuleDataCoalesce enter\n"));
1057 CapsuleImageSize = 0;
1058 PrivateDataPtr =
NULL;
1059 CapsuleHeader =
NULL;
1060 CapsuleBeginFlag =
TRUE;
1068 if (EFI_ERROR (Status)) {
1081 Status =
GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize, &CapsuleNumber);
1082 if (EFI_ERROR (Status)) {
1086 DEBUG ((DEBUG_INFO,
"CapsuleSize - 0x%x\n", CapsuleSize));
1087 DEBUG ((DEBUG_INFO,
"CapsuleNumber - 0x%x\n", CapsuleNumber));
1088 DEBUG ((DEBUG_INFO,
"NumDescriptors - 0x%x\n", NumDescriptors));
1089 if ((CapsuleSize == 0) || (NumDescriptors == 0) || (CapsuleNumber == 0)) {
1090 return EFI_NOT_FOUND;
1094 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber));
1095 return EFI_BUFFER_TOO_SMALL;
1103 PrivateData.Signature = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
1104 PrivateData.CapsuleAllImageSize = (UINT64)CapsuleSize;
1105 PrivateData.CapsuleNumber = (UINT64)CapsuleNumber;
1106 PrivateData.CapsuleOffset[0] = 0;
1114 PrivateDataDesc[1].
Length = 0;
1119 NumDescriptors += 2;
1124 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleSize - 0x%x\n", CapsuleSize));
1125 return EFI_BUFFER_TOO_SMALL;
1132 BlockList = PrivateDataDesc;
1137 DEBUG ((DEBUG_ERROR,
"ERROR: NumDescriptors - 0x%x\n", NumDescriptors));
1138 return EFI_BUFFER_TOO_SMALL;
1145 if (DescriptorsSize >= (
MAX_ADDRESS - CapsuleSize)) {
1146 DEBUG ((DEBUG_ERROR,
"ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64)DescriptorsSize, (UINT64)CapsuleSize));
1147 return EFI_BUFFER_TOO_SMALL;
1154 DEBUG ((DEBUG_INFO,
"Capsule Memory range from 0x%8X to 0x%8X\n", (
UINTN)*MemoryBase, (
UINTN)*MemoryBase + *MemorySize));
1155 if ((
UINTN)*MemoryBase < (
UINTN)MIN_COALESCE_ADDR) {
1156 if (((
UINTN)*MemoryBase + *MemorySize) < (
UINTN)MIN_COALESCE_ADDR) {
1157 DEBUG ((DEBUG_ERROR,
"ERROR: *MemoryBase + *MemorySize - 0x%x\n", (
UINTN)*MemoryBase + *MemorySize));
1158 return EFI_BUFFER_TOO_SMALL;
1160 *MemorySize = *MemorySize - ((
UINTN)MIN_COALESCE_ADDR - (
UINTN)*MemoryBase);
1161 *MemoryBase = (VOID *)(
UINTN)MIN_COALESCE_ADDR;
1165 if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
1166 DEBUG ((DEBUG_ERROR,
"ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize + DescriptorsSize));
1167 return EFI_BUFFER_TOO_SMALL;
1170 FreeMemBase = *MemoryBase;
1171 FreeMemSize = *MemorySize;
1172 DEBUG ((DEBUG_INFO,
"Capsule Free Memory from 0x%8X to 0x%8X\n", (
UINTN)FreeMemBase, (
UINTN)FreeMemBase + FreeMemSize));
1179 if (BlockList ==
NULL) {
1183 return EFI_BUFFER_TOO_SMALL;
1189 DestPtr = FreeMemBase + FreeMemSize - CapsuleSize;
1190 DestPtr = (UINT8 *)(((
UINTN)DestPtr +
sizeof (UINT64) - 1) & ~(
sizeof (UINT64) - 1));
1191 FreeMemBase = (UINT8 *)BlockList + DescriptorsSize;
1192 FreeMemSize = (
UINTN)DestPtr - (
UINTN)FreeMemBase;
1193 NewCapsuleBase = (VOID *)DestPtr;
1203 CurrentBlockDesc = BlockList;
1205 if (CapsuleTimes == 0) {
1210 ASSERT (CurrentBlockDesc->Union.
DataBlock == (UINT64)(
UINTN)&PrivateData);
1219 TempBlockDesc = CurrentBlockDesc;
1220 while (TempBlockDesc->
Length != 0) {
1235 if (RelocPtr ==
NULL) {
1236 return EFI_BUFFER_TOO_SMALL;
1242 "Capsule reloc data block from 0x%8X to 0x%8X with size 0x%8X\n",
1265 if (CapsuleTimes > 1) {
1270 if (CapsuleBeginFlag) {
1271 CapsuleBeginFlag =
FALSE;
1278 ASSERT (CapsuleIndex < CapsuleNumber);
1283 CapsuleImageSize += SizeLeft;
1287 ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1288 ASSERT ((
UINTN)DestPtr >= (
UINTN)CapsuleImageBase);
1289 PrivateDataPtr->CapsuleOffset[CapsuleIndex++] = (
UINTN)DestPtr - (
UINTN)CapsuleImageBase;
1295 ASSERT (CurrentBlockDesc->
Length <= SizeLeft);
1300 "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",
1301 (UINT64)CapsuleTimes,
1303 (UINT64)(
UINTN)DestPtr,
1306 DestPtr += CurrentBlockDesc->
Length;
1307 SizeLeft -= CurrentBlockDesc->
Length;
1309 if (SizeLeft == 0) {
1313 CapsuleBeginFlag =
TRUE;
1321 ASSERT ((
UINTN)DestPtr == (
UINTN)NewCapsuleBase);
1336 *MemorySize = (
UINTN)CapsuleSize;
1337 *MemoryBase = (VOID *)NewCapsuleBase;
1339 ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1340 ASSERT (PrivateDataPtr->CapsuleAllImageSize == CapsuleImageSize);
1341 ASSERT (PrivateDataPtr->CapsuleNumber == CapsuleIndex);
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN ValidateCapsuleByMemoryResource(IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource, IN EFI_PHYSICAL_ADDRESS Address, IN UINT64 Size)
UINT8 * FindFreeMem(EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList, UINT8 *MemBase, UINTN MemSize, UINTN DataSize)
EFI_STATUS GetCapsuleInfo(IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc, IN OUT UINTN *NumDescriptors OPTIONAL, IN OUT UINTN *CapsuleSize OPTIONAL, IN OUT UINTN *CapsuleNumber OPTIONAL)
EFI_STATUS EFIAPI CapsuleDataCoalesce(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PHYSICAL_ADDRESS *BlockListBuffer, IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource, IN OUT VOID **MemoryBase, IN OUT UINTN *MemorySize)
EFI_CAPSULE_BLOCK_DESCRIPTOR * RelocateBlockDescriptors(IN EFI_PEI_SERVICES **PeiServices, IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList, IN UINTN NumDescriptors, IN UINT8 *MemBase, IN UINTN MemSize)
BOOLEAN IsOverlapped(UINT8 *Buff1, UINTN Size1, UINT8 *Buff2, UINTN Size2)
EFI_STATUS BuildCapsuleDescriptors(IN EFI_PHYSICAL_ADDRESS *BlockListBuffer, IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource, OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList)
VOID CapsuleTestPatternPreCoalesce(IN EFI_PEI_SERVICES **PeiServices, IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc)
EFI_CAPSULE_BLOCK_DESCRIPTOR * ValidateCapsuleIntegrity(IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList, IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource)
BOOLEAN IsCapsuleCorrupted(IN EFI_CAPSULE_HEADER *CapsuleHeader)
#define DEBUG(Expression)
#define DEBUG_CODE(Expression)
UINT64 EFI_PHYSICAL_ADDRESS
EFI_PHYSICAL_ADDRESS DataBlock
EFI_PHYSICAL_ADDRESS ContinuationPointer