2 FFS file access utilities.
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "FwVolDriver.h"
19 #define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address))
22 Set File State in the FfsHeader.
24 @param State File state to be set into FFS header.
25 @param FfsHeader Points to the FFS file header
31 IN EFI_FFS_FILE_HEADER
*FfsHeader
35 // Set File State in the FfsHeader
37 FfsHeader
->State
= (EFI_FFS_FILE_STATE
) (FfsHeader
->State
^ State
);
42 Get the FFS file state by checking the highest bit set in the header's state field.
44 @param ErasePolarity Erase polarity attribute of the firmware volume
45 @param FfsHeader Points to the FFS file header
47 @return FFS File state
52 IN UINT8 ErasePolarity
,
53 IN EFI_FFS_FILE_HEADER
*FfsHeader
56 EFI_FFS_FILE_STATE FileState
;
59 FileState
= FfsHeader
->State
;
61 if (ErasePolarity
!= 0) {
62 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
66 while (HighestBit
!= 0 && ((HighestBit
& FileState
) == 0)) {
70 return (EFI_FFS_FILE_STATE
) HighestBit
;
74 Convert the Buffer Address to LBA Entry Address.
76 @param FvDevice Cached FvDevice
77 @param BufferAddress Address of Buffer
78 @param LbaListEntry Pointer to the got LBA entry that contains the address.
80 @retval EFI_NOT_FOUND Buffer address is out of FvDevice.
81 @retval EFI_SUCCESS LBA entry is found for Buffer address.
86 IN FV_DEVICE
*FvDevice
,
87 IN EFI_PHYSICAL_ADDRESS BufferAddress
,
88 OUT LBA_ENTRY
**LbaListEntry
94 Link
= FvDevice
->LbaHeader
.ForwardLink
;
95 LbaEntry
= (LBA_ENTRY
*) Link
;
98 // Locate LBA which contains the address
100 while (&LbaEntry
->Link
!= &FvDevice
->LbaHeader
) {
101 if ((EFI_PHYSICAL_ADDRESS
) (UINTN
) (LbaEntry
->StartingAddress
) > BufferAddress
) {
105 Link
= LbaEntry
->Link
.ForwardLink
;
106 LbaEntry
= (LBA_ENTRY
*) Link
;
109 if (&LbaEntry
->Link
== &FvDevice
->LbaHeader
) {
110 return EFI_NOT_FOUND
;
113 Link
= LbaEntry
->Link
.BackLink
;
114 LbaEntry
= (LBA_ENTRY
*) Link
;
116 if (&LbaEntry
->Link
== &FvDevice
->LbaHeader
) {
117 return EFI_NOT_FOUND
;
120 *LbaListEntry
= LbaEntry
;
126 Convert the Buffer Address to LBA Address & Offset.
128 @param FvDevice Cached FvDevice
129 @param BufferAddress Address of Buffer
130 @param Lba Pointer to the gob Lba value
131 @param Offset Pointer to the got Offset
133 @retval EFI_NOT_FOUND Buffer address is out of FvDevice.
134 @retval EFI_SUCCESS LBA and Offset is found for Buffer address.
139 IN FV_DEVICE
*FvDevice
,
140 IN EFI_PHYSICAL_ADDRESS BufferAddress
,
150 Status
= Buffer2LbaEntry (
155 if (EFI_ERROR (Status
)) {
159 *Lba
= LbaEntry
->LbaIndex
;
160 *Offset
= (UINTN
) BufferAddress
- (UINTN
) LbaEntry
->StartingAddress
;
166 Check if a block of buffer is erased.
168 @param ErasePolarity Erase polarity attribute of the firmware volume
169 @param Buffer The buffer to be checked
170 @param BufferSize Size of the buffer in bytes
172 @retval TRUE The block of buffer is erased
173 @retval FALSE The block of buffer is not erased
178 IN UINT8 ErasePolarity
,
186 if (ErasePolarity
== 1) {
192 for (Count
= 0; Count
< BufferSize
; Count
++) {
193 if (Buffer
[Count
] != EraseByte
) {
202 Verify checksum of the firmware volume header.
204 @param FvHeader Points to the firmware volume header to be checked
206 @retval TRUE Checksum verification passed
207 @retval FALSE Checksum verification failed
211 VerifyFvHeaderChecksum (
212 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
217 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
);
227 Verify checksum of the FFS file header.
229 @param FfsHeader Points to the FFS file header to be checked
231 @retval TRUE Checksum verification passed
232 @retval FALSE Checksum verification failed
236 VerifyHeaderChecksum (
237 IN EFI_FFS_FILE_HEADER
*FfsHeader
240 UINT8 HeaderChecksum
;
242 HeaderChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
243 HeaderChecksum
= (UINT8
) (HeaderChecksum
- FfsHeader
->State
- FfsHeader
->IntegrityCheck
.Checksum
.File
);
245 if (HeaderChecksum
== 0) {
253 Verify checksum of the FFS file data.
255 @param FfsHeader Points to the FFS file header to be checked
257 @retval TRUE Checksum verification passed
258 @retval FALSE Checksum verification failed
263 IN EFI_FFS_FILE_HEADER
*FfsHeader
267 EFI_FV_FILE_ATTRIBUTES Attributes
;
270 Attributes
= FfsHeader
->Attributes
;
272 if ((Attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
274 FileSize
= *(UINT32
*) FfsHeader
->Size
& 0x00FFFFFF;
277 // Check checksum of FFS data
279 FileChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FileSize
- sizeof (EFI_FFS_FILE_HEADER
));
280 FileChecksum
= (UINT8
) (FileChecksum
+ FfsHeader
->IntegrityCheck
.Checksum
.File
);
282 if (FileChecksum
== 0) {
290 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
300 Check if it's a valid FFS file header.
302 @param ErasePolarity Erase polarity attribute of the firmware volume
303 @param FfsHeader Points to the FFS file header to be checked
305 @retval TRUE Valid FFS file header
306 @retval FALSE Invalid FFS file header
311 IN UINT8 ErasePolarity
,
312 IN EFI_FFS_FILE_HEADER
*FfsHeader
315 EFI_FFS_FILE_STATE FileState
;
318 // Check if it is a free space
323 sizeof (EFI_FFS_FILE_HEADER
)
328 FileState
= GetFileState (ErasePolarity
, FfsHeader
);
331 case EFI_FILE_HEADER_CONSTRUCTION
:
335 case EFI_FILE_HEADER_INVALID
:
338 case EFI_FILE_HEADER_VALID
:
342 case EFI_FILE_DATA_VALID
:
346 case EFI_FILE_MARKED_FOR_UPDATE
:
350 case EFI_FILE_DELETED
:
352 // Here we need to verify header checksum
354 if (!VerifyHeaderChecksum (FfsHeader
)) {
370 Get next possible of Firmware File System Header.
372 @param ErasePolarity Erase polarity attribute of the firmware volume
373 @param FfsHeader Points to the FFS file header to be skipped.
375 @return Pointer to next FFS header.
379 GetNextPossibleFileHeader (
380 IN UINT8 ErasePolarity
,
381 IN EFI_FFS_FILE_HEADER
*FfsHeader
387 if (!IsValidFFSHeader (ErasePolarity
, FfsHeader
)) {
391 return (EFI_PHYSICAL_ADDRESS
) (UINTN
) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
394 FileLength
= *(UINT32
*) FfsHeader
->Size
& 0x00FFFFFF;
397 // Since FileLength is not multiple of 8, we need skip some bytes
398 // to get next possible header
400 SkipLength
= FileLength
;
401 while ((SkipLength
& 0x07) != 0) {
405 return (EFI_PHYSICAL_ADDRESS
) (UINTN
) FfsHeader
+ SkipLength
;
409 Search FFS file with the same FFS name in FV Cache.
411 @param FvDevice Cached FV image.
412 @param FfsHeader Points to the FFS file header to be skipped.
413 @param StateBit FFS file state bit to be checked.
415 @return Pointer to next found FFS header. NULL will return if no found.
418 EFI_FFS_FILE_HEADER
*
420 IN FV_DEVICE
*FvDevice
,
421 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
422 IN EFI_FFS_FILE_STATE StateBit
426 EFI_FFS_FILE_HEADER
*NextFfsFile
;
429 // Search duplicate file, not from the beginning of FV,
430 // just search the next ocurrence of this file
432 NextFfsFile
= FfsHeader
;
435 Ptr
= (UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (
436 GetNextPossibleFileHeader (FvDevice
->ErasePolarity
,
439 NextFfsFile
= (EFI_FFS_FILE_HEADER
*) Ptr
;
441 if ((UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (FvDevice
->CachedFv
) + FvDevice
->FwVolHeader
->FvLength
- Ptr
<
442 sizeof (EFI_FFS_FILE_HEADER
)
447 if (!IsValidFFSHeader (FvDevice
->ErasePolarity
, NextFfsFile
)) {
451 if (!VerifyFileChecksum (NextFfsFile
)) {
455 if (CompareGuid (&NextFfsFile
->Name
, &FfsHeader
->Name
)) {
456 if (GetFileState (FvDevice
->ErasePolarity
, NextFfsFile
) == StateBit
) {
460 } while (Ptr
< (UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (FvDevice
->CachedFv
) + FvDevice
->FwVolHeader
->FvLength
);
466 Change FFS file header state and write to FV.
468 @param FvDevice Cached FV image.
469 @param FfsHeader Points to the FFS file header to be updated.
470 @param State FFS file state to be set.
472 @retval EFI_SUCCESS File state is writen into FV.
473 @retval others File state can't be writen into FV.
478 IN FV_DEVICE
*FvDevice
,
479 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
480 IN EFI_FFS_FILE_STATE State
486 UINTN NumBytesWritten
;
491 SetFileState (State
, FfsHeader
);
495 (EFI_PHYSICAL_ADDRESS
) (UINTN
) (&FfsHeader
->State
),
500 // Write the state byte into FV
502 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
503 Status
= FvDevice
->Fvb
->Write (
514 Check if it's a valid FFS file.
515 Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
517 @param FvDevice Cached FV image.
518 @param FfsHeader Points to the FFS file to be checked
520 @retval TRUE Valid FFS file
521 @retval FALSE Invalid FFS file
526 IN FV_DEVICE
*FvDevice
,
527 IN EFI_FFS_FILE_HEADER
*FfsHeader
530 EFI_FFS_FILE_STATE FileState
;
533 ErasePolarity
= FvDevice
->ErasePolarity
;
535 FileState
= GetFileState (ErasePolarity
, FfsHeader
);
538 case EFI_FILE_DATA_VALID
:
539 if (!VerifyFileChecksum (FfsHeader
)) {
543 if (FfsHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
547 // Check if there is another duplicated file with the EFI_FILE_DATA_VALID
549 if (DuplicateFileExist (FvDevice
, FfsHeader
, EFI_FILE_DATA_VALID
) != NULL
) {
555 case EFI_FILE_MARKED_FOR_UPDATE
:
556 if (!VerifyFileChecksum (FfsHeader
)) {
560 if (FfsHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
562 // since its data area is not unperturbed, it cannot be reclaimed,
563 // marked it as deleted
565 UpdateHeaderBit (FvDevice
, FfsHeader
, EFI_FILE_DELETED
);
568 } else if (DuplicateFileExist (FvDevice
, FfsHeader
, EFI_FILE_DATA_VALID
) != NULL
) {
570 // Here the found file is more recent than this file,
571 // mark it as deleted
573 UpdateHeaderBit (FvDevice
, FfsHeader
, EFI_FILE_DELETED
);
582 case EFI_FILE_DELETED
:
583 if (!VerifyFileChecksum (FfsHeader
)) {
597 Locate the first file in FV.
599 @param FvDevice Cached FV image.
600 @param FirstFile Points to the got first FFS file header.
602 @retval EFI_NOT_FOUND No FFS file is found in FV.
603 @retval EFI_SUCCESS The first FFS file is got.
608 IN FV_DEVICE
*FvDevice
,
609 OUT EFI_FFS_FILE_HEADER
**FirstFile
612 FFS_FILE_LIST_ENTRY
*TmpFileList
;
615 Link
= FvDevice
->FfsFileListHeader
.ForwardLink
;
617 if (Link
== &FvDevice
->FfsFileListHeader
) {
618 return EFI_NOT_FOUND
;
621 TmpFileList
= (FFS_FILE_LIST_ENTRY
*) Link
;
622 *FirstFile
= (EFI_FFS_FILE_HEADER
*) TmpFileList
->FfsHeader
;