Esempio n. 1
0
/**
  Close a specified file handle.

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

  @retval  EFI_SUCCESS            The file was closed.
  @retval  EFI_INVALID_PARAMETER  The parameter "This" is NULL.

**/
EFI_STATUS
FileClose (
  IN EFI_FILE  *This
  )
{
  SEMIHOST_FCB   *Fcb;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS(This);

  if (!Fcb->IsRoot) {
    SemihostFileClose (Fcb->SemihostHandle);
    //
    // The file size might have been reduced from its actual
    // size on the host file system with FileSetInfo(). In
    // that case, the file has to be truncated.
    //
    if (Fcb->Info.FileSize < Fcb->Info.PhysicalSize) {
      TruncateFile (Fcb->FileName, Fcb->Info.FileSize);
    }
    FreePool (Fcb->FileName);
  }

  FreeFCB (Fcb);

  return EFI_SUCCESS;
}
Esempio n. 2
0
EFI_STATUS
FileSetPosition (
  IN EFI_FILE *File,
  IN UINT64   Position
  )
{
  SEMIHOST_FCB *Fcb    = NULL;
  UINTN        Length;
  EFI_STATUS   Status;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  if (!Fcb->IsRoot) {
    Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
    if (!EFI_ERROR(Status) && (Length < Position)) {
      Position = Length;
    }

    Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);
    if (!EFI_ERROR(Status)) {
      Fcb->Position = Position;
    }
  } else {
    Fcb->Position = Position;
    Status = EFI_SUCCESS;
  }

  return Status;
}
Esempio n. 3
0
EFI_STATUS
FileDelete (
  IN EFI_FILE *File
  )
{
  SEMIHOST_FCB *Fcb = NULL;
  EFI_STATUS   Status;
  CHAR8        *FileName;
  UINTN        NameSize;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  if (!Fcb->IsRoot) {
    // Get the filename from the Fcb
    NameSize = AsciiStrLen (Fcb->FileName);
    FileName = AllocatePool (NameSize + 1);

    AsciiStrCpy (FileName, Fcb->FileName);

    // Close the file if it's open.  Disregard return status,
    // since it might give an error if the file isn't open.
    File->Close (File);

    // Call the semihost interface to delete the file.
    Status = SemihostFileRemove (FileName);
  } else {
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}
Esempio n. 4
0
/**
  Write data to an open file.

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

  @retval  EFI_SUCCESS            The data was written.
  @retval  EFI_ACCESS_DENIED      Attempt to write into a read only file or
                                  in a file opened in read only mode.
  @retval  EFI_DEVICE_ERROR       The last issued semi-hosting operation failed.
  @retval  EFI_INVALID_PARAMETER  At least one of the three input pointers is NULL.

**/
EFI_STATUS
FileWrite (
  IN     EFI_FILE *This,
  IN OUT UINTN    *BufferSize,
  IN     VOID     *Buffer
  )
{
  SEMIHOST_FCB   *Fcb;
  EFI_STATUS     Status;
  UINTN          WriteSize;
  RETURN_STATUS  Return;
  UINTN          Length;

  if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS (This);

  // We cannot write a read-only file
  if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)
      || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {
    return EFI_ACCESS_DENIED;
  }

  //
  // If the position has been set past the end of the file, first grow the
  // file from its current size "Fcb->Info.FileSize" to "Fcb->Position"
  // size, filling the gap with zeros.
  //
  if (Fcb->Position > Fcb->Info.FileSize) {
    Status = ExtendFile (Fcb, Fcb->Position - Fcb->Info.FileSize);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Fcb->Info.FileSize = Fcb->Position;
  }

  WriteSize = *BufferSize;
  Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);
  if (RETURN_ERROR (Return)) {
    return EFI_DEVICE_ERROR;
  }

  Fcb->Position += *BufferSize;
  if (Fcb->Position > Fcb->Info.FileSize) {
    Fcb->Info.FileSize = Fcb->Position;
  }

  Return = SemihostFileLength (Fcb->SemihostHandle, &Length);
  if (RETURN_ERROR (Return)) {
    return EFI_DEVICE_ERROR;
  }
  Fcb->Info.PhysicalSize = Length;

  return EFI_SUCCESS;
}
Esempio n. 5
0
/**
  Set information about a file or a file system.

  @param[in]  This             A pointer to the EFI_FILE_PROTOCOL instance that
                               is the file handle the information is for.
  @param[in]  InformationType  The type identifier for the information being set :
                               EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
                               EFI_FILE_SYSTEM_VOLUME_LABEL_ID
  @param[in]  BufferSize       The size, in bytes, of Buffer.
  @param[in]  Buffer           A pointer to the data buffer to write. The type of the
                               data inside the buffer is indicated by InformationType.

  @retval  EFI_SUCCESS            The information was set.
  @retval  EFI_UNSUPPORTED        The InformationType is not known.
  @retval  EFI_DEVICE_ERROR       The last issued semi-hosting operation failed.
  @retval  EFI_ACCESS_DENIED      An attempt is being made to change the
                                  EFI_FILE_DIRECTORY Attribute.
  @retval  EFI_ACCESS_DENIED      InformationType is EFI_FILE_INFO_ID and
                                  the file is a read-only file or has been
                                  opened in read-only mode and an attempt is
                                  being made to modify a field other than
                                  Attribute.
  @retval  EFI_ACCESS_DENIED      An attempt is made to change the name of a file
                                  to a file that is already present.
  @retval  EFI_WRITE_PROTECTED    An attempt is being made to modify a
                                  read-only attribute.
  @retval  EFI_BAD_BUFFER_SIZE    The size of the buffer is lower than that indicated by
                                  the data inside the buffer.
  @retval  EFI_OUT_OF_RESOURCES   An allocation needed to process the request failed.
  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.

**/
EFI_STATUS
FileSetInfo (
  IN EFI_FILE  *This,
  IN EFI_GUID  *InformationType,
  IN UINTN     BufferSize,
  IN VOID      *Buffer
  )
{
  SEMIHOST_FCB          *Fcb;
  EFI_FILE_INFO         *Info;
  EFI_FILE_SYSTEM_INFO  *SystemInfo;
  CHAR16                *VolumeLabel;

  if ((This == NULL) || (InformationType == NULL) || (Buffer == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS (This);

  if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
    Info = Buffer;
    if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {
      return EFI_INVALID_PARAMETER;
    }
    if (BufferSize < Info->Size) {
      return EFI_BAD_BUFFER_SIZE;
    }
    return SetFileInfo (Fcb, Info);
  } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
    SystemInfo = Buffer;
    if (SystemInfo->Size <
        (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {
      return EFI_INVALID_PARAMETER;
    }
    if (BufferSize < SystemInfo->Size) {
      return EFI_BAD_BUFFER_SIZE;
    }
    Buffer = SystemInfo->VolumeLabel;

    if (StrSize (Buffer) > 0) {
      VolumeLabel = AllocateCopyPool (StrSize (Buffer), Buffer);
      if (VolumeLabel != NULL) {
        FreePool (mSemihostFsLabel);
        mSemihostFsLabel = VolumeLabel;
        return EFI_SUCCESS;
      } else {
        return EFI_OUT_OF_RESOURCES;
      }
    } else {
      return EFI_INVALID_PARAMETER;
    }
  } else if (!CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
    return EFI_UNSUPPORTED;
  } else {
    return EFI_UNSUPPORTED;
  }
}
Esempio n. 6
0
EFI_STATUS
FileGetPosition (
  IN  EFI_FILE    *File,
  OUT UINT64      *Position
  )
{
  SEMIHOST_FCB *Fcb = NULL;
    
  if (Position == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  *Position = Fcb->Position;

  return EFI_SUCCESS;
}
Esempio n. 7
0
/**
  Return a file's current position.

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

  @retval  EFI_SUCCESS            The position was returned.
  @retval  EFI_INVALID_PARAMETER  The parameter "This" or "Position" is NULL.

**/
EFI_STATUS
FileGetPosition (
  IN  EFI_FILE    *This,
  OUT UINT64      *Position
  )
{
  SEMIHOST_FCB *Fcb;

  if ((This == NULL) || (Position == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS(This);

  *Position = Fcb->Position;

  return EFI_SUCCESS;
}
Esempio n. 8
0
/**
  Return information about a file or a file system.

  @param[in]      This             A pointer to the EFI_FILE_PROTOCOL instance that
                                   is the file handle the requested information is for.
  @param[in]      InformationType  The type identifier for the information being requested :
                                   EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
                                   EFI_FILE_SYSTEM_VOLUME_LABEL_ID
  @param[in out]  BufferSize       The size, in bytes, of Buffer.
  @param[out]     Buffer           A pointer to the data buffer to return. The type of the
                                   data inside the buffer is indicated by InformationType.

  @retval  EFI_SUCCESS           The information was returned.
  @retval  EFI_UNSUPPORTED       The InformationType is not known.
  @retval  EFI_BUFFER_TOO_SMALL  The BufferSize is too small to return the information.
                                 BufferSize has been updated with the size needed to
                                 complete the request.
  @retval  EFI_INVALID_PARAMETER  The parameter "This" or "InformationType" or "BufferSize"
                                  is NULL or "Buffer" is NULL and "*Buffersize" is greater
                                  than 0.

**/
EFI_STATUS
FileGetInfo (
  IN     EFI_FILE  *This,
  IN     EFI_GUID  *InformationType,
  IN OUT UINTN     *BufferSize,
  OUT    VOID      *Buffer
  )
{
  SEMIHOST_FCB *Fcb;
  EFI_STATUS   Status;
  UINTN        ResultSize;

  if ((This == NULL)                         ||
      (InformationType == NULL)              ||
      (BufferSize == NULL)                   ||
      ((Buffer == NULL) && (*BufferSize > 0))  ) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS(This);

  if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
    Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);
  } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
    Status = GetFileInfo (Fcb, BufferSize, Buffer);
  } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
    ResultSize = StrSize (mSemihostFsLabel);

    if (*BufferSize >= ResultSize) {
      StrCpy (Buffer, mSemihostFsLabel);
      Status = EFI_SUCCESS;
    } else {
      Status = EFI_BUFFER_TOO_SMALL;
    }

    *BufferSize = ResultSize;
  } else {
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}
Esempio n. 9
0
EFI_STATUS
FileFlush (
  IN EFI_FILE *File
  )
{
  SEMIHOST_FCB *Fcb;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  if (Fcb->IsRoot) {
    return EFI_SUCCESS;
  } else {
    if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)
        || !(Fcb->OpenMode & EFI_FILE_MODE_WRITE)) {
      return EFI_ACCESS_DENIED;
    } else {
      return EFI_SUCCESS;
    }
  }
}
Esempio n. 10
0
EFI_STATUS
FileGetInfo (
  IN     EFI_FILE *File,
  IN     EFI_GUID *InformationType,
  IN OUT UINTN    *BufferSize,
  OUT    VOID     *Buffer
  )
{
  SEMIHOST_FCB *Fcb = NULL;
  EFI_STATUS   Status = EFI_UNSUPPORTED;
  
  Fcb = SEMIHOST_FCB_FROM_THIS(File);
  
  if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) {
    Status = GetFilesystemInfo(Fcb, BufferSize, Buffer);  
  } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) {
    Status = GetFileInfo(Fcb, BufferSize, Buffer);  
  }
    
  return Status;
}
Esempio n. 11
0
/**
  Set a file's current position.

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

  @retval  EFI_SUCCESS       The position was set.
  @retval  EFI_DEVICE_ERROR  The semi-hosting positionning operation failed.
  @retval  EFI_UNSUPPORTED   The seek request for nonzero is not valid on open
                             directories.
  @retval  EFI_INVALID_PARAMETER  The parameter "This" is NULL.

**/
EFI_STATUS
FileSetPosition (
  IN EFI_FILE *This,
  IN UINT64   Position
  )
{
  SEMIHOST_FCB   *Fcb;
  RETURN_STATUS  Return;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS (This);

  if (Fcb->IsRoot) {
    if (Position != 0) {
      return EFI_UNSUPPORTED;
    }
  }
  else {
    //
    // UEFI Spec section 12.5:
    // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
    // be set to the end of the file."
    //
    if (Position == 0xFFFFFFFFFFFFFFFF) {
      Position = Fcb->Info.FileSize;
    }
    Return = SemihostFileSeek (Fcb->SemihostHandle, MIN (Position, Fcb->Info.FileSize));
    if (RETURN_ERROR (Return)) {
      return EFI_DEVICE_ERROR;
    }
  }

  Fcb->Position = Position;

  return EFI_SUCCESS;
}
Esempio n. 12
0
/**
  Read data from an open file.

  @param[in]      This        A pointer to the EFI_FILE_PROTOCOL instance that
                              is the file handle to read data from.
  @param[in out]  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[out]     Buffer      The buffer into which the data is read.

  @retval  EFI_SUCCESS            The data was read.
  @retval  EFI_DEVICE_ERROR       On entry, the current file position is
                                  beyond the end of the file, or the semi-hosting
                                  interface reported an error while performing the
                                  read operation.
  @retval  EFI_INVALID_PARAMETER  At least one of the three input pointers is NULL.

**/
EFI_STATUS
FileRead (
  IN     EFI_FILE  *This,
  IN OUT UINTN     *BufferSize,
  OUT    VOID      *Buffer
  )
{
  SEMIHOST_FCB   *Fcb;
  EFI_STATUS     Status;
  RETURN_STATUS  Return;

  if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS (This);

  if (Fcb->IsRoot) {
    // The semi-hosting interface does not allow to list files on the host machine.
    Status = EFI_UNSUPPORTED;
  } else {
    Status = EFI_SUCCESS;
    if (Fcb->Position >= Fcb->Info.FileSize) {
      *BufferSize = 0;
      if (Fcb->Position > Fcb->Info.FileSize) {
        Status = EFI_DEVICE_ERROR;
      }
    } else {
      Return = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);
      if (RETURN_ERROR (Return)) {
        Status = EFI_DEVICE_ERROR;
      } else {
        Fcb->Position += *BufferSize;
      }
    }
  }

  return Status;
}
Esempio n. 13
0
EFI_STATUS
FileWrite (
  IN     EFI_FILE *File,
  IN OUT UINTN    *BufferSize,
  IN     VOID     *Buffer
  )
{
  SEMIHOST_FCB *Fcb    = NULL;
  EFI_STATUS   Status;
  UINTN        WriteSize = *BufferSize;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);

  if (!EFI_ERROR(Status)) {
    // Semihost write return the number of bytes *NOT* written.
    *BufferSize -= WriteSize;
    Fcb->Position += *BufferSize;
  }
  
  return Status;
}
Esempio n. 14
0
EFI_STATUS
FileClose (
  IN EFI_FILE *File
  )
{
  SEMIHOST_FCB *Fcb    = NULL;
  EFI_STATUS   Status  = EFI_SUCCESS;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  if (Fcb->IsRoot == TRUE) {
    FreeFCB (Fcb);
    Status = EFI_SUCCESS;
  } else {
    Status = SemihostFileClose (Fcb->SemihostHandle);
    if (!EFI_ERROR(Status)) {
      FreePool (Fcb->FileName);
      FreeFCB (Fcb);
    }
  }
  
  return Status;
}
Esempio n. 15
0
/**
  Close and delete a file.

  @param[in]  This  A pointer to the EFI_FILE_PROTOCOL instance that is the file
                    handle to delete.

  @retval  EFI_SUCCESS              The file was closed and deleted.
  @retval  EFI_WARN_DELETE_FAILURE  The handle was closed, but the file was not deleted.
  @retval  EFI_INVALID_PARAMETER    The parameter "This" is NULL.

**/
EFI_STATUS
FileDelete (
  IN EFI_FILE *This
  )
{
  SEMIHOST_FCB   *Fcb;
  RETURN_STATUS  Return;
  CHAR8          *FileName;
  UINTN          NameSize;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Fcb = SEMIHOST_FCB_FROM_THIS (This);

  if (!Fcb->IsRoot) {
    // Get the filename from the Fcb
    NameSize = AsciiStrLen (Fcb->FileName);
    FileName = AllocatePool (NameSize + 1);

    AsciiStrCpy (FileName, Fcb->FileName);

    // Close the file if it's open.  Disregard return status,
    // since it might give an error if the file isn't open.
    This->Close (This);

    // Call the semihost interface to delete the file.
    Return = SemihostFileRemove (FileName);
    if (RETURN_ERROR (Return)) {
      return EFI_WARN_DELETE_FAILURE;
    }
    return EFI_SUCCESS;
  } else {
    return EFI_WARN_DELETE_FAILURE;
  }
}
Esempio n. 16
0
EFI_STATUS
FileRead (
  IN     EFI_FILE *File,
  IN OUT UINTN    *BufferSize,
  OUT    VOID     *Buffer
  )
{
  SEMIHOST_FCB *Fcb = NULL;
  EFI_STATUS   Status;

  Fcb = SEMIHOST_FCB_FROM_THIS(File);

  if (Fcb->IsRoot == TRUE) {
    // By design, the Semihosting feature does not allow to list files on the host machine.
    Status = EFI_UNSUPPORTED;
  } else {
    Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);
    if (!EFI_ERROR (Status)) {
      Fcb->Position += *BufferSize;
    }
  }

  return Status;
}