/** @file EFI_FILE_PROTOCOL.Write() member function for the Virtio Filesystem driver. Copyright (C) 2020, Red Hat, Inc. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "VirtioFsDxe.h" EFI_STATUS EFIAPI VirtioFsSimpleFileWrite ( IN EFI_FILE_PROTOCOL *This, IN OUT UINTN *BufferSize, IN VOID *Buffer ) { VIRTIO_FS_FILE *VirtioFsFile; VIRTIO_FS *VirtioFs; EFI_STATUS Status; UINTN Transferred; UINTN Left; VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This); VirtioFs = VirtioFsFile->OwnerFs; if (VirtioFsFile->IsDirectory) { return EFI_UNSUPPORTED; } if (!VirtioFsFile->IsOpenForWriting) { return EFI_ACCESS_DENIED; } Status = EFI_SUCCESS; Transferred = 0; Left = *BufferSize; while (Left > 0) { UINT32 WriteSize; // // Honor the write buffer size limit. // WriteSize = (UINT32)MIN ((UINTN)VirtioFs->MaxWrite, Left); Status = VirtioFsFuseWrite ( VirtioFs, VirtioFsFile->NodeId, VirtioFsFile->FuseHandle, VirtioFsFile->FilePosition + Transferred, &WriteSize, (UINT8 *)Buffer + Transferred ); if (!EFI_ERROR (Status) && WriteSize == 0) { // // Progress should have been made. // Status = EFI_DEVICE_ERROR; } if (EFI_ERROR (Status)) { break; } Transferred += WriteSize; Left -= WriteSize; } *BufferSize = Transferred; VirtioFsFile->FilePosition += Transferred; // // According to the UEFI spec, // // - 'Partial writes only occur when there has been a data error during the // write attempt (such as "file space full")', and // // - (as an example) EFI_VOLUME_FULL is returned when 'The volume is full'. // // These together imply that after a partial write, we have to return an // error. In other words, (Transferred > 0) is inconsequential for the return // value. // return Status; }