2 Implements functions to pad firmware file.
4 Copyright (c) 2006 - 2018, 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"
20 Calculate the checksum for a PAD file.
22 @param PadFileHeader The Pad File to be caculeted the checksum.
27 IN EFI_FFS_FILE_HEADER
*PadFileHeader
30 if ((PadFileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
32 if (IS_FFS_FILE2 (PadFileHeader
)) {
34 // Calculate checksum of Pad File Data
36 PadFileHeader
->IntegrityCheck
.Checksum
.File
=
37 CalculateCheckSum8 ((UINT8
*) PadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
), FFS_FILE2_SIZE (PadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
));
41 // Calculate checksum of Pad File Data
43 PadFileHeader
->IntegrityCheck
.Checksum
.File
=
44 CalculateCheckSum8 ((UINT8
*) PadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FFS_FILE_SIZE (PadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
));
49 PadFileHeader
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
57 Create a PAD File in the Free Space.
59 @param FvDevice Firmware Volume Device.
60 @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted.
61 @param Size Pad file Size, not include the header.
62 @param PadFileEntry The Ffs File Entry that points to this Pad File.
64 @retval EFI_SUCCESS Successfully create a PAD file.
65 @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file.
66 @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment.
67 @retval EFI_DEVICE_ERROR Free space is not erased.
70 FvCreatePadFileInFreeSpace (
71 IN FV_DEVICE
*FvDevice
,
72 IN FREE_SPACE_ENTRY
*FreeSpaceEntry
,
74 OUT FFS_FILE_LIST_ENTRY
**PadFileEntry
78 EFI_FFS_FILE_HEADER
*PadFileHeader
;
80 UINTN NumBytesWritten
;
83 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
87 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
88 FileSize
= Size
+ HeaderSize
;
89 if (FileSize
> 0x00FFFFFF) {
90 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
91 FileSize
= Size
+ HeaderSize
;
94 if (FreeSpaceEntry
->Length
< FileSize
) {
95 return EFI_OUT_OF_RESOURCES
;
98 if ((Size
& 0x07) != 0) {
99 return EFI_INVALID_PARAMETER
;
102 StartPos
= FreeSpaceEntry
->StartingAddress
;
105 // First double check the space
107 if (!IsBufferErased (
108 FvDevice
->ErasePolarity
,
112 return EFI_DEVICE_ERROR
;
115 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) StartPos
;
118 // Create File Step 1
120 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
122 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
123 StateOffset
= Offset
+ (UINT8
*) &PadFileHeader
->State
- (UINT8
*) PadFileHeader
;
125 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
130 &PadFileHeader
->State
132 if (EFI_ERROR (Status
)) {
133 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
137 // Update Free Space Entry, since header is allocated
139 FreeSpaceEntry
->Length
-= HeaderSize
;
140 FreeSpaceEntry
->StartingAddress
+= HeaderSize
;
143 // Fill File Name Guid, here we assign a NULL-GUID to Pad files
145 ZeroMem (&PadFileHeader
->Name
, sizeof (EFI_GUID
));
148 // Fill File Type, checksum(0), Attributes(0), Size
150 PadFileHeader
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
151 PadFileHeader
->Attributes
= 0;
152 if ((FileSize
) > 0x00FFFFFF) {
153 ((EFI_FFS_FILE_HEADER2
*) PadFileHeader
)->ExtendedSize
= (UINT32
) FileSize
;
154 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
155 PadFileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
157 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
158 *(UINT32
*) PadFileHeader
->Size
|= FileSize
;
161 SetHeaderChecksum (PadFileHeader
);
162 SetPadFileChecksum (PadFileHeader
);
164 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
166 NumBytesWritten
= HeaderSize
;
171 (UINT8
*) PadFileHeader
173 if (EFI_ERROR (Status
)) {
178 // Step 2, then Mark header valid, since no data write,
179 // mark the data valid at the same time.
181 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
182 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
184 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
185 StateOffset
= Offset
+ (UINT8
*) &PadFileHeader
->State
- (UINT8
*) PadFileHeader
;
187 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
192 &PadFileHeader
->State
194 if (EFI_ERROR (Status
)) {
195 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
196 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
200 // Update Free Space Entry, since header is allocated
202 FreeSpaceEntry
->Length
-= Size
;
203 FreeSpaceEntry
->StartingAddress
+= Size
;
206 // If successfully, insert an FfsFileEntry at the end of ffs file list
208 FfsFileEntry
= AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY
));
209 ASSERT (FfsFileEntry
!= NULL
);
211 FfsFileEntry
->FfsHeader
= (UINT8
*) (UINTN
) StartPos
;
212 InsertTailList (&FvDevice
->FfsFileListHeader
, &FfsFileEntry
->Link
);
214 *PadFileEntry
= FfsFileEntry
;
215 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
221 Fill pad file header within firmware cache.
223 @param PadFileHeader The start of the Pad File Buffer.
224 @param PadFileLength The length of the pad file including the header.
229 IN EFI_FFS_FILE_HEADER
*PadFileHeader
,
230 IN UINTN PadFileLength
234 // Fill File Name Guid, here we assign a NULL-GUID to Pad files
236 ZeroMem (&PadFileHeader
->Name
, sizeof (EFI_GUID
));
239 // Fill File Type, checksum(0), Attributes(0), Size
241 PadFileHeader
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
242 PadFileHeader
->Attributes
= 0;
243 if (PadFileLength
> 0x00FFFFFF) {
244 ((EFI_FFS_FILE_HEADER2
*) PadFileHeader
)->ExtendedSize
= (UINT32
) PadFileLength
;
245 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
246 PadFileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
248 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
249 *(UINT32
*) PadFileHeader
->Size
|= PadFileLength
;
252 SetHeaderChecksum (PadFileHeader
);
253 SetPadFileChecksum (PadFileHeader
);
256 // Set File State to 0x00000111
258 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
259 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
260 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
266 Create entire FFS file.
268 @param FileHeader Starting Address of a Buffer that hold the FFS File image.
269 @param FfsFileBuffer The source buffer that contains the File Data.
270 @param BufferSize The length of FfsFileBuffer.
271 @param ActualFileSize Size of FFS file.
272 @param FileName The Guid of Ffs File.
273 @param FileType The type of the written Ffs File.
274 @param FileAttributes The attributes of the written Ffs File.
276 @retval EFI_INVALID_PARAMETER File type is not valid.
277 @retval EFI_SUCCESS FFS file is successfully created.
282 OUT EFI_FFS_FILE_HEADER
*FileHeader
,
283 IN UINT8
*FfsFileBuffer
,
285 IN UINTN ActualFileSize
,
286 IN EFI_GUID
*FileName
,
287 IN EFI_FV_FILETYPE FileType
,
288 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
291 EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute
;
292 EFI_FFS_FILE_HEADER
*TmpFileHeader
;
295 // File Type value 0x0E~0xE0 are reserved
297 if ((FileType
> EFI_FV_FILETYPE_SMM_CORE
) && (FileType
< 0xE0)) {
298 return EFI_INVALID_PARAMETER
;
301 TmpFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileBuffer
;
303 // First fill all fields ready in FfsFileBuffer
305 CopyGuid (&TmpFileHeader
->Name
, FileName
);
306 TmpFileHeader
->Type
= FileType
;
309 // Convert the FileAttributes to FFSFileAttributes
311 FvFileAttrib2FfsFileAttrib (FileAttributes
, &TmpFileAttribute
);
313 TmpFileHeader
->Attributes
= TmpFileAttribute
;
315 if (ActualFileSize
> 0x00FFFFFF) {
316 ((EFI_FFS_FILE_HEADER2
*) FileHeader
)->ExtendedSize
= (UINT32
) ActualFileSize
;
317 *(UINT32
*) FileHeader
->Size
&= 0xFF000000;
318 FileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
320 *(UINT32
*) FileHeader
->Size
&= 0xFF000000;
321 *(UINT32
*) FileHeader
->Size
|= ActualFileSize
;
324 SetHeaderChecksum (TmpFileHeader
);
325 SetFileChecksum (TmpFileHeader
, ActualFileSize
);
327 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, TmpFileHeader
);
328 SetFileState (EFI_FILE_HEADER_VALID
, TmpFileHeader
);
329 SetFileState (EFI_FILE_DATA_VALID
, TmpFileHeader
);
332 // Copy data from FfsFileBuffer to FileHeader(cache)
334 CopyMem (FileHeader
, FfsFileBuffer
, BufferSize
);
340 Fill some other extra space using 0xFF(Erase Value).
342 @param ErasePolarity Fv erase value.
343 @param FileHeader Point to the start of FFS File.
344 @param ExtraLength The pading length.
349 IN UINT8 ErasePolarity
,
350 IN EFI_FFS_FILE_HEADER
*FileHeader
,
357 if (IS_FFS_FILE2 (FileHeader
)) {
358 Ptr
= (UINT8
*) FileHeader
+ FFS_FILE2_SIZE (FileHeader
);
360 Ptr
= (UINT8
*) FileHeader
+ FFS_FILE_SIZE (FileHeader
);
363 if (ErasePolarity
== 0) {
369 // Fill the non-used space with Padding Byte
371 SetMem (Ptr
, ExtraLength
, PadingByte
);
377 Free File List entry pointed by FileListHead.
379 @param FileListHeader FileListEntry Header.
384 IN LIST_ENTRY
*FileListHead
387 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
388 LIST_ENTRY
*NextEntry
;
390 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) (FileListHead
->ForwardLink
);
393 // Loop the whole list entry to free resources
395 while (&FfsFileEntry
->Link
!= FileListHead
) {
396 NextEntry
= (&FfsFileEntry
->Link
)->ForwardLink
;
397 FreePool (FfsFileEntry
);
398 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) NextEntry
;
405 Create a new file within a PAD file area.
407 @param FvDevice Firmware Volume Device.
408 @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state).
409 @param BufferSize The size of FfsFileBuffer.
410 @param ActualFileSize The actual file length, it may not be multiples of 8.
411 @param FileName The FFS File Name.
412 @param FileType The FFS File Type.
413 @param FileAttributes The Attributes of the FFS File to be created.
415 @retval EFI_SUCCESS Successfully create a new file within the found PAD file area.
416 @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found.
417 @retval other errors New file is created failed.
421 FvCreateNewFileInsidePadFile (
422 IN FV_DEVICE
*FvDevice
,
423 IN UINT8
*FfsFileBuffer
,
425 IN UINTN ActualFileSize
,
426 IN EFI_GUID
*FileName
,
427 IN EFI_FV_FILETYPE FileType
,
428 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
431 UINTN RequiredAlignment
;
432 FFS_FILE_LIST_ENTRY
*PadFileEntry
;
436 EFI_FFS_FILE_HEADER
*FileHeader
;
437 EFI_FFS_FILE_HEADER
*OldPadFileHeader
;
438 EFI_FFS_FILE_HEADER
*PadFileHeader
;
439 EFI_FFS_FILE_HEADER
*TailPadFileHeader
;
442 UINTN NumBytesWritten
;
444 LIST_ENTRY NewFileList
;
445 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
446 FFS_FILE_LIST_ENTRY
*FfsEntry
;
447 FFS_FILE_LIST_ENTRY
*NextFfsEntry
;
450 // First get the required alignment from the File Attributes
452 RequiredAlignment
= GetRequiredAlignment (FileAttributes
);
455 // Find a suitable PAD File
457 Status
= FvLocatePadFile (
465 if (EFI_ERROR (Status
)) {
466 return EFI_OUT_OF_RESOURCES
;
469 OldPadFileHeader
= (EFI_FFS_FILE_HEADER
*) PadFileEntry
->FfsHeader
;
472 // Step 1: Update Pad File Header
474 SetFileState (EFI_FILE_MARKED_FOR_UPDATE
, OldPadFileHeader
);
476 StartPos
= PadFileEntry
->FfsHeader
;
478 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
479 StateOffset
= Offset
+ (UINT8
*) &OldPadFileHeader
->State
- (UINT8
*) OldPadFileHeader
;
481 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
486 &OldPadFileHeader
->State
488 if (EFI_ERROR (Status
)) {
489 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, OldPadFileHeader
);
494 // Step 2: Update Pad area
496 InitializeListHead (&NewFileList
);
498 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
499 PadAreaLength
= FFS_FILE2_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
500 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
502 PadAreaLength
= FFS_FILE_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
503 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
508 // Insert a PAD file before to achieve required alignment
510 FvFillPadFile (PadFileHeader
, PadSize
);
511 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
512 ASSERT (NewFileListEntry
!= NULL
);
513 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
514 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
517 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
);
519 Status
= FvFillFfsFile (
528 if (EFI_ERROR (Status
)) {
529 FreeFileList (&NewFileList
);
533 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
534 ASSERT (NewFileListEntry
!= NULL
);
536 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
537 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
539 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
541 if (PadAreaLength
> (BufferSize
+ PadSize
)) {
542 if ((PadAreaLength
- BufferSize
- PadSize
) >= sizeof (EFI_FFS_FILE_HEADER
)) {
544 // we can insert another PAD file
546 TailPadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
);
547 FvFillPadFile (TailPadFileHeader
, PadAreaLength
- BufferSize
- PadSize
);
549 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
550 ASSERT (NewFileListEntry
!= NULL
);
552 NewFileListEntry
->FfsHeader
= (UINT8
*) TailPadFileHeader
;
553 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
556 // because left size cannot hold another PAD file header,
557 // adjust the writing file size (just in cache)
560 FvDevice
->ErasePolarity
,
562 PadAreaLength
- BufferSize
- PadSize
567 // Start writing to FV
569 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
570 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
572 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
575 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
577 NumBytesWritten
= PadAreaLength
;
584 if (EFI_ERROR (Status
)) {
585 FreeFileList (&NewFileList
);
586 FvDevice
->CurrentFfsFile
= NULL
;
591 // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
593 SetFileState (EFI_FILE_HEADER_INVALID
, OldPadFileHeader
);
595 StartPos
= PadFileEntry
->FfsHeader
;
597 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
598 StateOffset
= Offset
+ (UINT8
*) &OldPadFileHeader
->State
- (UINT8
*) OldPadFileHeader
;
600 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
605 &OldPadFileHeader
->State
607 if (EFI_ERROR (Status
)) {
608 SetFileState (EFI_FILE_HEADER_INVALID
, OldPadFileHeader
);
609 FreeFileList (&NewFileList
);
610 FvDevice
->CurrentFfsFile
= NULL
;
615 // If all successfully, update FFS_FILE_LIST
619 // Delete old pad file entry
621 FfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.BackLink
;
622 NextFfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.ForwardLink
;
624 FreePool (PadFileEntry
);
626 FfsEntry
->Link
.ForwardLink
= NewFileList
.ForwardLink
;
627 (NewFileList
.ForwardLink
)->BackLink
= &FfsEntry
->Link
;
628 NextFfsEntry
->Link
.BackLink
= NewFileList
.BackLink
;
629 (NewFileList
.BackLink
)->ForwardLink
= &NextFfsEntry
->Link
;
637 @param NumOfFiles Number of FfsBuffer.
638 @param FfsBuffer An array of pointer to an FFS File Buffer
648 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
649 if (FfsBuffer
[Index
] != NULL
) {
650 FreePool (FfsBuffer
[Index
]);
656 Create multiple files within a PAD File area.
658 @param FvDevice Firmware Volume Device.
659 @param PadFileEntry The pad file entry to be written in.
660 @param NumOfFiles Total File number to be written.
661 @param BufferSize The array of buffer size of each FfsBuffer.
662 @param ActualFileSize The array of actual file size.
663 @param PadSize The array of leading pad file size for each FFS File
664 @param FfsBuffer The array of Ffs Buffer pointer.
665 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
666 used to get name, attributes, type, etc.
668 @retval EFI_SUCCESS Add the input multiple files into PAD file area.
669 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
670 @retval other error Files can't be added into PAD file area.
674 FvCreateMultipleFilesInsidePadFile (
675 IN FV_DEVICE
*FvDevice
,
676 IN FFS_FILE_LIST_ENTRY
*PadFileEntry
,
678 IN UINTN
*BufferSize
,
679 IN UINTN
*ActualFileSize
,
681 IN UINT8
**FfsBuffer
,
682 IN EFI_FV_WRITE_FILE_DATA
*FileData
686 EFI_FFS_FILE_HEADER
*OldPadFileHeader
;
688 EFI_FFS_FILE_HEADER
*PadFileHeader
;
689 EFI_FFS_FILE_HEADER
*FileHeader
;
690 EFI_FFS_FILE_HEADER
*TailPadFileHeader
;
693 LIST_ENTRY NewFileList
;
694 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
696 UINTN NumBytesWritten
;
698 FFS_FILE_LIST_ENTRY
*FfsEntry
;
699 FFS_FILE_LIST_ENTRY
*NextFfsEntry
;
701 InitializeListHead (&NewFileList
);
703 NewFileListEntry
= NULL
;
705 OldPadFileHeader
= (EFI_FFS_FILE_HEADER
*) PadFileEntry
->FfsHeader
;
706 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
707 PadAreaLength
= FFS_FILE2_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
709 PadAreaLength
= FFS_FILE_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
712 Status
= UpdateHeaderBit (
715 EFI_FILE_MARKED_FOR_UPDATE
717 if (EFI_ERROR (Status
)) {
724 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
725 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
727 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
729 FileHeader
= PadFileHeader
;
731 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
732 if (PadSize
[Index
] != 0) {
733 FvFillPadFile (PadFileHeader
, PadSize
[Index
]);
734 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
735 if (NewFileListEntry
== NULL
) {
736 FreeFileList (&NewFileList
);
737 return EFI_OUT_OF_RESOURCES
;
740 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
741 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
744 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
[Index
]);
745 Status
= FvFillFfsFile (
749 ActualFileSize
[Index
],
750 FileData
[Index
].NameGuid
,
751 FileData
[Index
].Type
,
752 FileData
[Index
].FileAttributes
754 if (EFI_ERROR (Status
)) {
755 FreeFileList (&NewFileList
);
759 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
760 if (NewFileListEntry
== NULL
) {
761 FreeFileList (&NewFileList
);
762 return EFI_OUT_OF_RESOURCES
;
765 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
766 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
768 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[Index
]);
769 TotalSize
+= PadSize
[Index
];
770 TotalSize
+= BufferSize
[Index
];
773 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
775 // Maybe we need a tail pad file
777 if (PadAreaLength
> TotalSize
) {
778 if ((PadAreaLength
- TotalSize
) >= sizeof (EFI_FFS_FILE_HEADER
)) {
780 // we can insert another PAD file
782 TailPadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[NumOfFiles
- 1]);
783 FvFillPadFile (TailPadFileHeader
, PadAreaLength
- TotalSize
);
785 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
786 if (NewFileListEntry
== NULL
) {
787 FreeFileList (&NewFileList
);
788 FvDevice
->CurrentFfsFile
= NULL
;
789 return EFI_OUT_OF_RESOURCES
;
792 NewFileListEntry
->FfsHeader
= (UINT8
*) TailPadFileHeader
;
793 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
796 // because left size cannot hold another PAD file header,
797 // adjust the writing file size (just in cache)
800 FvDevice
->ErasePolarity
,
802 PadAreaLength
- TotalSize
807 // Start writing to FV
809 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
810 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
812 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
815 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
817 NumBytesWritten
= PadAreaLength
;
824 if (EFI_ERROR (Status
)) {
825 FreeFileList (&NewFileList
);
826 FvDevice
->CurrentFfsFile
= NULL
;
830 Status
= UpdateHeaderBit (
833 EFI_FILE_HEADER_INVALID
835 if (EFI_ERROR (Status
)) {
836 FreeFileList (&NewFileList
);
837 FvDevice
->CurrentFfsFile
= NULL
;
842 // Update File List Link
846 // First delete old pad file entry
848 FfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.BackLink
;
849 NextFfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.ForwardLink
;
851 FreePool (PadFileEntry
);
853 FfsEntry
->Link
.ForwardLink
= NewFileList
.ForwardLink
;
854 (NewFileList
.ForwardLink
)->BackLink
= &FfsEntry
->Link
;
855 NextFfsEntry
->Link
.BackLink
= NewFileList
.BackLink
;
856 (NewFileList
.BackLink
)->ForwardLink
= &NextFfsEntry
->Link
;
862 Create multiple files within the Free Space.
864 @param FvDevice Firmware Volume Device.
865 @param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted.
866 @param NumOfFiles Total File number to be written.
867 @param BufferSize The array of buffer size of each FfsBuffer.
868 @param ActualFileSize The array of actual file size.
869 @param PadSize The array of leading pad file size for each FFS File
870 @param FfsBuffer The array of Ffs Buffer pointer.
871 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
872 used to get name, attributes, type, etc.
874 @retval EFI_SUCCESS Add the input multiple files into PAD file area.
875 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
876 @retval other error Files can't be added into PAD file area.
880 FvCreateMultipleFilesInsideFreeSpace (
881 IN FV_DEVICE
*FvDevice
,
882 IN FREE_SPACE_ENTRY
*FreeSpaceEntry
,
884 IN UINTN
*BufferSize
,
885 IN UINTN
*ActualFileSize
,
887 IN UINT8
**FfsBuffer
,
888 IN EFI_FV_WRITE_FILE_DATA
*FileData
893 EFI_FFS_FILE_HEADER
*PadFileHeader
;
894 EFI_FFS_FILE_HEADER
*FileHeader
;
896 LIST_ENTRY NewFileList
;
897 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
899 UINTN NumBytesWritten
;
902 InitializeListHead (&NewFileList
);
904 NewFileListEntry
= NULL
;
907 StartPos
= FreeSpaceEntry
->StartingAddress
;
908 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) StartPos
;
909 FileHeader
= PadFileHeader
;
911 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
912 if (PadSize
[Index
] != 0) {
913 FvFillPadFile (PadFileHeader
, PadSize
[Index
]);
914 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
915 if (NewFileListEntry
== NULL
) {
916 FreeFileList (&NewFileList
);
917 return EFI_OUT_OF_RESOURCES
;
920 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
921 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
924 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
[Index
]);
925 Status
= FvFillFfsFile (
929 ActualFileSize
[Index
],
930 FileData
[Index
].NameGuid
,
931 FileData
[Index
].Type
,
932 FileData
[Index
].FileAttributes
934 if (EFI_ERROR (Status
)) {
935 FreeFileList (&NewFileList
);
939 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
940 if (NewFileListEntry
== NULL
) {
941 FreeFileList (&NewFileList
);
942 return EFI_OUT_OF_RESOURCES
;
945 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
946 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
948 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[Index
]);
949 TotalSize
+= PadSize
[Index
];
950 TotalSize
+= BufferSize
[Index
];
953 if (FreeSpaceEntry
->Length
< TotalSize
) {
954 FreeFileList (&NewFileList
);
955 return EFI_OUT_OF_RESOURCES
;
958 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
961 // Start writing to FV
963 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
965 NumBytesWritten
= TotalSize
;
972 if (EFI_ERROR (Status
)) {
973 FreeFileList (&NewFileList
);
974 FvDevice
->CurrentFfsFile
= NULL
;
978 FreeSpaceEntry
->Length
-= TotalSize
;
979 FreeSpaceEntry
->StartingAddress
+= TotalSize
;
981 NewFileListEntry
= (FFS_FILE_LIST_ENTRY
*) (NewFileList
.ForwardLink
);
983 while (NewFileListEntry
!= (FFS_FILE_LIST_ENTRY
*) &NewFileList
) {
984 InsertTailList (&FvDevice
->FfsFileListHeader
, &NewFileListEntry
->Link
);
985 NewFileListEntry
= (FFS_FILE_LIST_ENTRY
*) (NewFileListEntry
->Link
.ForwardLink
);
992 Write multiple files into FV in reliable method.
994 @param FvDevice Firmware Volume Device.
995 @param NumOfFiles Total File number to be written.
996 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
997 used to get name, attributes, type, etc
998 @param FileOperation The array of operation for each file.
1000 @retval EFI_SUCCESS Files are added into FV.
1001 @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files.
1002 @retval EFI_INVALID_PARAMETER File number is less than or equal to 1.
1003 @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files.
1007 FvCreateMultipleFiles (
1008 IN FV_DEVICE
*FvDevice
,
1009 IN UINTN NumOfFiles
,
1010 IN EFI_FV_WRITE_FILE_DATA
*FileData
,
1011 IN BOOLEAN
*FileOperation
1015 UINT8
*FfsBuffer
[MAX_FILES
];
1018 UINTN BufferSize
[MAX_FILES
];
1019 UINTN ActualFileSize
[MAX_FILES
];
1020 UINTN RequiredAlignment
[MAX_FILES
];
1021 UINTN PadSize
[MAX_FILES
];
1022 FFS_FILE_LIST_ENTRY
*PadFileEntry
;
1023 UINTN TotalSizeNeeded
;
1024 FREE_SPACE_ENTRY
*FreeSpaceEntry
;
1025 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
1027 EFI_GUID FileNameGuid
;
1028 EFI_FV_FILETYPE OldFileType
;
1029 EFI_FV_FILE_ATTRIBUTES OldFileAttributes
;
1031 FFS_FILE_LIST_ENTRY
*OldFfsFileEntry
[MAX_FILES
];
1032 EFI_FFS_FILE_HEADER
*OldFileHeader
[MAX_FILES
];
1033 BOOLEAN IsCreateFile
;
1037 // To use this function, we must ensure that the NumOfFiles is great
1040 if (NumOfFiles
<= 1) {
1041 return EFI_INVALID_PARAMETER
;
1044 if (NumOfFiles
> MAX_FILES
) {
1045 return EFI_UNSUPPORTED
;
1050 SetMem (FfsBuffer
, NumOfFiles
, 0);
1051 SetMem (RequiredAlignment
, NumOfFiles
, 8);
1052 SetMem (PadSize
, NumOfFiles
, 0);
1053 ZeroMem (OldFfsFileEntry
, sizeof (OldFfsFileEntry
));
1054 ZeroMem (OldFileHeader
, sizeof (OldFileHeader
));
1059 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1060 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
1061 ActualFileSize
[Index1
] = FileData
[Index1
].BufferSize
+ HeaderSize
;
1062 if (ActualFileSize
[Index1
] > 0x00FFFFFF) {
1063 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
1064 ActualFileSize
[Index1
] = FileData
[Index1
].BufferSize
+ HeaderSize
;
1066 BufferSize
[Index1
] = ActualFileSize
[Index1
];
1068 if (BufferSize
[Index1
] == HeaderSize
) {
1070 // clear file attributes, zero-length file does not have any attributes
1072 FileData
[Index1
].FileAttributes
= 0;
1075 while ((BufferSize
[Index1
] & 0x07) != 0) {
1076 BufferSize
[Index1
]++;
1079 FfsBuffer
[Index1
] = AllocateZeroPool (BufferSize
[Index1
]);
1082 // Copy File Data into FileBuffer
1085 FfsBuffer
[Index1
] + HeaderSize
,
1086 FileData
[Index1
].Buffer
,
1087 FileData
[Index1
].BufferSize
1090 if (FvDevice
->ErasePolarity
== 1) {
1091 for (Index2
= 0; Index2
< HeaderSize
; Index2
++) {
1092 FfsBuffer
[Index1
][Index2
] = (UINT8
)~FfsBuffer
[Index1
][Index2
];
1096 if ((FileData
[Index1
].FileAttributes
& EFI_FV_FILE_ATTRIB_ALIGNMENT
) != 0) {
1097 RequiredAlignment
[Index1
] = GetRequiredAlignment (FileData
[Index1
].FileAttributes
);
1100 // If update file, mark the original file header to
1101 // EFI_FILE_MARKED_FOR_UPDATE
1103 IsCreateFile
= FileOperation
[Index1
];
1104 if (!IsCreateFile
) {
1109 Status
= Fv
->GetNextFile (
1117 if (EFI_ERROR (Status
)) {
1118 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1121 } while (!CompareGuid (&FileNameGuid
, FileData
[Index1
].NameGuid
));
1124 // Get FfsFileEntry from the search key
1126 OldFfsFileEntry
[Index1
] = (FFS_FILE_LIST_ENTRY
*) Key
;
1127 OldFileHeader
[Index1
] = (EFI_FFS_FILE_HEADER
*) OldFfsFileEntry
[Index1
]->FfsHeader
;
1128 Status
= UpdateHeaderBit (
1130 OldFileHeader
[Index1
],
1131 EFI_FILE_MARKED_FOR_UPDATE
1133 if (EFI_ERROR (Status
)) {
1134 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1140 // First to search a suitable pad file that can hold so
1143 Status
= FvSearchSuitablePadFile (
1153 if (Status
== EFI_NOT_FOUND
) {
1155 // Try to find a free space that can hold these files
1157 Status
= FvSearchSuitableFreeSpace (
1166 if (EFI_ERROR (Status
)) {
1167 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1168 return EFI_OUT_OF_RESOURCES
;
1170 Status
= FvCreateMultipleFilesInsideFreeSpace (
1183 // Create multiple files inside such a pad file
1184 // to achieve lock-step update
1186 Status
= FvCreateMultipleFilesInsidePadFile (
1198 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1200 if (EFI_ERROR (Status
)) {
1204 // Delete those updated files
1206 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1207 IsCreateFile
= FileOperation
[Index1
];
1208 if (!IsCreateFile
&& OldFfsFileEntry
[Index1
] != NULL
) {
1209 (OldFfsFileEntry
[Index1
]->Link
.BackLink
)->ForwardLink
= OldFfsFileEntry
[Index1
]->Link
.ForwardLink
;
1210 (OldFfsFileEntry
[Index1
]->Link
.ForwardLink
)->BackLink
= OldFfsFileEntry
[Index1
]->Link
.BackLink
;
1211 FreePool (OldFfsFileEntry
[Index1
]);
1215 // Set those files' state to EFI_FILE_DELETED
1217 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1218 IsCreateFile
= FileOperation
[Index1
];
1219 if (!IsCreateFile
&& OldFileHeader
[Index1
] != NULL
) {
1220 Status
= UpdateHeaderBit (FvDevice
, OldFileHeader
[Index1
], EFI_FILE_DELETED
);
1221 if (EFI_ERROR (Status
)) {