/** Worker function that extends the size of an open file. The extension is filled with zeros. @param[in] Fcb Internal description of the opened file @param[in] Size The number of bytes, the file has to be extended. @retval EFI_SUCCESS The file was extended. @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. **/ STATIC EFI_STATUS ExtendFile ( IN SEMIHOST_FCB *Fcb, IN UINTN Size ) { RETURN_STATUS Return; UINTN Remaining; CHAR8 WriteBuffer[128]; UINTN WriteNb; UINTN WriteSize; Return = SemihostFileSeek (Fcb->SemihostHandle, Fcb->Info.FileSize); if (RETURN_ERROR (Return)) { return EFI_DEVICE_ERROR; } Remaining = Size; SetMem (WriteBuffer, 0, sizeof(WriteBuffer)); while (Remaining > 0) { WriteNb = MIN (Remaining, sizeof(WriteBuffer)); WriteSize = WriteNb; Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, WriteBuffer); if (RETURN_ERROR (Return)) { return EFI_DEVICE_ERROR; } Remaining -= WriteNb; } return EFI_SUCCESS; }
/** 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; }
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; }
/** 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); }