3 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/FvLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
22 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
23 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
26 Returns the highest bit set of the State field
28 @param ErasePolarity Erase Polarity as defined by EFI_FVB_ERASE_POLARITY
29 in the Attributes field.
30 @param FfsHeader Pointer to FFS File Header.
32 @return the highest bit in the State field
36 IN UINT8 ErasePolarity
,
37 IN EFI_FFS_FILE_HEADER
*FfsHeader
40 EFI_FFS_FILE_STATE FileState
;
41 EFI_FFS_FILE_STATE HighestBit
;
43 FileState
= FfsHeader
->State
;
45 if (ErasePolarity
!= 0) {
46 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
50 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
58 Calculates the checksum of the header of a file.
60 @param FileHeader Pointer to FFS File Header.
62 @return Checksum of the header.
65 CalculateHeaderChecksum (
66 IN EFI_FFS_FILE_HEADER
*FileHeader
74 ptr
= (UINT8
*) FileHeader
;
76 for (Index
= 0; Index
< sizeof (EFI_FFS_FILE_HEADER
) - 3; Index
+= 4) {
77 Sum
= (UINT8
) (Sum
+ ptr
[Index
]);
78 Sum
= (UINT8
) (Sum
+ ptr
[Index
+ 1]);
79 Sum
= (UINT8
) (Sum
+ ptr
[Index
+ 2]);
80 Sum
= (UINT8
) (Sum
+ ptr
[Index
+ 3]);
83 for (; Index
< sizeof (EFI_FFS_FILE_HEADER
); Index
++) {
84 Sum
= (UINT8
) (Sum
+ ptr
[Index
]);
87 // State field (since this indicates the different state of file).
89 Sum
= (UINT8
) (Sum
- FileHeader
->State
);
91 // Checksum field of the file is not part of the header checksum.
93 Sum
= (UINT8
) (Sum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
99 Given the input file pointer, search for the next matching file in the
100 FFS volume as defined by SearchType. The search starts from FileHeader inside
101 the Firmware Volume defined by FwVolHeader.
103 @param SearchType Filter to find only files of this type.
104 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
105 @param FwVolHeader Pointer to the FV header of the volume to search.
106 This parameter must point to a valid FFS volume.
107 @param FileHeader Pointer to the current file from which to begin searching.
108 This pointer will be updated upon return to reflect the file found.
110 @retval EFI_NOT_FOUND No files matching the search criteria were found
116 IN EFI_FV_FILETYPE SearchType
,
117 IN EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
,
118 IN OUT EFI_FFS_FILE_HEADER
**FileHeader
121 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FvExtHeader
;
123 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
125 UINT32 FileOccupiedSize
;
131 FvLength
= FwVolHeader
->FvLength
;
132 if (FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
138 // If FileHeader is not specified (NULL) start with the first file in the
139 // firmware volume. Otherwise, start from the FileHeader.
141 if (*FileHeader
== NULL
) {
143 if (FwVolHeader
->ExtHeaderOffset
!= 0) {
145 FvExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)((UINT8
*)FwVolHeader
+
146 FwVolHeader
->ExtHeaderOffset
);
148 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FvExtHeader
+
149 FvExtHeader
->ExtHeaderSize
);
153 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+
154 FwVolHeader
->HeaderLength
);
158 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINTN
)FwVolHeader
+
159 ALIGN_VALUE((UINTN
)FfsFileHeader
-
160 (UINTN
)FwVolHeader
, 8));
163 // Length is 24 bits wide so mask upper 8 bits
164 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
166 FileLength
= FFS_FILE_SIZE(*FileHeader
);
167 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
168 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) *FileHeader
+ FileOccupiedSize
);
171 FileOffset
= (UINT32
) ((UINT8
*) FfsFileHeader
- (UINT8
*) FwVolHeader
);
173 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
175 // Get FileState which is the highest bit of the State
177 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
181 case EFI_FILE_HEADER_INVALID
:
182 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER
);
183 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
186 case EFI_FILE_DATA_VALID
:
187 case EFI_FILE_MARKED_FOR_UPDATE
:
188 if (CalculateHeaderChecksum (FfsFileHeader
) == 0) {
189 FileLength
= FFS_FILE_SIZE(FfsFileHeader
);
190 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
192 if ((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) {
194 *FileHeader
= FfsFileHeader
;
199 FileOffset
+= FileOccupiedSize
;
200 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ FileOccupiedSize
);
202 return EFI_NOT_FOUND
;
206 case EFI_FILE_DELETED
:
207 FileLength
= FFS_FILE_SIZE(FfsFileHeader
);
208 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
209 FileOffset
+= FileOccupiedSize
;
210 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ FileOccupiedSize
);
214 return EFI_NOT_FOUND
;
219 return EFI_NOT_FOUND
;
223 Locates a section within a series of sections
224 with the specified section type.
226 @param[in] Sections The sections to search
227 @param[in] SizeOfSections Total size of all sections
228 @param[in] SectionType The section type to locate
229 @param[out] FoundSection The FFS section if found
231 @retval EFI_SUCCESS The file and section was found
232 @retval EFI_NOT_FOUND The file and section was not found
233 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
237 FindFfsSectionInSections (
239 IN UINTN SizeOfSections
,
240 IN EFI_SECTION_TYPE SectionType
,
241 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
244 EFI_PHYSICAL_ADDRESS CurrentAddress
;
246 EFI_PHYSICAL_ADDRESS EndOfSections
;
247 EFI_COMMON_SECTION_HEADER
*Section
;
248 EFI_PHYSICAL_ADDRESS EndOfSection
;
251 // Loop through the FFS file sections
253 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Sections
;
254 EndOfSections
= EndOfSection
+ SizeOfSections
;
256 if (EndOfSection
== EndOfSections
) {
259 CurrentAddress
= EndOfSection
;
261 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
) CurrentAddress
;
263 Size
= SECTION_SIZE (Section
);
264 if (Size
< sizeof (*Section
)) {
265 return EFI_VOLUME_CORRUPTED
;
268 EndOfSection
= CurrentAddress
+ Size
;
269 if (EndOfSection
> EndOfSections
) {
270 return EFI_VOLUME_CORRUPTED
;
272 Size
= GET_OCCUPIED_SIZE (Size
, 4);
275 // Look for the requested section type
277 if (Section
->Type
== SectionType
) {
278 *FoundSection
= Section
;
283 return EFI_NOT_FOUND
;
287 Given the input file pointer, search for the next matching section in the
290 @param SearchType Filter to find only sections of this type.
291 @param FfsFileHeader Pointer to the current file to search.
292 @param SectionHeader Pointer to the Section matching SectionType in FfsFileHeader.
293 NULL if section not found
295 @retval EFI_NOT_FOUND No files matching the search criteria were found
301 IN EFI_SECTION_TYPE SectionType
,
302 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
303 IN OUT EFI_COMMON_SECTION_HEADER
**SectionHeader
307 EFI_COMMON_SECTION_HEADER
*Section
;
311 // Size is 24 bits wide so mask upper 8 bits.
312 // Does not include FfsFileHeader header size
313 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
315 Section
= (EFI_COMMON_SECTION_HEADER
*) (FfsFileHeader
+ 1);
316 FileSize
= FFS_FILE_SIZE(FfsFileHeader
);
317 FileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
319 Status
= FindFfsSectionInSections (
329 Given the input file pointer, search for the next matching section in the
332 @param SearchType Filter to find only sections of this type.
333 @param FfsFileHeader Pointer to the current file to search.
334 @param SectionData Pointer to the Section matching SectionType in FfsFileHeader.
335 NULL if section not found
336 @param SectionDataSize The size of SectionData
338 @retval EFI_NOT_FOUND No files matching the search criteria were found
344 IN EFI_SECTION_TYPE SectionType
,
345 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
346 IN OUT VOID
**SectionData
,
347 IN OUT UINTN
*SectionDataSize
351 EFI_COMMON_SECTION_HEADER
*Section
;
352 UINT32 SectionLength
;
356 // Size is 24 bits wide so mask upper 8 bits.
357 // Does not include FfsFileHeader header size
358 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
360 Section
= (EFI_COMMON_SECTION_HEADER
*) (FfsFileHeader
+ 1);
361 FileSize
= FFS_FILE_SIZE(FfsFileHeader
);
362 FileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
366 while (ParsedLength
< FileSize
) {
367 if (Section
->Type
== SectionType
) {
368 *SectionData
= (VOID
*) (Section
+ 1);
369 *SectionDataSize
= SECTION_SIZE(Section
);
373 // Size is 24 bits wide so mask upper 8 bits.
374 // SectionLength is adjusted it is 4 byte aligned.
375 // Go to the next section
377 SectionLength
= SECTION_SIZE(Section
);
378 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
380 ParsedLength
+= SectionLength
;
381 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ SectionLength
);
384 return EFI_NOT_FOUND
;