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 if (IS_FFS_FILE2 (FfsHeader
)) {
243 HeaderChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER2
));
245 HeaderChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
247 HeaderChecksum
= (UINT8
) (HeaderChecksum
- FfsHeader
->State
- FfsHeader
->IntegrityCheck
.Checksum
.File
);
249 if (HeaderChecksum
== 0) {
257 Verify checksum of the FFS file data.
259 @param FfsHeader Points to the FFS file header to be checked
261 @retval TRUE Checksum verification passed
262 @retval FALSE Checksum verification failed
267 IN EFI_FFS_FILE_HEADER
*FfsHeader
271 EFI_FV_FILE_ATTRIBUTES Attributes
;
273 Attributes
= FfsHeader
->Attributes
;
275 if ((Attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
278 // Check checksum of FFS data
280 if (IS_FFS_FILE2 (FfsHeader
)) {
281 FileChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER2
), FFS_FILE2_SIZE (FfsHeader
) - sizeof (EFI_FFS_FILE_HEADER2
));
283 FileChecksum
= CalculateSum8 ((UINT8
*) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FFS_FILE_SIZE (FfsHeader
) - sizeof (EFI_FFS_FILE_HEADER
));
285 FileChecksum
= (UINT8
) (FileChecksum
+ FfsHeader
->IntegrityCheck
.Checksum
.File
);
287 if (FileChecksum
== 0) {
295 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
305 Check if it's a valid FFS file header.
307 @param ErasePolarity Erase polarity attribute of the firmware volume
308 @param FfsHeader Points to the FFS file header to be checked
310 @retval TRUE Valid FFS file header
311 @retval FALSE Invalid FFS file header
316 IN UINT8 ErasePolarity
,
317 IN EFI_FFS_FILE_HEADER
*FfsHeader
320 EFI_FFS_FILE_STATE FileState
;
323 // Check if it is a free space
328 sizeof (EFI_FFS_FILE_HEADER
)
333 FileState
= GetFileState (ErasePolarity
, FfsHeader
);
336 case EFI_FILE_HEADER_CONSTRUCTION
:
340 case EFI_FILE_HEADER_INVALID
:
343 case EFI_FILE_HEADER_VALID
:
347 case EFI_FILE_DATA_VALID
:
351 case EFI_FILE_MARKED_FOR_UPDATE
:
355 case EFI_FILE_DELETED
:
357 // Here we need to verify header checksum
359 if (!VerifyHeaderChecksum (FfsHeader
)) {
375 Get next possible of Firmware File System Header.
377 @param ErasePolarity Erase polarity attribute of the firmware volume
378 @param FfsHeader Points to the FFS file header to be skipped.
380 @return Pointer to next FFS header.
384 GetNextPossibleFileHeader (
385 IN UINT8 ErasePolarity
,
386 IN EFI_FFS_FILE_HEADER
*FfsHeader
392 if (!IsValidFFSHeader (ErasePolarity
, FfsHeader
)) {
396 if (IS_FFS_FILE2 (FfsHeader
)) {
397 return (EFI_PHYSICAL_ADDRESS
) (UINTN
) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
399 return (EFI_PHYSICAL_ADDRESS
) (UINTN
) FfsHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
403 if (IS_FFS_FILE2 (FfsHeader
)) {
404 FileLength
= FFS_FILE2_SIZE (FfsHeader
);
406 FileLength
= FFS_FILE_SIZE (FfsHeader
);
410 // Since FileLength is not multiple of 8, we need skip some bytes
411 // to get next possible header
413 SkipLength
= FileLength
;
414 while ((SkipLength
& 0x07) != 0) {
418 return (EFI_PHYSICAL_ADDRESS
) (UINTN
) FfsHeader
+ SkipLength
;
422 Search FFS file with the same FFS name in FV Cache.
424 @param FvDevice Cached FV image.
425 @param FfsHeader Points to the FFS file header to be skipped.
426 @param StateBit FFS file state bit to be checked.
428 @return Pointer to next found FFS header. NULL will return if no found.
431 EFI_FFS_FILE_HEADER
*
433 IN FV_DEVICE
*FvDevice
,
434 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
435 IN EFI_FFS_FILE_STATE StateBit
439 EFI_FFS_FILE_HEADER
*NextFfsFile
;
442 // Search duplicate file, not from the beginning of FV,
443 // just search the next ocurrence of this file
445 NextFfsFile
= FfsHeader
;
448 Ptr
= (UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (
449 GetNextPossibleFileHeader (FvDevice
->ErasePolarity
,
452 NextFfsFile
= (EFI_FFS_FILE_HEADER
*) Ptr
;
454 if ((UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (FvDevice
->CachedFv
) + FvDevice
->FwVolHeader
->FvLength
- Ptr
<
455 sizeof (EFI_FFS_FILE_HEADER
)
460 if (!IsValidFFSHeader (FvDevice
->ErasePolarity
, NextFfsFile
)) {
464 if (!VerifyFileChecksum (NextFfsFile
)) {
468 if (CompareGuid (&NextFfsFile
->Name
, &FfsHeader
->Name
)) {
469 if (GetFileState (FvDevice
->ErasePolarity
, NextFfsFile
) == StateBit
) {
473 } while (Ptr
< (UINT8
*) PHYSICAL_ADDRESS_TO_POINTER (FvDevice
->CachedFv
) + FvDevice
->FwVolHeader
->FvLength
);
479 Change FFS file header state and write to FV.
481 @param FvDevice Cached FV image.
482 @param FfsHeader Points to the FFS file header to be updated.
483 @param State FFS file state to be set.
485 @retval EFI_SUCCESS File state is writen into FV.
486 @retval others File state can't be writen into FV.
491 IN FV_DEVICE
*FvDevice
,
492 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
493 IN EFI_FFS_FILE_STATE State
499 UINTN NumBytesWritten
;
504 SetFileState (State
, FfsHeader
);
508 (EFI_PHYSICAL_ADDRESS
) (UINTN
) (&FfsHeader
->State
),
513 // Write the state byte into FV
515 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
516 Status
= FvDevice
->Fvb
->Write (
527 Check if it's a valid FFS file.
528 Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
530 @param FvDevice Cached FV image.
531 @param FfsHeader Points to the FFS file to be checked
533 @retval TRUE Valid FFS file
534 @retval FALSE Invalid FFS file
539 IN FV_DEVICE
*FvDevice
,
540 IN EFI_FFS_FILE_HEADER
*FfsHeader
543 EFI_FFS_FILE_STATE FileState
;
546 ErasePolarity
= FvDevice
->ErasePolarity
;
548 FileState
= GetFileState (ErasePolarity
, FfsHeader
);
551 case EFI_FILE_DATA_VALID
:
552 if (!VerifyFileChecksum (FfsHeader
)) {
556 if (FfsHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
560 // Check if there is another duplicated file with the EFI_FILE_DATA_VALID
562 if (DuplicateFileExist (FvDevice
, FfsHeader
, EFI_FILE_DATA_VALID
) != NULL
) {
568 case EFI_FILE_MARKED_FOR_UPDATE
:
569 if (!VerifyFileChecksum (FfsHeader
)) {
573 if (FfsHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
575 // since its data area is not unperturbed, it cannot be reclaimed,
576 // marked it as deleted
578 UpdateHeaderBit (FvDevice
, FfsHeader
, EFI_FILE_DELETED
);
581 } else if (DuplicateFileExist (FvDevice
, FfsHeader
, EFI_FILE_DATA_VALID
) != NULL
) {
583 // Here the found file is more recent than this file,
584 // mark it as deleted
586 UpdateHeaderBit (FvDevice
, FfsHeader
, EFI_FILE_DELETED
);
595 case EFI_FILE_DELETED
:
596 if (!VerifyFileChecksum (FfsHeader
)) {