]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioFsDxe/FuseOpenOrCreate.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseOpenOrCreate.c
CommitLineData
a70860f4
LE
1/** @file\r
2 FUSE_CREATE 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 <Library/BaseLib.h> // AsciiStrSize()\r
10\r
11#include "VirtioFsDxe.h"\r
12\r
13/**\r
14 Send a FUSE_CREATE request to the Virtio Filesystem device, for opening a\r
15 regular file with (O_RDWR | O_CREAT) semantics.\r
16\r
17 The function may only be called after VirtioFsFuseInitSession() returns\r
18 successfully and before VirtioFsUninit() is called.\r
19\r
20 @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_CREATE\r
21 request to. On output, the FUSE request counter\r
22 "VirtioFs->RequestId" will have been incremented.\r
23\r
24 @param[in] ParentNodeId The inode number of the direct parent directory of\r
25 the regular file to open or create.\r
26\r
27 @param[in] Name The single-component filename of the regular file to\r
28 open or create, under the parent directory\r
29 identified by ParentNodeId.\r
30\r
31 @param[out] NodeId The inode number of the regular file, returned by\r
32 the Virtio Filesystem device.\r
33\r
34 @param[out] FuseHandle The open file handle returned by the Virtio\r
35 Filesystem device.\r
36\r
37 @retval EFI_SUCCESS The regular file has been opened, and (if necessary)\r
38 created.\r
39\r
40 @return The "errno" value mapped to an EFI_STATUS code, if the\r
41 Virtio Filesystem device explicitly reported an error.\r
42\r
43 @return Error codes propagated from VirtioFsSgListsValidate(),\r
44 VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),\r
45 VirtioFsFuseCheckResponse().\r
46**/\r
47EFI_STATUS\r
48VirtioFsFuseOpenOrCreate (\r
ac0a286f
MK
49 IN OUT VIRTIO_FS *VirtioFs,\r
50 IN UINT64 ParentNodeId,\r
51 IN CHAR8 *Name,\r
52 OUT UINT64 *NodeId,\r
53 OUT UINT64 *FuseHandle\r
a70860f4
LE
54 )\r
55{\r
ac0a286f
MK
56 VIRTIO_FS_FUSE_REQUEST CommonReq;\r
57 VIRTIO_FS_FUSE_CREATE_REQUEST CreateReq;\r
58 VIRTIO_FS_IO_VECTOR ReqIoVec[3];\r
59 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;\r
60 VIRTIO_FS_FUSE_RESPONSE CommonResp;\r
61 VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;\r
62 VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;\r
63 VIRTIO_FS_FUSE_OPEN_RESPONSE OpenResp;\r
64 VIRTIO_FS_IO_VECTOR RespIoVec[4];\r
65 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;\r
66 EFI_STATUS Status;\r
a70860f4
LE
67\r
68 //\r
69 // Set up the scatter-gather lists.\r
70 //\r
71 ReqIoVec[0].Buffer = &CommonReq;\r
72 ReqIoVec[0].Size = sizeof CommonReq;\r
73 ReqIoVec[1].Buffer = &CreateReq;\r
74 ReqIoVec[1].Size = sizeof CreateReq;\r
75 ReqIoVec[2].Buffer = Name;\r
76 ReqIoVec[2].Size = AsciiStrSize (Name);\r
77 ReqSgList.IoVec = ReqIoVec;\r
78 ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);\r
79\r
80 RespIoVec[0].Buffer = &CommonResp;\r
81 RespIoVec[0].Size = sizeof CommonResp;\r
82 RespIoVec[1].Buffer = &NodeResp;\r
83 RespIoVec[1].Size = sizeof NodeResp;\r
84 RespIoVec[2].Buffer = &AttrResp;\r
85 RespIoVec[2].Size = sizeof AttrResp;\r
86 RespIoVec[3].Buffer = &OpenResp;\r
87 RespIoVec[3].Size = sizeof OpenResp;\r
88 RespSgList.IoVec = RespIoVec;\r
89 RespSgList.NumVec = ARRAY_SIZE (RespIoVec);\r
90\r
91 //\r
92 // Validate the scatter-gather lists; calculate the total transfer sizes.\r
93 //\r
94 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);\r
95 if (EFI_ERROR (Status)) {\r
96 return Status;\r
97 }\r
98\r
99 //\r
100 // Populate the common request header.\r
101 //\r
ac0a286f
MK
102 Status = VirtioFsFuseNewRequest (\r
103 VirtioFs,\r
104 &CommonReq,\r
105 ReqSgList.TotalSize,\r
106 VirtioFsFuseOpCreate,\r
107 ParentNodeId\r
108 );\r
a70860f4
LE
109 if (EFI_ERROR (Status)) {\r
110 return Status;\r
111 }\r
112\r
113 //\r
114 // Populate the FUSE_CREATE-specific fields.\r
115 //\r
116 // VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR is why this request can never open a\r
117 // directory (EISDIR). And VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR is consistent with\r
118 // the only OpenMode of EFI_FILE_PROTOCOL.Open() that enables filesystem\r
119 // object creation -- that is, Create/Read/Write.\r
120 //\r
ac0a286f
MK
121 CreateReq.Flags = VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR;\r
122 CreateReq.Mode = (VIRTIO_FS_FUSE_MODE_PERM_RUSR |\r
123 VIRTIO_FS_FUSE_MODE_PERM_WUSR |\r
124 VIRTIO_FS_FUSE_MODE_PERM_RGRP |\r
125 VIRTIO_FS_FUSE_MODE_PERM_WGRP |\r
126 VIRTIO_FS_FUSE_MODE_PERM_ROTH |\r
127 VIRTIO_FS_FUSE_MODE_PERM_WOTH);\r
a70860f4
LE
128 CreateReq.Umask = 0;\r
129 CreateReq.Padding = 0;\r
130\r
131 //\r
132 // Submit the request.\r
133 //\r
134 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);\r
135 if (EFI_ERROR (Status)) {\r
136 return Status;\r
137 }\r
138\r
139 //\r
140 // Verify the response (all response buffers are fixed size).\r
141 //\r
142 Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);\r
143 if (EFI_ERROR (Status)) {\r
144 if (Status == EFI_DEVICE_ERROR) {\r
ac0a286f
MK
145 DEBUG ((\r
146 DEBUG_ERROR,\r
147 "%a: Label=\"%s\" ParentNodeId=%Lu Name=\"%a\" "\r
148 "Errno=%d\n",\r
149 __FUNCTION__,\r
150 VirtioFs->Label,\r
151 ParentNodeId,\r
152 Name,\r
153 CommonResp.Error\r
154 ));\r
a70860f4
LE
155 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);\r
156 }\r
ac0a286f 157\r
a70860f4
LE
158 return Status;\r
159 }\r
160\r
161 //\r
162 // Output the NodeId of the (possibly new) regular file. Also output the open\r
163 // file handle.\r
164 //\r
165 *NodeId = NodeResp.NodeId;\r
166 *FuseHandle = OpenResp.FileHandle;\r
167 return EFI_SUCCESS;\r
168}\r