X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=IntelFrameworkModulePkg%2FUniversal%2FFirmwareVolume%2FFwVolDxe%2FFwVolWrite.c;fp=IntelFrameworkModulePkg%2FUniversal%2FFirmwareVolume%2FFwVolDxe%2FFwVolWrite.c;h=0000000000000000000000000000000000000000;hp=804f9661acb3537ab9035ba81d78b4026afbe081;hb=aa7fc1c11c3d57d82842dbede50d064639671a98;hpb=4286eb22f4aec33b90574b998a31f8bd34dd4f47 diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c deleted file mode 100644 index 804f9661ac..0000000000 --- a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c +++ /dev/null @@ -1,1614 +0,0 @@ -/** @file - Implements write firmware file. - - Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "FwVolDriver.h" - -/** - Calculate the checksum for the FFS header. - - @param FfsHeader FFS File Header which needs to calculate the checksum - -**/ -VOID -SetHeaderChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader - ) -{ - EFI_FFS_FILE_STATE State; - UINT8 FileChecksum; - - // - // The state and the File checksum are not included - // - State = FfsHeader->State; - FfsHeader->State = 0; - - FileChecksum = FfsHeader->IntegrityCheck.Checksum.File; - FfsHeader->IntegrityCheck.Checksum.File = 0; - - FfsHeader->IntegrityCheck.Checksum.Header = 0; - - if (IS_FFS_FILE2 (FfsHeader)) { - FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( - (UINT8 *) FfsHeader, - sizeof (EFI_FFS_FILE_HEADER2) - ); - } else { - FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 ( - (UINT8 *) FfsHeader, - sizeof (EFI_FFS_FILE_HEADER) - ); - } - - FfsHeader->State = State; - FfsHeader->IntegrityCheck.Checksum.File = FileChecksum; - - return ; -} - -/** - Calculate the checksum for the FFS File. - - @param FfsHeader FFS File Header which needs to calculate the checksum - @param ActualFileSize The whole Ffs File Length. - -**/ -VOID -SetFileChecksum ( - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN UINTN ActualFileSize - ) -{ - if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { - - FfsHeader->IntegrityCheck.Checksum.File = 0; - - if (IS_FFS_FILE2 (FfsHeader)) { - FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( - (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), - ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2) - ); - } else { - FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ( - (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), - ActualFileSize - sizeof (EFI_FFS_FILE_HEADER) - ); - } - - } else { - - FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; - - } - - return ; -} - -/** - Get the alignment value from File Attributes. - - @param FfsAttributes FFS attribute - - @return Alignment value. - -**/ -UINTN -GetRequiredAlignment ( - IN EFI_FV_FILE_ATTRIBUTES FfsAttributes - ) -{ - UINTN AlignmentValue; - - AlignmentValue = FfsAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT; - - if (AlignmentValue <= 3) { - return 0x08; - } - - if (AlignmentValue > 16) { - // - // Anyway, we won't reach this code - // - return 0x08; - } - - return (UINTN)1 << AlignmentValue; - -} - -/** - Calculate the leading Pad file size to meet the alignment requirement. - - @param FvDevice Cached Firmware Volume. - @param StartAddress The starting address to write the FFS File. - @param BufferSize The FFS File Buffer Size. - @param RequiredAlignment FFS File Data alignment requirement. - - @return The required Pad File Size. - -**/ -UINTN -CalculatePadFileSize ( - IN FV_DEVICE *FvDevice, - IN EFI_PHYSICAL_ADDRESS StartAddress, - IN UINTN BufferSize, - IN UINTN RequiredAlignment - ) -{ - UINTN DataStartPos; - UINTN RelativePos; - UINTN PadSize; - - if (BufferSize > 0x00FFFFFF) { - DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2); - } else { - DataStartPos = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER); - } - RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv; - - PadSize = 0; - - while ((RelativePos & (RequiredAlignment - 1)) != 0) { - RelativePos++; - PadSize++; - } - // - // If padsize is 0, no pad file needed; - // If padsize is great than 24, then pad file can be created - // - if ((PadSize == 0) || (PadSize >= sizeof (EFI_FFS_FILE_HEADER))) { - return PadSize; - } - - // - // Perhaps following method can save space - // - RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv + sizeof (EFI_FFS_FILE_HEADER); - PadSize = sizeof (EFI_FFS_FILE_HEADER); - - while ((RelativePos & (RequiredAlignment - 1)) != 0) { - RelativePos++; - PadSize++; - } - - return PadSize; -} - -/** - Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES. - - @param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES - @param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value. - -**/ -VOID -FvFileAttrib2FfsFileAttrib ( - IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib, - OUT UINT8 *FfsFileAttrib - ) -{ - UINT8 FvFileAlignment; - UINT8 FfsFileAlignment; - UINT8 FfsFileAlignment2; - - FvFileAlignment = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT); - FfsFileAlignment = 0; - FfsFileAlignment2 = 0; - - switch (FvFileAlignment) { - case 0: - // - // fall through - // - case 1: - // - // fall through - // - case 2: - // - // fall through - // - case 3: - // - // fall through - // - FfsFileAlignment = 0; - break; - - case 4: - // - // fall through - // - case 5: - // - // fall through - // - case 6: - // - // fall through - // - FfsFileAlignment = 1; - break; - - case 7: - // - // fall through - // - case 8: - // - // fall through - // - FfsFileAlignment = 2; - break; - - case 9: - FfsFileAlignment = 3; - break; - - case 10: - // - // fall through - // - case 11: - // - // fall through - // - FfsFileAlignment = 4; - break; - - case 12: - // - // fall through - // - case 13: - // - // fall through - // - case 14: - // - // fall through - // - FfsFileAlignment = 5; - break; - - case 15: - FfsFileAlignment = 6; - break; - - case 16: - FfsFileAlignment = 7; - break; - - case 17: - FfsFileAlignment = 0; - FfsFileAlignment2 = 1; - break; - case 18: - FfsFileAlignment = 1; - FfsFileAlignment2 = 1; - break; - case 19: - FfsFileAlignment = 2; - FfsFileAlignment2 = 1; - break; - case 20: - FfsFileAlignment = 3; - FfsFileAlignment2 = 1; - break; - case 21: - FfsFileAlignment = 4; - FfsFileAlignment2 = 1; - break; - case 22: - FfsFileAlignment = 5; - FfsFileAlignment2 = 1; - break; - case 23: - FfsFileAlignment = 6; - FfsFileAlignment2 = 1; - break; - case 24: - FfsFileAlignment = 7; - FfsFileAlignment2 = 1; - break; - } - - *FfsFileAttrib = (UINT8) ((FfsFileAlignment << 3) | (FfsFileAlignment2 << 1)); - - return ; -} - -/** - Locate a free space entry that can hold this FFS file. - - @param FvDevice Cached Firmware Volume. - @param Size The FFS file size. - @param RequiredAlignment FFS File Data alignment requirement. - @param PadSize Pointer to the size of leading Pad File. - @param FreeSpaceEntry Pointer to the Free Space Entry that meets the requirement. - - @retval EFI_SUCCESS The free space entry is found. - @retval EFI_NOT_FOUND The free space entry can't be found. - -**/ -EFI_STATUS -FvLocateFreeSpaceEntry ( - IN FV_DEVICE *FvDevice, - IN UINTN Size, - IN UINTN RequiredAlignment, - OUT UINTN *PadSize, - OUT FREE_SPACE_ENTRY **FreeSpaceEntry - ) -{ - FREE_SPACE_ENTRY *FreeSpaceListEntry; - LIST_ENTRY *Link; - UINTN PadFileSize; - - Link = FvDevice->FreeSpaceHeader.ForwardLink; - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; - - // - // Loop the free space entry list to find one that can hold the - // required the file size - // - while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { - PadFileSize = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress, - Size, - RequiredAlignment - ); - if (FreeSpaceListEntry->Length >= Size + PadFileSize) { - *FreeSpaceEntry = FreeSpaceListEntry; - *PadSize = PadFileSize; - return EFI_SUCCESS; - } - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; - } - - return EFI_NOT_FOUND; - -} - -/** - Locate Pad File for writing, this is got from FV Cache. - - @param FvDevice Cached Firmware Volume. - @param Size The required FFS file size. - @param RequiredAlignment FFS File Data alignment requirement. - @param PadSize Pointer to the size of leading Pad File. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvLocatePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN Size, - IN UINTN RequiredAlignment, - OUT UINTN *PadSize, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ) -{ - FFS_FILE_LIST_ENTRY *FileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FFS_FILE_HEADER *FileHeader; - UINTN PadAreaLength; - UINTN PadFileSize; - UINTN HeaderSize; - - FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; - - // - // travel through the whole file list to get the pad file entry - // - while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { - - FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { - // - // we find one valid pad file, check its free area length - // - if (IS_FFS_FILE2 (FileHeader)) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; - } - - PadFileSize = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize, - Size, - RequiredAlignment - ); - if (PadAreaLength >= (Size + PadFileSize)) { - *PadSize = PadFileSize; - *PadFileEntry = FileEntry; - return EFI_SUCCESS; - } - } - - FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); - } - - return EFI_NOT_FOUND; -} - -/** - Locate a suitable pad file for multiple file writing. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The totalsize that can hold these files. - @param PadFileEntry Pointer to the Pad File Entry that meets the requirement. - - @retval EFI_SUCCESS The required pad file is found. - @retval EFI_NOT_FOUND The required pad file can't be found. - -**/ -EFI_STATUS -FvSearchSuitablePadFile ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FFS_FILE_LIST_ENTRY **PadFileEntry - ) -{ - FFS_FILE_LIST_ENTRY *FileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FFS_FILE_HEADER *FileHeader; - UINTN PadAreaLength; - UINTN TotalSize; - UINTN Index; - UINTN HeaderSize; - - FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink; - - // - // travel through the whole file list to get the pad file entry - // - while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) { - - FileHeader = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader; - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) { - // - // we find one valid pad file, check its length - // - if (IS_FFS_FILE2 (FileHeader)) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize; - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize; - } - TotalSize = 0; - - for (Index = 0; Index < NumOfFiles; Index++) { - PadSize[Index] = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize, - BufferSize[Index], - RequiredAlignment[Index] - ); - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - - if (TotalSize > PadAreaLength) { - break; - } - } - - if (PadAreaLength >= TotalSize) { - *PadFileEntry = FileEntry; - *TotalSizeNeeded = TotalSize; - return EFI_SUCCESS; - } - } - - FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink); - } - - return EFI_NOT_FOUND; -} - -/** - Locate a Free Space entry which can hold these files, including - meeting the alignment requirements. - - @param FvDevice Cached Firmware Volume. - @param NumOfFiles The number of Files that needed updating - @param BufferSize The array of each file size. - @param RequiredAlignment The array of of FFS File Data alignment requirement. - @param PadSize The array of size of each leading Pad File. - @param TotalSizeNeeded The got total size that can hold these files. - @param FreeSpaceEntry The Free Space Entry that can hold these files. - - @retval EFI_SUCCESS The free space entry is found. - @retval EFI_NOT_FOUND The free space entry can't be found. - -**/ -EFI_STATUS -FvSearchSuitableFreeSpace ( - IN FV_DEVICE *FvDevice, - IN UINTN NumOfFiles, - IN UINTN *BufferSize, - IN UINTN *RequiredAlignment, - OUT UINTN *PadSize, - OUT UINTN *TotalSizeNeeded, - OUT FREE_SPACE_ENTRY **FreeSpaceEntry - ) -{ - FREE_SPACE_ENTRY *FreeSpaceListEntry; - LIST_ENTRY *Link; - UINTN TotalSize; - UINTN Index; - UINT8 *StartAddr; - - Link = FvDevice->FreeSpaceHeader.ForwardLink; - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) Link; - - while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) { - TotalSize = 0; - StartAddr = FreeSpaceListEntry->StartingAddress; - - // - // Calculate the totalsize we need - // - for (Index = 0; Index < NumOfFiles; Index++) { - // - // Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file - // have had its leading pad file. - // - PadSize[Index] = CalculatePadFileSize ( - FvDevice, - (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize, - BufferSize[Index], - RequiredAlignment[Index] - ); - - TotalSize += PadSize[Index]; - TotalSize += BufferSize[Index]; - - if (TotalSize > FreeSpaceListEntry->Length) { - break; - } - } - - if (FreeSpaceListEntry->Length >= TotalSize) { - *FreeSpaceEntry = FreeSpaceListEntry; - *TotalSizeNeeded = TotalSize; - return EFI_SUCCESS; - } - - FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink; - } - - return EFI_NOT_FOUND; -} - -/** - Calculate the length of the remaining space in FV. - - @param FvDevice Cached Firmware Volume - @param Offset Current offset to FV base address. - @param Lba LBA number for the current offset. - @param LOffset Offset in block for the current offset. - - @return the length of remaining space. - -**/ -UINTN -CalculateRemainingLength ( - IN FV_DEVICE *FvDevice, - IN UINTN Offset, - OUT EFI_LBA *Lba, - OUT UINTN *LOffset - ) -{ - LIST_ENTRY *Link; - LBA_ENTRY *LbaEntry; - UINTN Count; - - Count = 0; - *Lba = 0; - Link = FvDevice->LbaHeader.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - if (Count > Offset) { - break; - } - - Count += LbaEntry->BlockLength; - (*Lba)++; - Link = LbaEntry->Link.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - } - - if (Count <= Offset) { - return 0; - } - - Link = LbaEntry->Link.BackLink; - LbaEntry = (LBA_ENTRY *) Link; - - (*Lba)--; - *LOffset = (UINTN) (LbaEntry->BlockLength - (Count - Offset)); - - Count = 0; - while (&LbaEntry->Link != &FvDevice->LbaHeader) { - - Count += LbaEntry->BlockLength; - - Link = LbaEntry->Link.ForwardLink; - LbaEntry = (LBA_ENTRY *) Link; - } - - Count -= *LOffset; - - return Count; -} - -/** - Writes data beginning at Lba:Offset from FV. The write terminates either - when *NumBytes of data have been written, or when the firmware end is - reached. *NumBytes is updated to reflect the actual number of bytes - written. - - @param FvDevice Cached Firmware Volume - @param Offset Offset in the block at which to begin write - @param NumBytes At input, indicates the requested write size. - At output, indicates the actual number of bytes written. - @param Buffer Buffer containing source data for the write. - - @retval EFI_SUCCESS Data is successfully written into FV. - @return error Data is failed written. - -**/ -EFI_STATUS -FvcWrite ( - IN FV_DEVICE *FvDevice, - IN UINTN Offset, - IN OUT UINTN *NumBytes, - IN UINT8 *Buffer - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_LBA Lba; - UINTN LOffset; - EFI_FVB_ATTRIBUTES_2 FvbAttributes; - UINTN RemainingLength; - UINTN WriteLength; - UINT8 *TmpBuffer; - - LOffset = 0; - RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset); - if ((UINTN) (*NumBytes) > RemainingLength) { - *NumBytes = (UINTN) RemainingLength; - return EFI_INVALID_PARAMETER; - } - - Fvb = FvDevice->Fvb; - - Status = Fvb->GetAttributes ( - Fvb, - &FvbAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) { - return EFI_ACCESS_DENIED; - } - - RemainingLength = *NumBytes; - WriteLength = RemainingLength; - TmpBuffer = Buffer; - - do { - Status = Fvb->Write ( - Fvb, - Lba, - LOffset, - &WriteLength, - TmpBuffer - ); - if (!EFI_ERROR (Status)) { - goto Done; - } - - if (Status == EFI_BAD_BUFFER_SIZE) { - Lba++; - LOffset = 0; - TmpBuffer += WriteLength; - RemainingLength -= WriteLength; - WriteLength = (UINTN) RemainingLength; - - continue; - } else { - return Status; - } - } while (1); - -Done: - return EFI_SUCCESS; -} - -/** - Create a new FFS file into Firmware Volume device. - - @param FvDevice Cached Firmware Volume. - @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 FFS fle is added into FV. - @retval EFI_INVALID_PARAMETER File type is not valid. - @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. - @retval EFI_NOT_FOUND FV has no enough space for the added file. - -**/ -EFI_STATUS -FvCreateNewFile ( - 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 - ) -{ - EFI_STATUS Status; - EFI_FFS_FILE_HEADER *FileHeader; - EFI_PHYSICAL_ADDRESS BufferPtr; - UINTN Offset; - UINTN NumBytesWritten; - UINTN StateOffset; - FREE_SPACE_ENTRY *FreeSpaceEntry; - UINTN RequiredAlignment; - UINTN PadFileSize; - FFS_FILE_LIST_ENTRY *PadFileEntry; - EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - UINTN HeaderSize; - - // - // File Type: 0x0E~0xE0 are reserved - // - if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) { - return EFI_INVALID_PARAMETER; - } - - // - // First find a free space that can hold this image. - // Check alignment, FFS at least must be aligned at 8-byte boundary - // - RequiredAlignment = GetRequiredAlignment (FileAttributes); - - Status = FvLocateFreeSpaceEntry ( - FvDevice, - BufferSize, - RequiredAlignment, - &PadFileSize, - &FreeSpaceEntry - ); - if (EFI_ERROR (Status)) { - // - // Maybe we need to find a PAD file that can hold this image - // - Status = FvCreateNewFileInsidePadFile ( - FvDevice, - FfsFileBuffer, - BufferSize, - ActualFileSize, - FileName, - FileType, - FileAttributes - ); - - return Status; - } - - BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; - - // - // If we need a leading PAD File, create it first. - // - if (PadFileSize != 0) { - Status = FvCreatePadFileInFreeSpace ( - FvDevice, - FreeSpaceEntry, - PadFileSize - sizeof (EFI_FFS_FILE_HEADER), - &PadFileEntry - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - // - // Maybe we create a pad file, so re-get the free space starting address - // and length - // - BufferPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress; - - // - // File creation step 1: Allocate File Header, - // Mark EFI_FILE_HEADER_CONSTRUCTION bit to TRUE, - // Write Name, IntegrityCheck.Header, Type, Attributes, and Size - // - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer; - if (ActualFileSize > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - } else { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - } - SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // update Free Space Entry, now need to substract the file header length - // - FreeSpaceEntry->StartingAddress += HeaderSize; - FreeSpaceEntry->Length -= HeaderSize; - - CopyGuid (&FileHeader->Name, FileName); - FileHeader->Type = FileType; - - // - // Convert FvFileAttribute to FfsFileAttributes - // - FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute); - - FileHeader->Attributes = TmpFileAttribute; - - // - // File size is including the FFS File Header. - // - 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; - } - - SetHeaderChecksum (FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - - NumBytesWritten = HeaderSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - (UINT8 *) FileHeader - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // end of step 1 - // - // File creation step 2: - // MARK EFI_FILE_HEADER_VALID bit to TRUE, - // Write IntegrityCheck.File, File Data - // - SetFileState (EFI_FILE_HEADER_VALID, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // update Free Space Entry, now need to substract the file data length - // - FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize); - FreeSpaceEntry->Length -= (BufferSize - HeaderSize); - - // - // Calculate File Checksum - // - SetFileChecksum (FileHeader, ActualFileSize); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - - NumBytesWritten = BufferSize; - Status = FvcWrite ( - FvDevice, - Offset, - &NumBytesWritten, - FfsFileBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // each time write block successfully, write also to cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FfsFileBuffer, - NumBytesWritten - ); - - // - // Step 3: Mark EFI_FILE_DATA_VALID to TRUE - // - SetFileState (EFI_FILE_DATA_VALID, FileHeader); - - Offset = (UINTN) (BufferPtr - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // update header 2 cache - // - CopyMem ( - (UINT8 *) (UINTN) BufferPtr, - FileHeader, - HeaderSize - ); - - // - // 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) BufferPtr; - InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); - - // - // Set cache file to this file - // - FvDevice->CurrentFfsFile = FfsFileEntry; - - return EFI_SUCCESS; -} - -/** - Update a File, so after successful update, there are 2 files existing - in FV, one is marked for deleted, and another one is valid. - - @param FvDevice Cached Firmware Volume. - @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 NewFileType The FFS File Type. - @param NewFileAttributes The Attributes of the FFS File to be created. - - @retval EFI_SUCCESS FFS fle is updated into FV. - @retval EFI_INVALID_PARAMETER File type is not valid. - @retval EFI_DEVICE_ERROR FV doesn't set writable attribute. - @retval EFI_NOT_FOUND FV has no enough space for the added file. - FFS with same file name is not found in FV. - -**/ -EFI_STATUS -FvUpdateFile ( - IN FV_DEVICE *FvDevice, - IN UINT8 *FfsFileBuffer, - IN UINTN BufferSize, - IN UINTN ActualFileSize, - IN EFI_GUID *FileName, - IN EFI_FV_FILETYPE NewFileType, - IN EFI_FV_FILE_ATTRIBUTES NewFileAttributes - ) -{ - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - UINTN NumBytesWritten; - EFI_FV_FILETYPE OldFileType; - EFI_FV_FILE_ATTRIBUTES OldFileAttributes; - UINTN OldFileSize; - EFI_FFS_FILE_HEADER *OldFileHeader; - UINTN OldOffset; - UINTN OldStateOffset; - FFS_FILE_LIST_ENTRY *OldFfsFileEntry; - UINTN Key; - EFI_GUID FileNameGuid; - - Fv = &FvDevice->Fv; - - // - // Step 1, find old file, - // Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE in the older header - // - - // - // Check if the file was read last time. - // - OldFileHeader = NULL; - OldFfsFileEntry = FvDevice->CurrentFfsFile; - - if (OldFfsFileEntry != NULL) { - OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; - } - - if ((OldFfsFileEntry == NULL) || (!CompareGuid (&OldFileHeader->Name, FileName))) { - Key = 0; - do { - OldFileType = 0; - Status = Fv->GetNextFile ( - Fv, - &Key, - &OldFileType, - &FileNameGuid, - &OldFileAttributes, - &OldFileSize - ); - if (EFI_ERROR (Status)) { - return Status; - } - } while (!CompareGuid (&FileNameGuid, FileName)); - - // - // Get FfsFileEntry from the search key - // - OldFfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; - - // - // Double check file state before being ready to be removed - // - OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader; - } else { - // - // Mark the cache file to invalid - // - FvDevice->CurrentFfsFile = NULL; - } - // - // Update File: Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE - // - SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); - - OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); - OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - OldStateOffset, - &NumBytesWritten, - &OldFileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader); - - return Status; - } - - // - // Step 2, Create New Files - // - Status = FvCreateNewFile ( - FvDevice, - FfsFileBuffer, - BufferSize, - ActualFileSize, - FileName, - NewFileType, - NewFileAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // If successfully, remove this file entry, - // although delete file may fail. - // - (OldFfsFileEntry->Link.BackLink)->ForwardLink = OldFfsFileEntry->Link.ForwardLink; - (OldFfsFileEntry->Link.ForwardLink)->BackLink = OldFfsFileEntry->Link.BackLink; - FreePool (OldFfsFileEntry); - - // - // Step 3: Delete old files, - // by marking EFI_FILE_DELETED to TRUE - // - SetFileState (EFI_FILE_DELETED, OldFileHeader); - - OldOffset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv); - OldStateOffset = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - OldStateOffset, - &NumBytesWritten, - &OldFileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_DELETED, OldFileHeader); - - return Status; - } - - return EFI_SUCCESS; -} - -/** - Deleted a given file from FV device. - - @param FvDevice Cached Firmware Volume. - @param NameGuid The FFS File Name. - - @retval EFI_SUCCESS FFS file with the specified FFS name is removed. - @retval EFI_NOT_FOUND FFS file with the specified FFS name is not found. - -**/ -EFI_STATUS -FvDeleteFile ( - IN FV_DEVICE *FvDevice, - IN EFI_GUID *NameGuid - ) -{ - EFI_STATUS Status; - UINTN Key; - EFI_GUID FileNameGuid; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN FileSize; - EFI_FFS_FILE_HEADER *FileHeader; - FFS_FILE_LIST_ENTRY *FfsFileEntry; - EFI_FFS_FILE_STATE FileState; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - UINTN Offset; - UINTN StateOffset; - UINTN NumBytesWritten; - - Fv = &FvDevice->Fv; - - // - // Check if the file was read last time. - // - FileHeader = NULL; - FfsFileEntry = FvDevice->CurrentFfsFile; - - if (FfsFileEntry != NULL) { - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - } - - if ((FfsFileEntry == NULL) || (!CompareGuid (&FileHeader->Name, NameGuid))) { - // - // Next search for the file using GetNextFile - // - Key = 0; - do { - FileType = 0; - Status = Fv->GetNextFile ( - Fv, - &Key, - &FileType, - &FileNameGuid, - &FileAttributes, - &FileSize - ); - if (EFI_ERROR (Status)) { - return Status; - } - } while (!CompareGuid (&FileNameGuid, NameGuid)); - - // - // Get FfsFileEntry from the search key - // - FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key; - - // - // Double check file state before being ready to be removed - // - FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader; - } else { - // - // Mark the cache file to NULL - // - FvDevice->CurrentFfsFile = NULL; - } - - FileState = GetFileState (FvDevice->ErasePolarity, FileHeader); - - if (FileState == EFI_FILE_HEADER_INVALID) { - return EFI_NOT_FOUND; - } - - if (FileState == EFI_FILE_DELETED) { - return EFI_NOT_FOUND; - } - // - // Delete File: Mark EFI_FILE_DELETED to TRUE - // - SetFileState (EFI_FILE_DELETED, FileHeader); - - Offset = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader - FvDevice->CachedFv); - StateOffset = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader; - - NumBytesWritten = sizeof (EFI_FFS_FILE_STATE); - Status = FvcWrite ( - FvDevice, - StateOffset, - &NumBytesWritten, - &FileHeader->State - ); - if (EFI_ERROR (Status)) { - // - // if failed, write the bit back in the cache, its XOR operation. - // - SetFileState (EFI_FILE_DELETED, FileHeader); - - return Status; - } - // - // If successfully, remove this file entry - // - FvDevice->CurrentFfsFile = NULL; - - (FfsFileEntry->Link.BackLink)->ForwardLink = FfsFileEntry->Link.ForwardLink; - (FfsFileEntry->Link.ForwardLink)->BackLink = FfsFileEntry->Link.BackLink; - FreePool (FfsFileEntry); - - return EFI_SUCCESS; -} - -/** - Writes one or more files to the firmware volume. - - @param This Indicates the calling context. - @param NumberOfFiles Number of files. - @param WritePolicy WritePolicy indicates the level of reliability - for the write in the event of a power failure or - other system failure during the write operation. - @param FileData FileData is an pointer to an array of - EFI_FV_WRITE_DATA. Each element of array - FileData represents a file to be written. - - @retval EFI_SUCCESS Files successfully written to firmware volume - @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated. - @retval EFI_DEVICE_ERROR Device error. - @retval EFI_WRITE_PROTECTED Write protected. - @retval EFI_NOT_FOUND Not found. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_UNSUPPORTED This function not supported. - -**/ -EFI_STATUS -EFIAPI -FvWriteFile ( - IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, - IN UINT32 NumberOfFiles, - IN EFI_FV_WRITE_POLICY WritePolicy, - IN EFI_FV_WRITE_FILE_DATA *FileData - ) -{ - EFI_STATUS Status; - UINTN Index1; - UINTN Index2; - UINT8 *FileBuffer; - UINTN BufferSize; - UINTN ActualSize; - UINT8 ErasePolarity; - FV_DEVICE *FvDevice; - EFI_FV_FILETYPE FileType; - EFI_FV_FILE_ATTRIBUTES FileAttributes; - UINTN Size; - BOOLEAN CreateNewFile[MAX_FILES]; - UINTN NumDelete; - EFI_FV_ATTRIBUTES FvAttributes; - UINT32 AuthenticationStatus; - UINTN HeaderSize; - - if (NumberOfFiles > MAX_FILES) { - return EFI_UNSUPPORTED; - } - - Status = EFI_SUCCESS; - - SetMem (CreateNewFile, NumberOfFiles, TRUE); - - FvDevice = FV_DEVICE_FROM_THIS (This); - - // - // First check the volume attributes. - // - Status = This->GetVolumeAttributes ( - This, - &FvAttributes - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Can we have write right? - // - if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) { - return EFI_WRITE_PROTECTED; - } - - ErasePolarity = FvDevice->ErasePolarity; - - // - // Loop for all files - // - NumDelete = 0; - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - - if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) { - // - // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV. - // - DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n")); - return EFI_INVALID_PARAMETER; - } - - if (FileData[Index1].BufferSize == 0) { - // - // Here we will delete this file - // - Status = This->ReadFile ( - This, - FileData[Index1].NameGuid, - NULL, - &Size, - &FileType, - &FileAttributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - NumDelete++; - } else { - return Status; - } - } - - if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) { - // - // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD: - // "Standard firmware file system services will not return the handle of any pad files, - // nor will they permit explicit creation of such files." - // - return EFI_INVALID_PARAMETER; - } - } - - if ((NumDelete != NumberOfFiles) && (NumDelete != 0)) { - // - // A delete was request with a multiple file write - // - return EFI_INVALID_PARAMETER; - } - - if (NumDelete == NumberOfFiles) { - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - // - // Delete Files - // - Status = FvDeleteFile (FvDevice, FileData[Index1].NameGuid); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; - } - - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - Status = This->ReadFile ( - This, - FileData[Index1].NameGuid, - NULL, - &Size, - &FileType, - &FileAttributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - CreateNewFile[Index1] = FALSE; - } else if (Status == EFI_NOT_FOUND) { - CreateNewFile[Index1] = TRUE; - } else { - return Status; - } - // - // Checking alignment - // - if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) { - UINT8 FFSAlignmentValue; - UINT8 FvAlignmentValue; - - FFSAlignmentValue = (UINT8) (FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT); - FvAlignmentValue = (UINT8) (((UINT32) (FvAttributes & EFI_FV2_ALIGNMENT)) >> 16); - - if (FFSAlignmentValue > FvAlignmentValue) { - return EFI_INVALID_PARAMETER; - } - } - } - - if ((WritePolicy != EFI_FV_RELIABLE_WRITE) && (WritePolicy != EFI_FV_UNRELIABLE_WRITE)) { - return EFI_INVALID_PARAMETER; - } - // - // Checking the reliable write is supported by FV - // - - if ((WritePolicy == EFI_FV_RELIABLE_WRITE) && (NumberOfFiles > 1)) { - // - // Only for multiple files, reliable write is meaningful - // - Status = FvCreateMultipleFiles ( - FvDevice, - NumberOfFiles, - FileData, - CreateNewFile - ); - - return Status; - } - - for (Index1 = 0; Index1 < NumberOfFiles; Index1++) { - // - // Making Buffersize QWORD boundary, and add file tail. - // - HeaderSize = sizeof (EFI_FFS_FILE_HEADER); - ActualSize = FileData[Index1].BufferSize + HeaderSize; - if (ActualSize > 0x00FFFFFF) { - HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); - ActualSize = FileData[Index1].BufferSize + HeaderSize; - } - BufferSize = ActualSize; - - while ((BufferSize & 0x07) != 0) { - BufferSize++; - } - - FileBuffer = AllocateZeroPool (BufferSize); - if (FileBuffer == NULL) { - return Status; - } - // - // Copy File Data into FileBuffer - // - CopyMem ( - FileBuffer + HeaderSize, - FileData[Index1].Buffer, - FileData[Index1].BufferSize - ); - - if (ErasePolarity == 1) { - // - // Fill the file header and padding byte with Erase Byte - // - for (Index2 = 0; Index2 < HeaderSize; Index2++) { - FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; - } - - for (Index2 = ActualSize; Index2 < BufferSize; Index2++) { - FileBuffer[Index2] = (UINT8)~FileBuffer[Index2]; - } - } - - if (CreateNewFile[Index1]) { - Status = FvCreateNewFile ( - FvDevice, - FileBuffer, - BufferSize, - ActualSize, - FileData[Index1].NameGuid, - FileData[Index1].Type, - FileData[Index1].FileAttributes - ); - } else { - Status = FvUpdateFile ( - FvDevice, - FileBuffer, - BufferSize, - ActualSize, - FileData[Index1].NameGuid, - FileData[Index1].Type, - FileData[Index1].FileAttributes - ); - } - - FreePool (FileBuffer); - - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -}