\r
#include "VirtioFsDxe.h"\r
\r
+/**\r
+ Read from a regular file.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ReadRegularFile (\r
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ VIRTIO_FS *VirtioFs;\r
+ EFI_STATUS Status;\r
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
+ UINTN Transferred;\r
+ UINTN Left;\r
+\r
+ VirtioFs = VirtioFsFile->OwnerFs;\r
+ //\r
+ // The UEFI spec forbids reads that start beyond the end of the file.\r
+ //\r
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);\r
+ if (EFI_ERROR (Status) || VirtioFsFile->FilePosition > FuseAttr.Size) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Transferred = 0;\r
+ Left = *BufferSize;\r
+ while (Left > 0) {\r
+ UINT32 ReadSize;\r
+\r
+ //\r
+ // FUSE_READ cannot express a >=4GB buffer size.\r
+ //\r
+ ReadSize = (UINT32)MIN ((UINTN)MAX_UINT32, Left);\r
+ Status = VirtioFsFuseReadFileOrDir (\r
+ VirtioFs,\r
+ VirtioFsFile->NodeId,\r
+ VirtioFsFile->FuseHandle,\r
+ FALSE, // IsDir\r
+ VirtioFsFile->FilePosition + Transferred,\r
+ &ReadSize,\r
+ (UINT8 *)Buffer + Transferred\r
+ );\r
+ if (EFI_ERROR (Status) || ReadSize == 0) {\r
+ break;\r
+ }\r
+ Transferred += ReadSize;\r
+ Left -= ReadSize;\r
+ }\r
+\r
+ *BufferSize = Transferred;\r
+ VirtioFsFile->FilePosition += Transferred;\r
+ //\r
+ // If we managed to read some data, return success. If zero bytes were\r
+ // transferred due to zero-sized buffer on input or due to EOF on first read,\r
+ // return SUCCESS. Otherwise, return the error due to which zero bytes were\r
+ // transferred.\r
+ //\r
+ return (Transferred > 0) ? EFI_SUCCESS : Status;\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
VirtioFsSimpleFileRead (\r
OUT VOID *Buffer\r
)\r
{\r
- return EFI_NO_MEDIA;\r
+ VIRTIO_FS_FILE *VirtioFsFile;\r
+ EFI_STATUS Status;\r
+\r
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r
+\r
+ if (VirtioFsFile->IsDirectory) {\r
+ Status = EFI_NO_MEDIA;\r
+ } else {\r
+ Status = ReadRegularFile (VirtioFsFile, BufferSize, Buffer);\r
+ }\r
+ return Status;\r
}\r