2 FUSE_INIT wrapper for the Virtio Filesystem device.
4 Copyright (C) 2020, Red Hat, Inc.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "VirtioFsDxe.h"
12 Send a FUSE_INIT request to the Virtio Filesystem device, for starting the
15 From virtio-v1.1-cs01-87fa6b5d8155, 5.11.5 Device Initialization: "On
16 initialization the driver first discovers the device's virtqueues. The FUSE
17 session is started by sending a FUSE_INIT request as defined by the FUSE
18 protocol on one request virtqueue."
20 The function may only be called after VirtioFsInit() returns successfully and
21 before VirtioFsUninit() is called.
23 @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_INIT
24 request to. The FUSE request counter
25 "VirtioFs->RequestId" is set to 1 on output. The
26 maximum write buffer size exposed in the FUSE_INIT
27 response is saved in "VirtioFs->MaxWrite", on
30 @retval EFI_SUCCESS The FUSE session has been started.
32 @retval EFI_UNSUPPORTED FUSE interface version or feature negotiation
35 @return The "errno" value mapped to an EFI_STATUS code, if
36 the Virtio Filesystem device explicitly reported an
39 @return Error codes propagated from
40 VirtioFsSgListsValidate(), VirtioFsFuseNewRequest(),
41 VirtioFsSgListsSubmit(),
42 VirtioFsFuseCheckResponse().
45 VirtioFsFuseInitSession (
46 IN OUT VIRTIO_FS
*VirtioFs
49 VIRTIO_FS_FUSE_REQUEST CommonReq
;
50 VIRTIO_FS_FUSE_INIT_REQUEST InitReq
;
51 VIRTIO_FS_IO_VECTOR ReqIoVec
[2];
52 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList
;
53 VIRTIO_FS_FUSE_RESPONSE CommonResp
;
54 VIRTIO_FS_FUSE_INIT_RESPONSE InitResp
;
55 VIRTIO_FS_IO_VECTOR RespIoVec
[2];
56 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList
;
60 // Initialize the FUSE request counter.
62 VirtioFs
->RequestId
= 1;
65 // Set up the scatter-gather lists.
67 ReqIoVec
[0].Buffer
= &CommonReq
;
68 ReqIoVec
[0].Size
= sizeof CommonReq
;
69 ReqIoVec
[1].Buffer
= &InitReq
;
70 ReqIoVec
[1].Size
= sizeof InitReq
;
71 ReqSgList
.IoVec
= ReqIoVec
;
72 ReqSgList
.NumVec
= ARRAY_SIZE (ReqIoVec
);
74 RespIoVec
[0].Buffer
= &CommonResp
;
75 RespIoVec
[0].Size
= sizeof CommonResp
;
76 RespIoVec
[1].Buffer
= &InitResp
;
77 RespIoVec
[1].Size
= sizeof InitResp
;
78 RespSgList
.IoVec
= RespIoVec
;
79 RespSgList
.NumVec
= ARRAY_SIZE (RespIoVec
);
82 // Validate the scatter-gather lists; calculate the total transfer sizes.
84 Status
= VirtioFsSgListsValidate (VirtioFs
, &ReqSgList
, &RespSgList
);
85 if (EFI_ERROR (Status
)) {
90 // Populate the common request header.
92 Status
= VirtioFsFuseNewRequest (
99 if (EFI_ERROR (Status
)) {
104 // Populate the FUSE_INIT-specific fields.
106 InitReq
.Major
= VIRTIO_FS_FUSE_MAJOR
;
107 InitReq
.Minor
= VIRTIO_FS_FUSE_MINOR
;
108 InitReq
.MaxReadahead
= 0;
109 InitReq
.Flags
= VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS
;
112 // Submit the request.
114 Status
= VirtioFsSgListsSubmit (VirtioFs
, &ReqSgList
, &RespSgList
);
115 if (EFI_ERROR (Status
)) {
120 // Verify the response (all response buffers are fixed size).
122 Status
= VirtioFsFuseCheckResponse (&RespSgList
, CommonReq
.Unique
, NULL
);
123 if (EFI_ERROR (Status
)) {
124 if (Status
== EFI_DEVICE_ERROR
) {
127 "%a: Label=\"%s\" Errno=%d\n",
132 Status
= VirtioFsErrnoToEfiStatus (CommonResp
.Error
);
139 // Check FUSE interface version / feature compatibility.
141 if ((InitResp
.Major
< InitReq
.Major
) ||
142 ((InitResp
.Major
== InitReq
.Major
) && (InitResp
.Minor
< InitReq
.Minor
)) ||
143 ((InitResp
.Flags
& VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS
) == 0) ||
144 (InitResp
.MaxWrite
< SIZE_4KB
))
146 return EFI_UNSUPPORTED
;
150 // Save the maximum write buffer size for FUSE_WRITE requests.
152 VirtioFs
->MaxWrite
= InitResp
.MaxWrite
;