summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorSébastien Szymanski <sebastien.szymanski@armadeus.com>2024-03-26 10:34:31 +0100
committerTom Rini <trini@konsulko.com>2024-04-10 09:34:53 -0600
commitd2986567b27dae764b19886bcda1d24b7c41d075 (patch)
tree5f37a76eb3cb4e612312445b0f4f9fdacffceec7 /net
parent6821d13fb0c40345989ef42851eed38851e7e582 (diff)
downloadu-boot-d2986567b27dae764b19886bcda1d24b7c41d075.tar.gz
u-boot-d2986567b27dae764b19886bcda1d24b7c41d075.tar.bz2
u-boot-d2986567b27dae764b19886bcda1d24b7c41d075.zip
net: nfs: fix file handle length in NFSv3
The NFS protocol uses file handles to refer to file or directory. In NFSv2 file handles have a fixed size of 32 bytes. In NFSv3 file handles have a variable length up to 64 bytes. This is also true for the MOUNT protocol. [1] When the NFSv3 server replies with a file handle length > 32 bytes, U-Boot only copies 32 bytes of that file handle and the next LOOKUP Call fails: BIOS> nfs ${loadaddr} 192.168.1.51:/nfsroot/opos93dev-br/boot/Image Using ethernet@428a0000 device File transfer via NFS from server 192.168.1.51; our IP address is 192.168.1.133 Filename '/nfsroot/opos93dev-br/boot/Image'. Load address: 0x80400000 Loading: *** ERROR: File lookup fail done BIOS> Looking at this transfer in Wireshark, we can see that the server replies with the following file handle: length: 36 [hash (CRC-32): 0x230ac67b] FileHandle: 0100070101005e000000000091763911f87c449fa73c298552db19ba0c9f60002980cfd2 and U-Boot sends the following file handle in the next LOOKUP Call: length: 32 [hash (CRC-32): 0x6314131b] FileHandle: 000000240100070101005e000000000091763911f87c449fa73c298552db19ba Fix this by using a variable length file handle for dirfh. [1] https://www.rfc-editor.org/rfc/rfc1813.html#page-106 Fixes: b0baca982048 ("net: NFS: Add NFSv3 support") Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com> Tested-by: Andrew Davis <afd@ti.com>
Diffstat (limited to 'net')
-rw-r--r--net/nfs.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/net/nfs.c b/net/nfs.c
index 7a8887ef23..c18282448c 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -57,7 +57,8 @@ static int nfs_offset = -1;
static int nfs_len;
static const ulong nfs_timeout = CONFIG_NFS_TIMEOUT;
-static char dirfh[NFS_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */
+static char dirfh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */
+static unsigned int dirfh3_length; /* (variable) length of dirfh when NFSv3 */
static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */
static unsigned int filefh3_length; /* (variable) length of filefh when NFSv3 */
@@ -377,9 +378,9 @@ static void nfs_lookup_req(char *fname)
rpc_req(PROG_NFS, NFS_LOOKUP, data, len);
} else { /* NFS_V3 */
- *p++ = htonl(NFS_FHSIZE); /* Dir handle length */
- memcpy(p, dirfh, NFS_FHSIZE);
- p += (NFS_FHSIZE / 4);
+ *p++ = htonl(dirfh3_length); /* Dir handle length */
+ memcpy(p, dirfh, dirfh3_length);
+ p += (dirfh3_length / 4);
*p++ = htonl(fnamelen);
if (fnamelen & 3)
*(p + fnamelen / 4) = 0;
@@ -565,7 +566,14 @@ static int nfs_mount_reply(uchar *pkt, unsigned len)
fs_mounted = 1;
/* NFSv2 and NFSv3 use same structure */
- memcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ if (choosen_nfs_version != NFS_V3) {
+ memcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
+ } else {
+ dirfh3_length = ntohl(rpc_pkt.u.reply.data[1]);
+ if (dirfh3_length > NFS3_FHSIZE)
+ dirfh3_length = NFS3_FHSIZE;
+ memcpy(dirfh, rpc_pkt.u.reply.data + 2, dirfh3_length);
+ }
return 0;
}