]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioFsDxe/FuseRead.c
UefiPayloadPkg: Fix build error
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseRead.c
CommitLineData
d98d7e30
LE
1/** @file\r
2 FUSE_READ / FUSE_READDIRPLUS wrapper for the Virtio Filesystem device.\r
3\r
4 Copyright (C) 2020, Red Hat, Inc.\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7**/\r
8\r
9#include "VirtioFsDxe.h"\r
10\r
11/**\r
12 Read a chunk from a regular file or a directory stream, by sending the\r
13 FUSE_READ / FUSE_READDIRPLUS request to the Virtio Filesystem device.\r
14\r
15 The function may only be called after VirtioFsFuseInitSession() returns\r
16 successfully and before VirtioFsUninit() is called.\r
17\r
18 @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_READ\r
19 or FUSE_READDIRPLUS request to. On output, the FUSE\r
20 request counter "VirtioFs->RequestId" will have been\r
21 incremented.\r
22\r
23 @param[in] NodeId The inode number of the regular file or directory\r
24 stream to read from.\r
25\r
26 @param[in] FuseHandle The open handle to the regular file or directory\r
27 stream to read from.\r
28\r
29 @param[in] IsDir TRUE if NodeId and FuseHandle refer to a directory,\r
30 FALSE if NodeId and FuseHandle refer to a regular\r
31 file.\r
32\r
33 @param[in] Offset If IsDir is FALSE: the absolute file position at\r
34 which to start reading.\r
35\r
36 If IsDir is TRUE: the directory stream cookie at\r
37 which to start or continue reading. The zero-valued\r
38 cookie identifies the start of the directory stream.\r
39 Further positions in the directory stream can be\r
40 passed in from the CookieForNextEntry field of\r
41 VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE.\r
42\r
43 @param[in,out] Size On input, the number of bytes to read. On successful\r
44 return, the number of bytes actually read, which may\r
45 be smaller than the value on input.\r
46\r
47 When reading a regular file (i.e., when IsDir is\r
48 FALSE), EOF can be detected by passing in a nonzero\r
49 Size, and finding a zero Size on output.\r
50\r
51 When reading a directory stream (i.e., when IsDir is\r
52 TRUE), Data consists of a sequence of variably-sized\r
53 records (directory entries). A read operation\r
54 returns the maximal sequence of records that fits in\r
55 Size, without having to truncate a record. In order\r
56 to guarantee progress, call\r
57\r
58 VirtioFsFuseStatFs (VirtioFs, NodeId,\r
59 &FilesysAttr)\r
60\r
61 first, to learn the maximum Namelen for the\r
62 directory stream. Then assign Size at least\r
63\r
64 VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE (\r
65 FilesysAttr.Namelen)\r
66\r
67 on input. (Remember that\r
68 VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE() may return\r
69 0 if its Namelen argument is invalid.) EOF can be\r
70 detected if Size is set on input like described\r
71 above, and Size is zero on output.\r
72\r
73 @param[out] Data Buffer to read the bytes from the regular file or\r
74 the directory stream into. The caller is responsible\r
75 for providing room for (at least) as many bytes in\r
76 Data as Size is on input.\r
77\r
78 @retval EFI_SUCCESS Read successful. The caller is responsible for checking\r
79 Size to learn the actual byte count transferred.\r
80\r
81 @return The "errno" value mapped to an EFI_STATUS code, if the\r
82 Virtio Filesystem device explicitly reported an error.\r
83\r
84 @return Error codes propagated from VirtioFsSgListsValidate(),\r
85 VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),\r
86 VirtioFsFuseCheckResponse().\r
87**/\r
88EFI_STATUS\r
89VirtioFsFuseReadFileOrDir (\r
ac0a286f
MK
90 IN OUT VIRTIO_FS *VirtioFs,\r
91 IN UINT64 NodeId,\r
92 IN UINT64 FuseHandle,\r
93 IN BOOLEAN IsDir,\r
94 IN UINT64 Offset,\r
95 IN OUT UINT32 *Size,\r
96 OUT VOID *Data\r
d98d7e30
LE
97 )\r
98{\r
ac0a286f
MK
99 VIRTIO_FS_FUSE_REQUEST CommonReq;\r
100 VIRTIO_FS_FUSE_READ_REQUEST ReadReq;\r
101 VIRTIO_FS_IO_VECTOR ReqIoVec[2];\r
102 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;\r
103 VIRTIO_FS_FUSE_RESPONSE CommonResp;\r
104 VIRTIO_FS_IO_VECTOR RespIoVec[2];\r
105 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;\r
106 EFI_STATUS Status;\r
107 UINTN TailBufferFill;\r
d98d7e30
LE
108\r
109 //\r
110 // Set up the scatter-gather lists.\r
111 //\r
112 ReqIoVec[0].Buffer = &CommonReq;\r
113 ReqIoVec[0].Size = sizeof CommonReq;\r
114 ReqIoVec[1].Buffer = &ReadReq;\r
115 ReqIoVec[1].Size = sizeof ReadReq;\r
116 ReqSgList.IoVec = ReqIoVec;\r
117 ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);\r
118\r
119 RespIoVec[0].Buffer = &CommonResp;\r
120 RespIoVec[0].Size = sizeof CommonResp;\r
121 RespIoVec[1].Buffer = Data;\r
122 RespIoVec[1].Size = *Size;\r
123 RespSgList.IoVec = RespIoVec;\r
124 RespSgList.NumVec = ARRAY_SIZE (RespIoVec);\r
125\r
126 //\r
127 // Validate the scatter-gather lists; calculate the total transfer sizes.\r
128 //\r
129 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);\r
130 if (EFI_ERROR (Status)) {\r
131 return Status;\r
132 }\r
133\r
134 //\r
135 // Populate the common request header.\r
136 //\r
137 Status = VirtioFsFuseNewRequest (\r
138 VirtioFs,\r
139 &CommonReq,\r
140 ReqSgList.TotalSize,\r
141 IsDir ? VirtioFsFuseOpReadDirPlus : VirtioFsFuseOpRead,\r
142 NodeId\r
143 );\r
144 if (EFI_ERROR (Status)) {\r
145 return Status;\r
146 }\r
147\r
148 //\r
149 // Populate the FUSE_READ- / FUSE_READDIRPLUS-specific fields.\r
150 //\r
151 ReadReq.FileHandle = FuseHandle;\r
152 ReadReq.Offset = Offset;\r
153 ReadReq.Size = *Size;\r
154 ReadReq.ReadFlags = 0;\r
155 ReadReq.LockOwner = 0;\r
156 ReadReq.Flags = 0;\r
157 ReadReq.Padding = 0;\r
158\r
159 //\r
160 // Submit the request.\r
161 //\r
162 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);\r
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
166\r
167 //\r
168 // Verify the response. Note that TailBufferFill is variable.\r
169 //\r
ac0a286f
MK
170 Status = VirtioFsFuseCheckResponse (\r
171 &RespSgList,\r
172 CommonReq.Unique,\r
173 &TailBufferFill\r
174 );\r
d98d7e30
LE
175 if (EFI_ERROR (Status)) {\r
176 if (Status == EFI_DEVICE_ERROR) {\r
ac0a286f
MK
177 DEBUG ((\r
178 DEBUG_ERROR,\r
179 "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "\r
180 "IsDir=%d Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n",\r
181 __FUNCTION__,\r
182 VirtioFs->Label,\r
183 NodeId,\r
184 FuseHandle,\r
185 IsDir,\r
186 Offset,\r
187 *Size,\r
188 Data,\r
189 CommonResp.Error\r
190 ));\r
d98d7e30
LE
191 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);\r
192 }\r
ac0a286f 193\r
d98d7e30
LE
194 return Status;\r
195 }\r
196\r
197 //\r
198 // Report the actual transfer size.\r
199 //\r
200 // Integer overflow in the (UINT32) cast below is not possible; the\r
201 // VIRTIO_FS_SCATTER_GATHER_LIST functions would have caught that.\r
202 //\r
203 *Size = (UINT32)TailBufferFill;\r
204 return EFI_SUCCESS;\r
205}\r