3 Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/FvLib.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
16 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
17 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
20 Returns the highest bit set of the State field
22 @param ErasePolarity Erase Polarity as defined by EFI_FVB_ERASE_POLARITY
23 in the Attributes field.
24 @param FfsHeader Pointer to FFS File Header.
26 @return the highest bit in the State field
30 IN UINT8 ErasePolarity
,
31 IN EFI_FFS_FILE_HEADER
*FfsHeader
34 EFI_FFS_FILE_STATE FileState
;
35 EFI_FFS_FILE_STATE HighestBit
;
37 FileState
= FfsHeader
->State
;
39 if (ErasePolarity
!= 0) {
40 FileState
= (EFI_FFS_FILE_STATE
) ~FileState
;
44 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
52 Calculates the checksum of the header of a file.
54 @param FileHeader Pointer to FFS File Header.
56 @return Checksum of the header.
59 CalculateHeaderChecksum (
60 IN EFI_FFS_FILE_HEADER
*FileHeader
69 ptr
= (UINT8
*)FileHeader
;
70 Size
= IS_FFS_FILE2 (FileHeader
) ? sizeof (EFI_FFS_FILE_HEADER2
) : sizeof (EFI_FFS_FILE_HEADER
);
72 for (Index
= 0; Index
< Size
- 3; Index
+= 4) {
73 Sum
= (UINT8
)(Sum
+ ptr
[Index
]);
74 Sum
= (UINT8
)(Sum
+ ptr
[Index
+ 1]);
75 Sum
= (UINT8
)(Sum
+ ptr
[Index
+ 2]);
76 Sum
= (UINT8
)(Sum
+ ptr
[Index
+ 3]);
79 for ( ; Index
< Size
; Index
++) {
80 Sum
= (UINT8
)(Sum
+ ptr
[Index
]);
84 // State field (since this indicates the different state of file).
86 Sum
= (UINT8
)(Sum
- FileHeader
->State
);
88 // Checksum field of the file is not part of the header checksum.
90 Sum
= (UINT8
)(Sum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
96 Given the input file pointer, search for the next matching file in the
97 FFS volume as defined by SearchType. The search starts from FileHeader inside
98 the Firmware Volume defined by FwVolHeader.
100 @param SearchType Filter to find only files of this type.
101 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
102 @param FwVolHeader Pointer to the FV header of the volume to search.
103 This parameter must point to a valid FFS volume.
104 @param FileHeader Pointer to the current file from which to begin searching.
105 This pointer will be updated upon return to reflect the file found.
107 @retval EFI_NOT_FOUND No files matching the search criteria were found
113 IN EFI_FV_FILETYPE SearchType
,
114 IN EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
,
115 IN OUT EFI_FFS_FILE_HEADER
**FileHeader
118 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
120 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
122 UINT32 FileOccupiedSize
;
128 FvLength
= FwVolHeader
->FvLength
;
129 if (FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
136 // If FileHeader is not specified (NULL) start with the first file in the
137 // firmware volume. Otherwise, start from the FileHeader.
139 if (*FileHeader
== NULL
) {
140 if (FwVolHeader
->ExtHeaderOffset
!= 0) {
141 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)((UINT8
*)FwVolHeader
+
142 FwVolHeader
->ExtHeaderOffset
);
144 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FvExtHeader
+
145 FvExtHeader
->ExtHeaderSize
);
147 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+
148 FwVolHeader
->HeaderLength
);
151 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINTN
)FwVolHeader
+
153 (UINTN
)FfsFileHeader
-
159 // Length is 24 bits wide so mask upper 8 bits
160 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
162 FileLength
= IS_FFS_FILE2 (*FileHeader
) ?
163 FFS_FILE2_SIZE (*FileHeader
) : FFS_FILE_SIZE (*FileHeader
);
164 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
165 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)*FileHeader
+ FileOccupiedSize
);
168 FileOffset
= (UINT32
)((UINT8
*)FfsFileHeader
- (UINT8
*)FwVolHeader
);
170 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
172 // Get FileState which is the highest bit of the State
174 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
177 case EFI_FILE_HEADER_INVALID
:
178 if (IS_FFS_FILE2 (FfsFileHeader
)) {
179 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER2
);
180 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
182 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER
);
183 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
188 case EFI_FILE_DATA_VALID
:
189 case EFI_FILE_MARKED_FOR_UPDATE
:
190 if (CalculateHeaderChecksum (FfsFileHeader
) == 0) {
191 FileLength
= IS_FFS_FILE2 (FfsFileHeader
) ?
192 FFS_FILE2_SIZE (FfsFileHeader
) : FFS_FILE_SIZE (FfsFileHeader
);
193 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
195 if ((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) {
196 *FileHeader
= FfsFileHeader
;
201 FileOffset
+= FileOccupiedSize
;
202 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
204 return EFI_NOT_FOUND
;
209 case EFI_FILE_DELETED
:
210 FileLength
= IS_FFS_FILE2 (FfsFileHeader
) ?
211 FFS_FILE2_SIZE (FfsFileHeader
) : FFS_FILE_SIZE (FfsFileHeader
);
212 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
213 FileOffset
+= FileOccupiedSize
;
214 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
218 return EFI_NOT_FOUND
;
222 return EFI_NOT_FOUND
;
226 Locates a section within a series of sections
227 with the specified section type.
229 @param[in] Sections The sections to search
230 @param[in] SizeOfSections Total size of all sections
231 @param[in] SectionType The section type to locate
232 @param[out] FoundSection The FFS section if found
234 @retval EFI_SUCCESS The file and section was found
235 @retval EFI_NOT_FOUND The file and section was not found
236 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
240 FindFfsSectionInSections (
242 IN UINTN SizeOfSections
,
243 IN EFI_SECTION_TYPE SectionType
,
244 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
247 EFI_PHYSICAL_ADDRESS CurrentAddress
;
249 EFI_PHYSICAL_ADDRESS EndOfSections
;
250 EFI_COMMON_SECTION_HEADER
*Section
;
251 EFI_PHYSICAL_ADDRESS EndOfSection
;
254 // Loop through the FFS file sections
256 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Sections
;
257 EndOfSections
= EndOfSection
+ SizeOfSections
;
259 if (EndOfSection
== EndOfSections
) {
263 CurrentAddress
= EndOfSection
;
265 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
)CurrentAddress
;
267 Size
= IS_SECTION2 (Section
) ? SECTION2_SIZE (Section
) : SECTION_SIZE (Section
);
268 if (Size
< sizeof (*Section
)) {
269 return EFI_VOLUME_CORRUPTED
;
272 EndOfSection
= CurrentAddress
+ Size
;
273 if (EndOfSection
> EndOfSections
) {
274 return EFI_VOLUME_CORRUPTED
;
277 Size
= GET_OCCUPIED_SIZE (Size
, 4);
280 // Look for the requested section type
282 if (Section
->Type
== SectionType
) {
283 *FoundSection
= Section
;
288 return EFI_NOT_FOUND
;
292 Given the input file pointer, search for the next matching section in the
295 @param SearchType Filter to find only sections of this type.
296 @param FfsFileHeader Pointer to the current file to search.
297 @param SectionHeader Pointer to the Section matching SectionType in FfsFileHeader.
298 NULL if section not found
300 @retval EFI_NOT_FOUND No files matching the search criteria were found
306 IN EFI_SECTION_TYPE SectionType
,
307 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
308 IN OUT EFI_COMMON_SECTION_HEADER
**SectionHeader
312 EFI_COMMON_SECTION_HEADER
*Section
;
316 // Size is 24 bits wide so mask upper 8 bits.
317 // Does not include FfsFileHeader header size
318 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
320 if (IS_FFS_FILE2 (FfsFileHeader
)) {
321 Section
= (EFI_COMMON_SECTION_HEADER
*)((EFI_FFS_FILE_HEADER2
*)FfsFileHeader
+ 1);
322 FileSize
= FFS_FILE2_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
324 Section
= (EFI_COMMON_SECTION_HEADER
*)(FfsFileHeader
+ 1);
325 FileSize
= FFS_FILE_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
328 Status
= FindFfsSectionInSections (
338 Given the input file pointer, search for the next matching section in the
341 @param SearchType Filter to find only sections of this type.
342 @param FfsFileHeader Pointer to the current file to search.
343 @param SectionData Pointer to the Section matching SectionType in FfsFileHeader.
344 NULL if section not found
345 @param SectionDataSize The size of SectionData
347 @retval EFI_NOT_FOUND No files matching the search criteria were found
353 IN EFI_SECTION_TYPE SectionType
,
354 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
355 IN OUT VOID
**SectionData
,
356 IN OUT UINTN
*SectionDataSize
360 EFI_COMMON_SECTION_HEADER
*Section
;
361 UINT32 SectionLength
;
365 // Size is 24 bits wide so mask upper 8 bits.
366 // Does not include FfsFileHeader header size
367 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
369 if (IS_FFS_FILE2 (FfsFileHeader
)) {
370 Section
= (EFI_COMMON_SECTION_HEADER
*)((EFI_FFS_FILE_HEADER2
*)FfsFileHeader
+ 1);
371 FileSize
= FFS_FILE2_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
373 Section
= (EFI_COMMON_SECTION_HEADER
*)(FfsFileHeader
+ 1);
374 FileSize
= FFS_FILE_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
379 while (ParsedLength
< FileSize
) {
380 if (Section
->Type
== SectionType
) {
381 if (IS_SECTION2 (Section
)) {
382 *SectionData
= (VOID
*)((EFI_COMMON_SECTION_HEADER2
*)Section
+ 1);
383 *SectionDataSize
= SECTION2_SIZE (Section
);
385 *SectionData
= (VOID
*)(Section
+ 1);
386 *SectionDataSize
= SECTION_SIZE (Section
);
393 // Size is 24 bits wide so mask upper 8 bits.
394 // SectionLength is adjusted it is 4 byte aligned.
395 // Go to the next section
397 SectionLength
= IS_SECTION2 (Section
) ? SECTION2_SIZE (Section
) : SECTION_SIZE (Section
);
398 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
400 ParsedLength
+= SectionLength
;
401 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
404 return EFI_NOT_FOUND
;