/** @file\r
Implements write firmware file.\r
\r
- Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
#include "FwVolDriver.h"\r
\r
/**\r
- Caculate the checksum for the FFS header.\r
+ Calculate the checksum for the FFS header.\r
\r
- @param FfsHeader FFS File Header which needs to caculate the checksum\r
+ @param FfsHeader FFS File Header which needs to calculate the checksum\r
\r
**/\r
VOID\r
)\r
{\r
EFI_FFS_FILE_STATE State;\r
- UINT8 HeaderChecksum;\r
UINT8 FileChecksum;\r
\r
//\r
\r
FfsHeader->IntegrityCheck.Checksum.Header = 0;\r
\r
- HeaderChecksum = CalculateSum8 (\r
- (UINT8 *)FfsHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
- );\r
-\r
- FfsHeader->IntegrityCheck.Checksum.Header = (UINT8) (~HeaderChecksum + 1);\r
+ if (IS_FFS_FILE2 (FfsHeader)) {\r
+ FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
+ (UINT8 *) FfsHeader,\r
+ sizeof (EFI_FFS_FILE_HEADER2)\r
+ );\r
+ } else {\r
+ FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
+ (UINT8 *) FfsHeader,\r
+ sizeof (EFI_FFS_FILE_HEADER)\r
+ );\r
+ }\r
\r
FfsHeader->State = State;\r
FfsHeader->IntegrityCheck.Checksum.File = FileChecksum;\r
}\r
\r
/**\r
- Caculate the checksum for the FFS File.\r
+ Calculate the checksum for the FFS File.\r
\r
- @param FfsHeader FFS File Header which needs to caculate the checksum\r
+ @param FfsHeader FFS File Header which needs to calculate the checksum\r
@param ActualFileSize The whole Ffs File Length.\r
\r
**/\r
IN UINTN ActualFileSize\r
)\r
{\r
- EFI_FFS_FILE_STATE State;\r
- UINT8 FileChecksum;\r
-\r
if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {\r
- //\r
- // The file state is not included\r
- //\r
- State = FfsHeader->State;\r
- FfsHeader->State = 0;\r
\r
FfsHeader->IntegrityCheck.Checksum.File = 0;\r
\r
- //\r
- // File checksum \r
- //\r
- FileChecksum = CalculateSum8 (\r
- (UINT8 *)(FfsHeader + 1),\r
- ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r
- );\r
-\r
- FfsHeader->IntegrityCheck.Checksum.File = (UINT8) (~FileChecksum + 1);\r
-\r
- FfsHeader->State = State;\r
+ if (IS_FFS_FILE2 (FfsHeader)) {\r
+ FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
+ (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2),\r
+ ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2)\r
+ );\r
+ } else {\r
+ FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
+ (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER),\r
+ ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r
+ );\r
+ }\r
\r
} else {\r
\r
}\r
\r
/**\r
- Caculate the leading Pad file size to meet the alignment requirement.\r
+ Calculate the leading Pad file size to meet the alignment requirement.\r
\r
@param FvDevice Cached Firmware Volume.\r
@param StartAddress The starting address to write the FFS File.\r
+ @param BufferSize The FFS File Buffer Size.\r
@param RequiredAlignment FFS File Data alignment requirement.\r
\r
@return The required Pad File Size.\r
\r
**/\r
UINTN\r
-CaculatePadFileSize (\r
+CalculatePadFileSize (\r
IN FV_DEVICE *FvDevice,\r
IN EFI_PHYSICAL_ADDRESS StartAddress,\r
+ IN UINTN BufferSize,\r
IN UINTN RequiredAlignment\r
)\r
{\r
UINTN RelativePos;\r
UINTN PadSize;\r
\r
- DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r
+ if (BufferSize > 0x00FFFFFF) {\r
+ DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2);\r
+ } else {\r
+ DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r
+ }\r
RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv;\r
\r
PadSize = 0;\r
{\r
UINT8 FvFileAlignment;\r
UINT8 FfsFileAlignment;\r
+ UINT8 FfsFileAlignment2;\r
\r
FvFileAlignment = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT);\r
FfsFileAlignment = 0;\r
+ FfsFileAlignment2 = 0;\r
\r
switch (FvFileAlignment) {\r
case 0:\r
case 16:\r
FfsFileAlignment = 7;\r
break;\r
+\r
+ case 17:\r
+ FfsFileAlignment = 0;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 18:\r
+ FfsFileAlignment = 1;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 19:\r
+ FfsFileAlignment = 2;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 20:\r
+ FfsFileAlignment = 3;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 21:\r
+ FfsFileAlignment = 4;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 22:\r
+ FfsFileAlignment = 5;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 23:\r
+ FfsFileAlignment = 6;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
+ case 24:\r
+ FfsFileAlignment = 7;\r
+ FfsFileAlignment2 = 1;\r
+ break;\r
}\r
\r
- *FfsFileAttrib = (UINT8) (FfsFileAlignment << 3);\r
+ *FfsFileAttrib = (UINT8) ((FfsFileAlignment << 3) | (FfsFileAlignment2 << 1));\r
\r
return ;\r
}\r
// required the file size\r
//\r
while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) {\r
- PadFileSize = CaculatePadFileSize (\r
+ PadFileSize = CalculatePadFileSize (\r
FvDevice,\r
(EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress,\r
+ Size,\r
RequiredAlignment\r
);\r
if (FreeSpaceListEntry->Length >= Size + PadFileSize) {\r
\r
}\r
\r
-/**\r
- Locate a free space that can hold this file.\r
-\r
- @param FvDevice Cached Firmware Volume.\r
- @param Size On input, it is the required size.\r
- On output, it is the actual size of free space.\r
- @param RequiredAlignment FFS File Data alignment requirement.\r
- @param PadSize Pointer to the size of leading Pad File.\r
- @param StartingAddress The starting address of the Free Space Entry\r
- that meets the requirement.\r
-\r
- @retval EFI_SUCCESS The free space is found.\r
- @retval EFI_NOT_FOUND The free space can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvLocateFreeSpace (\r
- IN FV_DEVICE *FvDevice,\r
- IN OUT UINTN *Size,\r
- IN UINTN RequiredAlignment,\r
- OUT UINTN *PadSize,\r
- OUT EFI_PHYSICAL_ADDRESS *StartingAddress\r
- )\r
-{\r
- EFI_STATUS Status;\r
- FREE_SPACE_ENTRY *FreeSpaceEntry;\r
-\r
- //\r
- // First find the free space entry\r
- //\r
- Status = FvLocateFreeSpaceEntry (\r
- FvDevice,\r
- *Size,\r
- RequiredAlignment,\r
- PadSize,\r
- &FreeSpaceEntry\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- *Size = FreeSpaceEntry->Length;\r
- *StartingAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
/**\r
Locate Pad File for writing, this is got from FV Cache.\r
\r
FFS_FILE_LIST_ENTRY *FileEntry;\r
EFI_FFS_FILE_STATE FileState;\r
EFI_FFS_FILE_HEADER *FileHeader;\r
- UINTN FileLength;\r
UINTN PadAreaLength;\r
UINTN PadFileSize;\r
+ UINTN HeaderSize;\r
\r
FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
\r
//\r
// we find one valid pad file, check its free area length\r
//\r
- FileLength = *(UINT32 *) FileHeader->Size & 0x00FFFFFF;\r
- PadAreaLength = FileLength - sizeof (EFI_FFS_FILE_HEADER);\r
+ if (IS_FFS_FILE2 (FileHeader)) {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
+ } else {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
+ }\r
\r
- PadFileSize = CaculatePadFileSize (\r
+ PadFileSize = CalculatePadFileSize (\r
FvDevice,\r
- (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER),\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize,\r
+ Size,\r
RequiredAlignment\r
);\r
if (PadAreaLength >= (Size + PadFileSize)) {\r
FFS_FILE_LIST_ENTRY *FileEntry;\r
EFI_FFS_FILE_STATE FileState;\r
EFI_FFS_FILE_HEADER *FileHeader;\r
- UINTN FileLength;\r
UINTN PadAreaLength;\r
UINTN TotalSize;\r
UINTN Index;\r
+ UINTN HeaderSize;\r
\r
FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
\r
//\r
// we find one valid pad file, check its length\r
//\r
- FileLength = *(UINT32 *) FileHeader->Size & 0x00FFFFFF;\r
- PadAreaLength = FileLength - sizeof (EFI_FFS_FILE_HEADER);\r
+ if (IS_FFS_FILE2 (FileHeader)) {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
+ } else {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
+ }\r
TotalSize = 0;\r
\r
for (Index = 0; Index < NumOfFiles; Index++) {\r
- PadSize[Index] = CaculatePadFileSize (\r
+ PadSize[Index] = CalculatePadFileSize (\r
FvDevice,\r
- (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER) + TotalSize,\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize,\r
+ BufferSize[Index],\r
RequiredAlignment[Index]\r
);\r
TotalSize += PadSize[Index];\r
StartAddr = FreeSpaceListEntry->StartingAddress;\r
\r
//\r
- // Caculate the totalsize we need\r
+ // Calculate the totalsize we need\r
//\r
for (Index = 0; Index < NumOfFiles; Index++) {\r
//\r
// Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file\r
// have had its leading pad file.\r
//\r
- PadSize[Index] = CaculatePadFileSize (\r
+ PadSize[Index] = CalculatePadFileSize (\r
FvDevice,\r
(EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize,\r
+ BufferSize[Index],\r
RequiredAlignment[Index]\r
);\r
\r
UINTN RemainingLength;\r
UINTN WriteLength;\r
UINT8 *TmpBuffer;\r
- \r
+\r
LOffset = 0;\r
RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset);\r
if ((UINTN) (*NumBytes) > RemainingLength) {\r
return Status;\r
}\r
\r
- if ((FvbAttributes & EFI_FV2_WRITE_STATUS) != 0) {\r
+ if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r
return EFI_ACCESS_DENIED;\r
}\r
\r
FFS_FILE_LIST_ENTRY *PadFileEntry;\r
EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;\r
FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
+ UINTN HeaderSize;\r
\r
//\r
// File Type: 0x0E~0xE0 are reserved\r
\r
//\r
// First find a free space that can hold this image.\r
- // Check alignment, FFS at least must be aligned at 8-byte boundry\r
+ // Check alignment, FFS at least must be aligned at 8-byte boundary\r
//\r
RequiredAlignment = GetRequiredAlignment (FileAttributes);\r
\r
// Write Name, IntegrityCheck.Header, Type, Attributes, and Size\r
//\r
FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;\r
+ if (ActualFileSize > 0x00FFFFFF) {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ } else {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ }\r
SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader);\r
\r
Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
CopyMem (\r
(UINT8 *) (UINTN) BufferPtr,\r
FileHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
+ HeaderSize\r
);\r
\r
//\r
- // update Free Space Entry, now need to substract the EFI_FFS_FILE_HEADER\r
+ // update Free Space Entry, now need to substract the file header length\r
//\r
- FreeSpaceEntry->StartingAddress += sizeof (EFI_FFS_FILE_HEADER);\r
- FreeSpaceEntry->Length -= sizeof (EFI_FFS_FILE_HEADER);\r
+ FreeSpaceEntry->StartingAddress += HeaderSize;\r
+ FreeSpaceEntry->Length -= HeaderSize;\r
\r
CopyGuid (&FileHeader->Name, FileName);\r
FileHeader->Type = FileType;\r
//\r
// File size is including the FFS File Header.\r
//\r
- *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
- *(UINT32 *) FileHeader->Size |= ActualFileSize;\r
+ if (ActualFileSize > 0x00FFFFFF) {\r
+ ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;\r
+ *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
+ FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+ } else {\r
+ *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
+ *(UINT32 *) FileHeader->Size |= ActualFileSize;\r
+ }\r
\r
SetHeaderChecksum (FileHeader);\r
\r
Offset = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
\r
- NumBytesWritten = sizeof (EFI_FFS_FILE_HEADER);\r
+ NumBytesWritten = HeaderSize;\r
Status = FvcWrite (\r
FvDevice,\r
Offset,\r
CopyMem (\r
(UINT8 *) (UINTN) BufferPtr,\r
FileHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
+ HeaderSize\r
);\r
\r
//\r
CopyMem (\r
(UINT8 *) (UINTN) BufferPtr,\r
FileHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
+ HeaderSize\r
);\r
\r
//\r
// update Free Space Entry, now need to substract the file data length\r
//\r
- FreeSpaceEntry->StartingAddress += (BufferSize - sizeof (EFI_FFS_FILE_HEADER));\r
- FreeSpaceEntry->Length -= (BufferSize - sizeof (EFI_FFS_FILE_HEADER));\r
+ FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize);\r
+ FreeSpaceEntry->Length -= (BufferSize - HeaderSize);\r
\r
//\r
- // Caculate File Checksum\r
+ // Calculate File Checksum\r
//\r
SetFileChecksum (FileHeader, ActualFileSize);\r
\r
CopyMem (\r
(UINT8 *) (UINTN) BufferPtr,\r
FileHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
+ HeaderSize\r
);\r
\r
//\r
UINTN NumDelete;\r
EFI_FV_ATTRIBUTES FvAttributes;\r
UINT32 AuthenticationStatus;\r
+ UINTN HeaderSize;\r
\r
if (NumberOfFiles > MAX_FILES) {\r
return EFI_UNSUPPORTED;\r
//\r
// Can we have write right?\r
//\r
- if ((FvAttributes & EFI_FV2_WRITE_STATUS) != 0) {\r
+ if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
//\r
NumDelete = 0;\r
for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
+\r
+ if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) {\r
+ //\r
+ // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV.\r
+ //\r
+ DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n"));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
if (FileData[Index1].BufferSize == 0) {\r
//\r
// Here we will delete this file\r
\r
if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) {\r
//\r
- // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD: \r
- // "Standard firmware file system services will not return the handle of any pad files, \r
+ // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD:\r
+ // "Standard firmware file system services will not return the handle of any pad files,\r
// nor will they permit explicit creation of such files."\r
//\r
return EFI_INVALID_PARAMETER;\r
\r
for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
//\r
- // Making Buffersize QWORD boundry, and add file tail.\r
+ // Making Buffersize QWORD boundary, and add file tail.\r
//\r
- ActualSize = FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER);\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
+ if (ActualSize > 0x00FFFFFF) {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
+ }\r
BufferSize = ActualSize;\r
\r
while ((BufferSize & 0x07) != 0) {\r
// Copy File Data into FileBuffer\r
//\r
CopyMem (\r
- FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
+ FileBuffer + HeaderSize,\r
FileData[Index1].Buffer,\r
FileData[Index1].BufferSize\r
);\r
//\r
// Fill the file header and padding byte with Erase Byte\r
//\r
- for (Index2 = 0; Index2 < sizeof (EFI_FFS_FILE_HEADER); Index2++) {\r
+ for (Index2 = 0; Index2 < HeaderSize; Index2++) {\r
FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r
}\r
\r