/** 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; }
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; }
/** Worker function that truncate a file specified by its name to a given size. @param[in] FileName The Null-terminated string of the name of the file to be opened. @param[in] Size The target size for the file. @retval EFI_SUCCESS The file was truncated. @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. **/ STATIC EFI_STATUS TruncateFile ( IN CHAR8 *FileName, IN UINTN Size ) { EFI_STATUS Status; RETURN_STATUS Return; UINTN FileHandle; UINT8 *Buffer; UINTN Remaining; UINTN Read; UINTN ToRead; Status = EFI_DEVICE_ERROR; FileHandle = 0; Buffer = NULL; Return = SemihostFileOpen ( FileName, SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY, &FileHandle ); if (RETURN_ERROR (Return)) { goto Error; } Buffer = AllocatePool (Size); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } Read = 0; Remaining = Size; while (Remaining > 0) { ToRead = Remaining; Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read); if (RETURN_ERROR (Return)) { goto Error; } Remaining -= ToRead; Read += ToRead; } Return = SemihostFileClose (FileHandle); FileHandle = 0; if (RETURN_ERROR (Return)) { goto Error; } Return = SemihostFileOpen ( FileName, SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY, &FileHandle ); if (RETURN_ERROR (Return)) { goto Error; } if (Size > 0) { Return = SemihostFileWrite (FileHandle, &Size, Buffer); if (RETURN_ERROR (Return)) { goto Error; } } Status = EFI_SUCCESS; Error: if (FileHandle != 0) { SemihostFileClose (FileHandle); } if (Buffer != NULL) { FreePool (Buffer); } return (Status); }