2 * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 #include <ipxe/time.h>
29 #include <ipxe/iobuf.h>
30 #include <ipxe/open.h>
31 #include <ipxe/features.h>
33 #include <ipxe/oncrpc.h>
34 #include <ipxe/oncrpc_iob.h>
35 #include <ipxe/portmap.h>
36 #include <ipxe/mount.h>
37 #include <ipxe/settings.h>
41 * Network File System protocol
45 /** NFS LOOKUP procedure */
47 /** NFS READLINK procedure */
48 #define NFS_READLINK 5
49 /** NFS READ procedure */
53 * Extract a file handle from the beginning of an I/O buffer
55 * @v io_buf I/O buffer
57 * @ret size Size of the data read
59 size_t nfs_iob_get_fh ( struct io_buffer
*io_buf
, struct nfs_fh
*fh
) {
60 fh
->size
= oncrpc_iob_get_int ( io_buf
);
63 return sizeof ( uint32_t );
65 memcpy (fh
->fh
, io_buf
->data
, fh
->size
);
66 iob_pull ( io_buf
, fh
->size
);
68 return fh
->size
+ sizeof ( uint32_t );
72 * Add a file handle to the end of an I/O buffer
74 * @v io_buf I/O buffer
76 * @ret size Size of the data written
78 size_t nfs_iob_add_fh ( struct io_buffer
*io_buf
, const struct nfs_fh
*fh
) {
81 s
= oncrpc_iob_add_int ( io_buf
, fh
->size
);
82 memcpy ( iob_put ( io_buf
, fh
->size
), &fh
->fh
, fh
->size
);
88 * Send a LOOKUP request
90 * @v intf Interface to send the request on
91 * @v session ONC RPC session
92 * @v fh The file handle of the the directory
93 * @v filename The file name
94 * @ret rc Return status code
96 int nfs_lookup ( struct interface
*intf
, struct oncrpc_session
*session
,
97 const struct nfs_fh
*fh
, const char *filename
) {
98 struct oncrpc_field fields
[] = {
99 ONCRPC_SUBFIELD ( array
, fh
->size
, &fh
->fh
),
100 ONCRPC_FIELD ( str
, filename
),
104 return oncrpc_call ( intf
, session
, NFS_LOOKUP
, fields
);
108 * Send a READLINK request
110 * @v intf Interface to send the request on
111 * @v session ONC RPC session
112 * @v fh The symlink file handle
113 * @ret rc Return status code
115 int nfs_readlink ( struct interface
*intf
, struct oncrpc_session
*session
,
116 const struct nfs_fh
*fh
) {
117 struct oncrpc_field fields
[] = {
118 ONCRPC_SUBFIELD ( array
, fh
->size
, &fh
->fh
),
122 return oncrpc_call ( intf
, session
, NFS_READLINK
, fields
);
126 * Send a READ request
128 * @v intf Interface to send the request on
129 * @v session ONC RPC session
130 * @v fh The file handle
132 * @v count Byte count
133 * @ret rc Return status code
135 int nfs_read ( struct interface
*intf
, struct oncrpc_session
*session
,
136 const struct nfs_fh
*fh
, uint64_t offset
, uint32_t count
) {
137 struct oncrpc_field fields
[] = {
138 ONCRPC_SUBFIELD ( array
, fh
->size
, &fh
->fh
),
139 ONCRPC_FIELD ( int64
, offset
),
140 ONCRPC_FIELD ( int32
, count
),
144 return oncrpc_call ( intf
, session
, NFS_READ
, fields
);
148 * Parse a LOOKUP reply
150 * @v lookup_reply A structure where the data will be saved
151 * @v reply The ONC RPC reply to get data from
152 * @ret rc Return status code
154 int nfs_get_lookup_reply ( struct nfs_lookup_reply
*lookup_reply
,
155 struct oncrpc_reply
*reply
) {
156 if ( ! lookup_reply
|| ! reply
)
159 lookup_reply
->status
= oncrpc_iob_get_int ( reply
->data
);
160 switch ( lookup_reply
->status
)
174 case NFS3ERR_NAMETOOLONG
:
175 return -ENAMETOOLONG
;
178 case NFS3ERR_BADHANDLE
:
179 case NFS3ERR_SERVERFAULT
:
184 nfs_iob_get_fh ( reply
->data
, &lookup_reply
->fh
);
186 if ( oncrpc_iob_get_int ( reply
->data
) == 1 )
187 lookup_reply
->ent_type
= oncrpc_iob_get_int ( reply
->data
);
192 * Parse a READLINK reply
194 * @v readlink_reply A structure where the data will be saved
195 * @v reply The ONC RPC reply to get data from
196 * @ret rc Return status code
198 int nfs_get_readlink_reply ( struct nfs_readlink_reply
*readlink_reply
,
199 struct oncrpc_reply
*reply
) {
200 if ( ! readlink_reply
|| ! reply
)
203 readlink_reply
->status
= oncrpc_iob_get_int ( reply
->data
);
204 switch ( readlink_reply
->status
)
214 case NFS3ERR_NOTSUPP
:
218 case NFS3ERR_BADHANDLE
:
219 case NFS3ERR_SERVERFAULT
:
224 if ( oncrpc_iob_get_int ( reply
->data
) == 1 )
225 iob_pull ( reply
->data
, 5 * sizeof ( uint32_t ) +
226 8 * sizeof ( uint64_t ) );
228 readlink_reply
->path_len
= oncrpc_iob_get_int ( reply
->data
);
229 readlink_reply
->path
= reply
->data
->data
;
237 * @v read_reply A structure where the data will be saved
238 * @v reply The ONC RPC reply to get data from
239 * @ret rc Return status code
241 int nfs_get_read_reply ( struct nfs_read_reply
*read_reply
,
242 struct oncrpc_reply
*reply
) {
243 if ( ! read_reply
|| ! reply
)
246 read_reply
->status
= oncrpc_iob_get_int ( reply
->data
);
247 switch ( read_reply
->status
)
265 case NFS3ERR_BADHANDLE
:
266 case NFS3ERR_SERVERFAULT
:
271 if ( oncrpc_iob_get_int ( reply
->data
) == 1 )
273 iob_pull ( reply
->data
, 5 * sizeof ( uint32_t ) );
274 read_reply
->filesize
= oncrpc_iob_get_int64 ( reply
->data
);
275 iob_pull ( reply
->data
, 7 * sizeof ( uint64_t ) );
278 read_reply
->count
= oncrpc_iob_get_int ( reply
->data
);
279 read_reply
->eof
= oncrpc_iob_get_int ( reply
->data
);
280 read_reply
->data_len
= oncrpc_iob_get_int ( reply
->data
);
281 read_reply
->data
= reply
->data
->data
;
283 if ( read_reply
->count
!= read_reply
->data_len
)