]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioFsDxe/FuseWrite.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseWrite.c
CommitLineData
6f7bc719
LE
1/** @file\r
2 FUSE_WRITE 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 Write a chunk to a regular file, by sending the FUSE_WRITE request to the\r
13 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_WRITE\r
19 request to. On output, the FUSE request counter\r
20 "VirtioFs->RequestId" will have been incremented.\r
21\r
22 @param[in] NodeId The inode number of the regular file to write to.\r
23\r
24 @param[in] FuseHandle The open handle to the regular file to write to.\r
25\r
26 @param[in] Offset The absolute file position at which to start\r
27 writing.\r
28\r
29 @param[in,out] Size On input, the number of bytes to write. On\r
30 successful return, the number of bytes actually\r
31 written, which may be smaller than the value on\r
32 input.\r
33\r
34 @param[in] Data The buffer to write to the regular file.\r
35\r
36 @retval EFI_SUCCESS Write successful. The caller is responsible for\r
37 checking Size to learn the actual byte count\r
38 transferred.\r
39\r
40 @retval EFI_BAD_BUFFER_SIZE On input, Size is larger than\r
41 "VirtioFs->MaxWrite".\r
42\r
43 @return The "errno" value mapped to an EFI_STATUS code,\r
44 if the Virtio Filesystem device explicitly\r
45 reported an error.\r
46\r
47 @return Error codes propagated from\r
48 VirtioFsSgListsValidate(),\r
49 VirtioFsFuseNewRequest(),\r
50 VirtioFsSgListsSubmit(),\r
51 VirtioFsFuseCheckResponse().\r
52**/\r
53EFI_STATUS\r
54VirtioFsFuseWrite (\r
ac0a286f
MK
55 IN OUT VIRTIO_FS *VirtioFs,\r
56 IN UINT64 NodeId,\r
57 IN UINT64 FuseHandle,\r
58 IN UINT64 Offset,\r
59 IN OUT UINT32 *Size,\r
60 IN VOID *Data\r
6f7bc719
LE
61 )\r
62{\r
ac0a286f
MK
63 VIRTIO_FS_FUSE_REQUEST CommonReq;\r
64 VIRTIO_FS_FUSE_WRITE_REQUEST WriteReq;\r
65 VIRTIO_FS_IO_VECTOR ReqIoVec[3];\r
66 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;\r
67 VIRTIO_FS_FUSE_RESPONSE CommonResp;\r
68 VIRTIO_FS_FUSE_WRITE_RESPONSE WriteResp;\r
69 VIRTIO_FS_IO_VECTOR RespIoVec[2];\r
70 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;\r
71 EFI_STATUS Status;\r
6f7bc719
LE
72\r
73 //\r
74 // Honor the write buffer size limit of the Virtio Filesystem device.\r
75 //\r
76 if (*Size > VirtioFs->MaxWrite) {\r
77 return EFI_BAD_BUFFER_SIZE;\r
78 }\r
79\r
80 //\r
81 // Set up the scatter-gather lists.\r
82 //\r
83 ReqIoVec[0].Buffer = &CommonReq;\r
84 ReqIoVec[0].Size = sizeof CommonReq;\r
85 ReqIoVec[1].Buffer = &WriteReq;\r
86 ReqIoVec[1].Size = sizeof WriteReq;\r
87 ReqIoVec[2].Buffer = Data;\r
88 ReqIoVec[2].Size = *Size;\r
89 ReqSgList.IoVec = ReqIoVec;\r
90 ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);\r
91\r
92 RespIoVec[0].Buffer = &CommonResp;\r
93 RespIoVec[0].Size = sizeof CommonResp;\r
94 RespIoVec[1].Buffer = &WriteResp;\r
95 RespIoVec[1].Size = sizeof WriteResp;\r
96 RespSgList.IoVec = RespIoVec;\r
97 RespSgList.NumVec = ARRAY_SIZE (RespIoVec);\r
98\r
99 //\r
100 // Validate the scatter-gather lists; calculate the total transfer sizes.\r
101 //\r
102 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);\r
103 if (EFI_ERROR (Status)) {\r
104 return Status;\r
105 }\r
106\r
107 //\r
108 // Populate the common request header.\r
109 //\r
ac0a286f
MK
110 Status = VirtioFsFuseNewRequest (\r
111 VirtioFs,\r
112 &CommonReq,\r
113 ReqSgList.TotalSize,\r
114 VirtioFsFuseOpWrite,\r
115 NodeId\r
116 );\r
6f7bc719
LE
117 if (EFI_ERROR (Status)) {\r
118 return Status;\r
119 }\r
120\r
121 //\r
122 // Populate the FUSE_WRITE-specific fields.\r
123 //\r
124 WriteReq.FileHandle = FuseHandle;\r
125 WriteReq.Offset = Offset;\r
126 WriteReq.Size = *Size;\r
127 WriteReq.WriteFlags = 0;\r
128 WriteReq.LockOwner = 0;\r
129 WriteReq.Flags = 0;\r
130 WriteReq.Padding = 0;\r
131\r
132 //\r
133 // Submit the request.\r
134 //\r
135 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139\r
140 //\r
141 // Verify the response (all response buffers are fixed size).\r
142 //\r
143 Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);\r
144 if (EFI_ERROR (Status)) {\r
145 if (Status == EFI_DEVICE_ERROR) {\r
ac0a286f
MK
146 DEBUG ((\r
147 DEBUG_ERROR,\r
148 "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "\r
149 "Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n",\r
150 __FUNCTION__,\r
151 VirtioFs->Label,\r
152 NodeId,\r
153 FuseHandle,\r
154 Offset,\r
155 *Size,\r
156 Data,\r
157 CommonResp.Error\r
158 ));\r
6f7bc719
LE
159 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);\r
160 }\r
ac0a286f 161\r
6f7bc719
LE
162 return Status;\r
163 }\r
164\r
165 //\r
166 // Report the actual transfer size.\r
167 //\r
168 *Size = WriteResp.Size;\r
169 return EFI_SUCCESS;\r
170}\r