2 EFI Firmware Volume routines which work on a Fv image in buffers.
4 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "FirmwareVolumeBufferLib.h"
16 #include "BinderFuncs.h"
21 #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
24 (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
36 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
39 if (SectionHeader
== NULL
) {
42 if (FvBufExpand3ByteSize(SectionHeader
->Size
) == 0xffffff) {
43 return sizeof(EFI_COMMON_SECTION_HEADER2
);
45 return sizeof(EFI_COMMON_SECTION_HEADER
);
51 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
55 if (SectionHeader
== NULL
) {
58 Length
= FvBufExpand3ByteSize(SectionHeader
->Size
);
59 if (Length
== 0xffffff) {
60 Length
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
71 FvBufCalculateChecksum16 (
78 FvBufCalculateChecksum8 (
96 Clears out all files from the Fv buffer in memory
100 SourceFv - Address of the Fv in memory, this firmware volume volume will
101 be modified, if SourceFfsFile exists
102 SourceFfsFile - Input FFS file to replace
112 EFI_FFS_FILE_HEADER
* FileToRm
;
113 UINTN FileToRmLength
;
115 Status
= FvBufFindFileByName(
120 if (EFI_ERROR (Status
)) {
124 FileToRmLength
= FvBufGetFfsFileSize (FileToRm
);
126 CommonLibBinderSetMem (
129 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
)
146 Clears out all files from the Fv buffer in memory
150 SourceFv - Address of the Fv in memory, this firmware volume volume will
151 be modified, if SourceFfsFile exists
152 SourceFfsFile - Input FFS file to replace
162 EFI_FFS_FILE_HEADER
*NextFile
;
163 EFI_FIRMWARE_VOLUME_HEADER
*TempFv
;
167 Status
= FvBufFindFileByName(
172 if (EFI_ERROR (Status
)) {
176 Status
= FvBufGetSize (Fv
, &FvLength
);
177 if (EFI_ERROR (Status
)) {
182 Status
= FvBufDuplicate (Fv
, (VOID
**)&TempFv
);
183 if (EFI_ERROR (Status
)) {
187 Status
= FvBufClearAllFiles (TempFv
);
188 if (EFI_ERROR (Status
)) {
192 // TempFv has been allocated. It must now be freed
198 Status
= FvBufFindNextFile (Fv
, &FileKey
, (VOID
**)&NextFile
);
199 if (Status
== EFI_NOT_FOUND
) {
201 } else if (EFI_ERROR (Status
)) {
202 CommonLibBinderFree (TempFv
);
206 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
210 Status
= FvBufAddFile (TempFv
, NextFile
);
211 if (EFI_ERROR (Status
)) {
212 CommonLibBinderFree (TempFv
);
218 CommonLibBinderCopyMem (Fv
, TempFv
, FvLength
);
219 CommonLibBinderFree (TempFv
);
233 Clears out all files from the Fv buffer in memory
237 SourceFfsFile - Input FFS file to update the checksum for
246 EFI_FFS_FILE_HEADER
* File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
247 EFI_FFS_FILE_STATE StateBackup
;
250 FileSize
= FvBufGetFfsFileSize (File
);
253 // Fill in checksums and state, they must be 0 for checksumming.
255 File
->IntegrityCheck
.Checksum
.Header
= 0;
256 File
->IntegrityCheck
.Checksum
.File
= 0;
257 StateBackup
= File
->State
;
260 File
->IntegrityCheck
.Checksum
.Header
=
261 FvBufCalculateChecksum8 (
263 FvBufGetFfsHeaderSize (File
)
266 if (File
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
267 File
->IntegrityCheck
.Checksum
.File
= FvBufCalculateChecksum8 (
268 (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
)),
269 FileSize
- FvBufGetFfsHeaderSize (File
)
272 File
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
275 File
->State
= StateBackup
;
282 FvBufChecksumHeader (
289 Clears out all files from the Fv buffer in memory
293 SourceFv - Address of the Fv in memory, this firmware volume volume will
294 be modified, if SourceFfsFile exists
295 SourceFfsFile - Input FFS file to replace
304 EFI_FIRMWARE_VOLUME_HEADER
* FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
306 FvHeader
->Checksum
= 0;
308 FvBufCalculateChecksum16 (
310 FvHeader
->HeaderLength
/ sizeof (UINT16
)
320 IN OUT VOID
**DestinationFv
326 Clears out all files from the Fv buffer in memory
330 SourceFv - Address of the Fv in memory
331 DestinationFv - Output for destination Fv
332 DestinationFv == NULL - invalid parameter
333 *DestinationFv == NULL - memory will be allocated
334 *DestinationFv != NULL - this address will be the destination
345 if (DestinationFv
== NULL
) {
346 return EFI_INVALID_PARAMETER
;
349 Status
= FvBufGetSize (SourceFv
, &size
);
350 if (EFI_ERROR (Status
)) {
354 if (*DestinationFv
== NULL
) {
355 *DestinationFv
= CommonLibBinderAllocate (size
);
358 CommonLibBinderCopyMem (*DestinationFv
, SourceFv
, size
);
373 Extends a firmware volume by the given number of bytes.
375 BUGBUG: Does not handle the case where the firmware volume has a
376 VTF (Volume Top File). The VTF will not be moved to the
377 end of the extended FV.
381 Fv - Source and destination firmware volume.
382 Note: The original firmware volume buffer is freed!
384 Size - The minimum size that the firmware volume is to be extended by.
385 The FV may be extended more than this size.
399 EFI_FIRMWARE_VOLUME_HEADER
* hdr
;
400 EFI_FV_BLOCK_MAP_ENTRY
* blk
;
402 Status
= FvBufGetSize (*Fv
, &OldSize
);
403 if (EFI_ERROR (Status
)) {
408 // Locate the block map in the fv header
410 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)*Fv
;
414 // Calculate the number of blocks needed to achieve the requested
417 BlockCount
= ((Size
+ (blk
->Length
- 1)) / blk
->Length
);
420 // Calculate the new size from the number of blocks that will be added
422 NewSize
= OldSize
+ (BlockCount
* blk
->Length
);
424 NewFv
= CommonLibBinderAllocate (NewSize
);
426 return EFI_OUT_OF_RESOURCES
;
432 CommonLibBinderCopyMem (NewFv
, *Fv
, OldSize
);
435 // Free the old fv buffer
437 CommonLibBinderFree (*Fv
);
440 // Locate the block map in the new fv header
442 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)NewFv
;
443 hdr
->FvLength
= NewSize
;
447 // Update the block map for the new fv
449 blk
->NumBlocks
+= (UINT32
)BlockCount
;
452 // Update the FV header checksum
454 FvBufChecksumHeader (NewFv
);
457 // Clear out the new area of the FV
459 CommonLibBinderSetMem (
460 (UINT8
*)NewFv
+ OldSize
,
462 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
466 // Set output with new fv that was created
483 Clears out all files from the Fv buffer in memory
487 Fv - Address of the Fv in memory
496 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
500 Status
= FvBufGetSize (Fv
, &size
);
501 if (EFI_ERROR (Status
)) {
505 CommonLibBinderSetMem(
506 (UINT8
*)hdr
+ hdr
->HeaderLength
,
507 size
- hdr
->HeaderLength
,
508 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
524 Clears out all files from the Fv buffer in memory
528 Fv - Address of the Fv in memory
537 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
538 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
542 while (blk
->Length
!= 0 || blk
->NumBlocks
!= 0) {
543 *Size
= *Size
+ (blk
->Length
* blk
->NumBlocks
);
544 if (*Size
>= 0x40000000) {
545 // If size is greater than 1GB, then assume it is corrupted
546 return EFI_VOLUME_CORRUPTED
;
552 // If size is 0, then assume the volume is corrupted
553 return EFI_VOLUME_CORRUPTED
;
573 Fv - Address of the Fv in memory
574 File - FFS file to add to Fv
582 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
584 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
585 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
594 Status
= FvBufGetSize (Fv
, &fvSize
);
595 if (EFI_ERROR (Status
)) {
599 FvbAttributes
= hdr
->Attributes
;
600 newSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
603 offset
= (UINTN
)ALIGN_POINTER (hdr
->HeaderLength
, 8);
604 offset
+ newSize
<= fvSize
;
605 offset
= (UINTN
)ALIGN_POINTER (offset
, 8)
608 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ offset
);
610 if (EFI_TEST_FFS_ATTRIBUTES_BIT(
613 EFI_FILE_HEADER_VALID
616 // BUGBUG: Need to make sure that the new file does not already
619 fsize
= FvBufGetFfsFileSize (fhdr
);
620 if (fsize
== 0 || (offset
+ fsize
> fvSize
)) {
621 return EFI_VOLUME_CORRUPTED
;
624 offset
= offset
+ fsize
;
629 while ((clearLoop
< newSize
) &&
630 (((UINT8
*)fhdr
)[clearLoop
] ==
631 (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0)
638 // We found a place in the FV which is empty and big enough for
641 if (clearLoop
>= newSize
) {
645 offset
= offset
+ 1; // Make some forward progress
648 if (offset
+ newSize
> fvSize
) {
649 return EFI_OUT_OF_RESOURCES
;
652 CommonLibBinderCopyMem (fhdr
, File
, newSize
);
659 FvBufAddFileWithExtend (
667 Adds a new FFS file. Extends the firmware volume if needed.
671 Fv - Source and destination firmware volume.
672 Note: If the FV is extended, then the original firmware volume
675 Size - The minimum size that the firmware volume is to be extended by.
676 The FV may be extended more than this size.
685 EFI_FFS_FILE_HEADER
* NewFile
;
687 NewFile
= (EFI_FFS_FILE_HEADER
*)File
;
690 // Try to add to the capsule volume
692 Status
= FvBufAddFile (*Fv
, NewFile
);
693 if (Status
== EFI_OUT_OF_RESOURCES
) {
695 // Try to extend the capsule volume by the size of the file
697 Status
= FvBufExtend (Fv
, FvBufExpand3ByteSize (NewFile
->Size
));
698 if (EFI_ERROR (Status
)) {
703 // Now, try to add the file again
705 Status
= FvBufAddFile (*Fv
, NewFile
);
721 Adds a new FFS VFT (Volume Top File) file. In other words, adds the
722 file to the end of the firmware volume.
726 Fv - Address of the Fv in memory
727 File - FFS file to add to Fv
737 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
739 EFI_FFS_FILE_HEADER
* NewFile
;
745 EFI_FFS_FILE_HEADER
*LastFile
;
751 Status
= FvBufGetSize (Fv
, &fvSize
);
752 if (EFI_ERROR (Status
)) {
756 erasedUint8
= (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0);
757 NewFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
759 if (NewFileSize
!= (UINTN
)ALIGN_POINTER (NewFileSize
, 8)) {
760 return EFI_INVALID_PARAMETER
;
764 // Find the last file in the FV
770 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&LastFile
);
771 LastFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
772 } while (!EFI_ERROR (Status
));
775 // If no files were found, then we start at the beginning of the FV
777 if (LastFile
== NULL
) {
778 LastFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ hdr
->HeaderLength
);
782 // We want to put the new file (VTF) at the end of the FV
784 NewFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ (fvSize
- NewFileSize
));
787 // Check to see if there is enough room for the VTF after the last file
790 if ((UINT8
*)NewFile
< ((UINT8
*)LastFile
+ LastFileSize
)) {
791 return EFI_OUT_OF_RESOURCES
;
795 // Loop to determine if the end of the FV is empty
798 while ((clearLoop
< NewFileSize
) &&
799 (((UINT8
*)NewFile
)[clearLoop
] == erasedUint8
)
805 // Check to see if there was not enough room for the file
807 if (clearLoop
< NewFileSize
) {
808 return EFI_OUT_OF_RESOURCES
;
811 CommonLibBinderCopyMem (NewFile
, File
, NewFileSize
);
818 FvBufCompact3ByteSize (
826 Expands the 3 byte size commonly used in Firmware Volume data structures
830 Size - Address of the 3 byte array representing the size
838 ((UINT8
*)SizeDest
)[0] = (UINT8
)Size
;
839 ((UINT8
*)SizeDest
)[1] = (UINT8
)(Size
>> 8);
840 ((UINT8
*)SizeDest
)[2] = (UINT8
)(Size
>> 16);
844 FvBufGetFfsFileSize (
845 IN EFI_FFS_FILE_HEADER
*Ffs
851 Get the FFS file size.
855 Ffs - Pointer to FFS header
866 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
867 return ((EFI_FFS_FILE_HEADER2
*)Ffs
)->ExtendedSize
;
869 return FvBufExpand3ByteSize(Ffs
->Size
);
873 FvBufGetFfsHeaderSize (
874 IN EFI_FFS_FILE_HEADER
*Ffs
880 Get the FFS header size.
884 Ffs - Pointer to FFS header
895 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
896 return sizeof(EFI_FFS_FILE_HEADER2
);
898 return sizeof(EFI_FFS_FILE_HEADER
);
902 FvBufExpand3ByteSize (
909 Expands the 3 byte size commonly used in Firmware Volume data structures
913 Size - Address of the 3 byte array representing the size
921 return (((UINT8
*)Size
)[2] << 16) +
922 (((UINT8
*)Size
)[1] << 8) +
936 Iterates through the files contained within the firmware volume
940 Fv - Address of the Fv in memory
941 Key - Should be 0 to get the first file. After that, it should be
942 passed back in without modifying it's contents to retrieve
944 File - Output file pointer
945 File == NULL - invalid parameter
946 otherwise - *File will be update to the location of the file
956 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
958 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
959 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
966 return EFI_INVALID_PARAMETER
;
969 Status
= FvBufGetSize (Fv
, &fvSize
);
970 if (EFI_ERROR (Status
)) {
975 *Key
= hdr
->HeaderLength
;
978 FvbAttributes
= hdr
->Attributes
;
981 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8);
982 (*Key
+ sizeof (*fhdr
)) < fvSize
;
983 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8)
986 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ *Key
);
987 fsize
= FvBufGetFfsFileSize (fhdr
);
989 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
992 EFI_FILE_HEADER_VALID
994 EFI_TEST_FFS_ATTRIBUTES_BIT(
997 EFI_FILE_HEADER_INVALID
1000 *Key
= *Key
+ 1; // Make some forward progress
1003 EFI_TEST_FFS_ATTRIBUTES_BIT(
1006 EFI_FILE_MARKED_FOR_UPDATE
1008 EFI_TEST_FFS_ATTRIBUTES_BIT(
1014 *Key
= *Key
+ fsize
;
1016 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1022 *File
= (UINT8
*)hdr
+ *Key
;
1023 *Key
= *Key
+ fsize
;
1027 *Key
= *Key
+ 1; // Make some forward progress
1030 return EFI_NOT_FOUND
;
1035 FvBufFindFileByName (
1042 Routine Description:
1044 Searches the Fv for a file by its name
1048 Fv - Address of the Fv in memory
1049 Name - Guid filename to search for in the firmware volume
1050 File - Output file pointer
1051 File == NULL - Only determine if the file exists, based on return
1052 value from the function call.
1053 otherwise - *File will be update to the location of the file
1059 EFI_VOLUME_CORRUPTED
1065 EFI_FFS_FILE_HEADER
*NextFile
;
1069 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1070 if (EFI_ERROR (Status
)) {
1074 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
1082 return EFI_NOT_FOUND
;
1087 FvBufFindFileByType (
1089 IN EFI_FV_FILETYPE Type
,
1094 Routine Description:
1096 Searches the Fv for a file by its type
1100 Fv - Address of the Fv in memory
1101 Type - FFS FILE type to search for
1102 File - Output file pointer
1103 (File == NULL) -> Only determine if the file exists, based on return
1104 value from the function call.
1105 otherwise -> *File will be update to the location of the file
1111 EFI_VOLUME_CORRUPTED
1117 EFI_FFS_FILE_HEADER
*NextFile
;
1121 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1122 if (EFI_ERROR (Status
)) {
1126 if (Type
== NextFile
->Type
) {
1134 return EFI_NOT_FOUND
;
1139 FvBufGetFileRawData (
1142 OUT UINTN
* RawDataSize
1146 Routine Description:
1148 Searches the requested file for raw data.
1150 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1151 or finds the EFI_SECTION_RAW section within the file and returns its data.
1155 FfsFile - Address of the FFS file in memory
1156 RawData - Pointer to the raw data within the file
1157 (This is NOT allocated. It is within the file.)
1158 RawDataSize - Size of the raw data within the file
1167 EFI_FFS_FILE_HEADER
* File
;
1168 EFI_RAW_SECTION
* Section
;
1170 File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
1173 // Is the file type == EFI_FV_FILETYPE_RAW?
1175 if (File
->Type
== EFI_FV_FILETYPE_RAW
) {
1177 // Raw filetypes don't have sections, so we just return the raw data
1179 *RawData
= (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
));
1180 *RawDataSize
= FvBufGetFfsFileSize (File
) - FvBufGetFfsHeaderSize (File
);
1185 // Within the file, we now need to find the EFI_SECTION_RAW section.
1187 Status
= FvBufFindSectionByType (File
, EFI_SECTION_RAW
, (VOID
**)&Section
);
1188 if (EFI_ERROR (Status
)) {
1192 *RawData
= (VOID
*)((UINT8
*)Section
+ FvBufGetSecHdrLen(Section
));
1194 FvBufGetSecFileLen (Section
) - FvBufGetSecHdrLen(Section
);
1202 FvBufPackageFreeformRawFile (
1203 IN EFI_GUID
* Filename
,
1205 IN UINTN RawDataSize
,
1210 Routine Description:
1212 Packages up a FFS file containing the input raw data.
1214 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1215 contain one EFI_FV_FILETYPE_RAW section.
1219 RawData - Pointer to the raw data to be packed
1220 RawDataSize - Size of the raw data to be packed
1221 FfsFile - Address of the packaged FFS file.
1222 Note: The called must deallocate this memory!
1230 EFI_FFS_FILE_HEADER
* NewFile
;
1232 EFI_RAW_SECTION
* NewSection
;
1233 UINT32 NewSectionSize
;
1238 // The section size is the DataSize + the size of the section header
1240 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION
) + (UINT32
)RawDataSize
;
1241 SecHdrLen
= sizeof (EFI_RAW_SECTION
);
1242 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1243 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION2
) + (UINT32
)RawDataSize
;
1244 SecHdrLen
= sizeof (EFI_RAW_SECTION2
);
1248 // The file size is the size of the file header + the section size
1250 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER
) + NewSectionSize
;
1251 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER
);
1252 if (NewFileSize
>= MAX_FFS_SIZE
) {
1253 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER2
) + NewSectionSize
;
1254 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER2
);
1258 // Try to allocate a buffer to build the new FFS file in
1260 NewFile
= CommonLibBinderAllocate (NewFileSize
);
1261 if (NewFile
== NULL
) {
1262 return EFI_OUT_OF_RESOURCES
;
1264 CommonLibBinderSetMem (NewFile
, NewFileSize
, 0);
1267 // The NewSection follow right after the FFS file header
1269 NewSection
= (EFI_RAW_SECTION
*)((UINT8
*)NewFile
+ FfsHdrLen
);
1270 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1271 FvBufCompact3ByteSize (NewSection
->Size
, 0xffffff);
1272 ((EFI_RAW_SECTION2
*)NewSection
)->ExtendedSize
= NewSectionSize
;
1274 FvBufCompact3ByteSize (NewSection
->Size
, NewSectionSize
);
1276 NewSection
->Type
= EFI_SECTION_RAW
;
1279 // Copy the actual file data into the buffer
1281 CommonLibBinderCopyMem ((UINT8
*)NewSection
+ SecHdrLen
, RawData
, RawDataSize
);
1284 // Initialize the FFS file header
1286 CommonLibBinderCopyMem (&NewFile
->Name
, Filename
, sizeof (EFI_GUID
));
1287 NewFile
->Attributes
= 0;
1288 if (NewFileSize
>= MAX_FFS_SIZE
) {
1289 FvBufCompact3ByteSize (NewFile
->Size
, 0x0);
1290 ((EFI_FFS_FILE_HEADER2
*)NewFile
)->ExtendedSize
= NewFileSize
;
1291 NewFile
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
1293 FvBufCompact3ByteSize (NewFile
->Size
, NewFileSize
);
1295 NewFile
->Type
= EFI_FV_FILETYPE_FREEFORM
;
1296 NewFile
->IntegrityCheck
.Checksum
.Header
=
1297 FvBufCalculateChecksum8 ((UINT8
*)NewFile
, FfsHdrLen
);
1298 NewFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1299 NewFile
->State
= (UINT8
)~( EFI_FILE_HEADER_CONSTRUCTION
|
1300 EFI_FILE_HEADER_VALID
|
1311 FvBufFindNextSection (
1312 IN VOID
*SectionsStart
,
1313 IN UINTN TotalSectionsSize
,
1319 Routine Description:
1321 Iterates through the sections contained within a given array of sections
1325 SectionsStart - Address of the start of the FFS sections array
1326 TotalSectionsSize - Total size of all the sections
1327 Key - Should be 0 to get the first section. After that, it should be
1328 passed back in without modifying it's contents to retrieve
1330 Section - Output section pointer
1331 (Section == NULL) -> invalid parameter
1332 otherwise -> *Section will be update to the location of the file
1338 EFI_VOLUME_CORRUPTED
1342 EFI_COMMON_SECTION_HEADER
*sectionHdr
;
1345 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 4); // Sections are DWORD aligned
1347 if ((*Key
+ sizeof (*sectionHdr
)) > TotalSectionsSize
) {
1348 return EFI_NOT_FOUND
;
1351 sectionHdr
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)SectionsStart
+ *Key
);
1352 sectionSize
= FvBufGetSecFileLen (sectionHdr
);
1354 if (sectionSize
< sizeof (EFI_COMMON_SECTION_HEADER
)) {
1355 return EFI_NOT_FOUND
;
1358 if ((*Key
+ sectionSize
) > TotalSectionsSize
) {
1359 return EFI_NOT_FOUND
;
1362 *Section
= (UINT8
*)sectionHdr
;
1363 *Key
= *Key
+ sectionSize
;
1370 FvBufCountSections (
1376 Routine Description:
1378 Searches the FFS file and counts the number of sections found.
1379 The sections are NOT recursed.
1383 FfsFile - Address of the FFS file in memory
1384 Count - The location to store the section count in
1390 EFI_VOLUME_CORRUPTED
1397 UINTN TotalSectionsSize
;
1398 EFI_COMMON_SECTION_HEADER
* NextSection
;
1400 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1402 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1403 FvBufGetFfsHeaderSize(FfsFile
);
1407 Status
= FvBufFindNextSection (
1411 (VOID
**)&NextSection
1413 if (Status
== EFI_NOT_FOUND
) {
1415 } else if (EFI_ERROR (Status
)) {
1420 // Increment the section counter
1426 return EFI_NOT_FOUND
;
1431 FvBufFindSectionByType (
1438 Routine Description:
1440 Searches the FFS file for a section by its type
1444 FfsFile - Address of the FFS file in memory
1445 Type - FFS FILE section type to search for
1446 Section - Output section pointer
1447 (Section == NULL) -> Only determine if the section exists, based on return
1448 value from the function call.
1449 otherwise -> *Section will be update to the location of the file
1455 EFI_VOLUME_CORRUPTED
1462 UINTN TotalSectionsSize
;
1463 EFI_COMMON_SECTION_HEADER
* NextSection
;
1465 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1467 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1468 FvBufGetFfsHeaderSize(FfsFile
);
1471 Status
= FvBufFindNextSection (
1475 (VOID
**)&NextSection
1477 if (EFI_ERROR (Status
)) {
1481 if (Type
== NextSection
->Type
) {
1482 if (Section
!= NULL
) {
1483 *Section
= NextSection
;
1489 return EFI_NOT_FOUND
;
1499 Routine Description:
1501 Shrinks a firmware volume (in place) to provide a minimal FV.
1503 BUGBUG: Does not handle the case where the firmware volume has a
1504 VTF (Volume Top File). The VTF will not be moved to the
1505 end of the extended FV.
1509 Fv - Firmware volume.
1520 UINT32 NewBlockSize
= 128;
1522 EFI_FFS_FILE_HEADER
* FileIt
;
1523 VOID
* EndOfLastFile
;
1525 EFI_FIRMWARE_VOLUME_HEADER
* FvHdr
;
1527 Status
= FvBufGetSize (Fv
, &OldSize
);
1528 if (EFI_ERROR (Status
)) {
1532 Status
= FvBufUnifyBlockSizes (Fv
, NewBlockSize
);
1533 if (EFI_ERROR (Status
)) {
1538 // Locate the block map in the fv header
1540 FvHdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1543 // Find the end of the last file
1546 EndOfLastFile
= (UINT8
*)FvHdr
+ FvHdr
->FvLength
;
1547 while (!EFI_ERROR (FvBufFindNextFile (Fv
, &Key
, (VOID
**)&FileIt
))) {
1549 (VOID
*)((UINT8
*)FileIt
+ FvBufGetFfsFileSize (FileIt
));
1553 // Set the BlockCount to have the minimal number of blocks for the Fv.
1555 BlockCount
= (UINT32
)((UINTN
)EndOfLastFile
- (UINTN
)Fv
);
1556 BlockCount
= BlockCount
+ NewBlockSize
- 1;
1557 BlockCount
= BlockCount
/ NewBlockSize
;
1560 // Adjust the block count to shrink the Fv in place.
1562 FvHdr
->BlockMap
[0].NumBlocks
= BlockCount
;
1563 FvHdr
->FvLength
= BlockCount
* NewBlockSize
;
1566 // Update the FV header checksum
1568 FvBufChecksumHeader (Fv
);
1576 FvBufUnifyBlockSizes (
1582 Routine Description:
1584 Searches the FFS file for a section by its type
1588 Fv - Address of the Fv in memory
1589 BlockSize - The size of the blocks to convert the Fv to. If the total size
1590 of the Fv is not evenly divisible by this size, then
1591 EFI_INVALID_PARAMETER will be returned.
1597 EFI_VOLUME_CORRUPTED
1601 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1602 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
1608 // Scan through the block map list, performing error checking, and adding
1609 // up the total Fv size.
1611 while( blk
->Length
!= 0 ||
1614 Size
= Size
+ (blk
->Length
* blk
->NumBlocks
);
1616 if ((UINT8
*)blk
> ((UINT8
*)hdr
+ hdr
->HeaderLength
)) {
1617 return EFI_VOLUME_CORRUPTED
;
1622 // Make sure that the Fv size is a multiple of the new block size.
1624 if ((Size
% BlockSize
) != 0) {
1625 return EFI_INVALID_PARAMETER
;
1629 // Zero out the entire block map.
1631 CommonLibBinderSetMem (
1633 (UINTN
)blk
- (UINTN
)&hdr
->BlockMap
,
1638 // Write out the single block map entry.
1640 hdr
->BlockMap
[0].Length
= (UINT32
)BlockSize
;
1641 hdr
->BlockMap
[0].NumBlocks
= Size
/ (UINT32
)BlockSize
;
1648 FvBufCalculateSum16 (
1654 Routine Description:
1656 This function calculates the UINT16 sum for the requested region.
1660 Buffer Pointer to buffer containing byte data of component.
1661 Size Size of the buffer
1675 // Perform the word sum for buffer
1677 for (Index
= 0; Index
< Size
; Index
++) {
1678 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
1681 return (UINT16
) Sum
;
1687 FvBufCalculateChecksum16 (
1693 Routine Description::
1695 This function calculates the value needed for a valid UINT16 checksum
1699 Buffer Pointer to buffer containing byte data of component.
1700 Size Size of the buffer
1704 The 16 bit checksum value needed.
1708 return (UINT16
)(0x10000 - FvBufCalculateSum16 (Buffer
, Size
));
1714 FvBufCalculateSum8 (
1722 This function calculates the UINT8 sum for the requested region.
1726 Buffer Pointer to buffer containing byte data of component.
1727 Size Size of the buffer
1731 The 8 bit checksum value needed.
1741 // Perform the byte sum for buffer
1743 for (Index
= 0; Index
< Size
; Index
++) {
1744 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
1753 FvBufCalculateChecksum8 (
1761 This function calculates the value needed for a valid UINT8 checksum
1765 Buffer Pointer to buffer containing byte data of component.
1766 Size Size of the buffer
1770 The 8 bit checksum value needed.
1774 return (UINT8
)(0x100 - FvBufCalculateSum8 (Buffer
, Size
));