]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioFsDxe/FuseLookup.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / FuseLookup.c
1 /** @file
2 FUSE_LOOKUP 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 <Library/BaseLib.h> // AsciiStrSize()
10
11 #include "VirtioFsDxe.h"
12
13 /**
14 Send a FUSE_LOOKUP request to the Virtio Filesystem device, for resolving a
15 filename to an inode.
16
17 The function returns EFI_NOT_FOUND exclusively if the Virtio Filesystem
18 device explicitly responds with ENOENT -- "No such file or directory".
19
20 The function may only be called after VirtioFsFuseInitSession() returns
21 successfully and before VirtioFsUninit() is called.
22
23 @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_LOOKUP
24 request to. On output, the FUSE request counter
25 "VirtioFs->RequestId" will have been incremented.
26
27 @param[in] DirNodeId The inode number of the directory in which Name
28 should be resolved to an inode.
29
30 @param[in] Name The single-component filename to resolve in the
31 directory identified by DirNodeId.
32
33 @param[out] NodeId The inode number which Name has been resolved to.
34
35 @param[out] FuseAttr The VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object
36 describing the properties of the resolved inode.
37
38 @retval EFI_SUCCESS Filename to inode resolution successful.
39
40 @retval EFI_NOT_FOUND The Virtio Filesystem device explicitly reported
41 ENOENT -- "No such file or directory".
42
43 @return The "errno" value mapped to an EFI_STATUS code, if the
44 Virtio Filesystem device explicitly reported an error
45 different from ENOENT. If said mapping resulted in
46 EFI_NOT_FOUND, it is remapped to EFI_DEVICE_ERROR.
47
48 @return Error codes propagated from VirtioFsSgListsValidate(),
49 VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
50 VirtioFsFuseCheckResponse(). EFI_NOT_FOUND is remapped
51 to EFI_DEVICE_ERROR.
52 **/
53 EFI_STATUS
54 VirtioFsFuseLookup (
55 IN OUT VIRTIO_FS *VirtioFs,
56 IN UINT64 DirNodeId,
57 IN CHAR8 *Name,
58 OUT UINT64 *NodeId,
59 OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr
60 )
61 {
62 VIRTIO_FS_FUSE_REQUEST CommonReq;
63 VIRTIO_FS_IO_VECTOR ReqIoVec[2];
64 VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
65 VIRTIO_FS_FUSE_RESPONSE CommonResp;
66 VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
67 VIRTIO_FS_IO_VECTOR RespIoVec[3];
68 VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
69 EFI_STATUS Status;
70
71 //
72 // Set up the scatter-gather lists.
73 //
74 ReqIoVec[0].Buffer = &CommonReq;
75 ReqIoVec[0].Size = sizeof CommonReq;
76 ReqIoVec[1].Buffer = Name;
77 ReqIoVec[1].Size = AsciiStrSize (Name);
78 ReqSgList.IoVec = ReqIoVec;
79 ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
80
81 RespIoVec[0].Buffer = &CommonResp;
82 RespIoVec[0].Size = sizeof CommonResp;
83 RespIoVec[1].Buffer = &NodeResp;
84 RespIoVec[1].Size = sizeof NodeResp;
85 RespIoVec[2].Buffer = FuseAttr;
86 RespIoVec[2].Size = sizeof *FuseAttr;
87 RespSgList.IoVec = RespIoVec;
88 RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
89
90 //
91 // Validate the scatter-gather lists; calculate the total transfer sizes.
92 //
93 Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
94 if (EFI_ERROR (Status)) {
95 goto Fail;
96 }
97
98 //
99 // Populate the common request header.
100 //
101 Status = VirtioFsFuseNewRequest (
102 VirtioFs,
103 &CommonReq,
104 ReqSgList.TotalSize,
105 VirtioFsFuseOpLookup,
106 DirNodeId
107 );
108 if (EFI_ERROR (Status)) {
109 goto Fail;
110 }
111
112 //
113 // Submit the request.
114 //
115 Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
116 if (EFI_ERROR (Status)) {
117 goto Fail;
118 }
119
120 //
121 // Verify the response (all response buffers are fixed size).
122 //
123 Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
124 if (EFI_ERROR (Status)) {
125 if (Status == EFI_DEVICE_ERROR) {
126 DEBUG ((
127 ((CommonResp.Error == VIRTIO_FS_FUSE_ERRNO_ENOENT) ?
128 DEBUG_VERBOSE :
129 DEBUG_ERROR),
130 "%a: Label=\"%s\" DirNodeId=%Lu Name=\"%a\" Errno=%d\n",
131 __FUNCTION__,
132 VirtioFs->Label,
133 DirNodeId,
134 Name,
135 CommonResp.Error
136 ));
137 if (CommonResp.Error == VIRTIO_FS_FUSE_ERRNO_ENOENT) {
138 return EFI_NOT_FOUND;
139 }
140
141 Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
142 }
143
144 goto Fail;
145 }
146
147 //
148 // Output the NodeId to which Name has been resolved to.
149 //
150 *NodeId = NodeResp.NodeId;
151 return EFI_SUCCESS;
152
153 Fail:
154 return (Status == EFI_NOT_FOUND) ? EFI_DEVICE_ERROR : Status;
155 }