2 Implements functions to pad firmware file.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "FwVolDriver.h"
13 Calculate the checksum for a PAD file.
15 @param PadFileHeader The Pad File to be caculeted the checksum.
20 IN EFI_FFS_FILE_HEADER
*PadFileHeader
23 if ((PadFileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) != 0) {
25 if (IS_FFS_FILE2 (PadFileHeader
)) {
27 // Calculate checksum of Pad File Data
29 PadFileHeader
->IntegrityCheck
.Checksum
.File
=
30 CalculateCheckSum8 ((UINT8
*) PadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
), FFS_FILE2_SIZE (PadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
));
34 // Calculate checksum of Pad File Data
36 PadFileHeader
->IntegrityCheck
.Checksum
.File
=
37 CalculateCheckSum8 ((UINT8
*) PadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FFS_FILE_SIZE (PadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
));
42 PadFileHeader
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
50 Create a PAD File in the Free Space.
52 @param FvDevice Firmware Volume Device.
53 @param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted.
54 @param Size Pad file Size, not include the header.
55 @param PadFileEntry The Ffs File Entry that points to this Pad File.
57 @retval EFI_SUCCESS Successfully create a PAD file.
58 @retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file.
59 @retval EFI_INVALID_PARAMETER Size is not 8 byte alignment.
60 @retval EFI_DEVICE_ERROR Free space is not erased.
63 FvCreatePadFileInFreeSpace (
64 IN FV_DEVICE
*FvDevice
,
65 IN FREE_SPACE_ENTRY
*FreeSpaceEntry
,
67 OUT FFS_FILE_LIST_ENTRY
**PadFileEntry
71 EFI_FFS_FILE_HEADER
*PadFileHeader
;
73 UINTN NumBytesWritten
;
76 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
80 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
81 FileSize
= Size
+ HeaderSize
;
82 if (FileSize
> 0x00FFFFFF) {
83 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
84 FileSize
= Size
+ HeaderSize
;
87 if (FreeSpaceEntry
->Length
< FileSize
) {
88 return EFI_OUT_OF_RESOURCES
;
91 if ((Size
& 0x07) != 0) {
92 return EFI_INVALID_PARAMETER
;
95 StartPos
= FreeSpaceEntry
->StartingAddress
;
98 // First double check the space
100 if (!IsBufferErased (
101 FvDevice
->ErasePolarity
,
105 return EFI_DEVICE_ERROR
;
108 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) StartPos
;
111 // Create File Step 1
113 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
115 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
116 StateOffset
= Offset
+ (UINT8
*) &PadFileHeader
->State
- (UINT8
*) PadFileHeader
;
118 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
123 &PadFileHeader
->State
125 if (EFI_ERROR (Status
)) {
126 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
130 // Update Free Space Entry, since header is allocated
132 FreeSpaceEntry
->Length
-= HeaderSize
;
133 FreeSpaceEntry
->StartingAddress
+= HeaderSize
;
136 // Fill File Name Guid, here we assign a NULL-GUID to Pad files
138 ZeroMem (&PadFileHeader
->Name
, sizeof (EFI_GUID
));
141 // Fill File Type, checksum(0), Attributes(0), Size
143 PadFileHeader
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
144 PadFileHeader
->Attributes
= 0;
145 if ((FileSize
) > 0x00FFFFFF) {
146 ((EFI_FFS_FILE_HEADER2
*) PadFileHeader
)->ExtendedSize
= (UINT32
) FileSize
;
147 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
148 PadFileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
150 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
151 *(UINT32
*) PadFileHeader
->Size
|= FileSize
;
154 SetHeaderChecksum (PadFileHeader
);
155 SetPadFileChecksum (PadFileHeader
);
157 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
159 NumBytesWritten
= HeaderSize
;
164 (UINT8
*) PadFileHeader
166 if (EFI_ERROR (Status
)) {
171 // Step 2, then Mark header valid, since no data write,
172 // mark the data valid at the same time.
174 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
175 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
177 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
178 StateOffset
= Offset
+ (UINT8
*) &PadFileHeader
->State
- (UINT8
*) PadFileHeader
;
180 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
185 &PadFileHeader
->State
187 if (EFI_ERROR (Status
)) {
188 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
189 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
193 // Update Free Space Entry, since header is allocated
195 FreeSpaceEntry
->Length
-= Size
;
196 FreeSpaceEntry
->StartingAddress
+= Size
;
199 // If successfully, insert an FfsFileEntry at the end of ffs file list
201 FfsFileEntry
= AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY
));
202 ASSERT (FfsFileEntry
!= NULL
);
204 FfsFileEntry
->FfsHeader
= (UINT8
*) (UINTN
) StartPos
;
205 InsertTailList (&FvDevice
->FfsFileListHeader
, &FfsFileEntry
->Link
);
207 *PadFileEntry
= FfsFileEntry
;
208 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
214 Fill pad file header within firmware cache.
216 @param PadFileHeader The start of the Pad File Buffer.
217 @param PadFileLength The length of the pad file including the header.
222 IN EFI_FFS_FILE_HEADER
*PadFileHeader
,
223 IN UINTN PadFileLength
227 // Fill File Name Guid, here we assign a NULL-GUID to Pad files
229 ZeroMem (&PadFileHeader
->Name
, sizeof (EFI_GUID
));
232 // Fill File Type, checksum(0), Attributes(0), Size
234 PadFileHeader
->Type
= EFI_FV_FILETYPE_FFS_PAD
;
235 PadFileHeader
->Attributes
= 0;
236 if (PadFileLength
> 0x00FFFFFF) {
237 ((EFI_FFS_FILE_HEADER2
*) PadFileHeader
)->ExtendedSize
= (UINT32
) PadFileLength
;
238 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
239 PadFileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
241 *(UINT32
*) PadFileHeader
->Size
&= 0xFF000000;
242 *(UINT32
*) PadFileHeader
->Size
|= PadFileLength
;
245 SetHeaderChecksum (PadFileHeader
);
246 SetPadFileChecksum (PadFileHeader
);
249 // Set File State to 0x00000111
251 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, PadFileHeader
);
252 SetFileState (EFI_FILE_HEADER_VALID
, PadFileHeader
);
253 SetFileState (EFI_FILE_DATA_VALID
, PadFileHeader
);
259 Create entire FFS file.
261 @param FileHeader Starting Address of a Buffer that hold the FFS File image.
262 @param FfsFileBuffer The source buffer that contains the File Data.
263 @param BufferSize The length of FfsFileBuffer.
264 @param ActualFileSize Size of FFS file.
265 @param FileName The Guid of Ffs File.
266 @param FileType The type of the written Ffs File.
267 @param FileAttributes The attributes of the written Ffs File.
269 @retval EFI_INVALID_PARAMETER File type is not valid.
270 @retval EFI_SUCCESS FFS file is successfully created.
275 OUT EFI_FFS_FILE_HEADER
*FileHeader
,
276 IN UINT8
*FfsFileBuffer
,
278 IN UINTN ActualFileSize
,
279 IN EFI_GUID
*FileName
,
280 IN EFI_FV_FILETYPE FileType
,
281 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
284 EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute
;
285 EFI_FFS_FILE_HEADER
*TmpFileHeader
;
288 // File Type value 0x0E~0xE0 are reserved
290 if ((FileType
> EFI_FV_FILETYPE_SMM_CORE
) && (FileType
< 0xE0)) {
291 return EFI_INVALID_PARAMETER
;
294 TmpFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileBuffer
;
296 // First fill all fields ready in FfsFileBuffer
298 CopyGuid (&TmpFileHeader
->Name
, FileName
);
299 TmpFileHeader
->Type
= FileType
;
302 // Convert the FileAttributes to FFSFileAttributes
304 FvFileAttrib2FfsFileAttrib (FileAttributes
, &TmpFileAttribute
);
306 TmpFileHeader
->Attributes
= TmpFileAttribute
;
308 if (ActualFileSize
> 0x00FFFFFF) {
309 ((EFI_FFS_FILE_HEADER2
*) FileHeader
)->ExtendedSize
= (UINT32
) ActualFileSize
;
310 *(UINT32
*) FileHeader
->Size
&= 0xFF000000;
311 FileHeader
->Attributes
|= FFS_ATTRIB_LARGE_FILE
;
313 *(UINT32
*) FileHeader
->Size
&= 0xFF000000;
314 *(UINT32
*) FileHeader
->Size
|= ActualFileSize
;
317 SetHeaderChecksum (TmpFileHeader
);
318 SetFileChecksum (TmpFileHeader
, ActualFileSize
);
320 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, TmpFileHeader
);
321 SetFileState (EFI_FILE_HEADER_VALID
, TmpFileHeader
);
322 SetFileState (EFI_FILE_DATA_VALID
, TmpFileHeader
);
325 // Copy data from FfsFileBuffer to FileHeader(cache)
327 CopyMem (FileHeader
, FfsFileBuffer
, BufferSize
);
333 Fill some other extra space using 0xFF(Erase Value).
335 @param ErasePolarity Fv erase value.
336 @param FileHeader Point to the start of FFS File.
337 @param ExtraLength The pading length.
342 IN UINT8 ErasePolarity
,
343 IN EFI_FFS_FILE_HEADER
*FileHeader
,
350 if (IS_FFS_FILE2 (FileHeader
)) {
351 Ptr
= (UINT8
*) FileHeader
+ FFS_FILE2_SIZE (FileHeader
);
353 Ptr
= (UINT8
*) FileHeader
+ FFS_FILE_SIZE (FileHeader
);
356 if (ErasePolarity
== 0) {
362 // Fill the non-used space with Padding Byte
364 SetMem (Ptr
, ExtraLength
, PadingByte
);
370 Free File List entry pointed by FileListHead.
372 @param FileListHeader FileListEntry Header.
377 IN LIST_ENTRY
*FileListHead
380 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
381 LIST_ENTRY
*NextEntry
;
383 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) (FileListHead
->ForwardLink
);
386 // Loop the whole list entry to free resources
388 while (&FfsFileEntry
->Link
!= FileListHead
) {
389 NextEntry
= (&FfsFileEntry
->Link
)->ForwardLink
;
390 FreePool (FfsFileEntry
);
391 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) NextEntry
;
398 Create a new file within a PAD file area.
400 @param FvDevice Firmware Volume Device.
401 @param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state).
402 @param BufferSize The size of FfsFileBuffer.
403 @param ActualFileSize The actual file length, it may not be multiples of 8.
404 @param FileName The FFS File Name.
405 @param FileType The FFS File Type.
406 @param FileAttributes The Attributes of the FFS File to be created.
408 @retval EFI_SUCCESS Successfully create a new file within the found PAD file area.
409 @retval EFI_OUT_OF_RESOURCES No suitable PAD file is found.
410 @retval other errors New file is created failed.
414 FvCreateNewFileInsidePadFile (
415 IN FV_DEVICE
*FvDevice
,
416 IN UINT8
*FfsFileBuffer
,
418 IN UINTN ActualFileSize
,
419 IN EFI_GUID
*FileName
,
420 IN EFI_FV_FILETYPE FileType
,
421 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
424 UINTN RequiredAlignment
;
425 FFS_FILE_LIST_ENTRY
*PadFileEntry
;
429 EFI_FFS_FILE_HEADER
*FileHeader
;
430 EFI_FFS_FILE_HEADER
*OldPadFileHeader
;
431 EFI_FFS_FILE_HEADER
*PadFileHeader
;
432 EFI_FFS_FILE_HEADER
*TailPadFileHeader
;
435 UINTN NumBytesWritten
;
437 LIST_ENTRY NewFileList
;
438 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
439 FFS_FILE_LIST_ENTRY
*FfsEntry
;
440 FFS_FILE_LIST_ENTRY
*NextFfsEntry
;
443 // First get the required alignment from the File Attributes
445 RequiredAlignment
= GetRequiredAlignment (FileAttributes
);
448 // Find a suitable PAD File
450 Status
= FvLocatePadFile (
458 if (EFI_ERROR (Status
)) {
459 return EFI_OUT_OF_RESOURCES
;
462 OldPadFileHeader
= (EFI_FFS_FILE_HEADER
*) PadFileEntry
->FfsHeader
;
465 // Step 1: Update Pad File Header
467 SetFileState (EFI_FILE_MARKED_FOR_UPDATE
, OldPadFileHeader
);
469 StartPos
= PadFileEntry
->FfsHeader
;
471 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
472 StateOffset
= Offset
+ (UINT8
*) &OldPadFileHeader
->State
- (UINT8
*) OldPadFileHeader
;
474 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
479 &OldPadFileHeader
->State
481 if (EFI_ERROR (Status
)) {
482 SetFileState (EFI_FILE_HEADER_CONSTRUCTION
, OldPadFileHeader
);
487 // Step 2: Update Pad area
489 InitializeListHead (&NewFileList
);
491 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
492 PadAreaLength
= FFS_FILE2_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
493 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
495 PadAreaLength
= FFS_FILE_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
496 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
501 // Insert a PAD file before to achieve required alignment
503 FvFillPadFile (PadFileHeader
, PadSize
);
504 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
505 ASSERT (NewFileListEntry
!= NULL
);
506 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
507 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
510 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
);
512 Status
= FvFillFfsFile (
521 if (EFI_ERROR (Status
)) {
522 FreeFileList (&NewFileList
);
526 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
527 ASSERT (NewFileListEntry
!= NULL
);
529 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
530 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
532 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
534 if (PadAreaLength
> (BufferSize
+ PadSize
)) {
535 if ((PadAreaLength
- BufferSize
- PadSize
) >= sizeof (EFI_FFS_FILE_HEADER
)) {
537 // we can insert another PAD file
539 TailPadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
);
540 FvFillPadFile (TailPadFileHeader
, PadAreaLength
- BufferSize
- PadSize
);
542 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
543 ASSERT (NewFileListEntry
!= NULL
);
545 NewFileListEntry
->FfsHeader
= (UINT8
*) TailPadFileHeader
;
546 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
549 // because left size cannot hold another PAD file header,
550 // adjust the writing file size (just in cache)
553 FvDevice
->ErasePolarity
,
555 PadAreaLength
- BufferSize
- PadSize
560 // Start writing to FV
562 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
563 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
565 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
568 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
570 NumBytesWritten
= PadAreaLength
;
577 if (EFI_ERROR (Status
)) {
578 FreeFileList (&NewFileList
);
579 FvDevice
->CurrentFfsFile
= NULL
;
584 // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
586 SetFileState (EFI_FILE_HEADER_INVALID
, OldPadFileHeader
);
588 StartPos
= PadFileEntry
->FfsHeader
;
590 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
591 StateOffset
= Offset
+ (UINT8
*) &OldPadFileHeader
->State
- (UINT8
*) OldPadFileHeader
;
593 NumBytesWritten
= sizeof (EFI_FFS_FILE_STATE
);
598 &OldPadFileHeader
->State
600 if (EFI_ERROR (Status
)) {
601 SetFileState (EFI_FILE_HEADER_INVALID
, OldPadFileHeader
);
602 FreeFileList (&NewFileList
);
603 FvDevice
->CurrentFfsFile
= NULL
;
608 // If all successfully, update FFS_FILE_LIST
612 // Delete old pad file entry
614 FfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.BackLink
;
615 NextFfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.ForwardLink
;
617 FreePool (PadFileEntry
);
619 FfsEntry
->Link
.ForwardLink
= NewFileList
.ForwardLink
;
620 (NewFileList
.ForwardLink
)->BackLink
= &FfsEntry
->Link
;
621 NextFfsEntry
->Link
.BackLink
= NewFileList
.BackLink
;
622 (NewFileList
.BackLink
)->ForwardLink
= &NextFfsEntry
->Link
;
630 @param NumOfFiles Number of FfsBuffer.
631 @param FfsBuffer An array of pointer to an FFS File Buffer
641 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
642 if (FfsBuffer
[Index
] != NULL
) {
643 FreePool (FfsBuffer
[Index
]);
649 Create multiple files within a PAD File area.
651 @param FvDevice Firmware Volume Device.
652 @param PadFileEntry The pad file entry to be written in.
653 @param NumOfFiles Total File number to be written.
654 @param BufferSize The array of buffer size of each FfsBuffer.
655 @param ActualFileSize The array of actual file size.
656 @param PadSize The array of leading pad file size for each FFS File
657 @param FfsBuffer The array of Ffs Buffer pointer.
658 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
659 used to get name, attributes, type, etc.
661 @retval EFI_SUCCESS Add the input multiple files into PAD file area.
662 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
663 @retval other error Files can't be added into PAD file area.
667 FvCreateMultipleFilesInsidePadFile (
668 IN FV_DEVICE
*FvDevice
,
669 IN FFS_FILE_LIST_ENTRY
*PadFileEntry
,
671 IN UINTN
*BufferSize
,
672 IN UINTN
*ActualFileSize
,
674 IN UINT8
**FfsBuffer
,
675 IN EFI_FV_WRITE_FILE_DATA
*FileData
679 EFI_FFS_FILE_HEADER
*OldPadFileHeader
;
681 EFI_FFS_FILE_HEADER
*PadFileHeader
;
682 EFI_FFS_FILE_HEADER
*FileHeader
;
683 EFI_FFS_FILE_HEADER
*TailPadFileHeader
;
686 LIST_ENTRY NewFileList
;
687 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
689 UINTN NumBytesWritten
;
691 FFS_FILE_LIST_ENTRY
*FfsEntry
;
692 FFS_FILE_LIST_ENTRY
*NextFfsEntry
;
694 InitializeListHead (&NewFileList
);
696 NewFileListEntry
= NULL
;
698 OldPadFileHeader
= (EFI_FFS_FILE_HEADER
*) PadFileEntry
->FfsHeader
;
699 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
700 PadAreaLength
= FFS_FILE2_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
702 PadAreaLength
= FFS_FILE_SIZE (OldPadFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
705 Status
= UpdateHeaderBit (
708 EFI_FILE_MARKED_FOR_UPDATE
710 if (EFI_ERROR (Status
)) {
717 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
718 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
720 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
722 FileHeader
= PadFileHeader
;
724 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
725 if (PadSize
[Index
] != 0) {
726 FvFillPadFile (PadFileHeader
, PadSize
[Index
]);
727 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
728 if (NewFileListEntry
== NULL
) {
729 FreeFileList (&NewFileList
);
730 return EFI_OUT_OF_RESOURCES
;
733 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
734 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
737 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
[Index
]);
738 Status
= FvFillFfsFile (
742 ActualFileSize
[Index
],
743 FileData
[Index
].NameGuid
,
744 FileData
[Index
].Type
,
745 FileData
[Index
].FileAttributes
747 if (EFI_ERROR (Status
)) {
748 FreeFileList (&NewFileList
);
752 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
753 if (NewFileListEntry
== NULL
) {
754 FreeFileList (&NewFileList
);
755 return EFI_OUT_OF_RESOURCES
;
758 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
759 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
761 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[Index
]);
762 TotalSize
+= PadSize
[Index
];
763 TotalSize
+= BufferSize
[Index
];
766 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
768 // Maybe we need a tail pad file
770 if (PadAreaLength
> TotalSize
) {
771 if ((PadAreaLength
- TotalSize
) >= sizeof (EFI_FFS_FILE_HEADER
)) {
773 // we can insert another PAD file
775 TailPadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[NumOfFiles
- 1]);
776 FvFillPadFile (TailPadFileHeader
, PadAreaLength
- TotalSize
);
778 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
779 if (NewFileListEntry
== NULL
) {
780 FreeFileList (&NewFileList
);
781 FvDevice
->CurrentFfsFile
= NULL
;
782 return EFI_OUT_OF_RESOURCES
;
785 NewFileListEntry
->FfsHeader
= (UINT8
*) TailPadFileHeader
;
786 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
789 // because left size cannot hold another PAD file header,
790 // adjust the writing file size (just in cache)
793 FvDevice
->ErasePolarity
,
795 PadAreaLength
- TotalSize
800 // Start writing to FV
802 if (IS_FFS_FILE2 (OldPadFileHeader
)) {
803 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
805 StartPos
= (UINT8
*) OldPadFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
808 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
810 NumBytesWritten
= PadAreaLength
;
817 if (EFI_ERROR (Status
)) {
818 FreeFileList (&NewFileList
);
819 FvDevice
->CurrentFfsFile
= NULL
;
823 Status
= UpdateHeaderBit (
826 EFI_FILE_HEADER_INVALID
828 if (EFI_ERROR (Status
)) {
829 FreeFileList (&NewFileList
);
830 FvDevice
->CurrentFfsFile
= NULL
;
835 // Update File List Link
839 // First delete old pad file entry
841 FfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.BackLink
;
842 NextFfsEntry
= (FFS_FILE_LIST_ENTRY
*) PadFileEntry
->Link
.ForwardLink
;
844 FreePool (PadFileEntry
);
846 FfsEntry
->Link
.ForwardLink
= NewFileList
.ForwardLink
;
847 (NewFileList
.ForwardLink
)->BackLink
= &FfsEntry
->Link
;
848 NextFfsEntry
->Link
.BackLink
= NewFileList
.BackLink
;
849 (NewFileList
.BackLink
)->ForwardLink
= &NextFfsEntry
->Link
;
855 Create multiple files within the Free Space.
857 @param FvDevice Firmware Volume Device.
858 @param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted.
859 @param NumOfFiles Total File number to be written.
860 @param BufferSize The array of buffer size of each FfsBuffer.
861 @param ActualFileSize The array of actual file size.
862 @param PadSize The array of leading pad file size for each FFS File
863 @param FfsBuffer The array of Ffs Buffer pointer.
864 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
865 used to get name, attributes, type, etc.
867 @retval EFI_SUCCESS Add the input multiple files into PAD file area.
868 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
869 @retval other error Files can't be added into PAD file area.
873 FvCreateMultipleFilesInsideFreeSpace (
874 IN FV_DEVICE
*FvDevice
,
875 IN FREE_SPACE_ENTRY
*FreeSpaceEntry
,
877 IN UINTN
*BufferSize
,
878 IN UINTN
*ActualFileSize
,
880 IN UINT8
**FfsBuffer
,
881 IN EFI_FV_WRITE_FILE_DATA
*FileData
886 EFI_FFS_FILE_HEADER
*PadFileHeader
;
887 EFI_FFS_FILE_HEADER
*FileHeader
;
889 LIST_ENTRY NewFileList
;
890 FFS_FILE_LIST_ENTRY
*NewFileListEntry
;
892 UINTN NumBytesWritten
;
895 InitializeListHead (&NewFileList
);
897 NewFileListEntry
= NULL
;
900 StartPos
= FreeSpaceEntry
->StartingAddress
;
901 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) StartPos
;
902 FileHeader
= PadFileHeader
;
904 for (Index
= 0; Index
< NumOfFiles
; Index
++) {
905 if (PadSize
[Index
] != 0) {
906 FvFillPadFile (PadFileHeader
, PadSize
[Index
]);
907 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
908 if (NewFileListEntry
== NULL
) {
909 FreeFileList (&NewFileList
);
910 return EFI_OUT_OF_RESOURCES
;
913 NewFileListEntry
->FfsHeader
= (UINT8
*) PadFileHeader
;
914 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
917 FileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) PadFileHeader
+ PadSize
[Index
]);
918 Status
= FvFillFfsFile (
922 ActualFileSize
[Index
],
923 FileData
[Index
].NameGuid
,
924 FileData
[Index
].Type
,
925 FileData
[Index
].FileAttributes
927 if (EFI_ERROR (Status
)) {
928 FreeFileList (&NewFileList
);
932 NewFileListEntry
= AllocatePool (sizeof (FFS_FILE_LIST_ENTRY
));
933 if (NewFileListEntry
== NULL
) {
934 FreeFileList (&NewFileList
);
935 return EFI_OUT_OF_RESOURCES
;
938 NewFileListEntry
->FfsHeader
= (UINT8
*) FileHeader
;
939 InsertTailList (&NewFileList
, &NewFileListEntry
->Link
);
941 PadFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FileHeader
+ BufferSize
[Index
]);
942 TotalSize
+= PadSize
[Index
];
943 TotalSize
+= BufferSize
[Index
];
946 if (FreeSpaceEntry
->Length
< TotalSize
) {
947 FreeFileList (&NewFileList
);
948 return EFI_OUT_OF_RESOURCES
;
951 FvDevice
->CurrentFfsFile
= NewFileListEntry
;
954 // Start writing to FV
956 Offset
= (UINTN
) (StartPos
- FvDevice
->CachedFv
);
958 NumBytesWritten
= TotalSize
;
965 if (EFI_ERROR (Status
)) {
966 FreeFileList (&NewFileList
);
967 FvDevice
->CurrentFfsFile
= NULL
;
971 FreeSpaceEntry
->Length
-= TotalSize
;
972 FreeSpaceEntry
->StartingAddress
+= TotalSize
;
974 NewFileListEntry
= (FFS_FILE_LIST_ENTRY
*) (NewFileList
.ForwardLink
);
976 while (NewFileListEntry
!= (FFS_FILE_LIST_ENTRY
*) &NewFileList
) {
977 InsertTailList (&FvDevice
->FfsFileListHeader
, &NewFileListEntry
->Link
);
978 NewFileListEntry
= (FFS_FILE_LIST_ENTRY
*) (NewFileListEntry
->Link
.ForwardLink
);
985 Write multiple files into FV in reliable method.
987 @param FvDevice Firmware Volume Device.
988 @param NumOfFiles Total File number to be written.
989 @param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
990 used to get name, attributes, type, etc
991 @param FileOperation The array of operation for each file.
993 @retval EFI_SUCCESS Files are added into FV.
994 @retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files.
995 @retval EFI_INVALID_PARAMETER File number is less than or equal to 1.
996 @retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files.
1000 FvCreateMultipleFiles (
1001 IN FV_DEVICE
*FvDevice
,
1002 IN UINTN NumOfFiles
,
1003 IN EFI_FV_WRITE_FILE_DATA
*FileData
,
1004 IN BOOLEAN
*FileOperation
1008 UINT8
*FfsBuffer
[MAX_FILES
];
1011 UINTN BufferSize
[MAX_FILES
];
1012 UINTN ActualFileSize
[MAX_FILES
];
1013 UINTN RequiredAlignment
[MAX_FILES
];
1014 UINTN PadSize
[MAX_FILES
];
1015 FFS_FILE_LIST_ENTRY
*PadFileEntry
;
1016 UINTN TotalSizeNeeded
;
1017 FREE_SPACE_ENTRY
*FreeSpaceEntry
;
1018 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
1020 EFI_GUID FileNameGuid
;
1021 EFI_FV_FILETYPE OldFileType
;
1022 EFI_FV_FILE_ATTRIBUTES OldFileAttributes
;
1024 FFS_FILE_LIST_ENTRY
*OldFfsFileEntry
[MAX_FILES
];
1025 EFI_FFS_FILE_HEADER
*OldFileHeader
[MAX_FILES
];
1026 BOOLEAN IsCreateFile
;
1030 // To use this function, we must ensure that the NumOfFiles is great
1033 if (NumOfFiles
<= 1) {
1034 return EFI_INVALID_PARAMETER
;
1037 if (NumOfFiles
> MAX_FILES
) {
1038 return EFI_UNSUPPORTED
;
1043 SetMem (FfsBuffer
, NumOfFiles
, 0);
1044 SetMem (RequiredAlignment
, NumOfFiles
, 8);
1045 SetMem (PadSize
, NumOfFiles
, 0);
1046 ZeroMem (OldFfsFileEntry
, sizeof (OldFfsFileEntry
));
1047 ZeroMem (OldFileHeader
, sizeof (OldFileHeader
));
1052 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1053 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
1054 ActualFileSize
[Index1
] = FileData
[Index1
].BufferSize
+ HeaderSize
;
1055 if (ActualFileSize
[Index1
] > 0x00FFFFFF) {
1056 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
1057 ActualFileSize
[Index1
] = FileData
[Index1
].BufferSize
+ HeaderSize
;
1059 BufferSize
[Index1
] = ActualFileSize
[Index1
];
1061 if (BufferSize
[Index1
] == HeaderSize
) {
1063 // clear file attributes, zero-length file does not have any attributes
1065 FileData
[Index1
].FileAttributes
= 0;
1068 while ((BufferSize
[Index1
] & 0x07) != 0) {
1069 BufferSize
[Index1
]++;
1072 FfsBuffer
[Index1
] = AllocateZeroPool (BufferSize
[Index1
]);
1075 // Copy File Data into FileBuffer
1078 FfsBuffer
[Index1
] + HeaderSize
,
1079 FileData
[Index1
].Buffer
,
1080 FileData
[Index1
].BufferSize
1083 if (FvDevice
->ErasePolarity
== 1) {
1084 for (Index2
= 0; Index2
< HeaderSize
; Index2
++) {
1085 FfsBuffer
[Index1
][Index2
] = (UINT8
)~FfsBuffer
[Index1
][Index2
];
1089 if ((FileData
[Index1
].FileAttributes
& EFI_FV_FILE_ATTRIB_ALIGNMENT
) != 0) {
1090 RequiredAlignment
[Index1
] = GetRequiredAlignment (FileData
[Index1
].FileAttributes
);
1093 // If update file, mark the original file header to
1094 // EFI_FILE_MARKED_FOR_UPDATE
1096 IsCreateFile
= FileOperation
[Index1
];
1097 if (!IsCreateFile
) {
1102 Status
= Fv
->GetNextFile (
1110 if (EFI_ERROR (Status
)) {
1111 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1114 } while (!CompareGuid (&FileNameGuid
, FileData
[Index1
].NameGuid
));
1117 // Get FfsFileEntry from the search key
1119 OldFfsFileEntry
[Index1
] = (FFS_FILE_LIST_ENTRY
*) Key
;
1120 OldFileHeader
[Index1
] = (EFI_FFS_FILE_HEADER
*) OldFfsFileEntry
[Index1
]->FfsHeader
;
1121 Status
= UpdateHeaderBit (
1123 OldFileHeader
[Index1
],
1124 EFI_FILE_MARKED_FOR_UPDATE
1126 if (EFI_ERROR (Status
)) {
1127 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1133 // First to search a suitable pad file that can hold so
1136 Status
= FvSearchSuitablePadFile (
1146 if (Status
== EFI_NOT_FOUND
) {
1148 // Try to find a free space that can hold these files
1150 Status
= FvSearchSuitableFreeSpace (
1159 if (EFI_ERROR (Status
)) {
1160 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1161 return EFI_OUT_OF_RESOURCES
;
1163 Status
= FvCreateMultipleFilesInsideFreeSpace (
1176 // Create multiple files inside such a pad file
1177 // to achieve lock-step update
1179 Status
= FvCreateMultipleFilesInsidePadFile (
1191 FreeFfsBuffer (NumOfFiles
, FfsBuffer
);
1193 if (EFI_ERROR (Status
)) {
1197 // Delete those updated files
1199 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1200 IsCreateFile
= FileOperation
[Index1
];
1201 if (!IsCreateFile
&& OldFfsFileEntry
[Index1
] != NULL
) {
1202 (OldFfsFileEntry
[Index1
]->Link
.BackLink
)->ForwardLink
= OldFfsFileEntry
[Index1
]->Link
.ForwardLink
;
1203 (OldFfsFileEntry
[Index1
]->Link
.ForwardLink
)->BackLink
= OldFfsFileEntry
[Index1
]->Link
.BackLink
;
1204 FreePool (OldFfsFileEntry
[Index1
]);
1208 // Set those files' state to EFI_FILE_DELETED
1210 for (Index1
= 0; Index1
< NumOfFiles
; Index1
++) {
1211 IsCreateFile
= FileOperation
[Index1
];
1212 if (!IsCreateFile
&& OldFileHeader
[Index1
] != NULL
) {
1213 Status
= UpdateHeaderBit (FvDevice
, OldFileHeader
[Index1
], EFI_FILE_DELETED
);
1214 if (EFI_ERROR (Status
)) {