net: nfs: add support for partial downloads from given offset
authorMarek Szyprowski <m.szyprowski@samsung.com>
Tue, 17 Mar 2020 13:03:10 +0000 (14:03 +0100)
committerJaehoon Chung <jh80.chung@samsung.com>
Wed, 12 Oct 2022 05:45:57 +0000 (14:45 +0900)
Add support for downloading file from the given offset (in bytes) and limit the size up to given
bytes.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Change-Id: I9f442d375d6b37986cb7c10f93c11d265886cceb

cmd/net.c
include/net.h
net/nfs.c

index 46f8c87b69201bb9085c29b9f214b7e9373e4d87..bed186458378964daaa79500b2de3af5a05b51ed 100644 (file)
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -326,6 +326,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[])
index c06b577808b9f198195fdde2b9d81955d4fd91df..bdcabed7e851e973b4dfaea2151e2d06dc2dcbf6 100644 (file)
@@ -568,6 +568,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;
 
index 9a88e8dec9986ebe88e59acda43aef6a8f0c0d4d..7d2419510fcdfea7dc50ceb099f1b4770341d953 100644 (file)
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -52,6 +52,8 @@ static unsigned long rpc_id;
 static int nfs_offset = -1;
 static int nfs_len;
 static const ulong nfs_timeout = CONFIG_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 */
@@ -712,7 +714,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;
@@ -810,7 +812,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();
                }
@@ -841,6 +843,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 */