2011-09-01 21:57:08 +02:00
|
|
|
/** @file
|
|
|
|
Implements functions to pad firmware file.
|
|
|
|
|
|
|
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
|
|
|
|
|
|
|
This program and the accompanying materials
|
|
|
|
are licensed and made available under the terms and conditions
|
|
|
|
of the BSD License which accompanies this distribution. The
|
|
|
|
full text of the license may be found at
|
|
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "FwVolDriver.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
Calculate the checksum for a PAD file.
|
|
|
|
|
|
|
|
@param PadFileHeader The Pad File to be caculeted the checksum.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
SetPadFileChecksum (
|
|
|
|
IN EFI_FFS_FILE_HEADER *PadFileHeader
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (PadFileHeader)) {
|
|
|
|
//
|
|
|
|
// Calculate checksum of Pad File Data
|
|
|
|
//
|
|
|
|
PadFileHeader->IntegrityCheck.Checksum.File =
|
|
|
|
CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2));
|
2011-09-01 21:57:08 +02:00
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// Calculate checksum of Pad File Data
|
|
|
|
//
|
|
|
|
PadFileHeader->IntegrityCheck.Checksum.File =
|
|
|
|
CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER));
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Create a PAD File in the Free Space.
|
|
|
|
|
|
|
|
@param FvDevice Firmware Volume Device.
|
|
|
|
@param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted.
|
|
|
|
@param Size Pad file Size, not include the header.
|
|
|
|
@param PadFileEntry The Ffs File Entry that points to this Pad File.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Successfully create a PAD file.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file.
|
|
|
|
@retval EFI_INVALID_PARAMETER Size is not 8 byte alignment.
|
|
|
|
@retval EFI_DEVICE_ERROR Free space is not erased.
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvCreatePadFileInFreeSpace (
|
|
|
|
IN FV_DEVICE *FvDevice,
|
|
|
|
IN FREE_SPACE_ENTRY *FreeSpaceEntry,
|
|
|
|
IN UINTN Size,
|
|
|
|
OUT FFS_FILE_LIST_ENTRY **PadFileEntry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_FFS_FILE_HEADER *PadFileHeader;
|
|
|
|
UINTN Offset;
|
|
|
|
UINTN NumBytesWritten;
|
|
|
|
UINTN StateOffset;
|
|
|
|
UINT8 *StartPos;
|
|
|
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
2011-10-27 12:46:50 +02:00
|
|
|
UINTN HeaderSize;
|
|
|
|
UINTN FileSize;
|
|
|
|
|
|
|
|
HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
FileSize = Size + HeaderSize;
|
|
|
|
if (FileSize > 0x00FFFFFF) {
|
|
|
|
HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
|
|
|
|
FileSize = Size + HeaderSize;
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (FreeSpaceEntry->Length < FileSize) {
|
2011-09-01 21:57:08 +02:00
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Size & 0x07) != 0) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
StartPos = FreeSpaceEntry->StartingAddress;
|
|
|
|
|
|
|
|
//
|
|
|
|
// First double check the space
|
|
|
|
//
|
|
|
|
if (!IsBufferErased (
|
|
|
|
FvDevice->ErasePolarity,
|
|
|
|
StartPos,
|
2011-10-27 12:46:50 +02:00
|
|
|
FileSize
|
2011-09-01 21:57:08 +02:00
|
|
|
)) {
|
|
|
|
return EFI_DEVICE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create File Step 1
|
|
|
|
//
|
|
|
|
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
|
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
|
|
|
|
|
|
|
|
NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
StateOffset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
&PadFileHeader->State
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Update Free Space Entry, since header is allocated
|
|
|
|
//
|
2011-10-27 12:46:50 +02:00
|
|
|
FreeSpaceEntry->Length -= HeaderSize;
|
|
|
|
FreeSpaceEntry->StartingAddress += HeaderSize;
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Fill File Name Guid, here we assign a NULL-GUID to Pad files
|
|
|
|
//
|
|
|
|
ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Fill File Type, checksum(0), Attributes(0), Size
|
|
|
|
//
|
|
|
|
PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
|
|
|
|
PadFileHeader->Attributes = 0;
|
2011-10-27 12:46:50 +02:00
|
|
|
if ((FileSize) > 0x00FFFFFF) {
|
|
|
|
((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize;
|
|
|
|
*(UINT32 *) PadFileHeader->Size &= 0xFF000000;
|
|
|
|
PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
|
|
|
|
} else {
|
|
|
|
*(UINT32 *) PadFileHeader->Size &= 0xFF000000;
|
|
|
|
*(UINT32 *) PadFileHeader->Size |= FileSize;
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
SetHeaderChecksum (PadFileHeader);
|
|
|
|
SetPadFileChecksum (PadFileHeader);
|
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
NumBytesWritten = HeaderSize;
|
2011-09-01 21:57:08 +02:00
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
Offset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
(UINT8 *) PadFileHeader
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Step 2, then Mark header valid, since no data write,
|
|
|
|
// mark the data valid at the same time.
|
|
|
|
//
|
|
|
|
SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
|
|
|
|
SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
|
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
StateOffset = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
|
|
|
|
|
|
|
|
NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
StateOffset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
&PadFileHeader->State
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
|
|
|
|
SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Update Free Space Entry, since header is allocated
|
|
|
|
//
|
|
|
|
FreeSpaceEntry->Length -= Size;
|
|
|
|
FreeSpaceEntry->StartingAddress += Size;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If successfully, insert an FfsFileEntry at the end of ffs file list
|
|
|
|
//
|
|
|
|
FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
ASSERT (FfsFileEntry != NULL);
|
|
|
|
|
|
|
|
FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos;
|
|
|
|
InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
|
|
|
|
|
|
|
|
*PadFileEntry = FfsFileEntry;
|
|
|
|
FvDevice->CurrentFfsFile = FfsFileEntry;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Fill pad file header within firmware cache.
|
|
|
|
|
|
|
|
@param PadFileHeader The start of the Pad File Buffer.
|
|
|
|
@param PadFileLength The length of the pad file including the header.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
FvFillPadFile (
|
|
|
|
IN EFI_FFS_FILE_HEADER *PadFileHeader,
|
|
|
|
IN UINTN PadFileLength
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fill File Name Guid, here we assign a NULL-GUID to Pad files
|
|
|
|
//
|
|
|
|
ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Fill File Type, checksum(0), Attributes(0), Size
|
|
|
|
//
|
|
|
|
PadFileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
|
|
|
|
PadFileHeader->Attributes = 0;
|
2011-10-27 12:46:50 +02:00
|
|
|
if (PadFileLength > 0x00FFFFFF) {
|
|
|
|
((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength;
|
|
|
|
*(UINT32 *) PadFileHeader->Size &= 0xFF000000;
|
|
|
|
PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
|
|
|
|
} else {
|
|
|
|
*(UINT32 *) PadFileHeader->Size &= 0xFF000000;
|
|
|
|
*(UINT32 *) PadFileHeader->Size |= PadFileLength;
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
SetHeaderChecksum (PadFileHeader);
|
|
|
|
SetPadFileChecksum (PadFileHeader);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set File State to 0x00000111
|
|
|
|
//
|
|
|
|
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
|
|
|
|
SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
|
|
|
|
SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Create entire FFS file.
|
|
|
|
|
|
|
|
@param FileHeader Starting Address of a Buffer that hold the FFS File image.
|
|
|
|
@param FfsFileBuffer The source buffer that contains the File Data.
|
|
|
|
@param BufferSize The length of FfsFileBuffer.
|
|
|
|
@param ActualFileSize Size of FFS file.
|
|
|
|
@param FileName The Guid of Ffs File.
|
|
|
|
@param FileType The type of the written Ffs File.
|
|
|
|
@param FileAttributes The attributes of the written Ffs File.
|
|
|
|
|
|
|
|
@retval EFI_INVALID_PARAMETER File type is not valid.
|
|
|
|
@retval EFI_SUCCESS FFS file is successfully created.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvFillFfsFile (
|
|
|
|
OUT EFI_FFS_FILE_HEADER *FileHeader,
|
|
|
|
IN UINT8 *FfsFileBuffer,
|
|
|
|
IN UINTN BufferSize,
|
|
|
|
IN UINTN ActualFileSize,
|
|
|
|
IN EFI_GUID *FileName,
|
|
|
|
IN EFI_FV_FILETYPE FileType,
|
|
|
|
IN EFI_FV_FILE_ATTRIBUTES FileAttributes
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;
|
|
|
|
EFI_FFS_FILE_HEADER *TmpFileHeader;
|
|
|
|
|
|
|
|
//
|
|
|
|
// File Type value 0x0E~0xE0 are reserved
|
|
|
|
//
|
|
|
|
if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;
|
|
|
|
//
|
|
|
|
// First fill all fields ready in FfsFileBuffer
|
|
|
|
//
|
|
|
|
CopyGuid (&TmpFileHeader->Name, FileName);
|
|
|
|
TmpFileHeader->Type = FileType;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Convert the FileAttributes to FFSFileAttributes
|
|
|
|
//
|
|
|
|
FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);
|
|
|
|
|
|
|
|
TmpFileHeader->Attributes = TmpFileAttribute;
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (ActualFileSize > 0x00FFFFFF) {
|
|
|
|
((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;
|
|
|
|
*(UINT32 *) FileHeader->Size &= 0xFF000000;
|
|
|
|
FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
|
|
|
|
} else {
|
|
|
|
*(UINT32 *) FileHeader->Size &= 0xFF000000;
|
|
|
|
*(UINT32 *) FileHeader->Size |= ActualFileSize;
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
SetHeaderChecksum (TmpFileHeader);
|
|
|
|
SetFileChecksum (TmpFileHeader, ActualFileSize);
|
|
|
|
|
|
|
|
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader);
|
|
|
|
SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader);
|
|
|
|
SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Copy data from FfsFileBuffer to FileHeader(cache)
|
|
|
|
//
|
|
|
|
CopyMem (FileHeader, FfsFileBuffer, BufferSize);
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Fill some other extra space using 0xFF(Erase Value).
|
|
|
|
|
|
|
|
@param ErasePolarity Fv erase value.
|
|
|
|
@param FileHeader Point to the start of FFS File.
|
|
|
|
@param ExtraLength The pading length.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
FvAdjustFfsFile (
|
|
|
|
IN UINT8 ErasePolarity,
|
|
|
|
IN EFI_FFS_FILE_HEADER *FileHeader,
|
|
|
|
IN UINTN ExtraLength
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINT8 *Ptr;
|
|
|
|
UINT8 PadingByte;
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (FileHeader)) {
|
|
|
|
Ptr = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader);
|
|
|
|
} else {
|
|
|
|
Ptr = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader);
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
if (ErasePolarity == 0) {
|
|
|
|
PadingByte = 0;
|
|
|
|
} else {
|
|
|
|
PadingByte = 0xFF;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Fill the non-used space with Padding Byte
|
|
|
|
//
|
|
|
|
SetMem (Ptr, ExtraLength, PadingByte);
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Free File List entry pointed by FileListHead.
|
|
|
|
|
|
|
|
@param FileListHeader FileListEntry Header.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
FreeFileList (
|
|
|
|
IN LIST_ENTRY *FileListHead
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
|
|
|
LIST_ENTRY *NextEntry;
|
|
|
|
|
|
|
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Loop the whole list entry to free resources
|
|
|
|
//
|
|
|
|
while (&FfsFileEntry->Link != FileListHead) {
|
|
|
|
NextEntry = (&FfsFileEntry->Link)->ForwardLink;
|
|
|
|
FreePool (FfsFileEntry);
|
|
|
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Create a new file within a PAD file area.
|
|
|
|
|
|
|
|
@param FvDevice Firmware Volume Device.
|
|
|
|
@param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state).
|
|
|
|
@param BufferSize The size of FfsFileBuffer.
|
|
|
|
@param ActualFileSize The actual file length, it may not be multiples of 8.
|
|
|
|
@param FileName The FFS File Name.
|
|
|
|
@param FileType The FFS File Type.
|
|
|
|
@param FileAttributes The Attributes of the FFS File to be created.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Successfully create a new file within the found PAD file area.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES No suitable PAD file is found.
|
|
|
|
@retval other errors New file is created failed.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvCreateNewFileInsidePadFile (
|
|
|
|
IN FV_DEVICE *FvDevice,
|
|
|
|
IN UINT8 *FfsFileBuffer,
|
|
|
|
IN UINTN BufferSize,
|
|
|
|
IN UINTN ActualFileSize,
|
|
|
|
IN EFI_GUID *FileName,
|
|
|
|
IN EFI_FV_FILETYPE FileType,
|
|
|
|
IN EFI_FV_FILE_ATTRIBUTES FileAttributes
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN RequiredAlignment;
|
|
|
|
FFS_FILE_LIST_ENTRY *PadFileEntry;
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN PadAreaLength;
|
|
|
|
UINTN PadSize;
|
|
|
|
EFI_FFS_FILE_HEADER *FileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *OldPadFileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *PadFileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *TailPadFileHeader;
|
|
|
|
UINTN StateOffset;
|
|
|
|
UINTN Offset;
|
|
|
|
UINTN NumBytesWritten;
|
|
|
|
UINT8 *StartPos;
|
|
|
|
LIST_ENTRY NewFileList;
|
|
|
|
FFS_FILE_LIST_ENTRY *NewFileListEntry;
|
|
|
|
FFS_FILE_LIST_ENTRY *FfsEntry;
|
|
|
|
FFS_FILE_LIST_ENTRY *NextFfsEntry;
|
|
|
|
|
|
|
|
//
|
|
|
|
// First get the required alignment from the File Attributes
|
|
|
|
//
|
|
|
|
RequiredAlignment = GetRequiredAlignment (FileAttributes);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Find a suitable PAD File
|
|
|
|
//
|
|
|
|
Status = FvLocatePadFile (
|
|
|
|
FvDevice,
|
|
|
|
BufferSize,
|
|
|
|
RequiredAlignment,
|
|
|
|
&PadSize,
|
|
|
|
&PadFileEntry
|
|
|
|
);
|
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Step 1: Update Pad File Header
|
|
|
|
//
|
|
|
|
SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader);
|
|
|
|
|
|
|
|
StartPos = PadFileEntry->FfsHeader;
|
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
|
|
|
|
|
|
|
|
NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
StateOffset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
&OldPadFileHeader->State
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Step 2: Update Pad area
|
|
|
|
//
|
|
|
|
InitializeListHead (&NewFileList);
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (OldPadFileHeader)) {
|
|
|
|
PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
|
|
|
|
} else {
|
|
|
|
PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (PadSize != 0) {
|
2011-09-01 21:57:08 +02:00
|
|
|
//
|
|
|
|
// Insert a PAD file before to achieve required alignment
|
|
|
|
//
|
|
|
|
FvFillPadFile (PadFileHeader, PadSize);
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
ASSERT (NewFileListEntry != NULL);
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
}
|
|
|
|
|
|
|
|
FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize);
|
|
|
|
|
|
|
|
Status = FvFillFfsFile (
|
|
|
|
FileHeader,
|
|
|
|
FfsFileBuffer,
|
|
|
|
BufferSize,
|
|
|
|
ActualFileSize,
|
|
|
|
FileName,
|
|
|
|
FileType,
|
|
|
|
FileAttributes
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2011-10-27 12:46:50 +02:00
|
|
|
FreeFileList (&NewFileList);
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
ASSERT (NewFileListEntry != NULL);
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
|
|
|
|
FvDevice->CurrentFfsFile = NewFileListEntry;
|
|
|
|
|
|
|
|
if (PadAreaLength > (BufferSize + PadSize)) {
|
|
|
|
if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
|
|
|
|
//
|
|
|
|
// we can insert another PAD file
|
|
|
|
//
|
|
|
|
TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize);
|
|
|
|
FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize);
|
|
|
|
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
ASSERT (NewFileListEntry != NULL);
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// because left size cannot hold another PAD file header,
|
|
|
|
// adjust the writing file size (just in cache)
|
|
|
|
//
|
|
|
|
FvAdjustFfsFile (
|
|
|
|
FvDevice->ErasePolarity,
|
|
|
|
FileHeader,
|
|
|
|
PadAreaLength - BufferSize - PadSize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Start writing to FV
|
|
|
|
//
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (OldPadFileHeader)) {
|
|
|
|
StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
|
|
|
|
} else {
|
|
|
|
StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
|
|
|
|
NumBytesWritten = PadAreaLength;
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
Offset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
StartPos
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFileList (&NewFileList);
|
2011-10-27 12:46:50 +02:00
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
|
|
|
|
//
|
|
|
|
SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
|
|
|
|
|
|
|
|
StartPos = PadFileEntry->FfsHeader;
|
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
StateOffset = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
|
|
|
|
|
|
|
|
NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
StateOffset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
&OldPadFileHeader->State
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
|
2011-10-27 12:46:50 +02:00
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If all successfully, update FFS_FILE_LIST
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Delete old pad file entry
|
|
|
|
//
|
|
|
|
FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
|
|
|
|
NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
|
|
|
|
|
|
|
|
FreePool (PadFileEntry);
|
|
|
|
|
|
|
|
FfsEntry->Link.ForwardLink = NewFileList.ForwardLink;
|
|
|
|
(NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
|
|
|
|
NextFfsEntry->Link.BackLink = NewFileList.BackLink;
|
|
|
|
(NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Free all FfsBuffer.
|
|
|
|
|
|
|
|
@param NumOfFiles Number of FfsBuffer.
|
|
|
|
@param FfsBuffer An array of pointer to an FFS File Buffer
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
FreeFfsBuffer (
|
|
|
|
IN UINTN NumOfFiles,
|
|
|
|
IN UINT8 **FfsBuffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINTN Index;
|
|
|
|
for (Index = 0; Index < NumOfFiles; Index++) {
|
|
|
|
if (FfsBuffer[Index] != NULL) {
|
|
|
|
FreePool (FfsBuffer[Index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Create multiple files within a PAD File area.
|
|
|
|
|
|
|
|
@param FvDevice Firmware Volume Device.
|
|
|
|
@param PadFileEntry The pad file entry to be written in.
|
|
|
|
@param NumOfFiles Total File number to be written.
|
|
|
|
@param BufferSize The array of buffer size of each FfsBuffer.
|
|
|
|
@param ActualFileSize The array of actual file size.
|
|
|
|
@param PadSize The array of leading pad file size for each FFS File
|
|
|
|
@param FfsBuffer The array of Ffs Buffer pointer.
|
|
|
|
@param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
|
|
|
|
used to get name, attributes, type, etc.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Add the input multiple files into PAD file area.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
|
|
|
|
@retval other error Files can't be added into PAD file area.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvCreateMultipleFilesInsidePadFile (
|
|
|
|
IN FV_DEVICE *FvDevice,
|
|
|
|
IN FFS_FILE_LIST_ENTRY *PadFileEntry,
|
|
|
|
IN UINTN NumOfFiles,
|
|
|
|
IN UINTN *BufferSize,
|
|
|
|
IN UINTN *ActualFileSize,
|
|
|
|
IN UINTN *PadSize,
|
|
|
|
IN UINT8 **FfsBuffer,
|
|
|
|
IN EFI_FV_WRITE_FILE_DATA *FileData
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_FFS_FILE_HEADER *OldPadFileHeader;
|
|
|
|
UINTN Index;
|
|
|
|
EFI_FFS_FILE_HEADER *PadFileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *FileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *TailPadFileHeader;
|
|
|
|
UINTN TotalSize;
|
|
|
|
UINTN PadAreaLength;
|
|
|
|
LIST_ENTRY NewFileList;
|
|
|
|
FFS_FILE_LIST_ENTRY *NewFileListEntry;
|
|
|
|
UINTN Offset;
|
|
|
|
UINTN NumBytesWritten;
|
|
|
|
UINT8 *StartPos;
|
|
|
|
FFS_FILE_LIST_ENTRY *FfsEntry;
|
|
|
|
FFS_FILE_LIST_ENTRY *NextFfsEntry;
|
|
|
|
|
|
|
|
InitializeListHead (&NewFileList);
|
|
|
|
|
|
|
|
NewFileListEntry = NULL;
|
|
|
|
|
|
|
|
OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (OldPadFileHeader)) {
|
|
|
|
PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
|
|
|
|
} else {
|
|
|
|
PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
Status = UpdateHeaderBit (
|
|
|
|
FvDevice,
|
|
|
|
OldPadFileHeader,
|
|
|
|
EFI_FILE_MARKED_FOR_UPDATE
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Update PAD area
|
|
|
|
//
|
|
|
|
TotalSize = 0;
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (OldPadFileHeader)) {
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
|
|
|
|
} else {
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
FileHeader = PadFileHeader;
|
|
|
|
|
|
|
|
for (Index = 0; Index < NumOfFiles; Index++) {
|
|
|
|
if (PadSize[Index] != 0) {
|
|
|
|
FvFillPadFile (PadFileHeader, PadSize[Index]);
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
if (NewFileListEntry == NULL) {
|
2011-10-27 12:46:50 +02:00
|
|
|
FreeFileList (&NewFileList);
|
2011-09-01 21:57:08 +02:00
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
}
|
|
|
|
|
|
|
|
FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
|
|
|
|
Status = FvFillFfsFile (
|
|
|
|
FileHeader,
|
|
|
|
FfsBuffer[Index],
|
|
|
|
BufferSize[Index],
|
|
|
|
ActualFileSize[Index],
|
|
|
|
FileData[Index].NameGuid,
|
|
|
|
FileData[Index].Type,
|
|
|
|
FileData[Index].FileAttributes
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2011-10-27 12:46:50 +02:00
|
|
|
FreeFileList (&NewFileList);
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
if (NewFileListEntry == NULL) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
|
|
|
|
TotalSize += PadSize[Index];
|
|
|
|
TotalSize += BufferSize[Index];
|
|
|
|
}
|
|
|
|
|
|
|
|
FvDevice->CurrentFfsFile = NewFileListEntry;
|
|
|
|
//
|
|
|
|
// Maybe we need a tail pad file
|
|
|
|
//
|
|
|
|
if (PadAreaLength > TotalSize) {
|
|
|
|
if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
|
|
|
|
//
|
|
|
|
// we can insert another PAD file
|
|
|
|
//
|
|
|
|
TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]);
|
|
|
|
FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize);
|
|
|
|
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
if (NewFileListEntry == NULL) {
|
|
|
|
FreeFileList (&NewFileList);
|
2011-10-27 12:46:50 +02:00
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
2011-09-01 21:57:08 +02:00
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// because left size cannot hold another PAD file header,
|
|
|
|
// adjust the writing file size (just in cache)
|
|
|
|
//
|
|
|
|
FvAdjustFfsFile (
|
|
|
|
FvDevice->ErasePolarity,
|
|
|
|
FileHeader,
|
|
|
|
PadAreaLength - TotalSize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Start writing to FV
|
|
|
|
//
|
2011-10-27 12:46:50 +02:00
|
|
|
if (IS_FFS_FILE2 (OldPadFileHeader)) {
|
|
|
|
StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
|
|
|
|
} else {
|
|
|
|
StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
|
|
|
|
NumBytesWritten = PadAreaLength;
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
Offset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
StartPos
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFileList (&NewFileList);
|
2011-10-27 12:46:50 +02:00
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = UpdateHeaderBit (
|
|
|
|
FvDevice,
|
|
|
|
OldPadFileHeader,
|
|
|
|
EFI_FILE_HEADER_INVALID
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFileList (&NewFileList);
|
2011-10-27 12:46:50 +02:00
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
2011-09-01 21:57:08 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Update File List Link
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// First delete old pad file entry
|
|
|
|
//
|
|
|
|
FfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
|
|
|
|
NextFfsEntry = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
|
|
|
|
|
|
|
|
FreePool (PadFileEntry);
|
|
|
|
|
|
|
|
FfsEntry->Link.ForwardLink = NewFileList.ForwardLink;
|
|
|
|
(NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
|
|
|
|
NextFfsEntry->Link.BackLink = NewFileList.BackLink;
|
|
|
|
(NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
/**
|
|
|
|
Create multiple files within the Free Space.
|
|
|
|
|
|
|
|
@param FvDevice Firmware Volume Device.
|
|
|
|
@param FreeSpaceEntry Indicating in which Free Space(Cache) the multiple files will be inserted.
|
|
|
|
@param NumOfFiles Total File number to be written.
|
|
|
|
@param BufferSize The array of buffer size of each FfsBuffer.
|
|
|
|
@param ActualFileSize The array of actual file size.
|
|
|
|
@param PadSize The array of leading pad file size for each FFS File
|
|
|
|
@param FfsBuffer The array of Ffs Buffer pointer.
|
|
|
|
@param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
|
|
|
|
used to get name, attributes, type, etc.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Add the input multiple files into PAD file area.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
|
|
|
|
@retval other error Files can't be added into PAD file area.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvCreateMultipleFilesInsideFreeSpace (
|
|
|
|
IN FV_DEVICE *FvDevice,
|
|
|
|
IN FREE_SPACE_ENTRY *FreeSpaceEntry,
|
|
|
|
IN UINTN NumOfFiles,
|
|
|
|
IN UINTN *BufferSize,
|
|
|
|
IN UINTN *ActualFileSize,
|
|
|
|
IN UINTN *PadSize,
|
|
|
|
IN UINT8 **FfsBuffer,
|
|
|
|
IN EFI_FV_WRITE_FILE_DATA *FileData
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN Index;
|
|
|
|
EFI_FFS_FILE_HEADER *PadFileHeader;
|
|
|
|
EFI_FFS_FILE_HEADER *FileHeader;
|
|
|
|
UINTN TotalSize;
|
|
|
|
LIST_ENTRY NewFileList;
|
|
|
|
FFS_FILE_LIST_ENTRY *NewFileListEntry;
|
|
|
|
UINTN Offset;
|
|
|
|
UINTN NumBytesWritten;
|
|
|
|
UINT8 *StartPos;
|
|
|
|
|
|
|
|
InitializeListHead (&NewFileList);
|
|
|
|
|
|
|
|
NewFileListEntry = NULL;
|
|
|
|
|
|
|
|
TotalSize = 0;
|
|
|
|
StartPos = FreeSpaceEntry->StartingAddress;
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
|
|
|
|
FileHeader = PadFileHeader;
|
|
|
|
|
|
|
|
for (Index = 0; Index < NumOfFiles; Index++) {
|
|
|
|
if (PadSize[Index] != 0) {
|
|
|
|
FvFillPadFile (PadFileHeader, PadSize[Index]);
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
if (NewFileListEntry == NULL) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
}
|
|
|
|
|
|
|
|
FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
|
|
|
|
Status = FvFillFfsFile (
|
|
|
|
FileHeader,
|
|
|
|
FfsBuffer[Index],
|
|
|
|
BufferSize[Index],
|
|
|
|
ActualFileSize[Index],
|
|
|
|
FileData[Index].NameGuid,
|
|
|
|
FileData[Index].Type,
|
|
|
|
FileData[Index].FileAttributes
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
|
|
|
|
if (NewFileListEntry == NULL) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
|
|
|
|
InsertTailList (&NewFileList, &NewFileListEntry->Link);
|
|
|
|
|
|
|
|
PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
|
|
|
|
TotalSize += PadSize[Index];
|
|
|
|
TotalSize += BufferSize[Index];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FreeSpaceEntry->Length < TotalSize) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
FvDevice->CurrentFfsFile = NewFileListEntry;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Start writing to FV
|
|
|
|
//
|
|
|
|
Offset = (UINTN) (StartPos - FvDevice->CachedFv);
|
|
|
|
|
|
|
|
NumBytesWritten = TotalSize;
|
|
|
|
Status = FvcWrite (
|
|
|
|
FvDevice,
|
|
|
|
Offset,
|
|
|
|
&NumBytesWritten,
|
|
|
|
StartPos
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFileList (&NewFileList);
|
|
|
|
FvDevice->CurrentFfsFile = NULL;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeSpaceEntry->Length -= TotalSize;
|
|
|
|
FreeSpaceEntry->StartingAddress += TotalSize;
|
|
|
|
|
|
|
|
NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink);
|
|
|
|
|
|
|
|
while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) {
|
|
|
|
InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link);
|
|
|
|
NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-09-01 21:57:08 +02:00
|
|
|
/**
|
|
|
|
Write multiple files into FV in reliable method.
|
|
|
|
|
|
|
|
@param FvDevice Firmware Volume Device.
|
|
|
|
@param NumOfFiles Total File number to be written.
|
|
|
|
@param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
|
|
|
|
used to get name, attributes, type, etc
|
|
|
|
@param FileOperation The array of operation for each file.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Files are added into FV.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files.
|
|
|
|
@retval EFI_INVALID_PARAMETER File number is less than or equal to 1.
|
|
|
|
@retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FvCreateMultipleFiles (
|
|
|
|
IN FV_DEVICE *FvDevice,
|
|
|
|
IN UINTN NumOfFiles,
|
|
|
|
IN EFI_FV_WRITE_FILE_DATA *FileData,
|
|
|
|
IN BOOLEAN *FileOperation
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT8 *FfsBuffer[MAX_FILES];
|
|
|
|
UINTN Index1;
|
|
|
|
UINTN Index2;
|
|
|
|
UINTN BufferSize[MAX_FILES];
|
|
|
|
UINTN ActualFileSize[MAX_FILES];
|
|
|
|
UINTN RequiredAlignment[MAX_FILES];
|
|
|
|
UINTN PadSize[MAX_FILES];
|
|
|
|
FFS_FILE_LIST_ENTRY *PadFileEntry;
|
|
|
|
UINTN TotalSizeNeeded;
|
|
|
|
FREE_SPACE_ENTRY *FreeSpaceEntry;
|
|
|
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
|
|
|
UINTN Key;
|
|
|
|
EFI_GUID FileNameGuid;
|
|
|
|
EFI_FV_FILETYPE OldFileType;
|
|
|
|
EFI_FV_FILE_ATTRIBUTES OldFileAttributes;
|
|
|
|
UINTN OldFileSize;
|
|
|
|
FFS_FILE_LIST_ENTRY *OldFfsFileEntry[MAX_FILES];
|
|
|
|
EFI_FFS_FILE_HEADER *OldFileHeader[MAX_FILES];
|
|
|
|
BOOLEAN IsCreateFile;
|
2011-10-27 12:46:50 +02:00
|
|
|
UINTN HeaderSize;
|
2011-09-01 21:57:08 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// To use this function, we must ensure that the NumOfFiles is great
|
|
|
|
// than 1
|
|
|
|
//
|
|
|
|
if (NumOfFiles <= 1) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NumOfFiles > MAX_FILES) {
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Fv = &FvDevice->Fv;
|
|
|
|
|
|
|
|
SetMem (FfsBuffer, NumOfFiles, 0);
|
|
|
|
SetMem (RequiredAlignment, NumOfFiles, 8);
|
|
|
|
SetMem (PadSize, NumOfFiles, 0);
|
|
|
|
ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry));
|
|
|
|
ZeroMem (OldFileHeader, sizeof (OldFileHeader));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Adjust file size
|
|
|
|
//
|
|
|
|
for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
|
2011-10-27 12:46:50 +02:00
|
|
|
HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
|
|
|
|
if (ActualFileSize[Index1] > 0x00FFFFFF) {
|
|
|
|
HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
|
|
|
|
ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
|
|
|
|
}
|
2011-09-01 21:57:08 +02:00
|
|
|
BufferSize[Index1] = ActualFileSize[Index1];
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if (BufferSize[Index1] == HeaderSize) {
|
2011-09-01 21:57:08 +02:00
|
|
|
//
|
|
|
|
// clear file attributes, zero-length file does not have any attributes
|
|
|
|
//
|
|
|
|
FileData[Index1].FileAttributes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((BufferSize[Index1] & 0x07) != 0) {
|
|
|
|
BufferSize[Index1]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Copy File Data into FileBuffer
|
|
|
|
//
|
|
|
|
CopyMem (
|
2011-10-27 12:46:50 +02:00
|
|
|
FfsBuffer[Index1] + HeaderSize,
|
2011-09-01 21:57:08 +02:00
|
|
|
FileData[Index1].Buffer,
|
|
|
|
FileData[Index1].BufferSize
|
|
|
|
);
|
|
|
|
|
|
|
|
if (FvDevice->ErasePolarity == 1) {
|
2011-10-27 12:46:50 +02:00
|
|
|
for (Index2 = 0; Index2 < HeaderSize; Index2++) {
|
2011-09-01 21:57:08 +02:00
|
|
|
FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {
|
2011-09-01 21:57:08 +02:00
|
|
|
RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes);
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// If update file, mark the original file header to
|
|
|
|
// EFI_FILE_MARKED_FOR_UPDATE
|
|
|
|
//
|
|
|
|
IsCreateFile = FileOperation[Index1];
|
|
|
|
if (!IsCreateFile) {
|
|
|
|
|
|
|
|
Key = 0;
|
|
|
|
do {
|
|
|
|
OldFileType = 0;
|
|
|
|
Status = Fv->GetNextFile (
|
|
|
|
Fv,
|
|
|
|
&Key,
|
|
|
|
&OldFileType,
|
|
|
|
&FileNameGuid,
|
|
|
|
&OldFileAttributes,
|
|
|
|
&OldFileSize
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFfsBuffer (NumOfFiles, FfsBuffer);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
} while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get FfsFileEntry from the search key
|
|
|
|
//
|
|
|
|
OldFfsFileEntry[Index1] = (FFS_FILE_LIST_ENTRY *) Key;
|
|
|
|
OldFileHeader[Index1] = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader;
|
|
|
|
Status = UpdateHeaderBit (
|
|
|
|
FvDevice,
|
|
|
|
OldFileHeader[Index1],
|
|
|
|
EFI_FILE_MARKED_FOR_UPDATE
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFfsBuffer (NumOfFiles, FfsBuffer);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// First to search a suitable pad file that can hold so
|
|
|
|
// many files
|
|
|
|
//
|
|
|
|
Status = FvSearchSuitablePadFile (
|
|
|
|
FvDevice,
|
|
|
|
NumOfFiles,
|
|
|
|
BufferSize,
|
|
|
|
RequiredAlignment,
|
|
|
|
PadSize,
|
|
|
|
&TotalSizeNeeded,
|
|
|
|
&PadFileEntry
|
|
|
|
);
|
|
|
|
|
|
|
|
if (Status == EFI_NOT_FOUND) {
|
|
|
|
//
|
|
|
|
// Try to find a free space that can hold these files
|
|
|
|
//
|
|
|
|
Status = FvSearchSuitableFreeSpace (
|
|
|
|
FvDevice,
|
|
|
|
NumOfFiles,
|
|
|
|
BufferSize,
|
|
|
|
RequiredAlignment,
|
|
|
|
PadSize,
|
|
|
|
&TotalSizeNeeded,
|
|
|
|
&FreeSpaceEntry
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreeFfsBuffer (NumOfFiles, FfsBuffer);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
2011-10-27 12:46:50 +02:00
|
|
|
Status = FvCreateMultipleFilesInsideFreeSpace (
|
2011-09-01 21:57:08 +02:00
|
|
|
FvDevice,
|
|
|
|
FreeSpaceEntry,
|
2011-10-27 12:46:50 +02:00
|
|
|
NumOfFiles,
|
|
|
|
BufferSize,
|
|
|
|
ActualFileSize,
|
|
|
|
PadSize,
|
|
|
|
FfsBuffer,
|
|
|
|
FileData
|
2011-09-01 21:57:08 +02:00
|
|
|
);
|
|
|
|
|
2011-10-27 12:46:50 +02:00
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// Create multiple files inside such a pad file
|
|
|
|
// to achieve lock-step update
|
|
|
|
//
|
|
|
|
Status = FvCreateMultipleFilesInsidePadFile (
|
|
|
|
FvDevice,
|
|
|
|
PadFileEntry,
|
|
|
|
NumOfFiles,
|
|
|
|
BufferSize,
|
|
|
|
ActualFileSize,
|
|
|
|
PadSize,
|
|
|
|
FfsBuffer,
|
|
|
|
FileData
|
|
|
|
);
|
2011-09-01 21:57:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeFfsBuffer (NumOfFiles, FfsBuffer);
|
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Delete those updated files
|
|
|
|
//
|
|
|
|
for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
|
|
|
|
IsCreateFile = FileOperation[Index1];
|
|
|
|
if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) {
|
|
|
|
(OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink = OldFfsFileEntry[Index1]->Link.ForwardLink;
|
|
|
|
(OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink = OldFfsFileEntry[Index1]->Link.BackLink;
|
|
|
|
FreePool (OldFfsFileEntry[Index1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Set those files' state to EFI_FILE_DELETED
|
|
|
|
//
|
|
|
|
for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
|
|
|
|
IsCreateFile = FileOperation[Index1];
|
|
|
|
if (!IsCreateFile && OldFileHeader[Index1] != NULL) {
|
|
|
|
Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|