2 EFI Firmware Volume routines which work on a Fv image in buffers.
4 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "FirmwareVolumeBufferLib.h"
10 #include "BinderFuncs.h"
15 #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
18 (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
30 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
33 if (SectionHeader
== NULL
) {
36 if (FvBufExpand3ByteSize(SectionHeader
->Size
) == 0xffffff) {
37 return sizeof(EFI_COMMON_SECTION_HEADER2
);
39 return sizeof(EFI_COMMON_SECTION_HEADER
);
45 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
49 if (SectionHeader
== NULL
) {
52 Length
= FvBufExpand3ByteSize(SectionHeader
->Size
);
53 if (Length
== 0xffffff) {
54 Length
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
65 FvBufCalculateChecksum16 (
72 FvBufCalculateChecksum8 (
90 Clears out all files from the Fv buffer in memory
94 SourceFv - Address of the Fv in memory, this firmware volume volume will
95 be modified, if SourceFfsFile exists
96 SourceFfsFile - Input FFS file to replace
106 EFI_FFS_FILE_HEADER
* FileToRm
;
107 UINTN FileToRmLength
;
109 Status
= FvBufFindFileByName(
114 if (EFI_ERROR (Status
)) {
118 FileToRmLength
= FvBufGetFfsFileSize (FileToRm
);
120 CommonLibBinderSetMem (
123 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
)
140 Clears out all files from the Fv buffer in memory
144 SourceFv - Address of the Fv in memory, this firmware volume volume will
145 be modified, if SourceFfsFile exists
146 SourceFfsFile - Input FFS file to replace
156 EFI_FFS_FILE_HEADER
*NextFile
;
157 EFI_FIRMWARE_VOLUME_HEADER
*TempFv
;
161 Status
= FvBufFindFileByName(
166 if (EFI_ERROR (Status
)) {
170 Status
= FvBufGetSize (Fv
, &FvLength
);
171 if (EFI_ERROR (Status
)) {
176 Status
= FvBufDuplicate (Fv
, (VOID
**)&TempFv
);
177 if (EFI_ERROR (Status
)) {
181 Status
= FvBufClearAllFiles (TempFv
);
182 if (EFI_ERROR (Status
)) {
183 CommonLibBinderFree (TempFv
);
187 // TempFv has been allocated. It must now be freed
193 Status
= FvBufFindNextFile (Fv
, &FileKey
, (VOID
**)&NextFile
);
194 if (Status
== EFI_NOT_FOUND
) {
196 } else if (EFI_ERROR (Status
)) {
197 CommonLibBinderFree (TempFv
);
201 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
205 Status
= FvBufAddFile (TempFv
, NextFile
);
206 if (EFI_ERROR (Status
)) {
207 CommonLibBinderFree (TempFv
);
213 CommonLibBinderCopyMem (Fv
, TempFv
, FvLength
);
214 CommonLibBinderFree (TempFv
);
228 Clears out all files from the Fv buffer in memory
232 SourceFfsFile - Input FFS file to update the checksum for
241 EFI_FFS_FILE_HEADER
* File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
242 EFI_FFS_FILE_STATE StateBackup
;
245 FileSize
= FvBufGetFfsFileSize (File
);
248 // Fill in checksums and state, they must be 0 for checksumming.
250 File
->IntegrityCheck
.Checksum
.Header
= 0;
251 File
->IntegrityCheck
.Checksum
.File
= 0;
252 StateBackup
= File
->State
;
255 File
->IntegrityCheck
.Checksum
.Header
=
256 FvBufCalculateChecksum8 (
258 FvBufGetFfsHeaderSize (File
)
261 if (File
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
262 File
->IntegrityCheck
.Checksum
.File
= FvBufCalculateChecksum8 (
263 (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
)),
264 FileSize
- FvBufGetFfsHeaderSize (File
)
267 File
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
270 File
->State
= StateBackup
;
277 FvBufChecksumHeader (
284 Clears out all files from the Fv buffer in memory
288 SourceFv - Address of the Fv in memory, this firmware volume volume will
289 be modified, if SourceFfsFile exists
290 SourceFfsFile - Input FFS file to replace
299 EFI_FIRMWARE_VOLUME_HEADER
* FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
301 FvHeader
->Checksum
= 0;
303 FvBufCalculateChecksum16 (
305 FvHeader
->HeaderLength
/ sizeof (UINT16
)
315 IN OUT VOID
**DestinationFv
321 Clears out all files from the Fv buffer in memory
325 SourceFv - Address of the Fv in memory
326 DestinationFv - Output for destination Fv
327 DestinationFv == NULL - invalid parameter
328 *DestinationFv == NULL - memory will be allocated
329 *DestinationFv != NULL - this address will be the destination
340 if (DestinationFv
== NULL
) {
341 return EFI_INVALID_PARAMETER
;
344 Status
= FvBufGetSize (SourceFv
, &size
);
345 if (EFI_ERROR (Status
)) {
349 if (*DestinationFv
== NULL
) {
350 *DestinationFv
= CommonLibBinderAllocate (size
);
351 if (*DestinationFv
== NULL
) {
352 return EFI_OUT_OF_RESOURCES
;
356 CommonLibBinderCopyMem (*DestinationFv
, SourceFv
, size
);
371 Extends a firmware volume by the given number of bytes.
373 BUGBUG: Does not handle the case where the firmware volume has a
374 VTF (Volume Top File). The VTF will not be moved to the
375 end of the extended FV.
379 Fv - Source and destination firmware volume.
380 Note: The original firmware volume buffer is freed!
382 Size - The minimum size that the firmware volume is to be extended by.
383 The FV may be extended more than this size.
397 EFI_FIRMWARE_VOLUME_HEADER
* hdr
;
398 EFI_FV_BLOCK_MAP_ENTRY
* blk
;
400 Status
= FvBufGetSize (*Fv
, &OldSize
);
401 if (EFI_ERROR (Status
)) {
406 // Locate the block map in the fv header
408 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)*Fv
;
412 // Calculate the number of blocks needed to achieve the requested
415 BlockCount
= ((Size
+ (blk
->Length
- 1)) / blk
->Length
);
418 // Calculate the new size from the number of blocks that will be added
420 NewSize
= OldSize
+ (BlockCount
* blk
->Length
);
422 NewFv
= CommonLibBinderAllocate (NewSize
);
424 return EFI_OUT_OF_RESOURCES
;
430 CommonLibBinderCopyMem (NewFv
, *Fv
, OldSize
);
433 // Free the old fv buffer
435 CommonLibBinderFree (*Fv
);
438 // Locate the block map in the new fv header
440 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)NewFv
;
441 hdr
->FvLength
= NewSize
;
445 // Update the block map for the new fv
447 blk
->NumBlocks
+= (UINT32
)BlockCount
;
450 // Update the FV header checksum
452 FvBufChecksumHeader (NewFv
);
455 // Clear out the new area of the FV
457 CommonLibBinderSetMem (
458 (UINT8
*)NewFv
+ OldSize
,
460 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
464 // Set output with new fv that was created
481 Clears out all files from the Fv buffer in memory
485 Fv - Address of the Fv in memory
494 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
498 Status
= FvBufGetSize (Fv
, &size
);
499 if (EFI_ERROR (Status
)) {
503 CommonLibBinderSetMem(
504 (UINT8
*)hdr
+ hdr
->HeaderLength
,
505 size
- hdr
->HeaderLength
,
506 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
522 Clears out all files from the Fv buffer in memory
526 Fv - Address of the Fv in memory
535 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
536 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
540 while (blk
->Length
!= 0 || blk
->NumBlocks
!= 0) {
541 *Size
= *Size
+ (blk
->Length
* blk
->NumBlocks
);
542 if (*Size
>= 0x40000000) {
543 // If size is greater than 1GB, then assume it is corrupted
544 return EFI_VOLUME_CORRUPTED
;
550 // If size is 0, then assume the volume is corrupted
551 return EFI_VOLUME_CORRUPTED
;
571 Fv - Address of the Fv in memory
572 File - FFS file to add to Fv
580 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
582 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
583 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
592 Status
= FvBufGetSize (Fv
, &fvSize
);
593 if (EFI_ERROR (Status
)) {
597 FvbAttributes
= hdr
->Attributes
;
598 newSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
601 offset
= (UINTN
)ALIGN_POINTER (hdr
->HeaderLength
, 8);
602 offset
+ newSize
<= fvSize
;
603 offset
= (UINTN
)ALIGN_POINTER (offset
, 8)
606 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ offset
);
608 if (EFI_TEST_FFS_ATTRIBUTES_BIT(
611 EFI_FILE_HEADER_VALID
614 // BUGBUG: Need to make sure that the new file does not already
617 fsize
= FvBufGetFfsFileSize (fhdr
);
618 if (fsize
== 0 || (offset
+ fsize
> fvSize
)) {
619 return EFI_VOLUME_CORRUPTED
;
622 offset
= offset
+ fsize
;
627 while ((clearLoop
< newSize
) &&
628 (((UINT8
*)fhdr
)[clearLoop
] ==
629 (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0)
636 // We found a place in the FV which is empty and big enough for
639 if (clearLoop
>= newSize
) {
643 offset
= offset
+ 1; // Make some forward progress
646 if (offset
+ newSize
> fvSize
) {
647 return EFI_OUT_OF_RESOURCES
;
650 CommonLibBinderCopyMem (fhdr
, File
, newSize
);
657 FvBufAddFileWithExtend (
665 Adds a new FFS file. Extends the firmware volume if needed.
669 Fv - Source and destination firmware volume.
670 Note: If the FV is extended, then the original firmware volume
673 Size - The minimum size that the firmware volume is to be extended by.
674 The FV may be extended more than this size.
683 EFI_FFS_FILE_HEADER
* NewFile
;
685 NewFile
= (EFI_FFS_FILE_HEADER
*)File
;
688 // Try to add to the capsule volume
690 Status
= FvBufAddFile (*Fv
, NewFile
);
691 if (Status
== EFI_OUT_OF_RESOURCES
) {
693 // Try to extend the capsule volume by the size of the file
695 Status
= FvBufExtend (Fv
, FvBufExpand3ByteSize (NewFile
->Size
));
696 if (EFI_ERROR (Status
)) {
701 // Now, try to add the file again
703 Status
= FvBufAddFile (*Fv
, NewFile
);
719 Adds a new FFS VFT (Volume Top File) file. In other words, adds the
720 file to the end of the firmware volume.
724 Fv - Address of the Fv in memory
725 File - FFS file to add to Fv
735 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
737 EFI_FFS_FILE_HEADER
* NewFile
;
743 EFI_FFS_FILE_HEADER
*LastFile
;
749 Status
= FvBufGetSize (Fv
, &fvSize
);
750 if (EFI_ERROR (Status
)) {
754 erasedUint8
= (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0);
755 NewFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
757 if (NewFileSize
!= (UINTN
)ALIGN_POINTER (NewFileSize
, 8)) {
758 return EFI_INVALID_PARAMETER
;
762 // Find the last file in the FV
768 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&LastFile
);
769 LastFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
770 } while (!EFI_ERROR (Status
));
773 // If no files were found, then we start at the beginning of the FV
775 if (LastFile
== NULL
) {
776 LastFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ hdr
->HeaderLength
);
780 // We want to put the new file (VTF) at the end of the FV
782 NewFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ (fvSize
- NewFileSize
));
785 // Check to see if there is enough room for the VTF after the last file
788 if ((UINT8
*)NewFile
< ((UINT8
*)LastFile
+ LastFileSize
)) {
789 return EFI_OUT_OF_RESOURCES
;
793 // Loop to determine if the end of the FV is empty
796 while ((clearLoop
< NewFileSize
) &&
797 (((UINT8
*)NewFile
)[clearLoop
] == erasedUint8
)
803 // Check to see if there was not enough room for the file
805 if (clearLoop
< NewFileSize
) {
806 return EFI_OUT_OF_RESOURCES
;
809 CommonLibBinderCopyMem (NewFile
, File
, NewFileSize
);
816 FvBufCompact3ByteSize (
824 Expands the 3 byte size commonly used in Firmware Volume data structures
828 Size - Address of the 3 byte array representing the size
836 ((UINT8
*)SizeDest
)[0] = (UINT8
)Size
;
837 ((UINT8
*)SizeDest
)[1] = (UINT8
)(Size
>> 8);
838 ((UINT8
*)SizeDest
)[2] = (UINT8
)(Size
>> 16);
842 FvBufGetFfsFileSize (
843 IN EFI_FFS_FILE_HEADER
*Ffs
849 Get the FFS file size.
853 Ffs - Pointer to FFS header
864 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
865 return (UINT32
) ((EFI_FFS_FILE_HEADER2
*)Ffs
)->ExtendedSize
;
867 return FvBufExpand3ByteSize(Ffs
->Size
);
871 FvBufGetFfsHeaderSize (
872 IN EFI_FFS_FILE_HEADER
*Ffs
878 Get the FFS header size.
882 Ffs - Pointer to FFS header
893 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
894 return sizeof(EFI_FFS_FILE_HEADER2
);
896 return sizeof(EFI_FFS_FILE_HEADER
);
900 FvBufExpand3ByteSize (
907 Expands the 3 byte size commonly used in Firmware Volume data structures
911 Size - Address of the 3 byte array representing the size
919 return (((UINT8
*)Size
)[2] << 16) +
920 (((UINT8
*)Size
)[1] << 8) +
934 Iterates through the files contained within the firmware volume
938 Fv - Address of the Fv in memory
939 Key - Should be 0 to get the first file. After that, it should be
940 passed back in without modifying it's contents to retrieve
942 File - Output file pointer
943 File == NULL - invalid parameter
944 otherwise - *File will be update to the location of the file
954 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
956 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
957 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
964 return EFI_INVALID_PARAMETER
;
967 Status
= FvBufGetSize (Fv
, &fvSize
);
968 if (EFI_ERROR (Status
)) {
973 *Key
= hdr
->HeaderLength
;
976 FvbAttributes
= hdr
->Attributes
;
979 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8);
980 (*Key
+ sizeof (*fhdr
)) < fvSize
;
981 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8)
984 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ *Key
);
985 fsize
= FvBufGetFfsFileSize (fhdr
);
987 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
990 EFI_FILE_HEADER_VALID
992 EFI_TEST_FFS_ATTRIBUTES_BIT(
995 EFI_FILE_HEADER_INVALID
998 *Key
= *Key
+ 1; // Make some forward progress
1001 EFI_TEST_FFS_ATTRIBUTES_BIT(
1004 EFI_FILE_MARKED_FOR_UPDATE
1006 EFI_TEST_FFS_ATTRIBUTES_BIT(
1012 *Key
= *Key
+ fsize
;
1014 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1020 *File
= (UINT8
*)hdr
+ *Key
;
1021 *Key
= *Key
+ fsize
;
1025 *Key
= *Key
+ 1; // Make some forward progress
1028 return EFI_NOT_FOUND
;
1033 FvBufFindFileByName (
1040 Routine Description:
1042 Searches the Fv for a file by its name
1046 Fv - Address of the Fv in memory
1047 Name - Guid filename to search for in the firmware volume
1048 File - Output file pointer
1049 File == NULL - Only determine if the file exists, based on return
1050 value from the function call.
1051 otherwise - *File will be update to the location of the file
1057 EFI_VOLUME_CORRUPTED
1063 EFI_FFS_FILE_HEADER
*NextFile
;
1067 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1068 if (EFI_ERROR (Status
)) {
1072 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
1080 return EFI_NOT_FOUND
;
1085 FvBufFindFileByType (
1087 IN EFI_FV_FILETYPE Type
,
1092 Routine Description:
1094 Searches the Fv for a file by its type
1098 Fv - Address of the Fv in memory
1099 Type - FFS FILE type to search for
1100 File - Output file pointer
1101 (File == NULL) -> Only determine if the file exists, based on return
1102 value from the function call.
1103 otherwise -> *File will be update to the location of the file
1109 EFI_VOLUME_CORRUPTED
1115 EFI_FFS_FILE_HEADER
*NextFile
;
1119 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1120 if (EFI_ERROR (Status
)) {
1124 if (Type
== NextFile
->Type
) {
1132 return EFI_NOT_FOUND
;
1137 FvBufGetFileRawData (
1140 OUT UINTN
* RawDataSize
1144 Routine Description:
1146 Searches the requested file for raw data.
1148 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1149 or finds the EFI_SECTION_RAW section within the file and returns its data.
1153 FfsFile - Address of the FFS file in memory
1154 RawData - Pointer to the raw data within the file
1155 (This is NOT allocated. It is within the file.)
1156 RawDataSize - Size of the raw data within the file
1165 EFI_FFS_FILE_HEADER
* File
;
1166 EFI_RAW_SECTION
* Section
;
1168 File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
1171 // Is the file type == EFI_FV_FILETYPE_RAW?
1173 if (File
->Type
== EFI_FV_FILETYPE_RAW
) {
1175 // Raw filetypes don't have sections, so we just return the raw data
1177 *RawData
= (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
));
1178 *RawDataSize
= FvBufGetFfsFileSize (File
) - FvBufGetFfsHeaderSize (File
);
1183 // Within the file, we now need to find the EFI_SECTION_RAW section.
1185 Status
= FvBufFindSectionByType (File
, EFI_SECTION_RAW
, (VOID
**)&Section
);
1186 if (EFI_ERROR (Status
)) {
1190 *RawData
= (VOID
*)((UINT8
*)Section
+ FvBufGetSecHdrLen(Section
));
1192 FvBufGetSecFileLen (Section
) - FvBufGetSecHdrLen(Section
);
1200 FvBufPackageFreeformRawFile (
1201 IN EFI_GUID
* Filename
,
1203 IN UINTN RawDataSize
,
1208 Routine Description:
1210 Packages up a FFS file containing the input raw data.
1212 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1213 contain one EFI_FV_FILETYPE_RAW section.
1217 RawData - Pointer to the raw data to be packed
1218 RawDataSize - Size of the raw data to be packed
1219 FfsFile - Address of the packaged FFS file.
1220 Note: The called must deallocate this memory!
1228 EFI_FFS_FILE_HEADER
* NewFile
;
1230 EFI_RAW_SECTION
* NewSection
;
1231 UINT32 NewSectionSize
;
1236 // The section size is the DataSize + the size of the section header
1238 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION
) + (UINT32
)RawDataSize
;
1239 SecHdrLen
= sizeof (EFI_RAW_SECTION
);
1240 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1241 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION2
) + (UINT32
)RawDataSize
;
1242 SecHdrLen
= sizeof (EFI_RAW_SECTION2
);
1246 // The file size is the size of the file header + the section size
1248 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER
) + NewSectionSize
;
1249 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER
);
1250 if (NewFileSize
>= MAX_FFS_SIZE
) {
1251 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER2
) + NewSectionSize
;
1252 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER2
);
1256 // Try to allocate a buffer to build the new FFS file in
1258 NewFile
= CommonLibBinderAllocate (NewFileSize
);
1259 if (NewFile
== NULL
) {
1260 return EFI_OUT_OF_RESOURCES
;
1262 CommonLibBinderSetMem (NewFile
, NewFileSize
, 0);
1265 // The NewSection follow right after the FFS file header
1267 NewSection
= (EFI_RAW_SECTION
*)((UINT8
*)NewFile
+ FfsHdrLen
);
1268 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1269 FvBufCompact3ByteSize (NewSection
->Size
, 0xffffff);
1270 ((EFI_RAW_SECTION2
*)NewSection
)->ExtendedSize
= NewSectionSize
;
1272 FvBufCompact3ByteSize (NewSection
->Size
, NewSectionSize
);
1274 NewSection
->Type
= EFI_SECTION_RAW
;
1277 // Copy the actual file data into the buffer
1279 CommonLibBinderCopyMem ((UINT8
*)NewSection
+ SecHdrLen
, RawData
, RawDataSize
);
1282 // Initialize the FFS file header
1284 CommonLibBinderCopyMem (&NewFile
->Name
, Filename
, sizeof (EFI_GUID
));
1285 NewFile
->Attributes
= 0;
1286 if (NewFileSize
>= MAX_FFS_SIZE
) {
1287 FvBufCompact3ByteSize (NewFile
->Size
, 0x0);
1288 ((EFI_FFS_FILE_HEADER2
*)NewFile
)->ExtendedSize
= NewFileSize
;
1289 NewFile
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
1291 FvBufCompact3ByteSize (NewFile
->Size
, NewFileSize
);
1293 NewFile
->Type
= EFI_FV_FILETYPE_FREEFORM
;
1294 NewFile
->IntegrityCheck
.Checksum
.Header
=
1295 FvBufCalculateChecksum8 ((UINT8
*)NewFile
, FfsHdrLen
);
1296 NewFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1297 NewFile
->State
= (UINT8
)~( EFI_FILE_HEADER_CONSTRUCTION
|
1298 EFI_FILE_HEADER_VALID
|
1309 FvBufFindNextSection (
1310 IN VOID
*SectionsStart
,
1311 IN UINTN TotalSectionsSize
,
1317 Routine Description:
1319 Iterates through the sections contained within a given array of sections
1323 SectionsStart - Address of the start of the FFS sections array
1324 TotalSectionsSize - Total size of all the sections
1325 Key - Should be 0 to get the first section. After that, it should be
1326 passed back in without modifying it's contents to retrieve
1328 Section - Output section pointer
1329 (Section == NULL) -> invalid parameter
1330 otherwise -> *Section will be update to the location of the file
1336 EFI_VOLUME_CORRUPTED
1340 EFI_COMMON_SECTION_HEADER
*sectionHdr
;
1343 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 4); // Sections are DWORD aligned
1345 if ((*Key
+ sizeof (*sectionHdr
)) > TotalSectionsSize
) {
1346 return EFI_NOT_FOUND
;
1349 sectionHdr
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)SectionsStart
+ *Key
);
1350 sectionSize
= FvBufGetSecFileLen (sectionHdr
);
1352 if (sectionSize
< sizeof (EFI_COMMON_SECTION_HEADER
)) {
1353 return EFI_NOT_FOUND
;
1356 if ((*Key
+ sectionSize
) > TotalSectionsSize
) {
1357 return EFI_NOT_FOUND
;
1360 *Section
= (UINT8
*)sectionHdr
;
1361 *Key
= *Key
+ sectionSize
;
1368 FvBufCountSections (
1374 Routine Description:
1376 Searches the FFS file and counts the number of sections found.
1377 The sections are NOT recursed.
1381 FfsFile - Address of the FFS file in memory
1382 Count - The location to store the section count in
1388 EFI_VOLUME_CORRUPTED
1395 UINTN TotalSectionsSize
;
1396 EFI_COMMON_SECTION_HEADER
* NextSection
;
1398 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1400 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1401 FvBufGetFfsHeaderSize(FfsFile
);
1405 Status
= FvBufFindNextSection (
1409 (VOID
**)&NextSection
1411 if (Status
== EFI_NOT_FOUND
) {
1413 } else if (EFI_ERROR (Status
)) {
1418 // Increment the section counter
1424 return EFI_NOT_FOUND
;
1429 FvBufFindSectionByType (
1436 Routine Description:
1438 Searches the FFS file for a section by its type
1442 FfsFile - Address of the FFS file in memory
1443 Type - FFS FILE section type to search for
1444 Section - Output section pointer
1445 (Section == NULL) -> Only determine if the section exists, based on return
1446 value from the function call.
1447 otherwise -> *Section will be update to the location of the file
1453 EFI_VOLUME_CORRUPTED
1460 UINTN TotalSectionsSize
;
1461 EFI_COMMON_SECTION_HEADER
* NextSection
;
1463 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1465 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1466 FvBufGetFfsHeaderSize(FfsFile
);
1469 Status
= FvBufFindNextSection (
1473 (VOID
**)&NextSection
1475 if (EFI_ERROR (Status
)) {
1479 if (Type
== NextSection
->Type
) {
1480 if (Section
!= NULL
) {
1481 *Section
= NextSection
;
1487 return EFI_NOT_FOUND
;
1497 Routine Description:
1499 Shrinks a firmware volume (in place) to provide a minimal FV.
1501 BUGBUG: Does not handle the case where the firmware volume has a
1502 VTF (Volume Top File). The VTF will not be moved to the
1503 end of the extended FV.
1507 Fv - Firmware volume.
1518 UINT32 NewBlockSize
= 128;
1520 EFI_FFS_FILE_HEADER
* FileIt
;
1521 VOID
* EndOfLastFile
;
1523 EFI_FIRMWARE_VOLUME_HEADER
* FvHdr
;
1525 Status
= FvBufGetSize (Fv
, &OldSize
);
1526 if (EFI_ERROR (Status
)) {
1530 Status
= FvBufUnifyBlockSizes (Fv
, NewBlockSize
);
1531 if (EFI_ERROR (Status
)) {
1536 // Locate the block map in the fv header
1538 FvHdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1541 // Find the end of the last file
1544 EndOfLastFile
= (UINT8
*)FvHdr
+ FvHdr
->FvLength
;
1545 while (!EFI_ERROR (FvBufFindNextFile (Fv
, &Key
, (VOID
**)&FileIt
))) {
1547 (VOID
*)((UINT8
*)FileIt
+ FvBufGetFfsFileSize (FileIt
));
1551 // Set the BlockCount to have the minimal number of blocks for the Fv.
1553 BlockCount
= (UINT32
)((UINTN
)EndOfLastFile
- (UINTN
)Fv
);
1554 BlockCount
= BlockCount
+ NewBlockSize
- 1;
1555 BlockCount
= BlockCount
/ NewBlockSize
;
1558 // Adjust the block count to shrink the Fv in place.
1560 FvHdr
->BlockMap
[0].NumBlocks
= BlockCount
;
1561 FvHdr
->FvLength
= BlockCount
* NewBlockSize
;
1564 // Update the FV header checksum
1566 FvBufChecksumHeader (Fv
);
1574 FvBufUnifyBlockSizes (
1580 Routine Description:
1582 Searches the FFS file for a section by its type
1586 Fv - Address of the Fv in memory
1587 BlockSize - The size of the blocks to convert the Fv to. If the total size
1588 of the Fv is not evenly divisible by this size, then
1589 EFI_INVALID_PARAMETER will be returned.
1595 EFI_VOLUME_CORRUPTED
1599 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1600 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
1606 // Scan through the block map list, performing error checking, and adding
1607 // up the total Fv size.
1609 while( blk
->Length
!= 0 ||
1612 Size
= Size
+ (blk
->Length
* blk
->NumBlocks
);
1614 if ((UINT8
*)blk
> ((UINT8
*)hdr
+ hdr
->HeaderLength
)) {
1615 return EFI_VOLUME_CORRUPTED
;
1620 // Make sure that the Fv size is a multiple of the new block size.
1622 if ((Size
% BlockSize
) != 0) {
1623 return EFI_INVALID_PARAMETER
;
1627 // Zero out the entire block map.
1629 CommonLibBinderSetMem (
1631 (UINTN
)blk
- (UINTN
)&hdr
->BlockMap
,
1636 // Write out the single block map entry.
1638 hdr
->BlockMap
[0].Length
= (UINT32
)BlockSize
;
1639 hdr
->BlockMap
[0].NumBlocks
= Size
/ (UINT32
)BlockSize
;
1646 FvBufCalculateSum16 (
1652 Routine Description:
1654 This function calculates the UINT16 sum for the requested region.
1658 Buffer Pointer to buffer containing byte data of component.
1659 Size Size of the buffer
1673 // Perform the word sum for buffer
1675 for (Index
= 0; Index
< Size
; Index
++) {
1676 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
1679 return (UINT16
) Sum
;
1685 FvBufCalculateChecksum16 (
1691 Routine Description::
1693 This function calculates the value needed for a valid UINT16 checksum
1697 Buffer Pointer to buffer containing byte data of component.
1698 Size Size of the buffer
1702 The 16 bit checksum value needed.
1706 return (UINT16
)(0x10000 - FvBufCalculateSum16 (Buffer
, Size
));
1712 FvBufCalculateSum8 (
1720 This function calculates the UINT8 sum for the requested region.
1724 Buffer Pointer to buffer containing byte data of component.
1725 Size Size of the buffer
1729 The 8 bit checksum value needed.
1739 // Perform the byte sum for buffer
1741 for (Index
= 0; Index
< Size
; Index
++) {
1742 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
1751 FvBufCalculateChecksum8 (
1759 This function calculates the value needed for a valid UINT8 checksum
1763 Buffer Pointer to buffer containing byte data of component.
1764 Size Size of the buffer
1768 The 8 bit checksum value needed.
1772 return (UINT8
)(0x100 - FvBufCalculateSum8 (Buffer
, Size
));