+EFI_STATUS\r
+ReallocateFvImage (\r
+ IN OUT MEMORY_FILE *FvImage,\r
+ IN OUT FV_INFO *FvInfo,\r
+ IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
+ IN OUT UINTN *FvImageCapacity\r
+ )\r
+/*++\r
+Routine Description:\r
+ Increase the size of FV image by 1 block. The routine may reallocate memory\r
+ depending on the capacity of the FV image.\r
+\r
+Arguments:\r
+ FvImage The memory image of the FV to add it to. The current offset\r
+ must be valid.\r
+ FvInfo Pointer to information about the FV.\r
+ VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
+ to the end of the FvImage then no VTF previously found.\r
+ FvImageCapacity Capacity of image buffer for FV.\r
+\r
+Returns:\r
+ EFI_SUCCESS The function completed successfully.\r
+ EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the reallocation.\r
+\r
+--*/\r
+{\r
+ CHAR8 *FileImage;\r
+ UINTN OldSize;\r
+ UINTN IncreaseSize;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ BOOLEAN AllocateNewMemory;\r
+ EFI_FFS_FILE_HEADER *NewVtfFileImage;\r
+ UINT32 VtfFileLength;\r
+ UINT8 TempByte;\r
+\r
+ OldSize = (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage;\r
+ IncreaseSize = FvInfo->FvBlocks[0].BlockLength;\r
+ assert (OldSize == FvInfo->FvBlocks[0].NumBlocks * FvInfo->FvBlocks[0].BlockLength);\r
+\r
+ //\r
+ // Assume we have enough capacity\r
+ //\r
+ AllocateNewMemory = FALSE;\r
+ \r
+\r
+ if (OldSize + IncreaseSize > *FvImageCapacity) {\r
+ AllocateNewMemory = TRUE;\r
+ //\r
+ // Increase capacity by one unit\r
+ //\r
+ *FvImageCapacity = OldSize + FV_CAPACITY_INCREASE_UNIT;\r
+ FileImage = malloc (*FvImageCapacity);\r
+\r
+ if (FileImage == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initialize the content per FV polarity\r
+ //\r
+ if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
+ memset (FileImage, -1, *FvImageCapacity);\r
+ } else {\r
+ memset (FileImage, 0, *FvImageCapacity);\r
+ }\r
+\r
+ //\r
+ // Copy the FV content before VTF\r
+ //\r
+ memcpy (FileImage, FvImage->FileImage, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage);\r
+ } else {\r
+ FileImage = FvImage->FileImage;\r
+ }\r
+\r
+ //\r
+ // Move VTF if it exists\r
+ //\r
+ NewVtfFileImage = (EFI_FFS_FILE_HEADER *) (FileImage + ((UINTN) *VtfFileImage - (UINTN) FvImage->FileImage) + IncreaseSize);\r
+ if ((UINTN) *VtfFileImage != (UINTN) FvImage->Eof) {\r
+ //\r
+ // Exchange the VTF buffer from end to start for two purpose:\r
+ // 1. Exchange: Preserve the default value per FV polarity\r
+ // 2. End->Start: Avoid destroying the VTF data during exchanging\r
+ //\r
+ VtfFileLength = GetLength ((*VtfFileImage)->Size);\r
+ while (VtfFileLength-- != 0) {\r
+ TempByte = ((UINT8 *) VtfFileImage)[VtfFileLength];\r
+ ((UINT8 *) VtfFileImage)[VtfFileLength] = ((UINT8 *) NewVtfFileImage)[VtfFileLength];\r
+ ((UINT8 *) NewVtfFileImage)[VtfFileLength] = TempByte;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update VTF Pointer\r
+ //\r
+ *VtfFileImage = NewVtfFileImage;\r
+\r
+ //\r
+ // Update FvInfo\r
+ //\r
+ FvInfo->FvBlocks[0].NumBlocks ++;\r
+\r
+ //\r
+ // Update FV Header\r
+ //\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FileImage;\r
+ FvHeader->FvBlockMap[0].NumBlocks = FvInfo->FvBlocks[0].NumBlocks;\r
+ FvHeader->FvLength = OldSize + IncreaseSize;\r
+ FvHeader->Checksum = 0;\r
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+ \r
+ //\r
+ // Update FvImage\r
+ //\r
+ if (AllocateNewMemory) {\r
+ free (FvImage->FileImage);\r
+ FvImage->CurrentFilePointer = FileImage + (FvImage->CurrentFilePointer - FvImage->FileImage); \r
+ FvImage->FileImage = FileImage;\r
+ }\r
+ FvImage->Eof = FvImage->FileImage + OldSize + IncreaseSize;\r
+\r
+ InitializeFvLib (FvImage->FileImage, OldSize + IncreaseSize);\r
+ return EFI_SUCCESS;\r
+}\r
+\r