From 4e9a9a677ec5886072c6a02fde72e65b1b5db00e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 17 Mar 2020 14:03:10 +0100 Subject: [PATCH] net: nfs: add support for partial downloads from given offset Add support for downloading file from the given offset (in bytes) and limit the size up to given bytes. Signed-off-by: Marek Szyprowski Change-Id: I9f442d375d6b37986cb7c10f93c11d265886cceb --- cmd/net.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/net.h | 7 +++++++ net/nfs.c | 11 +++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/cmd/net.c b/cmd/net.c index 9bbcdbc..35a13da 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -198,6 +198,8 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, ulong addr; net_boot_file_name_explicit = false; + net_boot_file_offset = 0; + net_boot_file_size_limit = 0; /* pre-set image_load_addr */ s = env_get("loadaddr"); @@ -283,6 +285,45 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, return rcode; } +int netboot_nfs(unsigned long addr, const char *filename, + unsigned long offset, unsigned long limit) +{ + int rcode = 0; + int size; + + image_load_addr = addr; + net_boot_file_name_explicit = true; + net_boot_file_offset = offset; + net_boot_file_size_limit = limit; + + copy_filename(net_boot_file_name, filename, + sizeof(net_boot_file_name)); + + bootstage_mark(BOOTSTAGE_ID_NET_START); + + size = net_loop(NFS); + if (size < 0) { + bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK); + return CMD_RET_FAILURE; + } + bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK); + + /* done if no file was loaded (no errors though) */ + if (size == 0) { + bootstage_error(BOOTSTAGE_ID_NET_LOADED); + return CMD_RET_SUCCESS; + } + + bootstage_mark(BOOTSTAGE_ID_NET_LOADED); + + if (rcode == CMD_RET_SUCCESS) + bootstage_mark(BOOTSTAGE_ID_NET_DONE); + else + bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR); + return rcode; +} + + #if defined(CONFIG_CMD_PING) static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/include/net.h b/include/net.h index 1bf9867..fa40596 100644 --- a/include/net.h +++ b/include/net.h @@ -559,6 +559,13 @@ extern char net_boot_file_name[1024];/* Boot File name */ extern bool net_boot_file_name_explicit; /* The actual transferred size of the bootfile (in bytes) */ extern u32 net_boot_file_size; + +/* Offset/size for partial downloads for nfsdown tool */ +extern u32 net_boot_file_size_limit; +extern u32 net_boot_file_offset; +extern int netboot_nfs(unsigned long addr, const char *filename, + unsigned long offset, unsigned long size); + /* Boot file size in blocks as reported by the DHCP server */ extern u32 net_boot_file_expected_size_in_blocks; diff --git a/net/nfs.c b/net/nfs.c index 6b81c41..da6fe1f 100644 --- a/net/nfs.c +++ b/net/nfs.c @@ -54,6 +54,8 @@ static unsigned long rpc_id; static int nfs_offset = -1; static int nfs_len; static ulong nfs_timeout = NFS_TIMEOUT; +u32 net_boot_file_size_limit; +u32 net_boot_file_offset; static char dirfh[NFS_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */ static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */ @@ -716,7 +718,7 @@ static int nfs_read_reply(uchar *pkt, unsigned len) if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len) return -9999; - if (store_block(data_ptr, nfs_offset, rlen)) + if (store_block(data_ptr, nfs_offset - net_boot_file_offset, rlen)) return -9999; return rlen; @@ -814,7 +816,7 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip, nfs_send(); } else { nfs_state = STATE_READ_REQ; - nfs_offset = 0; + nfs_offset = net_boot_file_offset; nfs_len = NFS_READ_SIZE; nfs_send(); } @@ -845,6 +847,11 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip, net_set_timeout_handler(nfs_timeout, nfs_timeout_handler); if (rlen > 0) { nfs_offset += rlen; + if (nfs_offset - net_boot_file_offset == + net_boot_file_size_limit) { + nfs_download_state = NETLOOP_SUCCESS; + nfs_state = STATE_UMOUNT_REQ; + } nfs_send(); } else if ((rlen == -NFSERR_ISDIR) || (rlen == -NFSERR_INVAL)) { /* symbolic link */ -- 2.7.4