2 EFI Firmware Volume routines which work on a Fv image in buffers.
4 Copyright (c) 1999 - 2016, 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
)) {
189 CommonLibBinderFree (TempFv
);
193 // TempFv has been allocated. It must now be freed
199 Status
= FvBufFindNextFile (Fv
, &FileKey
, (VOID
**)&NextFile
);
200 if (Status
== EFI_NOT_FOUND
) {
202 } else if (EFI_ERROR (Status
)) {
203 CommonLibBinderFree (TempFv
);
207 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
211 Status
= FvBufAddFile (TempFv
, NextFile
);
212 if (EFI_ERROR (Status
)) {
213 CommonLibBinderFree (TempFv
);
219 CommonLibBinderCopyMem (Fv
, TempFv
, FvLength
);
220 CommonLibBinderFree (TempFv
);
234 Clears out all files from the Fv buffer in memory
238 SourceFfsFile - Input FFS file to update the checksum for
247 EFI_FFS_FILE_HEADER
* File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
248 EFI_FFS_FILE_STATE StateBackup
;
251 FileSize
= FvBufGetFfsFileSize (File
);
254 // Fill in checksums and state, they must be 0 for checksumming.
256 File
->IntegrityCheck
.Checksum
.Header
= 0;
257 File
->IntegrityCheck
.Checksum
.File
= 0;
258 StateBackup
= File
->State
;
261 File
->IntegrityCheck
.Checksum
.Header
=
262 FvBufCalculateChecksum8 (
264 FvBufGetFfsHeaderSize (File
)
267 if (File
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
268 File
->IntegrityCheck
.Checksum
.File
= FvBufCalculateChecksum8 (
269 (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
)),
270 FileSize
- FvBufGetFfsHeaderSize (File
)
273 File
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
276 File
->State
= StateBackup
;
283 FvBufChecksumHeader (
290 Clears out all files from the Fv buffer in memory
294 SourceFv - Address of the Fv in memory, this firmware volume volume will
295 be modified, if SourceFfsFile exists
296 SourceFfsFile - Input FFS file to replace
305 EFI_FIRMWARE_VOLUME_HEADER
* FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
307 FvHeader
->Checksum
= 0;
309 FvBufCalculateChecksum16 (
311 FvHeader
->HeaderLength
/ sizeof (UINT16
)
321 IN OUT VOID
**DestinationFv
327 Clears out all files from the Fv buffer in memory
331 SourceFv - Address of the Fv in memory
332 DestinationFv - Output for destination Fv
333 DestinationFv == NULL - invalid parameter
334 *DestinationFv == NULL - memory will be allocated
335 *DestinationFv != NULL - this address will be the destination
346 if (DestinationFv
== NULL
) {
347 return EFI_INVALID_PARAMETER
;
350 Status
= FvBufGetSize (SourceFv
, &size
);
351 if (EFI_ERROR (Status
)) {
355 if (*DestinationFv
== NULL
) {
356 *DestinationFv
= CommonLibBinderAllocate (size
);
357 if (*DestinationFv
== NULL
) {
358 return EFI_OUT_OF_RESOURCES
;
362 CommonLibBinderCopyMem (*DestinationFv
, SourceFv
, size
);
377 Extends a firmware volume by the given number of bytes.
379 BUGBUG: Does not handle the case where the firmware volume has a
380 VTF (Volume Top File). The VTF will not be moved to the
381 end of the extended FV.
385 Fv - Source and destination firmware volume.
386 Note: The original firmware volume buffer is freed!
388 Size - The minimum size that the firmware volume is to be extended by.
389 The FV may be extended more than this size.
403 EFI_FIRMWARE_VOLUME_HEADER
* hdr
;
404 EFI_FV_BLOCK_MAP_ENTRY
* blk
;
406 Status
= FvBufGetSize (*Fv
, &OldSize
);
407 if (EFI_ERROR (Status
)) {
412 // Locate the block map in the fv header
414 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)*Fv
;
418 // Calculate the number of blocks needed to achieve the requested
421 BlockCount
= ((Size
+ (blk
->Length
- 1)) / blk
->Length
);
424 // Calculate the new size from the number of blocks that will be added
426 NewSize
= OldSize
+ (BlockCount
* blk
->Length
);
428 NewFv
= CommonLibBinderAllocate (NewSize
);
430 return EFI_OUT_OF_RESOURCES
;
436 CommonLibBinderCopyMem (NewFv
, *Fv
, OldSize
);
439 // Free the old fv buffer
441 CommonLibBinderFree (*Fv
);
444 // Locate the block map in the new fv header
446 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)NewFv
;
447 hdr
->FvLength
= NewSize
;
451 // Update the block map for the new fv
453 blk
->NumBlocks
+= (UINT32
)BlockCount
;
456 // Update the FV header checksum
458 FvBufChecksumHeader (NewFv
);
461 // Clear out the new area of the FV
463 CommonLibBinderSetMem (
464 (UINT8
*)NewFv
+ OldSize
,
466 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
470 // Set output with new fv that was created
487 Clears out all files from the Fv buffer in memory
491 Fv - Address of the Fv in memory
500 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
504 Status
= FvBufGetSize (Fv
, &size
);
505 if (EFI_ERROR (Status
)) {
509 CommonLibBinderSetMem(
510 (UINT8
*)hdr
+ hdr
->HeaderLength
,
511 size
- hdr
->HeaderLength
,
512 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
528 Clears out all files from the Fv buffer in memory
532 Fv - Address of the Fv in memory
541 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
542 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
546 while (blk
->Length
!= 0 || blk
->NumBlocks
!= 0) {
547 *Size
= *Size
+ (blk
->Length
* blk
->NumBlocks
);
548 if (*Size
>= 0x40000000) {
549 // If size is greater than 1GB, then assume it is corrupted
550 return EFI_VOLUME_CORRUPTED
;
556 // If size is 0, then assume the volume is corrupted
557 return EFI_VOLUME_CORRUPTED
;
577 Fv - Address of the Fv in memory
578 File - FFS file to add to Fv
586 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
588 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
589 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
598 Status
= FvBufGetSize (Fv
, &fvSize
);
599 if (EFI_ERROR (Status
)) {
603 FvbAttributes
= hdr
->Attributes
;
604 newSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
607 offset
= (UINTN
)ALIGN_POINTER (hdr
->HeaderLength
, 8);
608 offset
+ newSize
<= fvSize
;
609 offset
= (UINTN
)ALIGN_POINTER (offset
, 8)
612 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ offset
);
614 if (EFI_TEST_FFS_ATTRIBUTES_BIT(
617 EFI_FILE_HEADER_VALID
620 // BUGBUG: Need to make sure that the new file does not already
623 fsize
= FvBufGetFfsFileSize (fhdr
);
624 if (fsize
== 0 || (offset
+ fsize
> fvSize
)) {
625 return EFI_VOLUME_CORRUPTED
;
628 offset
= offset
+ fsize
;
633 while ((clearLoop
< newSize
) &&
634 (((UINT8
*)fhdr
)[clearLoop
] ==
635 (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0)
642 // We found a place in the FV which is empty and big enough for
645 if (clearLoop
>= newSize
) {
649 offset
= offset
+ 1; // Make some forward progress
652 if (offset
+ newSize
> fvSize
) {
653 return EFI_OUT_OF_RESOURCES
;
656 CommonLibBinderCopyMem (fhdr
, File
, newSize
);
663 FvBufAddFileWithExtend (
671 Adds a new FFS file. Extends the firmware volume if needed.
675 Fv - Source and destination firmware volume.
676 Note: If the FV is extended, then the original firmware volume
679 Size - The minimum size that the firmware volume is to be extended by.
680 The FV may be extended more than this size.
689 EFI_FFS_FILE_HEADER
* NewFile
;
691 NewFile
= (EFI_FFS_FILE_HEADER
*)File
;
694 // Try to add to the capsule volume
696 Status
= FvBufAddFile (*Fv
, NewFile
);
697 if (Status
== EFI_OUT_OF_RESOURCES
) {
699 // Try to extend the capsule volume by the size of the file
701 Status
= FvBufExtend (Fv
, FvBufExpand3ByteSize (NewFile
->Size
));
702 if (EFI_ERROR (Status
)) {
707 // Now, try to add the file again
709 Status
= FvBufAddFile (*Fv
, NewFile
);
725 Adds a new FFS VFT (Volume Top File) file. In other words, adds the
726 file to the end of the firmware volume.
730 Fv - Address of the Fv in memory
731 File - FFS file to add to Fv
741 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
743 EFI_FFS_FILE_HEADER
* NewFile
;
749 EFI_FFS_FILE_HEADER
*LastFile
;
755 Status
= FvBufGetSize (Fv
, &fvSize
);
756 if (EFI_ERROR (Status
)) {
760 erasedUint8
= (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0);
761 NewFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
763 if (NewFileSize
!= (UINTN
)ALIGN_POINTER (NewFileSize
, 8)) {
764 return EFI_INVALID_PARAMETER
;
768 // Find the last file in the FV
774 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&LastFile
);
775 LastFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
776 } while (!EFI_ERROR (Status
));
779 // If no files were found, then we start at the beginning of the FV
781 if (LastFile
== NULL
) {
782 LastFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ hdr
->HeaderLength
);
786 // We want to put the new file (VTF) at the end of the FV
788 NewFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ (fvSize
- NewFileSize
));
791 // Check to see if there is enough room for the VTF after the last file
794 if ((UINT8
*)NewFile
< ((UINT8
*)LastFile
+ LastFileSize
)) {
795 return EFI_OUT_OF_RESOURCES
;
799 // Loop to determine if the end of the FV is empty
802 while ((clearLoop
< NewFileSize
) &&
803 (((UINT8
*)NewFile
)[clearLoop
] == erasedUint8
)
809 // Check to see if there was not enough room for the file
811 if (clearLoop
< NewFileSize
) {
812 return EFI_OUT_OF_RESOURCES
;
815 CommonLibBinderCopyMem (NewFile
, File
, NewFileSize
);
822 FvBufCompact3ByteSize (
830 Expands the 3 byte size commonly used in Firmware Volume data structures
834 Size - Address of the 3 byte array representing the size
842 ((UINT8
*)SizeDest
)[0] = (UINT8
)Size
;
843 ((UINT8
*)SizeDest
)[1] = (UINT8
)(Size
>> 8);
844 ((UINT8
*)SizeDest
)[2] = (UINT8
)(Size
>> 16);
848 FvBufGetFfsFileSize (
849 IN EFI_FFS_FILE_HEADER
*Ffs
855 Get the FFS file size.
859 Ffs - Pointer to FFS header
870 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
871 return (UINT32
) ((EFI_FFS_FILE_HEADER2
*)Ffs
)->ExtendedSize
;
873 return FvBufExpand3ByteSize(Ffs
->Size
);
877 FvBufGetFfsHeaderSize (
878 IN EFI_FFS_FILE_HEADER
*Ffs
884 Get the FFS header size.
888 Ffs - Pointer to FFS header
899 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
900 return sizeof(EFI_FFS_FILE_HEADER2
);
902 return sizeof(EFI_FFS_FILE_HEADER
);
906 FvBufExpand3ByteSize (
913 Expands the 3 byte size commonly used in Firmware Volume data structures
917 Size - Address of the 3 byte array representing the size
925 return (((UINT8
*)Size
)[2] << 16) +
926 (((UINT8
*)Size
)[1] << 8) +
940 Iterates through the files contained within the firmware volume
944 Fv - Address of the Fv in memory
945 Key - Should be 0 to get the first file. After that, it should be
946 passed back in without modifying it's contents to retrieve
948 File - Output file pointer
949 File == NULL - invalid parameter
950 otherwise - *File will be update to the location of the file
960 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
962 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
963 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
970 return EFI_INVALID_PARAMETER
;
973 Status
= FvBufGetSize (Fv
, &fvSize
);
974 if (EFI_ERROR (Status
)) {
979 *Key
= hdr
->HeaderLength
;
982 FvbAttributes
= hdr
->Attributes
;
985 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8);
986 (*Key
+ sizeof (*fhdr
)) < fvSize
;
987 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8)
990 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ *Key
);
991 fsize
= FvBufGetFfsFileSize (fhdr
);
993 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
996 EFI_FILE_HEADER_VALID
998 EFI_TEST_FFS_ATTRIBUTES_BIT(
1001 EFI_FILE_HEADER_INVALID
1004 *Key
= *Key
+ 1; // Make some forward progress
1007 EFI_TEST_FFS_ATTRIBUTES_BIT(
1010 EFI_FILE_MARKED_FOR_UPDATE
1012 EFI_TEST_FFS_ATTRIBUTES_BIT(
1018 *Key
= *Key
+ fsize
;
1020 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1026 *File
= (UINT8
*)hdr
+ *Key
;
1027 *Key
= *Key
+ fsize
;
1031 *Key
= *Key
+ 1; // Make some forward progress
1034 return EFI_NOT_FOUND
;
1039 FvBufFindFileByName (
1046 Routine Description:
1048 Searches the Fv for a file by its name
1052 Fv - Address of the Fv in memory
1053 Name - Guid filename to search for in the firmware volume
1054 File - Output file pointer
1055 File == NULL - Only determine if the file exists, based on return
1056 value from the function call.
1057 otherwise - *File will be update to the location of the file
1063 EFI_VOLUME_CORRUPTED
1069 EFI_FFS_FILE_HEADER
*NextFile
;
1073 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1074 if (EFI_ERROR (Status
)) {
1078 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
1086 return EFI_NOT_FOUND
;
1091 FvBufFindFileByType (
1093 IN EFI_FV_FILETYPE Type
,
1098 Routine Description:
1100 Searches the Fv for a file by its type
1104 Fv - Address of the Fv in memory
1105 Type - FFS FILE type to search for
1106 File - Output file pointer
1107 (File == NULL) -> Only determine if the file exists, based on return
1108 value from the function call.
1109 otherwise -> *File will be update to the location of the file
1115 EFI_VOLUME_CORRUPTED
1121 EFI_FFS_FILE_HEADER
*NextFile
;
1125 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1126 if (EFI_ERROR (Status
)) {
1130 if (Type
== NextFile
->Type
) {
1138 return EFI_NOT_FOUND
;
1143 FvBufGetFileRawData (
1146 OUT UINTN
* RawDataSize
1150 Routine Description:
1152 Searches the requested file for raw data.
1154 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1155 or finds the EFI_SECTION_RAW section within the file and returns its data.
1159 FfsFile - Address of the FFS file in memory
1160 RawData - Pointer to the raw data within the file
1161 (This is NOT allocated. It is within the file.)
1162 RawDataSize - Size of the raw data within the file
1171 EFI_FFS_FILE_HEADER
* File
;
1172 EFI_RAW_SECTION
* Section
;
1174 File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
1177 // Is the file type == EFI_FV_FILETYPE_RAW?
1179 if (File
->Type
== EFI_FV_FILETYPE_RAW
) {
1181 // Raw filetypes don't have sections, so we just return the raw data
1183 *RawData
= (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
));
1184 *RawDataSize
= FvBufGetFfsFileSize (File
) - FvBufGetFfsHeaderSize (File
);
1189 // Within the file, we now need to find the EFI_SECTION_RAW section.
1191 Status
= FvBufFindSectionByType (File
, EFI_SECTION_RAW
, (VOID
**)&Section
);
1192 if (EFI_ERROR (Status
)) {
1196 *RawData
= (VOID
*)((UINT8
*)Section
+ FvBufGetSecHdrLen(Section
));
1198 FvBufGetSecFileLen (Section
) - FvBufGetSecHdrLen(Section
);
1206 FvBufPackageFreeformRawFile (
1207 IN EFI_GUID
* Filename
,
1209 IN UINTN RawDataSize
,
1214 Routine Description:
1216 Packages up a FFS file containing the input raw data.
1218 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1219 contain one EFI_FV_FILETYPE_RAW section.
1223 RawData - Pointer to the raw data to be packed
1224 RawDataSize - Size of the raw data to be packed
1225 FfsFile - Address of the packaged FFS file.
1226 Note: The called must deallocate this memory!
1234 EFI_FFS_FILE_HEADER
* NewFile
;
1236 EFI_RAW_SECTION
* NewSection
;
1237 UINT32 NewSectionSize
;
1242 // The section size is the DataSize + the size of the section header
1244 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION
) + (UINT32
)RawDataSize
;
1245 SecHdrLen
= sizeof (EFI_RAW_SECTION
);
1246 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1247 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION2
) + (UINT32
)RawDataSize
;
1248 SecHdrLen
= sizeof (EFI_RAW_SECTION2
);
1252 // The file size is the size of the file header + the section size
1254 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER
) + NewSectionSize
;
1255 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER
);
1256 if (NewFileSize
>= MAX_FFS_SIZE
) {
1257 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER2
) + NewSectionSize
;
1258 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER2
);
1262 // Try to allocate a buffer to build the new FFS file in
1264 NewFile
= CommonLibBinderAllocate (NewFileSize
);
1265 if (NewFile
== NULL
) {
1266 return EFI_OUT_OF_RESOURCES
;
1268 CommonLibBinderSetMem (NewFile
, NewFileSize
, 0);
1271 // The NewSection follow right after the FFS file header
1273 NewSection
= (EFI_RAW_SECTION
*)((UINT8
*)NewFile
+ FfsHdrLen
);
1274 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1275 FvBufCompact3ByteSize (NewSection
->Size
, 0xffffff);
1276 ((EFI_RAW_SECTION2
*)NewSection
)->ExtendedSize
= NewSectionSize
;
1278 FvBufCompact3ByteSize (NewSection
->Size
, NewSectionSize
);
1280 NewSection
->Type
= EFI_SECTION_RAW
;
1283 // Copy the actual file data into the buffer
1285 CommonLibBinderCopyMem ((UINT8
*)NewSection
+ SecHdrLen
, RawData
, RawDataSize
);
1288 // Initialize the FFS file header
1290 CommonLibBinderCopyMem (&NewFile
->Name
, Filename
, sizeof (EFI_GUID
));
1291 NewFile
->Attributes
= 0;
1292 if (NewFileSize
>= MAX_FFS_SIZE
) {
1293 FvBufCompact3ByteSize (NewFile
->Size
, 0x0);
1294 ((EFI_FFS_FILE_HEADER2
*)NewFile
)->ExtendedSize
= NewFileSize
;
1295 NewFile
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
1297 FvBufCompact3ByteSize (NewFile
->Size
, NewFileSize
);
1299 NewFile
->Type
= EFI_FV_FILETYPE_FREEFORM
;
1300 NewFile
->IntegrityCheck
.Checksum
.Header
=
1301 FvBufCalculateChecksum8 ((UINT8
*)NewFile
, FfsHdrLen
);
1302 NewFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1303 NewFile
->State
= (UINT8
)~( EFI_FILE_HEADER_CONSTRUCTION
|
1304 EFI_FILE_HEADER_VALID
|
1315 FvBufFindNextSection (
1316 IN VOID
*SectionsStart
,
1317 IN UINTN TotalSectionsSize
,
1323 Routine Description:
1325 Iterates through the sections contained within a given array of sections
1329 SectionsStart - Address of the start of the FFS sections array
1330 TotalSectionsSize - Total size of all the sections
1331 Key - Should be 0 to get the first section. After that, it should be
1332 passed back in without modifying it's contents to retrieve
1334 Section - Output section pointer
1335 (Section == NULL) -> invalid parameter
1336 otherwise -> *Section will be update to the location of the file
1342 EFI_VOLUME_CORRUPTED
1346 EFI_COMMON_SECTION_HEADER
*sectionHdr
;
1349 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 4); // Sections are DWORD aligned
1351 if ((*Key
+ sizeof (*sectionHdr
)) > TotalSectionsSize
) {
1352 return EFI_NOT_FOUND
;
1355 sectionHdr
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)SectionsStart
+ *Key
);
1356 sectionSize
= FvBufGetSecFileLen (sectionHdr
);
1358 if (sectionSize
< sizeof (EFI_COMMON_SECTION_HEADER
)) {
1359 return EFI_NOT_FOUND
;
1362 if ((*Key
+ sectionSize
) > TotalSectionsSize
) {
1363 return EFI_NOT_FOUND
;
1366 *Section
= (UINT8
*)sectionHdr
;
1367 *Key
= *Key
+ sectionSize
;
1374 FvBufCountSections (
1380 Routine Description:
1382 Searches the FFS file and counts the number of sections found.
1383 The sections are NOT recursed.
1387 FfsFile - Address of the FFS file in memory
1388 Count - The location to store the section count in
1394 EFI_VOLUME_CORRUPTED
1401 UINTN TotalSectionsSize
;
1402 EFI_COMMON_SECTION_HEADER
* NextSection
;
1404 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1406 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1407 FvBufGetFfsHeaderSize(FfsFile
);
1411 Status
= FvBufFindNextSection (
1415 (VOID
**)&NextSection
1417 if (Status
== EFI_NOT_FOUND
) {
1419 } else if (EFI_ERROR (Status
)) {
1424 // Increment the section counter
1430 return EFI_NOT_FOUND
;
1435 FvBufFindSectionByType (
1442 Routine Description:
1444 Searches the FFS file for a section by its type
1448 FfsFile - Address of the FFS file in memory
1449 Type - FFS FILE section type to search for
1450 Section - Output section pointer
1451 (Section == NULL) -> Only determine if the section exists, based on return
1452 value from the function call.
1453 otherwise -> *Section will be update to the location of the file
1459 EFI_VOLUME_CORRUPTED
1466 UINTN TotalSectionsSize
;
1467 EFI_COMMON_SECTION_HEADER
* NextSection
;
1469 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1471 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1472 FvBufGetFfsHeaderSize(FfsFile
);
1475 Status
= FvBufFindNextSection (
1479 (VOID
**)&NextSection
1481 if (EFI_ERROR (Status
)) {
1485 if (Type
== NextSection
->Type
) {
1486 if (Section
!= NULL
) {
1487 *Section
= NextSection
;
1493 return EFI_NOT_FOUND
;
1503 Routine Description:
1505 Shrinks a firmware volume (in place) to provide a minimal FV.
1507 BUGBUG: Does not handle the case where the firmware volume has a
1508 VTF (Volume Top File). The VTF will not be moved to the
1509 end of the extended FV.
1513 Fv - Firmware volume.
1524 UINT32 NewBlockSize
= 128;
1526 EFI_FFS_FILE_HEADER
* FileIt
;
1527 VOID
* EndOfLastFile
;
1529 EFI_FIRMWARE_VOLUME_HEADER
* FvHdr
;
1531 Status
= FvBufGetSize (Fv
, &OldSize
);
1532 if (EFI_ERROR (Status
)) {
1536 Status
= FvBufUnifyBlockSizes (Fv
, NewBlockSize
);
1537 if (EFI_ERROR (Status
)) {
1542 // Locate the block map in the fv header
1544 FvHdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1547 // Find the end of the last file
1550 EndOfLastFile
= (UINT8
*)FvHdr
+ FvHdr
->FvLength
;
1551 while (!EFI_ERROR (FvBufFindNextFile (Fv
, &Key
, (VOID
**)&FileIt
))) {
1553 (VOID
*)((UINT8
*)FileIt
+ FvBufGetFfsFileSize (FileIt
));
1557 // Set the BlockCount to have the minimal number of blocks for the Fv.
1559 BlockCount
= (UINT32
)((UINTN
)EndOfLastFile
- (UINTN
)Fv
);
1560 BlockCount
= BlockCount
+ NewBlockSize
- 1;
1561 BlockCount
= BlockCount
/ NewBlockSize
;
1564 // Adjust the block count to shrink the Fv in place.
1566 FvHdr
->BlockMap
[0].NumBlocks
= BlockCount
;
1567 FvHdr
->FvLength
= BlockCount
* NewBlockSize
;
1570 // Update the FV header checksum
1572 FvBufChecksumHeader (Fv
);
1580 FvBufUnifyBlockSizes (
1586 Routine Description:
1588 Searches the FFS file for a section by its type
1592 Fv - Address of the Fv in memory
1593 BlockSize - The size of the blocks to convert the Fv to. If the total size
1594 of the Fv is not evenly divisible by this size, then
1595 EFI_INVALID_PARAMETER will be returned.
1601 EFI_VOLUME_CORRUPTED
1605 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1606 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
1612 // Scan through the block map list, performing error checking, and adding
1613 // up the total Fv size.
1615 while( blk
->Length
!= 0 ||
1618 Size
= Size
+ (blk
->Length
* blk
->NumBlocks
);
1620 if ((UINT8
*)blk
> ((UINT8
*)hdr
+ hdr
->HeaderLength
)) {
1621 return EFI_VOLUME_CORRUPTED
;
1626 // Make sure that the Fv size is a multiple of the new block size.
1628 if ((Size
% BlockSize
) != 0) {
1629 return EFI_INVALID_PARAMETER
;
1633 // Zero out the entire block map.
1635 CommonLibBinderSetMem (
1637 (UINTN
)blk
- (UINTN
)&hdr
->BlockMap
,
1642 // Write out the single block map entry.
1644 hdr
->BlockMap
[0].Length
= (UINT32
)BlockSize
;
1645 hdr
->BlockMap
[0].NumBlocks
= Size
/ (UINT32
)BlockSize
;
1652 FvBufCalculateSum16 (
1658 Routine Description:
1660 This function calculates the UINT16 sum for the requested region.
1664 Buffer Pointer to buffer containing byte data of component.
1665 Size Size of the buffer
1679 // Perform the word sum for buffer
1681 for (Index
= 0; Index
< Size
; Index
++) {
1682 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
1685 return (UINT16
) Sum
;
1691 FvBufCalculateChecksum16 (
1697 Routine Description::
1699 This function calculates the value needed for a valid UINT16 checksum
1703 Buffer Pointer to buffer containing byte data of component.
1704 Size Size of the buffer
1708 The 16 bit checksum value needed.
1712 return (UINT16
)(0x10000 - FvBufCalculateSum16 (Buffer
, Size
));
1718 FvBufCalculateSum8 (
1726 This function calculates the UINT8 sum for the requested region.
1730 Buffer Pointer to buffer containing byte data of component.
1731 Size Size of the buffer
1735 The 8 bit checksum value needed.
1745 // Perform the byte sum for buffer
1747 for (Index
= 0; Index
< Size
; Index
++) {
1748 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
1757 FvBufCalculateChecksum8 (
1765 This function calculates the value needed for a valid UINT8 checksum
1769 Buffer Pointer to buffer containing byte data of component.
1770 Size Size of the buffer
1774 The 8 bit checksum value needed.
1778 return (UINT8
)(0x100 - FvBufCalculateSum8 (Buffer
, Size
));