]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioFsDxe/FuseInit.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseInit.c
1 /** @file
2 FUSE_INIT wrapper for the Virtio Filesystem device.
3
4 Copyright (C) 2020, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include "VirtioFsDxe.h"
10
11 /**
12 Send a FUSE_INIT request to the Virtio Filesystem device, for starting the
13 FUSE session.
14
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."
19
20 The function may only be called after VirtioFsInit() returns successfully and
21 before VirtioFsUninit() is called.
22
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
28 output.
29
30 @retval EFI_SUCCESS The FUSE session has been started.
31
32 @retval EFI_UNSUPPORTED FUSE interface version or feature negotiation
33 failed.
34
35 @return The "errno" value mapped to an EFI_STATUS code, if
36 the Virtio Filesystem device explicitly reported an
37 error.
38
39 @return Error codes propagated from
40 VirtioFsSgListsValidate(), VirtioFsFuseNewRequest(),
41 VirtioFsSgListsSubmit(),
42 VirtioFsFuseCheckResponse().
43 **/
44 EFI_STATUS
45 VirtioFsFuseInitSession (
46 IN OUT VIRTIO_FS *VirtioFs
47 )
48 {
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;
57 EFI_STATUS Status;
58
59 //
60 // Initialize the FUSE request counter.
61 //
62 VirtioFs->RequestId = 1;
63
64 //
65 // Set up the scatter-gather lists.
66 //
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);
73
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);
80
81 //
82 // Validate the scatter-gather lists; calculate the total transfer sizes.
83 //
84 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
85 if (EFI_ERROR (Status)) {
86 return Status;
87 }
88
89 //
90 // Populate the common request header.
91 //
92 Status = VirtioFsFuseNewRequest (
93 VirtioFs,
94 &CommonReq,
95 ReqSgList.TotalSize,
96 VirtioFsFuseOpInit,
97 0
98 );
99 if (EFI_ERROR (Status)) {
100 return Status;
101 }
102
103 //
104 // Populate the FUSE_INIT-specific fields.
105 //
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;
110
111 //
112 // Submit the request.
113 //
114 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
115 if (EFI_ERROR (Status)) {
116 return Status;
117 }
118
119 //
120 // Verify the response (all response buffers are fixed size).
121 //
122 Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
123 if (EFI_ERROR (Status)) {
124 if (Status == EFI_DEVICE_ERROR) {
125 DEBUG ((
126 DEBUG_ERROR,
127 "%a: Label=\"%s\" Errno=%d\n",
128 __FUNCTION__,
129 VirtioFs->Label,
130 CommonResp.Error
131 ));
132 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
133 }
134
135 return Status;
136 }
137
138 //
139 // Check FUSE interface version / feature compatibility.
140 //
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))
145 {
146 return EFI_UNSUPPORTED;
147 }
148
149 //
150 // Save the maximum write buffer size for FUSE_WRITE requests.
151 //
152 VirtioFs->MaxWrite = InitResp.MaxWrite;
153 return EFI_SUCCESS;
154 }