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
)) {
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
);
356 if (*DestinationFv
== NULL
) {
357 return EFI_OUT_OF_RESOURCES
;
361 CommonLibBinderCopyMem (*DestinationFv
, SourceFv
, size
);
376 Extends a firmware volume by the given number of bytes.
378 BUGBUG: Does not handle the case where the firmware volume has a
379 VTF (Volume Top File). The VTF will not be moved to the
380 end of the extended FV.
384 Fv - Source and destination firmware volume.
385 Note: The original firmware volume buffer is freed!
387 Size - The minimum size that the firmware volume is to be extended by.
388 The FV may be extended more than this size.
402 EFI_FIRMWARE_VOLUME_HEADER
* hdr
;
403 EFI_FV_BLOCK_MAP_ENTRY
* blk
;
405 Status
= FvBufGetSize (*Fv
, &OldSize
);
406 if (EFI_ERROR (Status
)) {
411 // Locate the block map in the fv header
413 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)*Fv
;
417 // Calculate the number of blocks needed to achieve the requested
420 BlockCount
= ((Size
+ (blk
->Length
- 1)) / blk
->Length
);
423 // Calculate the new size from the number of blocks that will be added
425 NewSize
= OldSize
+ (BlockCount
* blk
->Length
);
427 NewFv
= CommonLibBinderAllocate (NewSize
);
429 return EFI_OUT_OF_RESOURCES
;
435 CommonLibBinderCopyMem (NewFv
, *Fv
, OldSize
);
438 // Free the old fv buffer
440 CommonLibBinderFree (*Fv
);
443 // Locate the block map in the new fv header
445 hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)NewFv
;
446 hdr
->FvLength
= NewSize
;
450 // Update the block map for the new fv
452 blk
->NumBlocks
+= (UINT32
)BlockCount
;
455 // Update the FV header checksum
457 FvBufChecksumHeader (NewFv
);
460 // Clear out the new area of the FV
462 CommonLibBinderSetMem (
463 (UINT8
*)NewFv
+ OldSize
,
465 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
469 // Set output with new fv that was created
486 Clears out all files from the Fv buffer in memory
490 Fv - Address of the Fv in memory
499 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
503 Status
= FvBufGetSize (Fv
, &size
);
504 if (EFI_ERROR (Status
)) {
508 CommonLibBinderSetMem(
509 (UINT8
*)hdr
+ hdr
->HeaderLength
,
510 size
- hdr
->HeaderLength
,
511 (hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0
527 Clears out all files from the Fv buffer in memory
531 Fv - Address of the Fv in memory
540 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
541 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
545 while (blk
->Length
!= 0 || blk
->NumBlocks
!= 0) {
546 *Size
= *Size
+ (blk
->Length
* blk
->NumBlocks
);
547 if (*Size
>= 0x40000000) {
548 // If size is greater than 1GB, then assume it is corrupted
549 return EFI_VOLUME_CORRUPTED
;
555 // If size is 0, then assume the volume is corrupted
556 return EFI_VOLUME_CORRUPTED
;
576 Fv - Address of the Fv in memory
577 File - FFS file to add to Fv
585 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
587 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
588 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
597 Status
= FvBufGetSize (Fv
, &fvSize
);
598 if (EFI_ERROR (Status
)) {
602 FvbAttributes
= hdr
->Attributes
;
603 newSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
606 offset
= (UINTN
)ALIGN_POINTER (hdr
->HeaderLength
, 8);
607 offset
+ newSize
<= fvSize
;
608 offset
= (UINTN
)ALIGN_POINTER (offset
, 8)
611 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ offset
);
613 if (EFI_TEST_FFS_ATTRIBUTES_BIT(
616 EFI_FILE_HEADER_VALID
619 // BUGBUG: Need to make sure that the new file does not already
622 fsize
= FvBufGetFfsFileSize (fhdr
);
623 if (fsize
== 0 || (offset
+ fsize
> fvSize
)) {
624 return EFI_VOLUME_CORRUPTED
;
627 offset
= offset
+ fsize
;
632 while ((clearLoop
< newSize
) &&
633 (((UINT8
*)fhdr
)[clearLoop
] ==
634 (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0)
641 // We found a place in the FV which is empty and big enough for
644 if (clearLoop
>= newSize
) {
648 offset
= offset
+ 1; // Make some forward progress
651 if (offset
+ newSize
> fvSize
) {
652 return EFI_OUT_OF_RESOURCES
;
655 CommonLibBinderCopyMem (fhdr
, File
, newSize
);
662 FvBufAddFileWithExtend (
670 Adds a new FFS file. Extends the firmware volume if needed.
674 Fv - Source and destination firmware volume.
675 Note: If the FV is extended, then the original firmware volume
678 Size - The minimum size that the firmware volume is to be extended by.
679 The FV may be extended more than this size.
688 EFI_FFS_FILE_HEADER
* NewFile
;
690 NewFile
= (EFI_FFS_FILE_HEADER
*)File
;
693 // Try to add to the capsule volume
695 Status
= FvBufAddFile (*Fv
, NewFile
);
696 if (Status
== EFI_OUT_OF_RESOURCES
) {
698 // Try to extend the capsule volume by the size of the file
700 Status
= FvBufExtend (Fv
, FvBufExpand3ByteSize (NewFile
->Size
));
701 if (EFI_ERROR (Status
)) {
706 // Now, try to add the file again
708 Status
= FvBufAddFile (*Fv
, NewFile
);
724 Adds a new FFS VFT (Volume Top File) file. In other words, adds the
725 file to the end of the firmware volume.
729 Fv - Address of the Fv in memory
730 File - FFS file to add to Fv
740 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
742 EFI_FFS_FILE_HEADER
* NewFile
;
748 EFI_FFS_FILE_HEADER
*LastFile
;
754 Status
= FvBufGetSize (Fv
, &fvSize
);
755 if (EFI_ERROR (Status
)) {
759 erasedUint8
= (UINT8
)((hdr
->Attributes
& EFI_FVB2_ERASE_POLARITY
) ? 0xFF : 0);
760 NewFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
762 if (NewFileSize
!= (UINTN
)ALIGN_POINTER (NewFileSize
, 8)) {
763 return EFI_INVALID_PARAMETER
;
767 // Find the last file in the FV
773 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&LastFile
);
774 LastFileSize
= FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)File
);
775 } while (!EFI_ERROR (Status
));
778 // If no files were found, then we start at the beginning of the FV
780 if (LastFile
== NULL
) {
781 LastFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ hdr
->HeaderLength
);
785 // We want to put the new file (VTF) at the end of the FV
787 NewFile
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)hdr
+ (fvSize
- NewFileSize
));
790 // Check to see if there is enough room for the VTF after the last file
793 if ((UINT8
*)NewFile
< ((UINT8
*)LastFile
+ LastFileSize
)) {
794 return EFI_OUT_OF_RESOURCES
;
798 // Loop to determine if the end of the FV is empty
801 while ((clearLoop
< NewFileSize
) &&
802 (((UINT8
*)NewFile
)[clearLoop
] == erasedUint8
)
808 // Check to see if there was not enough room for the file
810 if (clearLoop
< NewFileSize
) {
811 return EFI_OUT_OF_RESOURCES
;
814 CommonLibBinderCopyMem (NewFile
, File
, NewFileSize
);
821 FvBufCompact3ByteSize (
829 Expands the 3 byte size commonly used in Firmware Volume data structures
833 Size - Address of the 3 byte array representing the size
841 ((UINT8
*)SizeDest
)[0] = (UINT8
)Size
;
842 ((UINT8
*)SizeDest
)[1] = (UINT8
)(Size
>> 8);
843 ((UINT8
*)SizeDest
)[2] = (UINT8
)(Size
>> 16);
847 FvBufGetFfsFileSize (
848 IN EFI_FFS_FILE_HEADER
*Ffs
854 Get the FFS file size.
858 Ffs - Pointer to FFS header
869 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
870 return (UINT32
) ((EFI_FFS_FILE_HEADER2
*)Ffs
)->ExtendedSize
;
872 return FvBufExpand3ByteSize(Ffs
->Size
);
876 FvBufGetFfsHeaderSize (
877 IN EFI_FFS_FILE_HEADER
*Ffs
883 Get the FFS header size.
887 Ffs - Pointer to FFS header
898 if (Ffs
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
899 return sizeof(EFI_FFS_FILE_HEADER2
);
901 return sizeof(EFI_FFS_FILE_HEADER
);
905 FvBufExpand3ByteSize (
912 Expands the 3 byte size commonly used in Firmware Volume data structures
916 Size - Address of the 3 byte array representing the size
924 return (((UINT8
*)Size
)[2] << 16) +
925 (((UINT8
*)Size
)[1] << 8) +
939 Iterates through the files contained within the firmware volume
943 Fv - Address of the Fv in memory
944 Key - Should be 0 to get the first file. After that, it should be
945 passed back in without modifying it's contents to retrieve
947 File - Output file pointer
948 File == NULL - invalid parameter
949 otherwise - *File will be update to the location of the file
959 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
961 EFI_FFS_FILE_HEADER
*fhdr
= NULL
;
962 EFI_FVB_ATTRIBUTES_2 FvbAttributes
;
969 return EFI_INVALID_PARAMETER
;
972 Status
= FvBufGetSize (Fv
, &fvSize
);
973 if (EFI_ERROR (Status
)) {
978 *Key
= hdr
->HeaderLength
;
981 FvbAttributes
= hdr
->Attributes
;
984 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8);
985 (*Key
+ sizeof (*fhdr
)) < fvSize
;
986 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 8)
989 fhdr
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*)hdr
+ *Key
);
990 fsize
= FvBufGetFfsFileSize (fhdr
);
992 if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
995 EFI_FILE_HEADER_VALID
997 EFI_TEST_FFS_ATTRIBUTES_BIT(
1000 EFI_FILE_HEADER_INVALID
1003 *Key
= *Key
+ 1; // Make some forward progress
1006 EFI_TEST_FFS_ATTRIBUTES_BIT(
1009 EFI_FILE_MARKED_FOR_UPDATE
1011 EFI_TEST_FFS_ATTRIBUTES_BIT(
1017 *Key
= *Key
+ fsize
;
1019 } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1025 *File
= (UINT8
*)hdr
+ *Key
;
1026 *Key
= *Key
+ fsize
;
1030 *Key
= *Key
+ 1; // Make some forward progress
1033 return EFI_NOT_FOUND
;
1038 FvBufFindFileByName (
1045 Routine Description:
1047 Searches the Fv for a file by its name
1051 Fv - Address of the Fv in memory
1052 Name - Guid filename to search for in the firmware volume
1053 File - Output file pointer
1054 File == NULL - Only determine if the file exists, based on return
1055 value from the function call.
1056 otherwise - *File will be update to the location of the file
1062 EFI_VOLUME_CORRUPTED
1068 EFI_FFS_FILE_HEADER
*NextFile
;
1072 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1073 if (EFI_ERROR (Status
)) {
1077 if (CommonLibBinderCompareGuid (Name
, &NextFile
->Name
)) {
1085 return EFI_NOT_FOUND
;
1090 FvBufFindFileByType (
1092 IN EFI_FV_FILETYPE Type
,
1097 Routine Description:
1099 Searches the Fv for a file by its type
1103 Fv - Address of the Fv in memory
1104 Type - FFS FILE type to search for
1105 File - Output file pointer
1106 (File == NULL) -> Only determine if the file exists, based on return
1107 value from the function call.
1108 otherwise -> *File will be update to the location of the file
1114 EFI_VOLUME_CORRUPTED
1120 EFI_FFS_FILE_HEADER
*NextFile
;
1124 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**)&NextFile
);
1125 if (EFI_ERROR (Status
)) {
1129 if (Type
== NextFile
->Type
) {
1137 return EFI_NOT_FOUND
;
1142 FvBufGetFileRawData (
1145 OUT UINTN
* RawDataSize
1149 Routine Description:
1151 Searches the requested file for raw data.
1153 This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1154 or finds the EFI_SECTION_RAW section within the file and returns its data.
1158 FfsFile - Address of the FFS file in memory
1159 RawData - Pointer to the raw data within the file
1160 (This is NOT allocated. It is within the file.)
1161 RawDataSize - Size of the raw data within the file
1170 EFI_FFS_FILE_HEADER
* File
;
1171 EFI_RAW_SECTION
* Section
;
1173 File
= (EFI_FFS_FILE_HEADER
*)FfsFile
;
1176 // Is the file type == EFI_FV_FILETYPE_RAW?
1178 if (File
->Type
== EFI_FV_FILETYPE_RAW
) {
1180 // Raw filetypes don't have sections, so we just return the raw data
1182 *RawData
= (VOID
*)((UINT8
*)File
+ FvBufGetFfsHeaderSize (File
));
1183 *RawDataSize
= FvBufGetFfsFileSize (File
) - FvBufGetFfsHeaderSize (File
);
1188 // Within the file, we now need to find the EFI_SECTION_RAW section.
1190 Status
= FvBufFindSectionByType (File
, EFI_SECTION_RAW
, (VOID
**)&Section
);
1191 if (EFI_ERROR (Status
)) {
1195 *RawData
= (VOID
*)((UINT8
*)Section
+ FvBufGetSecHdrLen(Section
));
1197 FvBufGetSecFileLen (Section
) - FvBufGetSecHdrLen(Section
);
1205 FvBufPackageFreeformRawFile (
1206 IN EFI_GUID
* Filename
,
1208 IN UINTN RawDataSize
,
1213 Routine Description:
1215 Packages up a FFS file containing the input raw data.
1217 The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1218 contain one EFI_FV_FILETYPE_RAW section.
1222 RawData - Pointer to the raw data to be packed
1223 RawDataSize - Size of the raw data to be packed
1224 FfsFile - Address of the packaged FFS file.
1225 Note: The called must deallocate this memory!
1233 EFI_FFS_FILE_HEADER
* NewFile
;
1235 EFI_RAW_SECTION
* NewSection
;
1236 UINT32 NewSectionSize
;
1241 // The section size is the DataSize + the size of the section header
1243 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION
) + (UINT32
)RawDataSize
;
1244 SecHdrLen
= sizeof (EFI_RAW_SECTION
);
1245 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1246 NewSectionSize
= (UINT32
)sizeof (EFI_RAW_SECTION2
) + (UINT32
)RawDataSize
;
1247 SecHdrLen
= sizeof (EFI_RAW_SECTION2
);
1251 // The file size is the size of the file header + the section size
1253 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER
) + NewSectionSize
;
1254 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER
);
1255 if (NewFileSize
>= MAX_FFS_SIZE
) {
1256 NewFileSize
= sizeof (EFI_FFS_FILE_HEADER2
) + NewSectionSize
;
1257 FfsHdrLen
= sizeof (EFI_FFS_FILE_HEADER2
);
1261 // Try to allocate a buffer to build the new FFS file in
1263 NewFile
= CommonLibBinderAllocate (NewFileSize
);
1264 if (NewFile
== NULL
) {
1265 return EFI_OUT_OF_RESOURCES
;
1267 CommonLibBinderSetMem (NewFile
, NewFileSize
, 0);
1270 // The NewSection follow right after the FFS file header
1272 NewSection
= (EFI_RAW_SECTION
*)((UINT8
*)NewFile
+ FfsHdrLen
);
1273 if (NewSectionSize
>= MAX_SECTION_SIZE
) {
1274 FvBufCompact3ByteSize (NewSection
->Size
, 0xffffff);
1275 ((EFI_RAW_SECTION2
*)NewSection
)->ExtendedSize
= NewSectionSize
;
1277 FvBufCompact3ByteSize (NewSection
->Size
, NewSectionSize
);
1279 NewSection
->Type
= EFI_SECTION_RAW
;
1282 // Copy the actual file data into the buffer
1284 CommonLibBinderCopyMem ((UINT8
*)NewSection
+ SecHdrLen
, RawData
, RawDataSize
);
1287 // Initialize the FFS file header
1289 CommonLibBinderCopyMem (&NewFile
->Name
, Filename
, sizeof (EFI_GUID
));
1290 NewFile
->Attributes
= 0;
1291 if (NewFileSize
>= MAX_FFS_SIZE
) {
1292 FvBufCompact3ByteSize (NewFile
->Size
, 0x0);
1293 ((EFI_FFS_FILE_HEADER2
*)NewFile
)->ExtendedSize
= NewFileSize
;
1294 NewFile
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
1296 FvBufCompact3ByteSize (NewFile
->Size
, NewFileSize
);
1298 NewFile
->Type
= EFI_FV_FILETYPE_FREEFORM
;
1299 NewFile
->IntegrityCheck
.Checksum
.Header
=
1300 FvBufCalculateChecksum8 ((UINT8
*)NewFile
, FfsHdrLen
);
1301 NewFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
1302 NewFile
->State
= (UINT8
)~( EFI_FILE_HEADER_CONSTRUCTION
|
1303 EFI_FILE_HEADER_VALID
|
1314 FvBufFindNextSection (
1315 IN VOID
*SectionsStart
,
1316 IN UINTN TotalSectionsSize
,
1322 Routine Description:
1324 Iterates through the sections contained within a given array of sections
1328 SectionsStart - Address of the start of the FFS sections array
1329 TotalSectionsSize - Total size of all the sections
1330 Key - Should be 0 to get the first section. After that, it should be
1331 passed back in without modifying it's contents to retrieve
1333 Section - Output section pointer
1334 (Section == NULL) -> invalid parameter
1335 otherwise -> *Section will be update to the location of the file
1341 EFI_VOLUME_CORRUPTED
1345 EFI_COMMON_SECTION_HEADER
*sectionHdr
;
1348 *Key
= (UINTN
)ALIGN_POINTER (*Key
, 4); // Sections are DWORD aligned
1350 if ((*Key
+ sizeof (*sectionHdr
)) > TotalSectionsSize
) {
1351 return EFI_NOT_FOUND
;
1354 sectionHdr
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)SectionsStart
+ *Key
);
1355 sectionSize
= FvBufGetSecFileLen (sectionHdr
);
1357 if (sectionSize
< sizeof (EFI_COMMON_SECTION_HEADER
)) {
1358 return EFI_NOT_FOUND
;
1361 if ((*Key
+ sectionSize
) > TotalSectionsSize
) {
1362 return EFI_NOT_FOUND
;
1365 *Section
= (UINT8
*)sectionHdr
;
1366 *Key
= *Key
+ sectionSize
;
1373 FvBufCountSections (
1379 Routine Description:
1381 Searches the FFS file and counts the number of sections found.
1382 The sections are NOT recursed.
1386 FfsFile - Address of the FFS file in memory
1387 Count - The location to store the section count in
1393 EFI_VOLUME_CORRUPTED
1400 UINTN TotalSectionsSize
;
1401 EFI_COMMON_SECTION_HEADER
* NextSection
;
1403 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1405 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1406 FvBufGetFfsHeaderSize(FfsFile
);
1410 Status
= FvBufFindNextSection (
1414 (VOID
**)&NextSection
1416 if (Status
== EFI_NOT_FOUND
) {
1418 } else if (EFI_ERROR (Status
)) {
1423 // Increment the section counter
1429 return EFI_NOT_FOUND
;
1434 FvBufFindSectionByType (
1441 Routine Description:
1443 Searches the FFS file for a section by its type
1447 FfsFile - Address of the FFS file in memory
1448 Type - FFS FILE section type to search for
1449 Section - Output section pointer
1450 (Section == NULL) -> Only determine if the section exists, based on return
1451 value from the function call.
1452 otherwise -> *Section will be update to the location of the file
1458 EFI_VOLUME_CORRUPTED
1465 UINTN TotalSectionsSize
;
1466 EFI_COMMON_SECTION_HEADER
* NextSection
;
1468 SectionStart
= (VOID
*)((UINTN
)FfsFile
+ FvBufGetFfsHeaderSize(FfsFile
));
1470 FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER
*)FfsFile
) -
1471 FvBufGetFfsHeaderSize(FfsFile
);
1474 Status
= FvBufFindNextSection (
1478 (VOID
**)&NextSection
1480 if (EFI_ERROR (Status
)) {
1484 if (Type
== NextSection
->Type
) {
1485 if (Section
!= NULL
) {
1486 *Section
= NextSection
;
1492 return EFI_NOT_FOUND
;
1502 Routine Description:
1504 Shrinks a firmware volume (in place) to provide a minimal FV.
1506 BUGBUG: Does not handle the case where the firmware volume has a
1507 VTF (Volume Top File). The VTF will not be moved to the
1508 end of the extended FV.
1512 Fv - Firmware volume.
1523 UINT32 NewBlockSize
= 128;
1525 EFI_FFS_FILE_HEADER
* FileIt
;
1526 VOID
* EndOfLastFile
;
1528 EFI_FIRMWARE_VOLUME_HEADER
* FvHdr
;
1530 Status
= FvBufGetSize (Fv
, &OldSize
);
1531 if (EFI_ERROR (Status
)) {
1535 Status
= FvBufUnifyBlockSizes (Fv
, NewBlockSize
);
1536 if (EFI_ERROR (Status
)) {
1541 // Locate the block map in the fv header
1543 FvHdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1546 // Find the end of the last file
1549 EndOfLastFile
= (UINT8
*)FvHdr
+ FvHdr
->FvLength
;
1550 while (!EFI_ERROR (FvBufFindNextFile (Fv
, &Key
, (VOID
**)&FileIt
))) {
1552 (VOID
*)((UINT8
*)FileIt
+ FvBufGetFfsFileSize (FileIt
));
1556 // Set the BlockCount to have the minimal number of blocks for the Fv.
1558 BlockCount
= (UINT32
)((UINTN
)EndOfLastFile
- (UINTN
)Fv
);
1559 BlockCount
= BlockCount
+ NewBlockSize
- 1;
1560 BlockCount
= BlockCount
/ NewBlockSize
;
1563 // Adjust the block count to shrink the Fv in place.
1565 FvHdr
->BlockMap
[0].NumBlocks
= BlockCount
;
1566 FvHdr
->FvLength
= BlockCount
* NewBlockSize
;
1569 // Update the FV header checksum
1571 FvBufChecksumHeader (Fv
);
1579 FvBufUnifyBlockSizes (
1585 Routine Description:
1587 Searches the FFS file for a section by its type
1591 Fv - Address of the Fv in memory
1592 BlockSize - The size of the blocks to convert the Fv to. If the total size
1593 of the Fv is not evenly divisible by this size, then
1594 EFI_INVALID_PARAMETER will be returned.
1600 EFI_VOLUME_CORRUPTED
1604 EFI_FIRMWARE_VOLUME_HEADER
*hdr
= (EFI_FIRMWARE_VOLUME_HEADER
*)Fv
;
1605 EFI_FV_BLOCK_MAP_ENTRY
*blk
= hdr
->BlockMap
;
1611 // Scan through the block map list, performing error checking, and adding
1612 // up the total Fv size.
1614 while( blk
->Length
!= 0 ||
1617 Size
= Size
+ (blk
->Length
* blk
->NumBlocks
);
1619 if ((UINT8
*)blk
> ((UINT8
*)hdr
+ hdr
->HeaderLength
)) {
1620 return EFI_VOLUME_CORRUPTED
;
1625 // Make sure that the Fv size is a multiple of the new block size.
1627 if ((Size
% BlockSize
) != 0) {
1628 return EFI_INVALID_PARAMETER
;
1632 // Zero out the entire block map.
1634 CommonLibBinderSetMem (
1636 (UINTN
)blk
- (UINTN
)&hdr
->BlockMap
,
1641 // Write out the single block map entry.
1643 hdr
->BlockMap
[0].Length
= (UINT32
)BlockSize
;
1644 hdr
->BlockMap
[0].NumBlocks
= Size
/ (UINT32
)BlockSize
;
1651 FvBufCalculateSum16 (
1657 Routine Description:
1659 This function calculates the UINT16 sum for the requested region.
1663 Buffer Pointer to buffer containing byte data of component.
1664 Size Size of the buffer
1678 // Perform the word sum for buffer
1680 for (Index
= 0; Index
< Size
; Index
++) {
1681 Sum
= (UINT16
) (Sum
+ Buffer
[Index
]);
1684 return (UINT16
) Sum
;
1690 FvBufCalculateChecksum16 (
1696 Routine Description::
1698 This function calculates the value needed for a valid UINT16 checksum
1702 Buffer Pointer to buffer containing byte data of component.
1703 Size Size of the buffer
1707 The 16 bit checksum value needed.
1711 return (UINT16
)(0x10000 - FvBufCalculateSum16 (Buffer
, Size
));
1717 FvBufCalculateSum8 (
1725 This function calculates the UINT8 sum for the requested region.
1729 Buffer Pointer to buffer containing byte data of component.
1730 Size Size of the buffer
1734 The 8 bit checksum value needed.
1744 // Perform the byte sum for buffer
1746 for (Index
= 0; Index
< Size
; Index
++) {
1747 Sum
= (UINT8
) (Sum
+ Buffer
[Index
]);
1756 FvBufCalculateChecksum8 (
1764 This function calculates the value needed for a valid UINT8 checksum
1768 Buffer Pointer to buffer containing byte data of component.
1769 Size Size of the buffer
1773 The 8 bit checksum value needed.
1777 return (UINT8
)(0x100 - FvBufCalculateSum8 (Buffer
, Size
));