Example #1
0
/**
  Sets a file's current position.

  @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the
                          file handle to set the requested position on.
  @param  Position        The byte position from the start of the file to set.

  @retval EFI_SUCCESS      The position was set.
  @retval EFI_UNSUPPORTED  The seek request for nonzero is not valid on open
                           directories.
  @retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemSetPosition (
    IN EFI_FILE_PROTOCOL        *This,
    IN UINT64                   Position
)
{
    FV_FILESYSTEM_INSTANCE      *Instance;
    FV_FILESYSTEM_FILE          *File;

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    if (File->FvFileInfo == Instance->Root->FvFileInfo) {
        if (Position != 0) {
            return EFI_UNSUPPORTED;
        }
        //
        // Reset directory position to first entry
        //
        File->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
    } else if (Position == 0xFFFFFFFFFFFFFFFFull) {
        File->Position = File->FvFileInfo->FileInfo.FileSize;
    } else {
        File->Position = Position;
    }

    return EFI_SUCCESS;
}
Example #2
0
/**
  Closes a specified file handle.

  @param  This          A pointer to the EFI_FILE_PROTOCOL instance that is the file
                        handle to close.

  @retval EFI_SUCCESS   The file was closed.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemClose (
    IN EFI_FILE_PROTOCOL  *This
)
{
    FV_FILESYSTEM_INSTANCE      *Instance;
    FV_FILESYSTEM_FILE          *File;

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    if (File != Instance->Root) {
        RemoveEntryList (&File->Link);
        FreePool (File);
    }
    return EFI_SUCCESS;
}
Example #3
0
/**
  Returns a file's current position.

  @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the file
                          handle to get the current position on.
  @param  Position        The address to return the file's current position value.

  @retval EFI_SUCCESS      The position was returned.
  @retval EFI_UNSUPPORTED  The request is not valid on open directories.
  @retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemGetPosition (
    IN     EFI_FILE_PROTOCOL    *This,
    OUT UINT64               *Position
)
{
    FV_FILESYSTEM_INSTANCE        *Instance;
    FV_FILESYSTEM_FILE            *File;

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    if (File->FvFileInfo == Instance->Root->FvFileInfo) {
        return EFI_UNSUPPORTED;
    } else {
        *Position = File->Position;
        return EFI_SUCCESS;
    }
}
Example #4
0
/**
  Writes data to a file.

  @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
                     handle to write data to.
  @param  BufferSize On input, the size of the Buffer. On output, the amount of data
                     actually written. In both cases, the size is measured in bytes.
  @param  Buffer     The buffer of data to write.

  @retval EFI_SUCCESS          Data was written.
  @retval EFI_UNSUPPORTED      Writes to open directory files are not supported.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_WRITE_PROTECTED  The file or medium is write-protected.
  @retval EFI_ACCESS_DENIED    The file was opened read only.
  @retval EFI_VOLUME_FULL      The volume is full.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemWrite (
    IN     EFI_FILE_PROTOCOL    *This,
    IN OUT UINTN                *BufferSize,
    IN     VOID                 *Buffer
)
{
    FV_FILESYSTEM_INSTANCE        *Instance;
    FV_FILESYSTEM_FILE            *File;

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    if (File->FvFileInfo == Instance->Root->FvFileInfo) {
        return EFI_UNSUPPORTED;
    } else {
        return EFI_WRITE_PROTECTED;
    }
}
Example #5
0
/**
  Returns information about a file.

  @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the file
                          handle the requested information is for.
  @param  InformationType The type identifier for the information being requested.
  @param  BufferSize      On input, the size of Buffer. On output, the amount of data
                          returned in Buffer. In both cases, the size is measured in bytes.
  @param  Buffer          A pointer to the data buffer to return. The buffer's type is
                          indicated by InformationType.

  @retval EFI_SUCCESS          The information was returned.
  @retval EFI_UNSUPPORTED      The InformationType is not known.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
                               BufferSize has been updated with the size needed to complete
                               the request.
**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemGetInfo (
    IN     EFI_FILE_PROTOCOL    *This,
    IN     EFI_GUID             *InformationType,
    IN OUT UINTN                *BufferSize,
    OUT VOID                 *Buffer
)
{
    FV_FILESYSTEM_FILE           *File;
    EFI_FILE_SYSTEM_INFO         *FsInfoOut;
    EFI_FILE_SYSTEM_VOLUME_LABEL *FsVolumeLabel;
    FV_FILESYSTEM_INSTANCE       *Instance;
    UINTN                        Size;
    EFI_STATUS                   Status;

    File = FVFS_FILE_FROM_FILE_THIS (This);

    if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
        //
        // Return filesystem info
        //
        Instance = File->Instance;

        Size = sizeof (EFI_FILE_SYSTEM_INFO) + StrSize (Instance->VolumeLabel) - sizeof (CHAR16);

        if (*BufferSize < Size) {
            *BufferSize = Size;
            return EFI_BUFFER_TOO_SMALL;
        }

        //
        // Cast output buffer for convenience
        //
        FsInfoOut = (EFI_FILE_SYSTEM_INFO *) Buffer;

        CopyMem (FsInfoOut, &mFsInfoTemplate, sizeof (EFI_FILE_SYSTEM_INFO));
        Status = StrnCpyS (FsInfoOut->VolumeLabel, (*BufferSize - OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel)) / sizeof (CHAR16), Instance->VolumeLabel, StrLen (Instance->VolumeLabel));
        ASSERT_EFI_ERROR (Status);
        FsInfoOut->Size = Size;
        return Status;
    } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
        //
        // Return file info
        //
        return FvFsGetFileInfo (File->FvFileInfo, BufferSize, (EFI_FILE_INFO *) Buffer);
    } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
        //
        // Return Volume Label
        //
        Instance = File->Instance;
        Size     = sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL) + StrSize (Instance->VolumeLabel) - sizeof (CHAR16);;
        if (*BufferSize < Size) {
            *BufferSize = Size;
            return EFI_BUFFER_TOO_SMALL;
        }

        FsVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL*) Buffer;
        Status        = StrnCpyS (FsVolumeLabel->VolumeLabel, (*BufferSize - OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel)) / sizeof (CHAR16), Instance->VolumeLabel, StrLen (Instance->VolumeLabel));
        ASSERT_EFI_ERROR (Status);
        return Status;
    } else {
        return EFI_UNSUPPORTED;
    }
}
Example #6
0
/**
  Reads data from a file.

  @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
                     handle to read data from.
  @param  BufferSize On input, the size of the Buffer. On output, the amount of data
                     returned in Buffer. In both cases, the size is measured in bytes.
  @param  Buffer     The buffer into which the data is read.

  @retval EFI_SUCCESS          Data was read.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_DEVICE_ERROR     An attempt was made to read from a deleted file.
  @retval EFI_DEVICE_ERROR     On entry, the current file position is beyond the end of the file.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
                               entry. BufferSize has been updated with the size
                               needed to complete the request.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemRead (
    IN     EFI_FILE_PROTOCOL      *This,
    IN OUT UINTN                  *BufferSize,
    OUT VOID                   *Buffer
)
{
    FV_FILESYSTEM_INSTANCE        *Instance;
    FV_FILESYSTEM_FILE            *File;
    EFI_STATUS                    Status;
    LIST_ENTRY                    *FvFileInfoLink;
    VOID                          *FileBuffer;
    UINTN                         FileSize;

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    if (File->FvFileInfo == Instance->Root->FvFileInfo) {
        if (File->DirReadNext) {
            //
            // Directory read: populate Buffer with an EFI_FILE_INFO
            //
            Status = FvFsGetFileInfo (File->DirReadNext, BufferSize, Buffer);
            if (!EFI_ERROR (Status)) {
                //
                // Successfully read a directory entry, now update the pointer to the
                // next file, which will be read on the next call to this function
                //
                FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, &File->DirReadNext->Link);
                if (IsNull (&Instance->FileInfoHead, FvFileInfoLink)) {
                    //
                    // No more files left
                    //
                    File->DirReadNext = NULL;
                } else {
                    File->DirReadNext = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
                }
            }
            return Status;
        } else {
            //
            // Directory read. All entries have been read, so return a zero-size
            // buffer.
            //
            *BufferSize = 0;
            return EFI_SUCCESS;
        }
    } else {
        FileSize = (UINTN)File->FvFileInfo->FileInfo.FileSize;

        FileBuffer = AllocateZeroPool (FileSize);
        if (FileBuffer == NULL) {
            return EFI_DEVICE_ERROR;
        }

        Status = FvFsReadFile (File->Instance->FvProtocol, File->FvFileInfo, &FileSize, &FileBuffer);
        if (EFI_ERROR (Status)) {
            return EFI_DEVICE_ERROR;
        }

        if (*BufferSize + File->Position > FileSize) {
            *BufferSize = (UINTN)(FileSize - File->Position);
        }

        CopyMem (Buffer, (UINT8*)FileBuffer + File->Position, *BufferSize);
        File->Position += *BufferSize;

        return EFI_SUCCESS;
    }
}
Example #7
0
/**
  Opens a new file relative to the source file's location.

  @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
                     handle to the source location. This would typically be an open
                     handle to a directory.
  @param  NewHandle  A pointer to the location to return the opened handle for the new
                     file.
  @param  FileName   The Null-terminated string of the name of the file to be opened.
                     The file name may contain the following path modifiers: "\", ".",
                     and "..".
  @param  OpenMode   The mode to open the file. The only valid combinations that the
                     file may be opened with are: Read, Read/Write, or Create/Read/Write.
  @param  Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
                     attribute bits for the newly created file.

  @retval EFI_SUCCESS          The file was opened.
  @retval EFI_NOT_FOUND        The specified file could not be found on the device.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_MEDIA_CHANGED    The device has a different medium in it or the medium is no
                               longer supported.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_WRITE_PROTECTED  An attempt was made to create a file, or open a file for write
                               when the media is write-protected.
  @retval EFI_ACCESS_DENIED    The service denied access to the file.
  @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
  @retval EFI_VOLUME_FULL      The volume is full.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemOpen (
    IN     EFI_FILE_PROTOCOL    *This,
    OUT EFI_FILE_PROTOCOL    **NewHandle,
    IN     CHAR16               *FileName,
    IN     UINT64               OpenMode,
    IN     UINT64               Attributes
)
{
    FV_FILESYSTEM_INSTANCE      *Instance;
    FV_FILESYSTEM_FILE          *File;
    FV_FILESYSTEM_FILE          *NewFile;
    FV_FILESYSTEM_FILE_INFO     *FvFileInfo;
    LIST_ENTRY                  *FvFileInfoLink;

    //
    // Check for a valid mode
    //
    switch (OpenMode) {
    case EFI_FILE_MODE_READ:
        break;

    default:
        return EFI_WRITE_PROTECTED;
    }

    File = FVFS_FILE_FROM_FILE_THIS (This);
    Instance = File->Instance;

    FileName = TrimFilePathToAbsolutePath (FileName);
    if (FileName == NULL) {
        return EFI_INVALID_PARAMETER;
    }

    if (FileName[0] == L'\\') {
        FileName++;
    }

    //
    // Check for opening root
    //
    if (StrCmp (FileName, L".") == 0 || StrCmp (FileName, L"") == 0) {
        NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
        if (NewFile == NULL) {
            return EFI_OUT_OF_RESOURCES;
        }
        NewFile->Signature = FVFS_FILE_SIGNATURE;
        NewFile->Instance  = Instance;
        NewFile->FvFileInfo = File->FvFileInfo;
        CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
        InitializeListHead (&NewFile->Link);
        InsertHeadList (&Instance->FileHead, &NewFile->Link);

        NewFile->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);

        *NewHandle = &NewFile->FileProtocol;
        return EFI_SUCCESS;
    }

    //
    // Do a linear search for a file in the FV with a matching filename
    //
    for (FvFileInfoLink = GetFirstNode (&Instance->FileInfoHead);
            !IsNull (&Instance->FileInfoHead, FvFileInfoLink);
            FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, FvFileInfoLink)) {
        FvFileInfo = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
        if (mUnicodeCollation->StriColl (mUnicodeCollation, &FvFileInfo->FileInfo.FileName[0], FileName) == 0) {
            NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
            if (NewFile == NULL) {
                return EFI_OUT_OF_RESOURCES;
            }

            NewFile->Signature = FVFS_FILE_SIGNATURE;
            NewFile->Instance  = Instance;
            NewFile->FvFileInfo = FvFileInfo;
            CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
            InitializeListHead (&NewFile->Link);
            InsertHeadList (&Instance->FileHead, &NewFile->Link);

            *NewHandle = &NewFile->FileProtocol;
            return EFI_SUCCESS;
        }
    }

    return EFI_NOT_FOUND;
}
Example #8
0
/**
  Opens a new file relative to the source file's location.

  @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
                     handle to the source location. This would typically be an open
                     handle to a directory.
  @param  NewHandle  A pointer to the location to return the opened handle for the new
                     file.
  @param  FileName   The Null-terminated string of the name of the file to be opened.
                     The file name may contain the following path modifiers: "\", ".",
                     and "..".
  @param  OpenMode   The mode to open the file. The only valid combinations that the
                     file may be opened with are: Read, Read/Write, or Create/Read/Write.
  @param  Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
                     attribute bits for the newly created file.

  @retval EFI_SUCCESS          The file was opened.
  @retval EFI_NOT_FOUND        The specified file could not be found on the device.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_MEDIA_CHANGED    The device has a different medium in it or the medium is no
                               longer supported.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_WRITE_PROTECTED  An attempt was made to create a file, or open a file for write
                               when the media is write-protected.
  @retval EFI_ACCESS_DENIED    The service denied access to the file.
  @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
  @retval EFI_VOLUME_FULL      The volume is full.

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemOpen (
  IN     EFI_FILE_PROTOCOL    *This,
     OUT EFI_FILE_PROTOCOL    **NewHandle,
  IN     CHAR16               *FileName,
  IN     UINT64               OpenMode,
  IN     UINT64               Attributes
  )
{
  FV_FILESYSTEM_INSTANCE      *Instance;
  FV_FILESYSTEM_FILE          *File;
  FV_FILESYSTEM_FILE          *NewFile;
  FV_FILESYSTEM_FILE_INFO     *FvFileInfo;
  LIST_ENTRY                  *FvFileInfoLink;
  EFI_STATUS                  Status;
  UINTN                       FileNameLength;
  UINTN                       NewFileNameLength;
  CHAR16                      *FileNameWithExtension;

  //
  // Check for a valid mode
  //
  switch (OpenMode) {
  case EFI_FILE_MODE_READ:
    break;

  default:
    return EFI_WRITE_PROTECTED;
  }

  File = FVFS_FILE_FROM_FILE_THIS (This);
  Instance = File->Instance;

  FileName = TrimFilePathToAbsolutePath (FileName);
  if (FileName == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (FileName[0] == L'\\') {
    FileName++;
  }

  //
  // Check for opening root
  //
  if (StrCmp (FileName, L".") == 0 || StrCmp (FileName, L"") == 0) {
    NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
    if (NewFile == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    NewFile->Signature = FVFS_FILE_SIGNATURE;
    NewFile->Instance  = Instance;
    NewFile->FvFileInfo = File->FvFileInfo;
    CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
    InitializeListHead (&NewFile->Link);
    InsertHeadList (&Instance->FileHead, &NewFile->Link);

    NewFile->DirReadNext = NULL;
    if (!IsListEmpty (&Instance->FileInfoHead)) {
      NewFile->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
    }

    *NewHandle = &NewFile->FileProtocol;
    return EFI_SUCCESS;
  }

  //
  // Do a linear search for a file in the FV with a matching filename
  //
  Status     = EFI_NOT_FOUND;
  FvFileInfo = NULL;
  for (FvFileInfoLink = GetFirstNode (&Instance->FileInfoHead);
      !IsNull (&Instance->FileInfoHead, FvFileInfoLink);
       FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, FvFileInfoLink)) {
    FvFileInfo = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
    if (mUnicodeCollation->StriColl (mUnicodeCollation, &FvFileInfo->FileInfo.FileName[0], FileName) == 0) {
      Status = EFI_SUCCESS;
      break;
    }
  }

  // If the file has not been found check if the filename exists with an extension
  // in case there was no extension present.
  // FvFileSystem adds a 'virtual' extension '.EFI' to EFI applications and drivers
  // present in the Firmware Volume
  if (Status == EFI_NOT_FOUND) {
    FileNameLength = StrLen (FileName);

    // Does the filename already contain the '.EFI' extension?
    if (mUnicodeCollation->StriColl (mUnicodeCollation, FileName + FileNameLength - 4, L".efi") != 0) {
      // No, there was no extension. So add one and search again for the file
      // NewFileNameLength = FileNameLength + 1 + 4 = (Number of non-null character) + (file extension) + (a null character)
      NewFileNameLength = FileNameLength + 1 + 4;
      FileNameWithExtension = AllocatePool (NewFileNameLength * 2);
      StrCpyS (FileNameWithExtension, NewFileNameLength, FileName);
      StrCatS (FileNameWithExtension, NewFileNameLength, L".EFI");

      for (FvFileInfoLink = GetFirstNode (&Instance->FileInfoHead);
          !IsNull (&Instance->FileInfoHead, FvFileInfoLink);
           FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, FvFileInfoLink)) {
        FvFileInfo = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
        if (mUnicodeCollation->StriColl (mUnicodeCollation, &FvFileInfo->FileInfo.FileName[0], FileNameWithExtension) == 0) {
          Status = EFI_SUCCESS;
          break;
        }
      }
    }
  }

  if (!EFI_ERROR (Status)) {
    NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
    if (NewFile == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    NewFile->Signature = FVFS_FILE_SIGNATURE;
    NewFile->Instance  = Instance;
    NewFile->FvFileInfo = FvFileInfo;
    CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
    InitializeListHead (&NewFile->Link);
    InsertHeadList (&Instance->FileHead, &NewFile->Link);

    *NewHandle = &NewFile->FileProtocol;
    return EFI_SUCCESS;
  }

  return EFI_NOT_FOUND;
}