3 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 FirmwareVolumeBuffer.c
18 EFI Firmware Volume routines which work on a Fv image in buffers.
22 #include "FirmwareVolumeBufferLib.h"
23 #include "BinderFuncs.h"
28 #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
31 (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
38 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
41 if (SectionHeader
== NULL
) {
44 if (FvBufExpand3ByteSize(SectionHeader
->Size
) == 0xffffff) {
45 return sizeof(EFI_COMMON_SECTION_HEADER2
);
47 return sizeof(EFI_COMMON_SECTION_HEADER
);
53 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
57 if (SectionHeader
== NULL
) {
60 Length
= FvBufExpand3ByteSize(SectionHeader
->Size
);
61 if (Length
== 0xffffff) {
62 Length
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
73 FvBufCalculateChecksum16 (
80 FvBufCalculateChecksum8 (
98 Clears out all files from the Fv buffer in memory
102 SourceFv - Address of the Fv in memory, this firmware volume volume will
103 be modified, if SourceFfsFile exists
104 SourceFfsFile - Input FFS file to replace
114 EFI_FFS_FILE_HEADER
* FileToRm
;
115 UINTN FileToRmLength
;
117 Status
= FvBufFindFileByName(
122 if (EFI_ERROR (Status
)) {
126 FileToRmLength
= FvBufGetFfsFileSize (FileToRm
);
128 CommonLibBinderSetMem (
131 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
)
148 Clears out all files from the Fv buffer in memory
152 SourceFv - Address of the Fv in memory, this firmware volume volume will
153 be modified, if SourceFfsFile exists
154 SourceFfsFile - Input FFS file to replace
164 EFI_FFS_FILE_HEADER
*NextFile
;
165 EFI_FIRMWARE_VOLUME_HEADER
*TempFv
;
169 Status
= FvBufFindFileByName(
174 if (EFI_ERROR (Status
)) {
178 Status
= FvBufGetSize (Fv
, &FvLength
);
179 if (EFI_ERROR (Status
)) {
184 Status
= FvBufDuplicate (Fv
, (VOID
**)&TempFv
);
185 if (EFI_ERROR (Status
)) {
189 Status
= FvBufClearAllFiles (TempFv
);
190 if (EFI_ERROR (Status
)) {
194 // TempFv has been allocated. It must now be freed
200 Status
= FvBufFindNextFile (Fv
, &FileKey
, (VOID
**)&NextFile
);
201 if (Status
== EFI_NOT_FOUND
) {
203 } else if (EFI_ERROR (Status
)) {
204 CommonLibBinderFree (TempFv
);
208 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
212 Status
= FvBufAddFile (TempFv
, NextFile
);
213 if (EFI_ERROR (Status
)) {
214 CommonLibBinderFree (TempFv
);
220 CommonLibBinderCopyMem (Fv
, TempFv
, FvLength
);
221 CommonLibBinderFree (TempFv
);
235 Clears out all files from the Fv buffer in memory
239 SourceFfsFile - Input FFS file to update the checksum for
248 EFI_FFS_FILE_HEADER
* File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
249 EFI_FFS_FILE_STATE StateBackup
;
252 FileSize
= FvBufGetFfsFileSize (File
);
255 // Fill in checksums and state, they must be 0 for checksumming.
257 File
->IntegrityCheck
.Checksum
.Header
= 0;
258 File
->IntegrityCheck
.Checksum
.File
= 0;
259 StateBackup
= File
->State
;
262 File
->IntegrityCheck
.Checksum
.Header
=
263 FvBufCalculateChecksum8 (
265 FvBufGetFfsHeaderSize (File
)
268 if (File
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
269 File
->IntegrityCheck
.Checksum
.File
= FvBufCalculateChecksum8 (
270 (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
)),
271 FileSize
- FvBufGetFfsHeaderSize (File
)
274 File
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
277 File
->State
= StateBackup
;
284 FvBufChecksumHeader (
291 Clears out all files from the Fv buffer in memory
295 SourceFv - Address of the Fv in memory, this firmware volume volume will
296 be modified, if SourceFfsFile exists
297 SourceFfsFile - Input FFS file to replace
306 EFI_FIRMWARE_VOLUME_HEADER
* FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
308 FvHeader
->Checksum
= 0;
310 FvBufCalculateChecksum16 (
312 FvHeader
->HeaderLength
/ sizeof (UINT16
)
322 IN OUT VOID
**DestinationFv
328 Clears out all files from the Fv buffer in memory
332 SourceFv - Address of the Fv in memory
333 DestinationFv - Output for destination Fv
334 DestinationFv == NULL - invalid parameter
335 *DestinationFv == NULL - memory will be allocated
336 *DestinationFv != NULL - this address will be the destination
347 if (DestinationFv
== NULL
) {
348 return EFI_INVALID_PARAMETER
;
351 Status
= FvBufGetSize (SourceFv
, &size
);
352 if (EFI_ERROR (Status
)) {
356 if (*DestinationFv
== NULL
) {
357 *DestinationFv
= CommonLibBinderAllocate (size
);
360 CommonLibBinderCopyMem (*DestinationFv
, SourceFv
, size
);
375 Extends a firmware volume by the given number of bytes.
377 BUGBUG: Does not handle the case where the firmware volume has a
378 VTF (Volume Top File). The VTF will not be moved to the
379 end of the extended FV.
383 Fv - Source and destination firmware volume.
384 Note: The original firmware volume buffer is freed!
386 Size - The minimum size that the firmware volume is to be extended by.
387 The FV may be extended more than this size.
401 EFI_FIRMWARE_VOLUME_HEADER
* hdr
;
402 EFI_FV_BLOCK_MAP_ENTRY
* blk
;
404 Status
= FvBufGetSize (*Fv
, &OldSize
);
405 if (EFI_ERROR (Status
)) {
410 // Locate the block map in the fv header
412 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)*Fv
;
416 // Calculate the number of blocks needed to achieve the requested
419 BlockCount
= ((Size
+ (blk
->Length
- 1)) / blk
->Length
);
422 // Calculate the new size from the number of blocks that will be added
424 NewSize
= OldSize
+ (BlockCount
* blk
->Length
);
426 NewFv
= CommonLibBinderAllocate (NewSize
);
428 return EFI_OUT_OF_RESOURCES
;
434 CommonLibBinderCopyMem (NewFv
, *Fv
, OldSize
);
437 // Free the old fv buffer
439 CommonLibBinderFree (*Fv
);
442 // Locate the block map in the new fv header
444 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)NewFv
;
445 hdr
->FvLength
= NewSize
;
449 // Update the block map for the new fv
451 blk
->NumBlocks
+= (UINT32
)BlockCount
;
454 // Update the FV header checksum
456 FvBufChecksumHeader (NewFv
);
459 // Clear out the new area of the FV
461 CommonLibBinderSetMem (
462 (UINT8
*)NewFv
+ OldSize
,
464 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
468 // Set output with new fv that was created
485 Clears out all files from the Fv buffer in memory
489 Fv - Address of the Fv in memory
498 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
502 Status
= FvBufGetSize (Fv
, &size
);
503 if (EFI_ERROR (Status
)) {
507 CommonLibBinderSetMem(
508 (UINT8
*)hdr
+ hdr
->HeaderLength
,
509 size
- hdr
->HeaderLength
,
510 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
526 Clears out all files from the Fv buffer in memory
530 Fv - Address of the Fv in memory
539 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
540 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
544 while (blk
->Length
!= 0 || blk
->NumBlocks
!= 0) {
545 *Size
= *Size
+ (blk
->Length
* blk
->NumBlocks
);
546 if (*Size
>= 0x40000000) {
547 // If size is greater than 1GB, then assume it is corrupted
548 return EFI_VOLUME_CORRUPTED
;
554 // If size is 0, then assume the volume is corrupted
555 return EFI_VOLUME_CORRUPTED
;
575 Fv - Address of the Fv in memory
576 File - FFS file to add to Fv
584 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
586 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
587 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
596 Status
= FvBufGetSize (Fv
, &fvSize
);
597 if (EFI_ERROR (Status
)) {
601 FvbAttributes
= hdr
->Attributes
;
602 newSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
605 offset
= (UINTN
)ALIGN_POINTER (hdr
->HeaderLength
, 8);
606 offset
+ newSize
<= fvSize
;
607 offset
= (UINTN
)ALIGN_POINTER (offset
, 8)
610 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ offset
);
612 if (EFI_TEST_FFS_ATTRIBUTES_BIT(
615 EFI_FILE_HEADER_VALID
618 // BUGBUG: Need to make sure that the new file does not already
621 fsize
= FvBufGetFfsFileSize (fhdr
);
622 if (fsize
== 0 || (offset
+ fsize
> fvSize
)) {
623 return EFI_VOLUME_CORRUPTED
;
626 offset
= offset
+ fsize
;
631 while ((clearLoop
< newSize
) &&
632 (((UINT8
*)fhdr
)[clearLoop
] ==
633 (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0)
640 // We found a place in the FV which is empty and big enough for
643 if (clearLoop
>= newSize
) {
647 offset
= offset
+ 1; // Make some forward progress
650 if (offset
+ newSize
> fvSize
) {
651 return EFI_OUT_OF_RESOURCES
;
654 CommonLibBinderCopyMem (fhdr
, File
, newSize
);
661 FvBufAddFileWithExtend (
669 Adds a new FFS file. Extends the firmware volume if needed.
673 Fv - Source and destination firmware volume.
674 Note: If the FV is extended, then the original firmware volume
677 Size - The minimum size that the firmware volume is to be extended by.
678 The FV may be extended more than this size.
687 EFI_FFS_FILE_HEADER
* NewFile
;
689 NewFile
= (EFI_FFS_FILE_HEADER
*)File
;
692 // Try to add to the capsule volume
694 Status
= FvBufAddFile (*Fv
, NewFile
);
695 if (Status
== EFI_OUT_OF_RESOURCES
) {
697 // Try to extend the capsule volume by the size of the file
699 Status
= FvBufExtend (Fv
, FvBufExpand3ByteSize (NewFile
->Size
));
700 if (EFI_ERROR (Status
)) {
705 // Now, try to add the file again
707 Status
= FvBufAddFile (*Fv
, NewFile
);
723 Adds a new FFS VFT (Volume Top File) file. In other words, adds the
724 file to the end of the firmware volume.
728 Fv - Address of the Fv in memory
729 File - FFS file to add to Fv
739 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
741 EFI_FFS_FILE_HEADER
* NewFile
;
747 EFI_FFS_FILE_HEADER
*LastFile
;
753 Status
= FvBufGetSize (Fv
, &fvSize
);
754 if (EFI_ERROR (Status
)) {
758 erasedUint8
= (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0);
759 NewFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
761 if (NewFileSize
!= (UINTN
)ALIGN_POINTER (NewFileSize
, 8)) {
762 return EFI_INVALID_PARAMETER
;
766 // Find the last file in the FV
772 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&LastFile
);
773 LastFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
774 } while (!EFI_ERROR (Status
));
777 // If no files were found, then we start at the beginning of the FV
779 if (LastFile
== NULL
) {
780 LastFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ hdr
->HeaderLength
);
784 // We want to put the new file (VTF) at the end of the FV
786 NewFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ (fvSize
- NewFileSize
));
789 // Check to see if there is enough room for the VTF after the last file
792 if ((UINT8
*)NewFile
< ((UINT8
*)LastFile
+ LastFileSize
)) {
793 return EFI_OUT_OF_RESOURCES
;
797 // Loop to determine if the end of the FV is empty
800 while ((clearLoop
< NewFileSize
) &&
801 (((UINT8
*)NewFile
)[clearLoop
] == erasedUint8
)
807 // Check to see if there was not enough room for the file
809 if (clearLoop
< NewFileSize
) {
810 return EFI_OUT_OF_RESOURCES
;
813 CommonLibBinderCopyMem (NewFile
, File
, NewFileSize
);
820 FvBufCompact3ByteSize (
828 Expands the 3 byte size commonly used in Firmware Volume data structures
832 Size - Address of the 3 byte array representing the size
840 ((UINT8
*)SizeDest
)[0] = (UINT8
)Size
;
841 ((UINT8
*)SizeDest
)[1] = (UINT8
)(Size
>> 8);
842 ((UINT8
*)SizeDest
)[2] = (UINT8
)(Size
>> 16);
846 FvBufGetFfsFileSize (
847 IN EFI_FFS_FILE_HEADER
*Ffs
853 Get the FFS file size.
857 Ffs - Pointer to FFS header
868 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
869 return ((EFI_FFS_FILE_HEADER2
*)Ffs
)->ExtendedSize
;
871 return FvBufExpand3ByteSize(Ffs
->Size
);
875 FvBufGetFfsHeaderSize (
876 IN EFI_FFS_FILE_HEADER
*Ffs
882 Get the FFS header size.
886 Ffs - Pointer to FFS header
897 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
898 return sizeof(EFI_FFS_FILE_HEADER2
);
900 return sizeof(EFI_FFS_FILE_HEADER
);
904 FvBufExpand3ByteSize (
911 Expands the 3 byte size commonly used in Firmware Volume data structures
915 Size - Address of the 3 byte array representing the size
923 return (((UINT8
*)Size
)[2] << 16) +
924 (((UINT8
*)Size
)[1] << 8) +
938 Iterates through the files contained within the firmware volume
942 Fv - Address of the Fv in memory
943 Key - Should be 0 to get the first file. After that, it should be
944 passed back in without modifying it's contents to retrieve
946 File - Output file pointer
947 File == NULL - invalid parameter
948 otherwise - *File will be update to the location of the file
958 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
960 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
961 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
968 return EFI_INVALID_PARAMETER
;
971 Status
= FvBufGetSize (Fv
, &fvSize
);
972 if (EFI_ERROR (Status
)) {
977 *Key
= hdr
->HeaderLength
;
980 FvbAttributes
= hdr
->Attributes
;
983 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8);
984 (*Key
+ sizeof (*fhdr
)) < fvSize
;
985 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8)
988 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ *Key
);
989 fsize
= FvBufGetFfsFileSize (fhdr
);
991 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
994 EFI_FILE_HEADER_VALID
996 EFI_TEST_FFS_ATTRIBUTES_BIT(
999 EFI_FILE_HEADER_INVALID
1002 *Key
= *Key
+ 1; // Make some forward progress
1005 EFI_TEST_FFS_ATTRIBUTES_BIT(
1008 EFI_FILE_MARKED_FOR_UPDATE
1010 EFI_TEST_FFS_ATTRIBUTES_BIT(
1016 *Key
= *Key
+ fsize
;
1018 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1024 *File
= (UINT8
*)hdr
+ *Key
;
1025 *Key
= *Key
+ fsize
;
1029 *Key
= *Key
+ 1; // Make some forward progress
1032 return EFI_NOT_FOUND
;
1037 FvBufFindFileByName (
1044 Routine Description:
1046 Searches the Fv for a file by its name
1050 Fv - Address of the Fv in memory
1051 Name - Guid filename to search for in the firmware volume
1052 File - Output file pointer
1053 File == NULL - Only determine if the file exists, based on return
1054 value from the function call.
1055 otherwise - *File will be update to the location of the file
1061 EFI_VOLUME_CORRUPTED
1067 EFI_FFS_FILE_HEADER
*NextFile
;
1071 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1072 if (EFI_ERROR (Status
)) {
1076 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
1084 return EFI_NOT_FOUND
;
1089 FvBufFindFileByType (
1091 IN EFI_FV_FILETYPE Type
,
1096 Routine Description:
1098 Searches the Fv for a file by its type
1102 Fv - Address of the Fv in memory
1103 Type - FFS FILE type to search for
1104 File - Output file pointer
1105 (File == NULL) -> Only determine if the file exists, based on return
1106 value from the function call.
1107 otherwise -> *File will be update to the location of the file
1113 EFI_VOLUME_CORRUPTED
1119 EFI_FFS_FILE_HEADER
*NextFile
;
1123 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1124 if (EFI_ERROR (Status
)) {
1128 if (Type
== NextFile
->Type
) {
1136 return EFI_NOT_FOUND
;
1141 FvBufGetFileRawData (
1144 OUT UINTN
* RawDataSize
1148 Routine Description:
1150 Searches the requested file for raw data.
1152 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1153 or finds the EFI_SECTION_RAW section within the file and returns its data.
1157 FfsFile - Address of the FFS file in memory
1158 RawData - Pointer to the raw data within the file
1159 (This is NOT allocated. It is within the file.)
1160 RawDataSize - Size of the raw data within the file
1169 EFI_FFS_FILE_HEADER
* File
;
1170 EFI_RAW_SECTION
* Section
;
1172 File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
1175 // Is the file type == EFI_FV_FILETYPE_RAW?
1177 if (File
->Type
== EFI_FV_FILETYPE_RAW
) {
1179 // Raw filetypes don't have sections, so we just return the raw data
1181 *RawData
= (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
));
1182 *RawDataSize
= FvBufGetFfsFileSize (File
) - FvBufGetFfsHeaderSize (File
);
1187 // Within the file, we now need to find the EFI_SECTION_RAW section.
1189 Status
= FvBufFindSectionByType (File
, EFI_SECTION_RAW
, (VOID
**)&Section
);
1190 if (EFI_ERROR (Status
)) {
1194 *RawData
= (VOID
*)((UINT8
*)Section
+ FvBufGetSecHdrLen(Section
));
1196 FvBufGetSecFileLen (Section
) - FvBufGetSecHdrLen(Section
);
1204 FvBufPackageFreeformRawFile (
1205 IN EFI_GUID
* Filename
,
1207 IN UINTN RawDataSize
,
1212 Routine Description:
1214 Packages up a FFS file containing the input raw data.
1216 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1217 contain one EFI_FV_FILETYPE_RAW section.
1221 RawData - Pointer to the raw data to be packed
1222 RawDataSize - Size of the raw data to be packed
1223 FfsFile - Address of the packaged FFS file.
1224 Note: The called must deallocate this memory!
1232 EFI_FFS_FILE_HEADER
* NewFile
;
1234 EFI_RAW_SECTION
* NewSection
;
1235 UINT32 NewSectionSize
;
1240 // The section size is the DataSize + the size of the section header
1242 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION
) + (UINT32
)RawDataSize
;
1243 SecHdrLen
= sizeof (EFI_RAW_SECTION
);
1244 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1245 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION2
) + (UINT32
)RawDataSize
;
1246 SecHdrLen
= sizeof (EFI_RAW_SECTION2
);
1250 // The file size is the size of the file header + the section size
1252 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER
) + NewSectionSize
;
1253 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER
);
1254 if (NewFileSize
>= MAX_FFS_SIZE
) {
1255 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER2
) + NewSectionSize
;
1256 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER2
);
1260 // Try to allocate a buffer to build the new FFS file in
1262 NewFile
= CommonLibBinderAllocate (NewFileSize
);
1263 if (NewFile
== NULL
) {
1264 return EFI_OUT_OF_RESOURCES
;
1266 CommonLibBinderSetMem (NewFile
, NewFileSize
, 0);
1269 // The NewSection follow right after the FFS file header
1271 NewSection
= (EFI_RAW_SECTION
*)((UINT8
*)NewFile
+ FfsHdrLen
);
1272 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1273 FvBufCompact3ByteSize (NewSection
->Size
, 0xffffff);
1274 ((EFI_RAW_SECTION2
*)NewSection
)->ExtendedSize
= NewSectionSize
;
1276 FvBufCompact3ByteSize (NewSection
->Size
, NewSectionSize
);
1278 NewSection
->Type
= EFI_SECTION_RAW
;
1281 // Copy the actual file data into the buffer
1283 CommonLibBinderCopyMem ((UINT8
*)NewSection
+ SecHdrLen
, RawData
, RawDataSize
);
1286 // Initialize the FFS file header
1288 CommonLibBinderCopyMem (&NewFile
->Name
, Filename
, sizeof (EFI_GUID
));
1289 NewFile
->Attributes
= 0;
1290 if (NewFileSize
>= MAX_FFS_SIZE
) {
1291 FvBufCompact3ByteSize (NewFile
->Size
, 0x0);
1292 ((EFI_FFS_FILE_HEADER2
*)NewFile
)->ExtendedSize
= NewFileSize
;
1293 NewFile
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
1295 FvBufCompact3ByteSize (NewFile
->Size
, NewFileSize
);
1297 NewFile
->Type
= EFI_FV_FILETYPE_FREEFORM
;
1298 NewFile
->IntegrityCheck
.Checksum
.Header
=
1299 FvBufCalculateChecksum8 ((UINT8
*)NewFile
, FfsHdrLen
);
1300 NewFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1301 NewFile
->State
= (UINT8
)~( EFI_FILE_HEADER_CONSTRUCTION
|
1302 EFI_FILE_HEADER_VALID
|
1313 FvBufFindNextSection (
1314 IN VOID
*SectionsStart
,
1315 IN UINTN TotalSectionsSize
,
1321 Routine Description:
1323 Iterates through the sections contained within a given array of sections
1327 SectionsStart - Address of the start of the FFS sections array
1328 TotalSectionsSize - Total size of all the sections
1329 Key - Should be 0 to get the first section. After that, it should be
1330 passed back in without modifying it's contents to retrieve
1332 Section - Output section pointer
1333 (Section == NULL) -> invalid parameter
1334 otherwise -> *Section will be update to the location of the file
1340 EFI_VOLUME_CORRUPTED
1344 EFI_COMMON_SECTION_HEADER
*sectionHdr
;
1347 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 4); // Sections are DWORD aligned
1349 if ((*Key
+ sizeof (*sectionHdr
)) > TotalSectionsSize
) {
1350 return EFI_NOT_FOUND
;
1353 sectionHdr
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)SectionsStart
+ *Key
);
1354 sectionSize
= FvBufGetSecFileLen (sectionHdr
);
1356 if (sectionSize
< sizeof (EFI_COMMON_SECTION_HEADER
)) {
1357 return EFI_NOT_FOUND
;
1360 if ((*Key
+ sectionSize
) > TotalSectionsSize
) {
1361 return EFI_NOT_FOUND
;
1364 *Section
= (UINT8
*)sectionHdr
;
1365 *Key
= *Key
+ sectionSize
;
1372 FvBufCountSections (
1378 Routine Description:
1380 Searches the FFS file and counts the number of sections found.
1381 The sections are NOT recursed.
1385 FfsFile - Address of the FFS file in memory
1386 Count - The location to store the section count in
1392 EFI_VOLUME_CORRUPTED
1399 UINTN TotalSectionsSize
;
1400 EFI_COMMON_SECTION_HEADER
* NextSection
;
1402 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1404 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1405 FvBufGetFfsHeaderSize(FfsFile
);
1409 Status
= FvBufFindNextSection (
1413 (VOID
**)&NextSection
1415 if (Status
== EFI_NOT_FOUND
) {
1417 } else if (EFI_ERROR (Status
)) {
1422 // Increment the section counter
1428 return EFI_NOT_FOUND
;
1433 FvBufFindSectionByType (
1440 Routine Description:
1442 Searches the FFS file for a section by its type
1446 FfsFile - Address of the FFS file in memory
1447 Type - FFS FILE section type to search for
1448 Section - Output section pointer
1449 (Section == NULL) -> Only determine if the section exists, based on return
1450 value from the function call.
1451 otherwise -> *Section will be update to the location of the file
1457 EFI_VOLUME_CORRUPTED
1464 UINTN TotalSectionsSize
;
1465 EFI_COMMON_SECTION_HEADER
* NextSection
;
1467 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1469 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1470 FvBufGetFfsHeaderSize(FfsFile
);
1473 Status
= FvBufFindNextSection (
1477 (VOID
**)&NextSection
1479 if (EFI_ERROR (Status
)) {
1483 if (Type
== NextSection
->Type
) {
1484 if (Section
!= NULL
) {
1485 *Section
= NextSection
;
1491 return EFI_NOT_FOUND
;
1501 Routine Description:
1503 Shrinks a firmware volume (in place) to provide a minimal FV.
1505 BUGBUG: Does not handle the case where the firmware volume has a
1506 VTF (Volume Top File). The VTF will not be moved to the
1507 end of the extended FV.
1511 Fv - Firmware volume.
1522 UINT32 NewBlockSize
= 128;
1524 EFI_FFS_FILE_HEADER
* FileIt
;
1525 VOID
* EndOfLastFile
;
1527 EFI_FIRMWARE_VOLUME_HEADER
* FvHdr
;
1529 Status
= FvBufGetSize (Fv
, &OldSize
);
1530 if (EFI_ERROR (Status
)) {
1534 Status
= FvBufUnifyBlockSizes (Fv
, NewBlockSize
);
1535 if (EFI_ERROR (Status
)) {
1540 // Locate the block map in the fv header
1542 FvHdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1545 // Find the end of the last file
1548 EndOfLastFile
= (UINT8
*)FvHdr
+ FvHdr
->FvLength
;
1549 while (!EFI_ERROR (FvBufFindNextFile (Fv
, &Key
, (VOID
**)&FileIt
))) {
1551 (VOID
*)((UINT8
*)FileIt
+ FvBufGetFfsFileSize (FileIt
));
1555 // Set the BlockCount to have the minimal number of blocks for the Fv.
1557 BlockCount
= (UINT32
)((UINTN
)EndOfLastFile
- (UINTN
)Fv
);
1558 BlockCount
= BlockCount
+ NewBlockSize
- 1;
1559 BlockCount
= BlockCount
/ NewBlockSize
;
1562 // Adjust the block count to shrink the Fv in place.
1564 FvHdr
->BlockMap
[0].NumBlocks
= BlockCount
;
1565 FvHdr
->FvLength
= BlockCount
* NewBlockSize
;
1568 // Update the FV header checksum
1570 FvBufChecksumHeader (Fv
);
1578 FvBufUnifyBlockSizes (
1584 Routine Description:
1586 Searches the FFS file for a section by its type
1590 Fv - Address of the Fv in memory
1591 BlockSize - The size of the blocks to convert the Fv to. If the total size
1592 of the Fv is not evenly divisible by this size, then
1593 EFI_INVALID_PARAMETER will be returned.
1599 EFI_VOLUME_CORRUPTED
1603 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1604 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
1610 // Scan through the block map list, performing error checking, and adding
1611 // up the total Fv size.
1613 while( blk
->Length
!= 0 ||
1616 Size
= Size
+ (blk
->Length
* blk
->NumBlocks
);
1618 if ((UINT8
*)blk
> ((UINT8
*)hdr
+ hdr
->HeaderLength
)) {
1619 return EFI_VOLUME_CORRUPTED
;
1624 // Make sure that the Fv size is a multiple of the new block size.
1626 if ((Size
% BlockSize
) != 0) {
1627 return EFI_INVALID_PARAMETER
;
1631 // Zero out the entire block map.
1633 CommonLibBinderSetMem (
1635 (UINTN
)blk
- (UINTN
)&hdr
->BlockMap
,
1640 // Write out the single block map entry.
1642 hdr
->BlockMap
[0].Length
= (UINT32
)BlockSize
;
1643 hdr
->BlockMap
[0].NumBlocks
= Size
/ (UINT32
)BlockSize
;
1650 FvBufCalculateSum16 (
1656 Routine Description:
1658 This function calculates the UINT16 sum for the requested region.
1662 Buffer Pointer to buffer containing byte data of component.
1663 Size Size of the buffer
1677 // Perform the word sum for buffer
1679 for (Index
= 0; Index
< Size
; Index
++) {
1680 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
1683 return (UINT16
) Sum
;
1689 FvBufCalculateChecksum16 (
1695 Routine Description::
1697 This function calculates the value needed for a valid UINT16 checksum
1701 Buffer Pointer to buffer containing byte data of component.
1702 Size Size of the buffer
1706 The 16 bit checksum value needed.
1710 return (UINT16
)(0x10000 - FvBufCalculateSum16 (Buffer
, Size
));
1716 FvBufCalculateSum8 (
1724 This function calculates the UINT8 sum for the requested region.
1728 Buffer Pointer to buffer containing byte data of component.
1729 Size Size of the buffer
1733 The 8 bit checksum value needed.
1743 // Perform the byte sum for buffer
1745 for (Index
= 0; Index
< Size
; Index
++) {
1746 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
1755 FvBufCalculateChecksum8 (
1763 This function calculates the value needed for a valid UINT8 checksum
1767 Buffer Pointer to buffer containing byte data of component.
1768 Size Size of the buffer
1772 The 8 bit checksum value needed.
1776 return (UINT8
)(0x100 - FvBufCalculateSum8 (Buffer
, Size
));