get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2173736/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2173736,
    "url": "http://patchwork.ozlabs.org/api/patches/2173736/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20251212-lwip_nfs-v2-4-9cb5a60520d8@linaro.org/",
    "project": {
        "id": 18,
        "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api",
        "name": "U-Boot",
        "link_name": "uboot",
        "list_id": "u-boot.lists.denx.de",
        "list_email": "u-boot@lists.denx.de",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20251212-lwip_nfs-v2-4-9cb5a60520d8@linaro.org>",
    "list_archive_url": null,
    "date": "2025-12-12T11:32:27",
    "name": "[v2,4/6] net: nfs: Move most NFS code to common files",
    "commit_ref": "3bc1197e3d7c54bcbd2dfb481cb4a9ae47f3e8d3",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "428b1e32a54dd142359234e0b82a86345ded65d9",
    "submitter": {
        "id": 88793,
        "url": "http://patchwork.ozlabs.org/api/people/88793/?format=api",
        "name": "Andrew Goodbody",
        "email": "andrew.goodbody@linaro.org"
    },
    "delegate": {
        "id": 157425,
        "url": "http://patchwork.ozlabs.org/api/users/157425/?format=api",
        "username": "jforissier",
        "first_name": "Jerome",
        "last_name": "Forissier",
        "email": "jerome.forissier@linaro.org"
    },
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20251212-lwip_nfs-v2-4-9cb5a60520d8@linaro.org/mbox/",
    "series": [
        {
            "id": 485199,
            "url": "http://patchwork.ozlabs.org/api/series/485199/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=485199",
            "date": "2025-12-12T11:32:23",
            "name": "net: Port NFS to lwIP",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/485199/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2173736/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2173736/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<u-boot-bounces@lists.denx.de>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=mC4bEDzd;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)",
            "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=linaro.org",
            "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de",
            "phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.b=\"mC4bEDzd\";\n\tdkim-atps=neutral",
            "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=linaro.org",
            "phobos.denx.de;\n spf=pass smtp.mailfrom=andrew.goodbody@linaro.org"
        ],
        "Received": [
            "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dSS5Q0smTz1xsK\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 12 Dec 2025 22:33:46 +1100 (AEDT)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 82E25839A8;\n\tFri, 12 Dec 2025 12:32:50 +0100 (CET)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 6DB9F835B3; Fri, 12 Dec 2025 12:32:41 +0100 (CET)",
            "from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com\n [IPv6:2a00:1450:4864:20::32a])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id D3683839A8\n for <u-boot@lists.denx.de>; Fri, 12 Dec 2025 12:32:31 +0100 (CET)",
            "by mail-wm1-x32a.google.com with SMTP id\n 5b1f17b1804b1-477aa218f20so7642955e9.0\n for <u-boot@lists.denx.de>; Fri, 12 Dec 2025 03:32:31 -0800 (PST)",
            "from artemis2.elfringham.co.uk\n ([2a0a:ef40:fed:3801:9287:1e8a:f239:8d00])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-47a8f8f39c6sm26277235e9.14.2025.12.12.03.32.28\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 12 Dec 2025 03:32:30 -0800 (PST)"
        ],
        "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de",
        "X-Spam-Level": "",
        "X-Spam-Status": "No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED,\n SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1765539151; x=1766143951; darn=lists.denx.de;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to; bh=N5ir08gmLEl0jm7hP9qz9pSmeSLcu9/3Kd4BOB8qECA=;\n b=mC4bEDzdcOWHKiwJKTaKMXow0f6u1b2pMatBy2NqE06dtk+fGsN5mTYQIHKVxQ2hba\n eTYsCE6YGhahRaMUqilF1BS6b904lIfkwq4Y3PDE/dH2BP0vh/C4FSmxWSIf+QV7Otx7\n 0sUXiGsv8YHqkNf4mbM8lbB8FiQ1ekZT1vadqkwmIcihPfmO9NmBV4GwpX6oMNks6mac\n rPg1IzYB8xXTsmw7tG/HimiwCCqNImR9Lw8ERDGVhUWnsoI4HU89vIZRvvJtd4h3i/nO\n OuAz+9pfsqIki5IyFXcFaQzpw6A6cHtQhULrKghKQQWt4kuMvcet5rdrvd3ED2/WAJOR\n giqg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1765539151; x=1766143951;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=N5ir08gmLEl0jm7hP9qz9pSmeSLcu9/3Kd4BOB8qECA=;\n b=lD0DDIEZNyUoSEe2ZO84q/vYG3WpI7QFDqE3DLjgKk1BTLfrR6NnQu99DXAAwTImF/\n V41eZi04fjNnYWW0OXc29s86ca5wwnwTlzETDw3Hb9ix92/4gjGUUsfxr8CI4rOhRXjq\n 5zwp9UOBRwYJAaDUGWH6YDcfaujKFFmUBxuw6SlGZouPFHp2mAorUZv8ezM4Hg6252Yx\n jmDUkP7tR161sZ4scTucjTlEHIZ2Dp/O4QPHXbOIO+T0hHRPlvrjbmGTLJRxVIGo6fs2\n Dxyl1DRiwTDIvMulwOb/C2PMw5NoZaX0tiAGSsRqqve6SV6NI2S0r1DcfHkJTRbFluMV\n 2QDQ==",
        "X-Gm-Message-State": "AOJu0YxCOTkhPuDgOuPoyw8RVpliHgTQ9kmJ/48qQNaWg2GyNR1hY/PD\n StgGkZuhAjyAYCdl9aANgfxxNFhsjP2BpwjDo/zprpzQ1hzWDcDBXRPzR1tC59ZaO2o=",
        "X-Gm-Gg": "AY/fxX7QNP0Fmsu+c9hbcmbhFZZhv4ZAC4JD+trcp09JC7dXNedocY8JigOAEGKtBHy\n vuIM6iQ7cfcYwDOjDngUoG9+rp6FkMSJDiKKbSf6+kFNm7IA7b4qdETA+zDVsONK3gM1vFFT7T0\n 4cXUUwV5uis57LbOanFT6VuAEbCi9eiWPT4qtwcbUmq+jCQNv0uxJlPkOqotv7OpFKgXBh5/7pZ\n r+dhvm6bkhZjrKFZfvhtVLxxR6EWety8FfL76rjAQjICn+s8jbv/jT/3rfqS/TZfmNarzDnKaGf\n OaOrq47FYe7Ld8UB6BAUCsXjjxPeOxxUyGLqBOjayr0dF9r2Fbl16HniysVjK5zG4MwoFZqWTSA\n m/3h/Fa32EEgAplLQ7lbPOz/7YJSwdAvXCZ5jGSmTLyJ8IN48Y9Xz8Gpsb6d1yDUCL7qGF6L+Ae\n R/kU+sEUkyQXEBErPKhK5Gb2vBu75tRAmaxJke/p8=",
        "X-Google-Smtp-Source": "\n AGHT+IH7flNm47Z17xjMAqRFAvNa95Kc5yZAbqhyMt+TIWVZB2NhKz4ySiUjN1Lj716F3oEJIk0pmw==",
        "X-Received": "by 2002:a05:600d:8447:b0:477:b642:9dc9 with SMTP id\n 5b1f17b1804b1-47a900bd698mr12291615e9.28.1765539150822;\n Fri, 12 Dec 2025 03:32:30 -0800 (PST)",
        "From": "Andrew Goodbody <andrew.goodbody@linaro.org>",
        "Date": "Fri, 12 Dec 2025 11:32:27 +0000",
        "Subject": "[PATCH v2 4/6] net: nfs: Move most NFS code to common files",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20251212-lwip_nfs-v2-4-9cb5a60520d8@linaro.org>",
        "References": "<20251212-lwip_nfs-v2-0-9cb5a60520d8@linaro.org>",
        "In-Reply-To": "<20251212-lwip_nfs-v2-0-9cb5a60520d8@linaro.org>",
        "To": "u-boot@lists.denx.de",
        "Cc": "Tom Rini <trini@konsulko.com>, Joe Hershberger <joe.hershberger@ni.com>,\n Ramon Fried <rfried.dev@gmail.com>,\n Jerome Forissier <jerome.forissier@linaro.org>,\n Simon Glass <sjg@chromium.org>, Benjamin Hahn <B.Hahn@phytec.de>,\n Heinrich Schuchardt <xypron.glpk@gmx.de>,\n Adriano Cordova <adrianox@gmail.com>,\n Max Merchel <Max.Merchel@ew.tq-group.com>,\n Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>,\n Andre Przywara <andre.przywara@arm.com>, Tim Harvey <tharvey@gateworks.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>,\n Michal Simek <michal.simek@amd.com>,\n Michael Trimarchi <michael@amarulasolutions.com>,\n Ibai Erkiaga <ibai.erkiaga-elorza@amd.com>,\n Wolfgang Wallner <wolfgang.wallner@br-automation.com>,\n \"Kory Maincent (TI.com)\" <kory.maincent@bootlin.com>,\n Martyn Welch <martyn.welch@collabora.com>,\n Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>,\n Andrew Goodbody <andrew.goodbody@linaro.org>",
        "X-Mailer": "b4 0.14.2",
        "X-BeenThere": "u-boot@lists.denx.de",
        "X-Mailman-Version": "2.1.39",
        "Precedence": "list",
        "List-Id": "U-Boot discussion <u-boot.lists.denx.de>",
        "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>",
        "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>",
        "List-Post": "<mailto:u-boot@lists.denx.de>",
        "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>",
        "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>",
        "Errors-To": "u-boot-bounces@lists.denx.de",
        "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>",
        "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de",
        "X-Virus-Status": "Clean"
    },
    "content": "Move most of the NFS code into common files so that it can be used by an\nlwIP port of NFS.\n\nAcked-by: Jerome Forissier <jerome.forissier@linaro.org>\nSigned-off-by: Andrew Goodbody <andrew.goodbody@linaro.org>\n---\n net/Makefile     |   1 +\n net/nfs-common.c | 861 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n net/nfs-common.h | 123 ++++++++\n net/nfs.c        | 848 +-----------------------------------------------------\n net/nfs.h        |  59 ----\n 5 files changed, 998 insertions(+), 894 deletions(-)",
    "diff": "diff --git a/net/Makefile b/net/Makefile\nindex 468820186cfc8287fb23a81e75f6a3594f46f261..3a32bc8b0e78404c3db2196ed802010988145bc8 100644\n--- a/net/Makefile\n+++ b/net/Makefile\n@@ -43,6 +43,7 @@ obj-$(CONFIG_$(PHASE_)DM_ETH) += eth-uclass.o\n obj-$(CONFIG_$(PHASE_)BOOTDEV_ETH) += eth_bootdev.o\n obj-$(CONFIG_DM_MDIO)  += mdio-uclass.o\n obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o\n+obj-$(CONFIG_CMD_NFS)  += nfs-common.o\n obj-$(CONFIG_$(PHASE_)DM_ETH) += eth_common.o\n obj-y += net-common.o\n endif\ndiff --git a/net/nfs-common.c b/net/nfs-common.c\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..a6a70677bd2d8350819dd7bce336d35cc3ae7bf8\n--- /dev/null\n+++ b/net/nfs-common.c\n@@ -0,0 +1,861 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * NFS support driver - based on etherboot and U-BOOT's tftp.c\n+ *\n+ * Masami Komiya <mkomiya@sonare.it> 2004\n+ *\n+ */\n+\n+/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read:\n+ * large portions are copied verbatim) as distributed in OSKit 0.97.  A few\n+ * changes were necessary to adapt the code to Etherboot and to fix several\n+ * inconsistencies.  Also the RPC message preparation is done \"by hand\" to\n+ * avoid adding netsprintf() which I find hard to understand and use.\n+ */\n+\n+/* NOTE 2: Etherboot does not care about things beyond the kernel image, so\n+ * it loads the kernel image off the boot server (ARP_SERVER) and does not\n+ * access the client root disk (root-path in dhcpd.conf), which would use\n+ * ARP_ROOTSERVER.  The root disk is something the operating system we are\n+ * about to load needs to use.\tThis is different from the OSKit 0.97 logic.\n+ */\n+\n+/* NOTE 3: Symlink handling introduced by Anselm M Hoffmeister, 2003-July-14\n+ * If a symlink is encountered, it is followed as far as possible (recursion\n+ * possible, maximum 16 steps). There is no clearing of \"..\"'s inside the\n+ * path, so please DON'T DO THAT. thx.\n+ */\n+\n+/* NOTE 4: NFSv3 support added by Guillaume GARDET, 2016-June-20.\n+ * NFSv2 is still used by default. But if server does not support NFSv2, then\n+ * NFSv3 is used, if available on NFS server.\n+ */\n+\n+/* NOTE 5: NFSv1 support added by Christian Gmeiner, Thomas Rienoessl,\n+ * September 27, 2018. As of now, NFSv3 is the default choice. If the server\n+ * does not support NFSv3, we fall back to versions 2 or 1.\n+ */\n+\n+#ifdef CONFIG_SYS_DIRECT_FLASH_NFS\n+#include <flash.h>\n+#endif\n+#include <image.h>\n+#include <log.h>\n+#include <net.h>\n+#include <mapmem.h>\n+#include \"nfs.h\"\n+#include \"nfs-common.h\"\n+\n+static int fs_mounted;\n+static char dirfh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */\n+static unsigned int dirfh3_length; /* (variable) length of dirfh when NFSv3 */\n+static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */\n+static unsigned int filefh3_length;\t/* (variable) length of filefh when NFSv3 */\n+\n+enum net_loop_state nfs_download_state;\n+char *nfs_filename;\n+char *nfs_path;\n+char nfs_path_buff[2048];\n+struct in_addr nfs_server_ip;\n+int nfs_server_mount_port;\n+int nfs_server_port;\n+int nfs_our_port;\n+int nfs_state;\n+int nfs_timeout_count;\n+unsigned long rpc_id;\n+int nfs_offset = -1;\n+int nfs_len;\n+\n+const ulong nfs_timeout = CONFIG_NFS_TIMEOUT;\n+\n+enum nfs_version choosen_nfs_version = NFS_V3;\n+\n+static inline int store_block(uchar *src, unsigned int offset, unsigned int len)\n+{\n+\tulong newsize = offset + len;\n+#ifdef CONFIG_SYS_DIRECT_FLASH_NFS\n+\tint i, rc = 0;\n+\n+\tfor (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {\n+\t\t/* start address in flash? */\n+\t\tif (image_load_addr + offset >= flash_info[i].start[0]) {\n+\t\t\trc = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (rc) { /* Flash is destination for this packet */\n+\t\trc = flash_write((uchar *)src, (ulong)image_load_addr + offset,\n+\t\t\t\t len);\n+\t\tif (rc) {\n+\t\t\tflash_perror(rc);\n+\t\t\treturn -1;\n+\t\t}\n+\t} else\n+#endif /* CONFIG_SYS_DIRECT_FLASH_NFS */\n+\t{\n+\t\tvoid *ptr = map_sysmem(image_load_addr + offset, len);\n+\n+\t\tmemcpy(ptr, src, len);\n+\t\tunmap_sysmem(ptr);\n+\t}\n+\n+\tif (net_boot_file_size < (offset + len))\n+\t\tnet_boot_file_size = newsize;\n+\treturn 0;\n+}\n+\n+char *nfs_basename(char *path)\n+{\n+\tchar *fname;\n+\n+\tfname = path + strlen(path) - 1;\n+\twhile (fname >= path) {\n+\t\tif (*fname == '/') {\n+\t\t\tfname++;\n+\t\t\tbreak;\n+\t\t}\n+\t\tfname--;\n+\t}\n+\treturn fname;\n+}\n+\n+char *nfs_dirname(char *path)\n+{\n+\tchar *fname;\n+\n+\tfname = nfs_basename(path);\n+\t--fname;\n+\t*fname = '\\0';\n+\treturn path;\n+}\n+\n+/**************************************************************************\n+ * RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries\n+ **************************************************************************\n+ */\n+static uint32_t *rpc_add_credentials(uint32_t *p)\n+{\n+\t/* Here's the executive summary on authentication requirements of the\n+\t * various NFS server implementations:\tLinux accepts both AUTH_NONE\n+\t * and AUTH_UNIX authentication (also accepts an empty hostname field\n+\t * in the AUTH_UNIX scheme).  *BSD refuses AUTH_NONE, but accepts\n+\t * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX\n+\t * scheme).  To be safe, use AUTH_UNIX and pass the hostname if we have\n+\t * it (if the BOOTP/DHCP reply didn't give one, just use an empty\n+\t * hostname).\n+\t */\n+\n+\t/* Provide an AUTH_UNIX credential.  */\n+\t*p++ = htonl(1);\t\t/* AUTH_UNIX */\n+\t*p++ = htonl(20);\t\t/* auth length */\n+\t*p++ = 0;\t\t\t/* stamp */\n+\t*p++ = 0;\t\t\t/* hostname string */\n+\t*p++ = 0;\t\t\t/* uid */\n+\t*p++ = 0;\t\t\t/* gid */\n+\t*p++ = 0;\t\t\t/* auxiliary gid list */\n+\n+\t/* Provide an AUTH_NONE verifier.  */\n+\t*p++ = 0;\t\t\t/* AUTH_NONE */\n+\t*p++ = 0;\t\t\t/* auth length */\n+\n+\treturn p;\n+}\n+\n+void rpc_req_common(int rpc_prog, int rpc_proc, uint32_t *data, int datalen,\n+\t\t    uchar *txbuff, int *pktlen, int *sport)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\tunsigned long id;\n+\tu32 *p;\n+\n+\tid = ++rpc_id;\n+\trpc_pkt.u.call.id = htonl(id);\n+\trpc_pkt.u.call.type = htonl(MSG_CALL);\n+\trpc_pkt.u.call.rpcvers = htonl(2);\t/* use RPC version 2 */\n+\trpc_pkt.u.call.prog = htonl(rpc_prog);\n+\tswitch (rpc_prog) {\n+\tcase PROG_NFS:\n+\t\tswitch (choosen_nfs_version) {\n+\t\tcase NFS_V1:\n+\t\tcase NFS_V2:\n+\t\t\trpc_pkt.u.call.vers = htonl(2);\n+\t\t\tbreak;\n+\n+\t\tcase NFS_V3:\n+\t\t\trpc_pkt.u.call.vers = htonl(3);\n+\t\t\tbreak;\n+\n+\t\tcase NFS_UNKOWN:\n+\t\t\t/* nothing to do */\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\tcase PROG_MOUNT:\n+\t\tswitch (choosen_nfs_version) {\n+\t\tcase NFS_V1:\n+\t\t\trpc_pkt.u.call.vers = htonl(1);\n+\t\t\tbreak;\n+\n+\t\tcase NFS_V2:\n+\t\t\trpc_pkt.u.call.vers = htonl(2);\n+\t\t\tbreak;\n+\n+\t\tcase NFS_V3:\n+\t\t\trpc_pkt.u.call.vers = htonl(3);\n+\t\t\tbreak;\n+\n+\t\tcase NFS_UNKOWN:\n+\t\t\t/* nothing to do */\n+\t\t\tbreak;\n+\t\t}\n+\t\tbreak;\n+\tcase PROG_PORTMAP:\n+\tdefault:\n+\t\trpc_pkt.u.call.vers = htonl(2);\t/* portmapper is version 2 */\n+\t}\n+\trpc_pkt.u.call.proc = htonl(rpc_proc);\n+\tp = rpc_pkt.u.call.data;\n+\n+\tif (datalen)\n+\t\tmemcpy(p, data, datalen * sizeof(uint32_t));\n+\n+\t*pktlen = (char *)p + datalen * sizeof(uint32_t) - (char *)&rpc_pkt;\n+\n+\tmemcpy(txbuff, &rpc_pkt.u.data[0], *pktlen);\n+\n+\tif (rpc_prog == PROG_PORTMAP)\n+\t\t*sport = SUNRPC_PORT;\n+\telse if (rpc_prog == PROG_MOUNT)\n+\t\t*sport = nfs_server_mount_port;\n+\telse\n+\t\t*sport = nfs_server_port;\n+}\n+\n+/**************************************************************************\n+ * RPC_LOOKUP - Lookup RPC Port numbers\n+ **************************************************************************\n+ */\n+static void rpc_lookup_req(int prog, int ver)\n+{\n+\tu32 data[16];\n+\n+\tdata[0] = 0; data[1] = 0;\t/* auth credential */\n+\tdata[2] = 0; data[3] = 0;\t/* auth verifier */\n+\tdata[4] = htonl(prog);\n+\tdata[5] = htonl(ver);\n+\tdata[6] = htonl(17);\t/* IP_UDP */\n+\tdata[7] = 0;\n+\trpc_req(PROG_PORTMAP, PORTMAP_GETPORT, data, 8);\n+}\n+\n+/**************************************************************************\n+ * NFS_MOUNT - Mount an NFS Filesystem\n+ **************************************************************************\n+ */\n+static void nfs_mount_req(char *path)\n+{\n+\tu32 data[1024];\n+\tu32 *p;\n+\tint len;\n+\tint pathlen;\n+\n+\tpathlen = strlen(path);\n+\n+\tp = &data[0];\n+\tp = rpc_add_credentials(p);\n+\n+\t*p++ = htonl(pathlen);\n+\tif (pathlen & 3)\n+\t\t*(p + pathlen / 4) = 0;\n+\tmemcpy(p, path, pathlen);\n+\tp += (pathlen + 3) / 4;\n+\n+\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\trpc_req(PROG_MOUNT, MOUNT_ADDENTRY, data, len);\n+}\n+\n+/**************************************************************************\n+ * NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server\n+ **************************************************************************\n+ */\n+static void nfs_umountall_req(void)\n+{\n+\tu32 data[1024];\n+\tu32 *p;\n+\tint len;\n+\n+\tif ((nfs_server_mount_port == -1) || !fs_mounted)\n+\t\t/* Nothing mounted, nothing to umount */\n+\t\treturn;\n+\n+\tp = &data[0];\n+\tp = rpc_add_credentials(p);\n+\n+\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\trpc_req(PROG_MOUNT, MOUNT_UMOUNTALL, data, len);\n+}\n+\n+/***************************************************************************\n+ * NFS_READLINK (AH 2003-07-14)\n+ * This procedure is called when read of the first block fails -\n+ * this probably happens when it's a directory or a symlink\n+ * In case of successful readlink(), the dirname is manipulated,\n+ * so that inside the nfs() function a recursion can be done.\n+ ***************************************************************************\n+ */\n+static void nfs_readlink_req(void)\n+{\n+\tu32 data[1024];\n+\tu32 *p;\n+\tint len;\n+\n+\tp = &data[0];\n+\tp = rpc_add_credentials(p);\n+\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\tmemcpy(p, filefh, NFS_FHSIZE);\n+\t\tp += (NFS_FHSIZE / 4);\n+\t} else { /* NFS_V3 */\n+\t\t*p++ = htonl(filefh3_length);\n+\t\tmemcpy(p, filefh, filefh3_length);\n+\t\tp += (filefh3_length / 4);\n+\t}\n+\n+\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\trpc_req(PROG_NFS, NFS_READLINK, data, len);\n+}\n+\n+/**************************************************************************\n+ * NFS_LOOKUP - Lookup Pathname\n+ **************************************************************************\n+ */\n+static void nfs_lookup_req(char *fname)\n+{\n+\tu32 data[1024];\n+\tu32 *p;\n+\tint len;\n+\tint fnamelen;\n+\n+\tfnamelen = strlen(fname);\n+\n+\tp = &data[0];\n+\tp = rpc_add_credentials(p);\n+\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\tmemcpy(p, dirfh, NFS_FHSIZE);\n+\t\tp += (NFS_FHSIZE / 4);\n+\t\t*p++ = htonl(fnamelen);\n+\t\tif (fnamelen & 3)\n+\t\t\t*(p + fnamelen / 4) = 0;\n+\t\tmemcpy(p, fname, fnamelen);\n+\t\tp += (fnamelen + 3) / 4;\n+\n+\t\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\t\trpc_req(PROG_NFS, NFS_LOOKUP, data, len);\n+\t} else {  /* NFS_V3 */\n+\t\t*p++ = htonl(dirfh3_length);\t/* Dir handle length */\n+\t\tmemcpy(p, dirfh, dirfh3_length);\n+\t\tp += (dirfh3_length / 4);\n+\t\t*p++ = htonl(fnamelen);\n+\t\tif (fnamelen & 3)\n+\t\t\t*(p + fnamelen / 4) = 0;\n+\t\tmemcpy(p, fname, fnamelen);\n+\t\tp += (fnamelen + 3) / 4;\n+\n+\t\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\t\trpc_req(PROG_NFS, NFS3PROC_LOOKUP, data, len);\n+\t}\n+}\n+\n+/**************************************************************************\n+ * NFS_READ - Read File on NFS Server\n+ **************************************************************************\n+ */\n+static void nfs_read_req(int offset, int readlen)\n+{\n+\tu32 data[1024];\n+\tu32 *p;\n+\tint len;\n+\n+\tp = &data[0];\n+\tp = rpc_add_credentials(p);\n+\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\tmemcpy(p, filefh, NFS_FHSIZE);\n+\t\tp += (NFS_FHSIZE / 4);\n+\t\t*p++ = htonl(offset);\n+\t\t*p++ = htonl(readlen);\n+\t\t*p++ = 0;\n+\t} else { /* NFS_V3 */\n+\t\t*p++ = htonl(filefh3_length);\n+\t\tmemcpy(p, filefh, filefh3_length);\n+\t\tp += (filefh3_length / 4);\n+\t\t*p++ = htonl(0); /* offset is 64-bit long, so fill with 0 */\n+\t\t*p++ = htonl(offset);\n+\t\t*p++ = htonl(readlen);\n+\t\t*p++ = 0;\n+\t}\n+\n+\tlen = (uint32_t *)p - (uint32_t *)&data[0];\n+\n+\trpc_req(PROG_NFS, NFS_READ, data, len);\n+}\n+\n+/**************************************************************************\n+ * RPC request dispatcher\n+ **************************************************************************\n+ */\n+void nfs_send(void)\n+{\n+\tswitch (nfs_state) {\n+\tcase STATE_PRCLOOKUP_PROG_MOUNT_REQ:\n+\t\tif (choosen_nfs_version != NFS_V3)\n+\t\t\trpc_lookup_req(PROG_MOUNT, 1);\n+\t\telse  /* NFS_V3 */\n+\t\t\trpc_lookup_req(PROG_MOUNT, 3);\n+\t\tbreak;\n+\tcase STATE_PRCLOOKUP_PROG_NFS_REQ:\n+\t\tif (choosen_nfs_version != NFS_V3)\n+\t\t\trpc_lookup_req(PROG_NFS, 2);\n+\t\telse  /* NFS_V3 */\n+\t\t\trpc_lookup_req(PROG_NFS, 3);\n+\t\tbreak;\n+\tcase STATE_MOUNT_REQ:\n+\t\tnfs_mount_req(nfs_path);\n+\t\tbreak;\n+\tcase STATE_UMOUNT_REQ:\n+\t\tnfs_umountall_req();\n+\t\tbreak;\n+\tcase STATE_LOOKUP_REQ:\n+\t\tnfs_lookup_req(nfs_filename);\n+\t\tbreak;\n+\tcase STATE_READ_REQ:\n+\t\tnfs_read_req(nfs_offset, nfs_len);\n+\t\tbreak;\n+\tcase STATE_READLINK_REQ:\n+\t\tnfs_readlink_req();\n+\t\tbreak;\n+\t}\n+}\n+\n+/**************************************************************************\n+ * Handlers for the reply from server\n+ **************************************************************************\n+ */\n+\n+static int rpc_handle_error(struct rpc_t *rpc_pkt)\n+{\n+\tif (rpc_pkt->u.reply.rstatus  ||\n+\t    rpc_pkt->u.reply.verifier ||\n+\t    rpc_pkt->u.reply.astatus  ||\n+\t    rpc_pkt->u.reply.data[0]) {\n+\t\tswitch (ntohl(rpc_pkt->u.reply.astatus)) {\n+\t\tcase NFS_RPC_SUCCESS: /* Not an error */\n+\t\t\tbreak;\n+\t\tcase NFS_RPC_PROG_MISMATCH: {\n+\t\t\t/* Remote can't support NFS version */\n+\t\t\tconst int min = ntohl(rpc_pkt->u.reply.data[0]);\n+\t\t\tconst int max = ntohl(rpc_pkt->u.reply.data[1]);\n+\n+\t\t\tif (max < NFS_V1 || max > NFS_V3 || min > NFS_V3) {\n+\t\t\t\tputs(\"*** ERROR: NFS version not supported\");\n+\t\t\t\tdebug(\": Requested: V%d, accepted: min V%d - max V%d\\n\",\n+\t\t\t\t      choosen_nfs_version,\n+\t\t\t\t      ntohl(rpc_pkt->u.reply.data[0]),\n+\t\t\t\t      ntohl(rpc_pkt->u.reply.data[1]));\n+\t\t\t\tputs(\"\\n\");\n+\t\t\t\tchoosen_nfs_version = NFS_UNKOWN;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tdebug(\"*** Warning: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\\n\",\n+\t\t\t      choosen_nfs_version,\n+\t\t\t      ntohl(rpc_pkt->u.reply.data[0]),\n+\t\t\t      ntohl(rpc_pkt->u.reply.data[1]));\n+\t\t\tdebug(\"Will retry with NFSv%d\\n\", min);\n+\t\t\tchoosen_nfs_version = min;\n+\t\t\treturn -NFS_RPC_PROG_MISMATCH;\n+\t\t}\n+\t\tcase NFS_RPC_PROG_UNAVAIL:\n+\t\tcase NFS_RPC_PROC_UNAVAIL:\n+\t\tcase NFS_RPC_GARBAGE_ARGS:\n+\t\tcase NFS_RPC_SYSTEM_ERR:\n+\t\tdefault: /* Unknown error on 'accept state' flag */\n+\t\t\tdebug(\"*** ERROR: accept state error (%d)\\n\",\n+\t\t\t      ntohl(rpc_pkt->u.reply.astatus));\n+\t\t\tbreak;\n+\t\t}\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int rpc_lookup_reply(int prog, uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\n+\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tif (rpc_pkt.u.reply.rstatus  ||\n+\t    rpc_pkt.u.reply.verifier ||\n+\t    rpc_pkt.u.reply.astatus)\n+\t\treturn -1;\n+\n+\tswitch (prog) {\n+\tcase PROG_MOUNT:\n+\t\tnfs_server_mount_port = ntohl(rpc_pkt.u.reply.data[0]);\n+\t\tbreak;\n+\tcase PROG_NFS:\n+\t\tnfs_server_port = ntohl(rpc_pkt.u.reply.data[0]);\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int nfs_mount_reply(uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\tint ret;\n+\n+\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tret = rpc_handle_error(&rpc_pkt);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfs_mounted = 1;\n+\t/*  NFSv2 and NFSv3 use same structure */\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\tmemcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);\n+\t} else {\n+\t\tdirfh3_length = ntohl(rpc_pkt.u.reply.data[1]);\n+\t\tif (dirfh3_length > NFS3_FHSIZE)\n+\t\t\tdirfh3_length  = NFS3_FHSIZE;\n+\t\tmemcpy(dirfh, rpc_pkt.u.reply.data + 2, dirfh3_length);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int nfs_umountall_reply(uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\n+\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tif (rpc_pkt.u.reply.rstatus  ||\n+\t    rpc_pkt.u.reply.verifier ||\n+\t    rpc_pkt.u.reply.astatus)\n+\t\treturn -1;\n+\n+\tfs_mounted = 0;\n+\tmemset(dirfh, 0, sizeof(dirfh));\n+\n+\treturn 0;\n+}\n+\n+static int nfs_lookup_reply(uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\tint ret;\n+\n+\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tret = rpc_handle_error(&rpc_pkt);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\tif (((uchar *)&rpc_pkt.u.reply.data[0] - (uchar *)&rpc_pkt + NFS_FHSIZE) > len)\n+\t\t\treturn -NFS_RPC_DROP;\n+\t\tmemcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);\n+\t} else {  /* NFS_V3 */\n+\t\tfilefh3_length = ntohl(rpc_pkt.u.reply.data[1]);\n+\t\tif (filefh3_length > NFS3_FHSIZE)\n+\t\t\tfilefh3_length  = NFS3_FHSIZE;\n+\t\tmemcpy(filefh, rpc_pkt.u.reply.data + 2, filefh3_length);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int nfs3_get_attributes_offset(uint32_t *data)\n+{\n+\tif (data[1]) {\n+\t\t/* 'attributes_follow' flag is TRUE,\n+\t\t * so we have attributes on 21 dwords\n+\t\t */\n+\t\t/* Skip unused values :\n+\t\t *\ttype;\t32 bits value,\n+\t\t *\tmode;\t32 bits value,\n+\t\t *\tnlink;\t32 bits value,\n+\t\t *\tuid;\t32 bits value,\n+\t\t *\tgid;\t32 bits value,\n+\t\t *\tsize;\t64 bits value,\n+\t\t *\tused;\t64 bits value,\n+\t\t *\trdev;\t64 bits value,\n+\t\t *\tfsid;\t64 bits value,\n+\t\t *\tfileid;\t64 bits value,\n+\t\t *\tatime;\t64 bits value,\n+\t\t *\tmtime;\t64 bits value,\n+\t\t *\tctime;\t64 bits value,\n+\t\t */\n+\t\treturn 22;\n+\t}\n+\n+\t/* 'attributes_follow' flag is FALSE,\n+\t * so we don't have any attributes\n+\t */\n+\treturn 1;\n+}\n+\n+static int nfs_readlink_reply(uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\tint rlen;\n+\tint nfsv3_data_offset = 0;\n+\n+\tmemcpy((unsigned char *)&rpc_pkt, pkt, len);\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tif (rpc_pkt.u.reply.rstatus  ||\n+\t    rpc_pkt.u.reply.verifier ||\n+\t    rpc_pkt.u.reply.astatus  ||\n+\t    rpc_pkt.u.reply.data[0])\n+\t\treturn -1;\n+\n+\tif (choosen_nfs_version == NFS_V3) {\n+\t\tnfsv3_data_offset =\n+\t\t\tnfs3_get_attributes_offset(rpc_pkt.u.reply.data);\n+\t}\n+\n+\t/* new path length */\n+\trlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);\n+\n+\tif (((uchar *)&rpc_pkt.u.reply.data[0] - (uchar *)&rpc_pkt + rlen) > len)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tif (*((char *)&rpc_pkt.u.reply.data[2 + nfsv3_data_offset]) != '/') {\n+\t\tint pathlen;\n+\n+\t\tstrcat(nfs_path, \"/\");\n+\t\tpathlen = strlen(nfs_path);\n+\t\tmemcpy(nfs_path + pathlen,\n+\t\t       (uchar *)&rpc_pkt.u.reply.data[2 + nfsv3_data_offset],\n+\t\t       rlen);\n+\t\tnfs_path[pathlen + rlen] = 0;\n+\t} else {\n+\t\tmemcpy(nfs_path,\n+\t\t       (uchar *)&rpc_pkt.u.reply.data[2 + nfsv3_data_offset],\n+\t\t       rlen);\n+\t\tnfs_path[rlen] = 0;\n+\t}\n+\treturn 0;\n+}\n+\n+static int nfs_read_reply(uchar *pkt, unsigned int len)\n+{\n+\tstruct rpc_t rpc_pkt;\n+\tint rlen;\n+\tuchar *data_ptr;\n+\n+\tmemcpy(&rpc_pkt.u.data[0], pkt, sizeof(rpc_pkt.u.reply));\n+\n+\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n+\t\treturn -NFS_RPC_ERR;\n+\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n+\t\treturn -NFS_RPC_DROP;\n+\n+\tif (rpc_pkt.u.reply.rstatus  ||\n+\t    rpc_pkt.u.reply.verifier ||\n+\t    rpc_pkt.u.reply.astatus  ||\n+\t    rpc_pkt.u.reply.data[0]) {\n+\t\tif (rpc_pkt.u.reply.rstatus)\n+\t\t\treturn -9999;\n+\t\tif (rpc_pkt.u.reply.astatus)\n+\t\t\treturn -9999;\n+\t\treturn -ntohl(rpc_pkt.u.reply.data[0]);\n+\t}\n+\n+\tif (nfs_offset != 0 && !((nfs_offset) %\n+\t\t\t(NFS_READ_SIZE / 2 * 10 * HASHES_PER_LINE)))\n+\t\tputs(\"\\n\\t \");\n+\tif (!(nfs_offset % ((NFS_READ_SIZE / 2) * 10)))\n+\t\tputc('#');\n+\n+\tif (choosen_nfs_version != NFS_V3) {\n+\t\trlen = ntohl(rpc_pkt.u.reply.data[18]);\n+\t\tdata_ptr = (uchar *)&rpc_pkt.u.reply.data[19];\n+\t} else {  /* NFS_V3 */\n+\t\tint nfsv3_data_offset =\n+\t\t\tnfs3_get_attributes_offset(rpc_pkt.u.reply.data);\n+\n+\t\t/* count value */\n+\t\trlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);\n+\t\t/* Skip unused values :\n+\t\t *\tEOF:\t\t32 bits value,\n+\t\t *\tdata_size:\t32 bits value,\n+\t\t */\n+\t\tdata_ptr = (uchar *)\n+\t\t\t&rpc_pkt.u.reply.data[4 + nfsv3_data_offset];\n+\t}\n+\n+\tif (((uchar *)&rpc_pkt.u.reply.data[0] - (uchar *)&rpc_pkt + rlen) > len)\n+\t\treturn -9999;\n+\n+\tif (store_block(data_ptr, nfs_offset, rlen))\n+\t\treturn -9999;\n+\n+\treturn rlen;\n+}\n+\n+void nfs_pkt_recv(uchar *pkt, unsigned int len)\n+{\n+\tint rlen;\n+\tint reply;\n+\n+\tswitch (nfs_state) {\n+\tcase STATE_PRCLOOKUP_PROG_MOUNT_REQ:\n+\t\tif (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP)\n+\t\t\tbreak;\n+\t\tnfs_state = STATE_PRCLOOKUP_PROG_NFS_REQ;\n+\t\tnfs_send();\n+\t\tbreak;\n+\n+\tcase STATE_PRCLOOKUP_PROG_NFS_REQ:\n+\t\tif (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP)\n+\t\t\tbreak;\n+\t\tnfs_state = STATE_MOUNT_REQ;\n+\t\tnfs_send();\n+\t\tbreak;\n+\n+\tcase STATE_MOUNT_REQ:\n+\t\treply = nfs_mount_reply(pkt, len);\n+\t\tif (reply == -NFS_RPC_DROP) {\n+\t\t\tbreak;\n+\t\t} else if (reply == -NFS_RPC_ERR) {\n+\t\t\tputs(\"*** ERROR: Cannot mount\\n\");\n+\t\t\t/* just to be sure... */\n+\t\t\tnfs_state = STATE_UMOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t} else if (reply == -NFS_RPC_PROG_MISMATCH &&\n+\t\t\t   choosen_nfs_version != NFS_UNKOWN) {\n+\t\t\tnfs_state = STATE_MOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t} else {\n+\t\t\tnfs_state = STATE_LOOKUP_REQ;\n+\t\t\tnfs_send();\n+\t\t}\n+\t\tbreak;\n+\n+\tcase STATE_UMOUNT_REQ:\n+\t\treply = nfs_umountall_reply(pkt, len);\n+\t\tif (reply == -NFS_RPC_DROP) {\n+\t\t\tbreak;\n+\t\t} else if (reply == -NFS_RPC_ERR) {\n+\t\t\tdebug(\"*** ERROR: Cannot umount\\n\");\n+\t\t\tnet_set_state(NETLOOP_FAIL);\n+\t\t} else {\n+\t\t\tputs(\"\\ndone\\n\");\n+\t\t\tnet_set_state(nfs_download_state);\n+\t\t}\n+\t\tbreak;\n+\n+\tcase STATE_LOOKUP_REQ:\n+\t\treply = nfs_lookup_reply(pkt, len);\n+\t\tif (reply == -NFS_RPC_DROP) {\n+\t\t\tbreak;\n+\t\t} else if (reply == -NFS_RPC_ERR) {\n+\t\t\tputs(\"*** ERROR: File lookup fail\\n\");\n+\t\t\tnfs_state = STATE_UMOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t} else if (reply == -NFS_RPC_PROG_MISMATCH &&\n+\t\t\t   choosen_nfs_version != NFS_UNKOWN) {\n+\t\t\t/* umount */\n+\t\t\tnfs_state = STATE_UMOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t\t/* And retry with another supported version */\n+\t\t\tnfs_state = STATE_PRCLOOKUP_PROG_MOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t} else {\n+\t\t\tnfs_state = STATE_READ_REQ;\n+\t\t\tnfs_offset = 0;\n+\t\t\tnfs_len = NFS_READ_SIZE;\n+\t\t\tnfs_send();\n+\t\t}\n+\t\tbreak;\n+\n+\tcase STATE_READLINK_REQ:\n+\t\treply = nfs_readlink_reply(pkt, len);\n+\t\tif (reply == -NFS_RPC_DROP) {\n+\t\t\tbreak;\n+\t\t} else if (reply == -NFS_RPC_ERR) {\n+\t\t\tputs(\"*** ERROR: Symlink fail\\n\");\n+\t\t\tnfs_state = STATE_UMOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t} else {\n+\t\t\tdebug(\"Symlink --> %s\\n\", nfs_path);\n+\t\t\tnfs_filename = nfs_basename(nfs_path);\n+\t\t\tnfs_path     = nfs_dirname(nfs_path);\n+\n+\t\t\tnfs_state = STATE_MOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t}\n+\t\tbreak;\n+\n+\tcase STATE_READ_REQ:\n+\t\trlen = nfs_read_reply(pkt, len);\n+\t\tif (rlen == -NFS_RPC_DROP)\n+\t\t\tbreak;\n+\t\tnfs_refresh_timeout();\n+\t\tif (rlen > 0) {\n+\t\t\tnfs_offset += rlen;\n+\t\t\tnfs_send();\n+\t\t} else if ((rlen == -NFSERR_ISDIR) || (rlen == -NFSERR_INVAL)) {\n+\t\t\t/* symbolic link */\n+\t\t\tnfs_state = STATE_READLINK_REQ;\n+\t\t\tnfs_send();\n+\t\t} else {\n+\t\t\tif (!rlen)\n+\t\t\t\tnfs_download_state = NETLOOP_SUCCESS;\n+\t\t\tif (rlen < 0)\n+\t\t\t\tdebug(\"NFS READ error (%d)\\n\", rlen);\n+\t\t\tnfs_state = STATE_UMOUNT_REQ;\n+\t\t\tnfs_send();\n+\t\t}\n+\t\tbreak;\n+\t}\n+}\n+\ndiff --git a/net/nfs-common.h b/net/nfs-common.h\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..a19b98b7b1f0cb323d5384ee8c22bf058f6446c9\n--- /dev/null\n+++ b/net/nfs-common.h\n@@ -0,0 +1,123 @@\n+/* SPDX-License-Identifier: GPL-2.0+ */\n+/*\n+ * (C) Masami Komiya <mkomiya@sonare.it> 2004\n+ */\n+\n+#ifndef __NFS_COMMON_H__\n+#define __NFS_COMMON_H__\n+\n+#define SUNRPC_PORT     111\n+\n+#define PROG_PORTMAP    100000\n+#define PROG_NFS        100003\n+#define PROG_MOUNT      100005\n+\n+#define MSG_CALL        0\n+#define MSG_REPLY       1\n+\n+#define HASHES_PER_LINE 65\t/* Number of \"loading\" hashes per line\t*/\n+#define NFS_RETRY_COUNT 30\n+\n+#define NFS_RPC_ERR\t1\n+#define NFS_RPC_DROP\t124\n+\n+#define NFSERR_PERM     1\n+#define NFSERR_NOENT    2\n+#define NFSERR_ACCES    13\n+#define NFSERR_ISDIR    21\n+#define NFSERR_INVAL    22\n+\n+/* Values for Accept State flag on RPC answers (See: rfc1831) */\n+enum rpc_accept_stat {\n+\tNFS_RPC_SUCCESS = 0,\t/* RPC executed successfully */\n+\tNFS_RPC_PROG_UNAVAIL = 1,\t/* remote hasn't exported program */\n+\tNFS_RPC_PROG_MISMATCH = 2,\t/* remote can't support version # */\n+\tNFS_RPC_PROC_UNAVAIL = 3,\t/* program can't support procedure */\n+\tNFS_RPC_GARBAGE_ARGS = 4,\t/* procedure can't decode params */\n+\tNFS_RPC_SYSTEM_ERR = 5\t/* errors like memory allocation failure */\n+};\n+\n+enum nfs_version {\n+\tNFS_UNKOWN = 0,\n+\tNFS_V1 = 1,\n+\tNFS_V2 = 2,\n+\tNFS_V3 = 3,\n+};\n+\n+extern enum net_loop_state nfs_download_state;\n+extern char *nfs_filename;\n+extern char *nfs_path;\n+extern char nfs_path_buff[2048];\n+extern struct in_addr nfs_server_ip;\n+extern int nfs_server_mount_port;\n+extern int nfs_server_port;\n+extern int nfs_our_port;\n+extern int nfs_timeout_count;\n+extern unsigned long rpc_id;\n+extern int nfs_offset;\n+extern int nfs_len;\n+\n+extern const ulong nfs_timeout;\n+\n+extern int nfs_state;\n+#define STATE_PRCLOOKUP_PROG_MOUNT_REQ\t1\n+#define STATE_PRCLOOKUP_PROG_NFS_REQ\t2\n+#define STATE_MOUNT_REQ\t\t\t3\n+#define STATE_UMOUNT_REQ\t\t4\n+#define STATE_LOOKUP_REQ\t\t5\n+#define STATE_READ_REQ\t\t\t6\n+#define STATE_READLINK_REQ\t\t7\n+\n+/*\n+ * Block size used for NFS read accesses.  A RPC reply packet (including  all\n+ * headers) must fit within a single Ethernet frame to avoid fragmentation.\n+ * However, if CONFIG_IP_DEFRAG is set, a bigger value could be used.  In any\n+ * case, most NFS servers are optimized for a power of 2.\n+ */\n+#define NFS_READ_SIZE\t1024\t/* biggest power of two that fits Ether frame */\n+#define NFS_MAX_ATTRS\t26\n+\n+struct rpc_t {\n+\tunion {\n+\t\tu8 data[NFS_READ_SIZE + (6 + NFS_MAX_ATTRS) *\n+\t\t\tsizeof(uint32_t)];\n+\t\tstruct {\n+\t\t\tu32 id;\n+\t\t\tu32 type;\n+\t\t\tu32 rpcvers;\n+\t\t\tu32 prog;\n+\t\t\tu32 vers;\n+\t\t\tu32 proc;\n+\t\t\tu32 data[1];\n+\t\t} call;\n+\t\tstruct {\n+\t\t\tu32 id;\n+\t\t\tu32 type;\n+\t\t\tu32 rstatus;\n+\t\t\tu32 verifier;\n+\t\t\tu32 v2;\n+\t\t\tu32 astatus;\n+\t\t\tu32 data[NFS_READ_SIZE / sizeof(u32) +\n+\t\t\t\tNFS_MAX_ATTRS];\n+\t\t} reply;\n+\t} u;\n+};\n+\n+char *nfs_basename(char *path);\n+char *nfs_dirname(char *path);\n+void rpc_req_common(int rpc_prog, int rpc_proc, uint32_t *data, int datalen,\n+\t\t    uchar *txbuff, int *pktlen, int *sport);\n+void nfs_send(void);\n+void nfs_pkt_recv(uchar *pkt, unsigned int len);\n+\n+extern enum nfs_version choosen_nfs_version;\n+\n+/*\n+ * Implementation specific functions called from common code\n+ */\n+void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen);\n+void nfs_refresh_timeout(void);\n+\n+/**********************************************************************/\n+\n+#endif /* __NFS_COMMON_H__ */\ndiff --git a/net/nfs.c b/net/nfs.c\nindex 7bae7c78642cb33e5040c44ed9d0378222069923..f5edc9b043ae1f0f8a1404b28506b8ad120fc5a5 100644\n--- a/net/nfs.c\n+++ b/net/nfs.c\n@@ -31,745 +31,31 @@\n  * September 27, 2018. As of now, NFSv3 is the default choice. If the server\n  * does not support NFSv3, we fall back to versions 2 or 1. */\n \n-#include <command.h>\n #include <display_options.h>\n-#ifdef CONFIG_SYS_DIRECT_FLASH_NFS\n-#include <flash.h>\n-#endif\n #include <image.h>\n #include <log.h>\n #include <net.h>\n #include <malloc.h>\n-#include <mapmem.h>\n #include \"nfs.h\"\n-#include \"bootp.h\"\n+#include \"nfs-common.h\"\n #include <time.h>\n \n-#define HASHES_PER_LINE 65\t/* Number of \"loading\" hashes per line\t*/\n-#define NFS_RETRY_COUNT 30\n-\n-#define NFS_RPC_ERR\t1\n-#define NFS_RPC_DROP\t124\n-\n-static int fs_mounted;\n-static unsigned long rpc_id;\n-static int nfs_offset = -1;\n-static int nfs_len;\n-static const ulong nfs_timeout = CONFIG_NFS_TIMEOUT;\n-\n-static char dirfh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */\n-static unsigned int dirfh3_length; /* (variable) length of dirfh when NFSv3 */\n-static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */\n-static unsigned int filefh3_length;\t/* (variable) length of filefh when NFSv3 */\n-\n-static enum net_loop_state nfs_download_state;\n-static struct in_addr nfs_server_ip;\n-static int nfs_server_mount_port;\n-static int nfs_server_port;\n-static int nfs_our_port;\n-static int nfs_timeout_count;\n-static int nfs_state;\n-#define STATE_PRCLOOKUP_PROG_MOUNT_REQ\t1\n-#define STATE_PRCLOOKUP_PROG_NFS_REQ\t2\n-#define STATE_MOUNT_REQ\t\t\t3\n-#define STATE_UMOUNT_REQ\t\t4\n-#define STATE_LOOKUP_REQ\t\t5\n-#define STATE_READ_REQ\t\t\t6\n-#define STATE_READLINK_REQ\t\t7\n-\n-static char *nfs_filename;\n-static char *nfs_path;\n-static char nfs_path_buff[2048];\n-\n-enum nfs_version {\n-\tNFS_UNKOWN = 0,\n-\tNFS_V1 = 1,\n-\tNFS_V2 = 2,\n-\tNFS_V3 = 3,\n-};\n-\n-static enum nfs_version choosen_nfs_version = NFS_V3;\n-static inline int store_block(uchar *src, unsigned offset, unsigned len)\n-{\n-\tulong newsize = offset + len;\n-#ifdef CONFIG_SYS_DIRECT_FLASH_NFS\n-\tint i, rc = 0;\n-\n-\tfor (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {\n-\t\t/* start address in flash? */\n-\t\tif (image_load_addr + offset >= flash_info[i].start[0]) {\n-\t\t\trc = 1;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\tif (rc) { /* Flash is destination for this packet */\n-\t\trc = flash_write((uchar *)src, (ulong)image_load_addr + offset,\n-\t\t\t\t len);\n-\t\tif (rc) {\n-\t\t\tflash_perror(rc);\n-\t\t\treturn -1;\n-\t\t}\n-\t} else\n-#endif /* CONFIG_SYS_DIRECT_FLASH_NFS */\n-\t{\n-\t\tvoid *ptr = map_sysmem(image_load_addr + offset, len);\n-\n-\t\tmemcpy(ptr, src, len);\n-\t\tunmap_sysmem(ptr);\n-\t}\n-\n-\tif (net_boot_file_size < (offset + len))\n-\t\tnet_boot_file_size = newsize;\n-\treturn 0;\n-}\n-\n-static char *basename(char *path)\n-{\n-\tchar *fname;\n-\n-\tfname = path + strlen(path) - 1;\n-\twhile (fname >= path) {\n-\t\tif (*fname == '/') {\n-\t\t\tfname++;\n-\t\t\tbreak;\n-\t\t}\n-\t\tfname--;\n-\t}\n-\treturn fname;\n-}\n-\n-static char *dirname(char *path)\n-{\n-\tchar *fname;\n-\n-\tfname = basename(path);\n-\t--fname;\n-\t*fname = '\\0';\n-\treturn path;\n-}\n-\n-/**************************************************************************\n-RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries\n-**************************************************************************/\n-static uint32_t *rpc_add_credentials(uint32_t *p)\n-{\n-\t/* Here's the executive summary on authentication requirements of the\n-\t * various NFS server implementations:\tLinux accepts both AUTH_NONE\n-\t * and AUTH_UNIX authentication (also accepts an empty hostname field\n-\t * in the AUTH_UNIX scheme).  *BSD refuses AUTH_NONE, but accepts\n-\t * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX\n-\t * scheme).  To be safe, use AUTH_UNIX and pass the hostname if we have\n-\t * it (if the BOOTP/DHCP reply didn't give one, just use an empty\n-\t * hostname).  */\n-\n-\t/* Provide an AUTH_UNIX credential.  */\n-\t*p++ = htonl(1);\t\t/* AUTH_UNIX */\n-\t*p++ = htonl(20);\t\t/* auth length */\n-\t*p++ = 0;\t\t\t/* stamp */\n-\t*p++ = 0;\t\t\t/* hostname string */\n-\t*p++ = 0;\t\t\t/* uid */\n-\t*p++ = 0;\t\t\t/* gid */\n-\t*p++ = 0;\t\t\t/* auxiliary gid list */\n-\n-\t/* Provide an AUTH_NONE verifier.  */\n-\t*p++ = 0;\t\t\t/* AUTH_NONE */\n-\t*p++ = 0;\t\t\t/* auth length */\n-\n-\treturn p;\n-}\n-\n /**************************************************************************\n RPC_LOOKUP - Lookup RPC Port numbers\n **************************************************************************/\n-static void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)\n+void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen)\n {\n-\tstruct rpc_t rpc_pkt;\n-\tunsigned long id;\n-\tuint32_t *p;\n \tint pktlen;\n \tint sport;\n \n-\tid = ++rpc_id;\n-\trpc_pkt.u.call.id = htonl(id);\n-\trpc_pkt.u.call.type = htonl(MSG_CALL);\n-\trpc_pkt.u.call.rpcvers = htonl(2);\t/* use RPC version 2 */\n-\trpc_pkt.u.call.prog = htonl(rpc_prog);\n-\tswitch (rpc_prog) {\n-\tcase PROG_NFS:\n-\t\tswitch (choosen_nfs_version) {\n-\t\tcase NFS_V1:\n-\t\tcase NFS_V2:\n-\t\t\trpc_pkt.u.call.vers = htonl(2);\n-\t\t\tbreak;\n-\n-\t\tcase NFS_V3:\n-\t\t\trpc_pkt.u.call.vers = htonl(3);\n-\t\t\tbreak;\n-\n-\t\tcase NFS_UNKOWN:\n-\t\t\t/* nothing to do */\n-\t\t\tbreak;\n-\t\t}\n-\t\tbreak;\n-\tcase PROG_MOUNT:\n-\t\tswitch (choosen_nfs_version) {\n-\t\tcase NFS_V1:\n-\t\t\trpc_pkt.u.call.vers = htonl(1);\n-\t\t\tbreak;\n-\n-\t\tcase NFS_V2:\n-\t\t\trpc_pkt.u.call.vers = htonl(2);\n-\t\t\tbreak;\n-\n-\t\tcase NFS_V3:\n-\t\t\trpc_pkt.u.call.vers = htonl(3);\n-\t\t\tbreak;\n-\n-\t\tcase NFS_UNKOWN:\n-\t\t\t/* nothing to do */\n-\t\t\tbreak;\n-\t\t}\n-\t\tbreak;\n-\tcase PROG_PORTMAP:\n-\tdefault:\n-\t\trpc_pkt.u.call.vers = htonl(2);\t/* portmapper is version 2 */\n-\t}\n-\trpc_pkt.u.call.proc = htonl(rpc_proc);\n-\tp = rpc_pkt.u.call.data;\n-\n-\tif (datalen)\n-\t\tmemcpy(p, data, datalen * sizeof(uint32_t));\n-\n-\tpktlen = (char *)p + datalen * sizeof(uint32_t) - (char *)&rpc_pkt;\n-\n-\tmemcpy((char *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE,\n-\t       &rpc_pkt.u.data[0], pktlen);\n-\n-\tif (rpc_prog == PROG_PORTMAP)\n-\t\tsport = SUNRPC_PORT;\n-\telse if (rpc_prog == PROG_MOUNT)\n-\t\tsport = nfs_server_mount_port;\n-\telse\n-\t\tsport = nfs_server_port;\n+\trpc_req_common(rpc_prog, rpc_proc, data, datalen,\n+\t\t       (char *)net_tx_packet + net_eth_hdr_size()\n+\t\t       + IP_UDP_HDR_SIZE, &pktlen, &sport);\n \n \tnet_send_udp_packet(net_server_ethaddr, nfs_server_ip, sport,\n \t\t\t    nfs_our_port, pktlen);\n }\n \n-/**************************************************************************\n-RPC_LOOKUP - Lookup RPC Port numbers\n-**************************************************************************/\n-static void rpc_lookup_req(int prog, int ver)\n-{\n-\tuint32_t data[16];\n-\n-\tdata[0] = 0; data[1] = 0;\t/* auth credential */\n-\tdata[2] = 0; data[3] = 0;\t/* auth verifier */\n-\tdata[4] = htonl(prog);\n-\tdata[5] = htonl(ver);\n-\tdata[6] = htonl(17);\t/* IP_UDP */\n-\tdata[7] = 0;\n-\trpc_req(PROG_PORTMAP, PORTMAP_GETPORT, data, 8);\n-}\n-\n-/**************************************************************************\n-NFS_MOUNT - Mount an NFS Filesystem\n-**************************************************************************/\n-static void nfs_mount_req(char *path)\n-{\n-\tuint32_t data[1024];\n-\tuint32_t *p;\n-\tint len;\n-\tint pathlen;\n-\n-\tpathlen = strlen(path);\n-\n-\tp = &(data[0]);\n-\tp = rpc_add_credentials(p);\n-\n-\t*p++ = htonl(pathlen);\n-\tif (pathlen & 3)\n-\t\t*(p + pathlen / 4) = 0;\n-\tmemcpy(p, path, pathlen);\n-\tp += (pathlen + 3) / 4;\n-\n-\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\trpc_req(PROG_MOUNT, MOUNT_ADDENTRY, data, len);\n-}\n-\n-/**************************************************************************\n-NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server\n-**************************************************************************/\n-static void nfs_umountall_req(void)\n-{\n-\tuint32_t data[1024];\n-\tuint32_t *p;\n-\tint len;\n-\n-\tif ((nfs_server_mount_port == -1) || (!fs_mounted))\n-\t\t/* Nothing mounted, nothing to umount */\n-\t\treturn;\n-\n-\tp = &(data[0]);\n-\tp = rpc_add_credentials(p);\n-\n-\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\trpc_req(PROG_MOUNT, MOUNT_UMOUNTALL, data, len);\n-}\n-\n-/***************************************************************************\n- * NFS_READLINK (AH 2003-07-14)\n- * This procedure is called when read of the first block fails -\n- * this probably happens when it's a directory or a symlink\n- * In case of successful readlink(), the dirname is manipulated,\n- * so that inside the nfs() function a recursion can be done.\n- **************************************************************************/\n-static void nfs_readlink_req(void)\n-{\n-\tuint32_t data[1024];\n-\tuint32_t *p;\n-\tint len;\n-\n-\tp = &(data[0]);\n-\tp = rpc_add_credentials(p);\n-\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\tmemcpy(p, filefh, NFS_FHSIZE);\n-\t\tp += (NFS_FHSIZE / 4);\n-\t} else { /* NFS_V3 */\n-\t\t*p++ = htonl(filefh3_length);\n-\t\tmemcpy(p, filefh, filefh3_length);\n-\t\tp += (filefh3_length / 4);\n-\t}\n-\n-\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\trpc_req(PROG_NFS, NFS_READLINK, data, len);\n-}\n-\n-/**************************************************************************\n-NFS_LOOKUP - Lookup Pathname\n-**************************************************************************/\n-static void nfs_lookup_req(char *fname)\n-{\n-\tuint32_t data[1024];\n-\tuint32_t *p;\n-\tint len;\n-\tint fnamelen;\n-\n-\tfnamelen = strlen(fname);\n-\n-\tp = &(data[0]);\n-\tp = rpc_add_credentials(p);\n-\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\tmemcpy(p, dirfh, NFS_FHSIZE);\n-\t\tp += (NFS_FHSIZE / 4);\n-\t\t*p++ = htonl(fnamelen);\n-\t\tif (fnamelen & 3)\n-\t\t\t*(p + fnamelen / 4) = 0;\n-\t\tmemcpy(p, fname, fnamelen);\n-\t\tp += (fnamelen + 3) / 4;\n-\n-\t\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\t\trpc_req(PROG_NFS, NFS_LOOKUP, data, len);\n-\t} else {  /* NFS_V3 */\n-\t\t*p++ = htonl(dirfh3_length);\t/* Dir handle length */\n-\t\tmemcpy(p, dirfh, dirfh3_length);\n-\t\tp += (dirfh3_length / 4);\n-\t\t*p++ = htonl(fnamelen);\n-\t\tif (fnamelen & 3)\n-\t\t\t*(p + fnamelen / 4) = 0;\n-\t\tmemcpy(p, fname, fnamelen);\n-\t\tp += (fnamelen + 3) / 4;\n-\n-\t\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\t\trpc_req(PROG_NFS, NFS3PROC_LOOKUP, data, len);\n-\t}\n-}\n-\n-/**************************************************************************\n-NFS_READ - Read File on NFS Server\n-**************************************************************************/\n-static void nfs_read_req(int offset, int readlen)\n-{\n-\tuint32_t data[1024];\n-\tuint32_t *p;\n-\tint len;\n-\n-\tp = &(data[0]);\n-\tp = rpc_add_credentials(p);\n-\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\tmemcpy(p, filefh, NFS_FHSIZE);\n-\t\tp += (NFS_FHSIZE / 4);\n-\t\t*p++ = htonl(offset);\n-\t\t*p++ = htonl(readlen);\n-\t\t*p++ = 0;\n-\t} else { /* NFS_V3 */\n-\t\t*p++ = htonl(filefh3_length);\n-\t\tmemcpy(p, filefh, filefh3_length);\n-\t\tp += (filefh3_length / 4);\n-\t\t*p++ = htonl(0); /* offset is 64-bit long, so fill with 0 */\n-\t\t*p++ = htonl(offset);\n-\t\t*p++ = htonl(readlen);\n-\t\t*p++ = 0;\n-\t}\n-\n-\tlen = (uint32_t *)p - (uint32_t *)&(data[0]);\n-\n-\trpc_req(PROG_NFS, NFS_READ, data, len);\n-}\n-\n-/**************************************************************************\n-RPC request dispatcher\n-**************************************************************************/\n-static void nfs_send(void)\n-{\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tswitch (nfs_state) {\n-\tcase STATE_PRCLOOKUP_PROG_MOUNT_REQ:\n-\t\tif (choosen_nfs_version != NFS_V3)\n-\t\t\trpc_lookup_req(PROG_MOUNT, 1);\n-\t\telse  /* NFS_V3 */\n-\t\t\trpc_lookup_req(PROG_MOUNT, 3);\n-\t\tbreak;\n-\tcase STATE_PRCLOOKUP_PROG_NFS_REQ:\n-\t\tif (choosen_nfs_version != NFS_V3)\n-\t\t\trpc_lookup_req(PROG_NFS, 2);\n-\t\telse  /* NFS_V3 */\n-\t\t\trpc_lookup_req(PROG_NFS, 3);\n-\t\tbreak;\n-\tcase STATE_MOUNT_REQ:\n-\t\tnfs_mount_req(nfs_path);\n-\t\tbreak;\n-\tcase STATE_UMOUNT_REQ:\n-\t\tnfs_umountall_req();\n-\t\tbreak;\n-\tcase STATE_LOOKUP_REQ:\n-\t\tnfs_lookup_req(nfs_filename);\n-\t\tbreak;\n-\tcase STATE_READ_REQ:\n-\t\tnfs_read_req(nfs_offset, nfs_len);\n-\t\tbreak;\n-\tcase STATE_READLINK_REQ:\n-\t\tnfs_readlink_req();\n-\t\tbreak;\n-\t}\n-}\n-\n-/**************************************************************************\n-Handlers for the reply from server\n-**************************************************************************/\n-\n-static int rpc_handle_error(struct rpc_t *rpc_pkt)\n-{\n-\tif (rpc_pkt->u.reply.rstatus  ||\n-\t    rpc_pkt->u.reply.verifier ||\n-\t    rpc_pkt->u.reply.astatus  ||\n-\t    rpc_pkt->u.reply.data[0]) {\n-\t\tswitch (ntohl(rpc_pkt->u.reply.astatus)) {\n-\t\tcase NFS_RPC_SUCCESS: /* Not an error */\n-\t\t\tbreak;\n-\t\tcase NFS_RPC_PROG_MISMATCH: {\n-\t\t\t/* Remote can't support NFS version */\n-\t\t\tconst int min = ntohl(rpc_pkt->u.reply.data[0]);\n-\t\t\tconst int max = ntohl(rpc_pkt->u.reply.data[1]);\n-\n-\t\t\tif (max < NFS_V1 || max > NFS_V3 || min > NFS_V3) {\n-\t\t\t\tputs(\"*** ERROR: NFS version not supported\");\n-\t\t\t\tdebug(\": Requested: V%d, accepted: min V%d - max V%d\\n\",\n-\t\t\t\t      choosen_nfs_version,\n-\t\t\t\t      ntohl(rpc_pkt->u.reply.data[0]),\n-\t\t\t\t      ntohl(rpc_pkt->u.reply.data[1]));\n-\t\t\t\tputs(\"\\n\");\n-\t\t\t\tchoosen_nfs_version = NFS_UNKOWN;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\n-\t\t\tdebug(\"*** Warning: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\\n\",\n-\t\t\t      choosen_nfs_version,\n-\t\t\t      ntohl(rpc_pkt->u.reply.data[0]),\n-\t\t\t      ntohl(rpc_pkt->u.reply.data[1]));\n-\t\t\tdebug(\"Will retry with NFSv%d\\n\", min);\n-\t\t\tchoosen_nfs_version = min;\n-\t\t\treturn -NFS_RPC_PROG_MISMATCH;\n-\t\t}\n-\t\tcase NFS_RPC_PROG_UNAVAIL:\n-\t\tcase NFS_RPC_PROC_UNAVAIL:\n-\t\tcase NFS_RPC_GARBAGE_ARGS:\n-\t\tcase NFS_RPC_SYSTEM_ERR:\n-\t\tdefault: /* Unknown error on 'accept state' flag */\n-\t\t\tdebug(\"*** ERROR: accept state error (%d)\\n\",\n-\t\t\t      ntohl(rpc_pkt->u.reply.astatus));\n-\t\t\tbreak;\n-\t\t}\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int rpc_lookup_reply(int prog, uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\n-\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tif (rpc_pkt.u.reply.rstatus  ||\n-\t    rpc_pkt.u.reply.verifier ||\n-\t    rpc_pkt.u.reply.astatus)\n-\t\treturn -1;\n-\n-\tswitch (prog) {\n-\tcase PROG_MOUNT:\n-\t\tnfs_server_mount_port = ntohl(rpc_pkt.u.reply.data[0]);\n-\t\tbreak;\n-\tcase PROG_NFS:\n-\t\tnfs_server_port = ntohl(rpc_pkt.u.reply.data[0]);\n-\t\tbreak;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int nfs_mount_reply(uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\tint ret;\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tret = rpc_handle_error(&rpc_pkt);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tfs_mounted = 1;\n-\t/*  NFSv2 and NFSv3 use same structure */\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\tmemcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);\n-\t} else {\n-\t\tdirfh3_length = ntohl(rpc_pkt.u.reply.data[1]);\n-\t\tif (dirfh3_length > NFS3_FHSIZE)\n-\t\t\tdirfh3_length  = NFS3_FHSIZE;\n-\t\tmemcpy(dirfh, rpc_pkt.u.reply.data + 2, dirfh3_length);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int nfs_umountall_reply(uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tif (rpc_pkt.u.reply.rstatus  ||\n-\t    rpc_pkt.u.reply.verifier ||\n-\t    rpc_pkt.u.reply.astatus)\n-\t\treturn -1;\n-\n-\tfs_mounted = 0;\n-\tmemset(dirfh, 0, sizeof(dirfh));\n-\n-\treturn 0;\n-}\n-\n-static int nfs_lookup_reply(uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\tint ret;\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tmemcpy(&rpc_pkt.u.data[0], pkt, len);\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tret = rpc_handle_error(&rpc_pkt);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\tif (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + NFS_FHSIZE) > len)\n-\t\t\treturn -NFS_RPC_DROP;\n-\t\tmemcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);\n-\t} else {  /* NFS_V3 */\n-\t\tfilefh3_length = ntohl(rpc_pkt.u.reply.data[1]);\n-\t\tif (filefh3_length > NFS3_FHSIZE)\n-\t\t\tfilefh3_length  = NFS3_FHSIZE;\n-\t\tmemcpy(filefh, rpc_pkt.u.reply.data + 2, filefh3_length);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int nfs3_get_attributes_offset(uint32_t *data)\n-{\n-\tif (data[1]) {\n-\t\t/* 'attributes_follow' flag is TRUE,\n-\t\t * so we have attributes on 21 dwords */\n-\t\t/* Skip unused values :\n-\t\t\ttype;\t32 bits value,\n-\t\t\tmode;\t32 bits value,\n-\t\t\tnlink;\t32 bits value,\n-\t\t\tuid;\t32 bits value,\n-\t\t\tgid;\t32 bits value,\n-\t\t\tsize;\t64 bits value,\n-\t\t\tused;\t64 bits value,\n-\t\t\trdev;\t64 bits value,\n-\t\t\tfsid;\t64 bits value,\n-\t\t\tfileid;\t64 bits value,\n-\t\t\tatime;\t64 bits value,\n-\t\t\tmtime;\t64 bits value,\n-\t\t\tctime;\t64 bits value,\n-\t\t*/\n-\t\treturn 22;\n-\t} else {\n-\t\t/* 'attributes_follow' flag is FALSE,\n-\t\t * so we don't have any attributes */\n-\t\treturn 1;\n-\t}\n-}\n-\n-static int nfs_readlink_reply(uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\tint rlen;\n-\tint nfsv3_data_offset = 0;\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tmemcpy((unsigned char *)&rpc_pkt, pkt, len);\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tif (rpc_pkt.u.reply.rstatus  ||\n-\t    rpc_pkt.u.reply.verifier ||\n-\t    rpc_pkt.u.reply.astatus  ||\n-\t    rpc_pkt.u.reply.data[0])\n-\t\treturn -1;\n-\n-\tif (choosen_nfs_version == NFS_V3) {\n-\t\tnfsv3_data_offset =\n-\t\t\tnfs3_get_attributes_offset(rpc_pkt.u.reply.data);\n-\t}\n-\n-\t/* new path length */\n-\trlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);\n-\n-\tif (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tif (*((char *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset])) != '/') {\n-\t\tint pathlen;\n-\n-\t\tstrcat(nfs_path, \"/\");\n-\t\tpathlen = strlen(nfs_path);\n-\t\tmemcpy(nfs_path + pathlen,\n-\t\t       (uchar *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset]),\n-\t\t       rlen);\n-\t\tnfs_path[pathlen + rlen] = 0;\n-\t} else {\n-\t\tmemcpy(nfs_path,\n-\t\t       (uchar *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset]),\n-\t\t       rlen);\n-\t\tnfs_path[rlen] = 0;\n-\t}\n-\treturn 0;\n-}\n-\n-static int nfs_read_reply(uchar *pkt, unsigned len)\n-{\n-\tstruct rpc_t rpc_pkt;\n-\tint rlen;\n-\tuchar *data_ptr;\n-\n-\tdebug(\"%s\\n\", __func__);\n-\n-\tmemcpy(&rpc_pkt.u.data[0], pkt, sizeof(rpc_pkt.u.reply));\n-\n-\tif (ntohl(rpc_pkt.u.reply.id) > rpc_id)\n-\t\treturn -NFS_RPC_ERR;\n-\telse if (ntohl(rpc_pkt.u.reply.id) < rpc_id)\n-\t\treturn -NFS_RPC_DROP;\n-\n-\tif (rpc_pkt.u.reply.rstatus  ||\n-\t    rpc_pkt.u.reply.verifier ||\n-\t    rpc_pkt.u.reply.astatus  ||\n-\t    rpc_pkt.u.reply.data[0]) {\n-\t\tif (rpc_pkt.u.reply.rstatus)\n-\t\t\treturn -9999;\n-\t\tif (rpc_pkt.u.reply.astatus)\n-\t\t\treturn -9999;\n-\t\treturn -ntohl(rpc_pkt.u.reply.data[0]);\n-\t}\n-\n-\tif ((nfs_offset != 0) && !((nfs_offset) %\n-\t\t\t(NFS_READ_SIZE / 2 * 10 * HASHES_PER_LINE)))\n-\t\tputs(\"\\n\\t \");\n-\tif (!(nfs_offset % ((NFS_READ_SIZE / 2) * 10)))\n-\t\tputc('#');\n-\n-\tif (choosen_nfs_version != NFS_V3) {\n-\t\trlen = ntohl(rpc_pkt.u.reply.data[18]);\n-\t\tdata_ptr = (uchar *)&(rpc_pkt.u.reply.data[19]);\n-\t} else {  /* NFS_V3 */\n-\t\tint nfsv3_data_offset =\n-\t\t\tnfs3_get_attributes_offset(rpc_pkt.u.reply.data);\n-\n-\t\t/* count value */\n-\t\trlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]);\n-\t\t/* Skip unused values :\n-\t\t\tEOF:\t\t32 bits value,\n-\t\t\tdata_size:\t32 bits value,\n-\t\t*/\n-\t\tdata_ptr = (uchar *)\n-\t\t\t&(rpc_pkt.u.reply.data[4 + nfsv3_data_offset]);\n-\t}\n-\n-\tif (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len)\n-\t\t\treturn -9999;\n-\n-\tif (store_block(data_ptr, nfs_offset, rlen))\n-\t\t\treturn -9999;\n-\n-\treturn rlen;\n-}\n-\n /**************************************************************************\n Interfaces of U-BOOT\n **************************************************************************/\n@@ -787,12 +73,14 @@ static void nfs_timeout_handler(void)\n \t}\n }\n \n+void nfs_refresh_timeout(void)\n+{\n+\tnet_set_timeout_handler(nfs_timeout, nfs_timeout_handler);\n+}\n+\n static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip,\n \t\t\tunsigned src, unsigned len)\n {\n-\tint rlen;\n-\tint reply;\n-\n \tdebug(\"%s\\n\", __func__);\n \n \tif (len > sizeof(struct rpc_t))\n@@ -801,117 +89,7 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip,\n \tif (dest != nfs_our_port)\n \t\treturn;\n \n-\tswitch (nfs_state) {\n-\tcase STATE_PRCLOOKUP_PROG_MOUNT_REQ:\n-\t\tif (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP)\n-\t\t\tbreak;\n-\t\tnfs_state = STATE_PRCLOOKUP_PROG_NFS_REQ;\n-\t\tnfs_send();\n-\t\tbreak;\n-\n-\tcase STATE_PRCLOOKUP_PROG_NFS_REQ:\n-\t\tif (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP)\n-\t\t\tbreak;\n-\t\tnfs_state = STATE_MOUNT_REQ;\n-\t\tnfs_send();\n-\t\tbreak;\n-\n-\tcase STATE_MOUNT_REQ:\n-\t\treply = nfs_mount_reply(pkt, len);\n-\t\tif (reply == -NFS_RPC_DROP) {\n-\t\t\tbreak;\n-\t\t} else if (reply == -NFS_RPC_ERR) {\n-\t\t\tputs(\"*** ERROR: Cannot mount\\n\");\n-\t\t\t/* just to be sure... */\n-\t\t\tnfs_state = STATE_UMOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t} else if (reply == -NFS_RPC_PROG_MISMATCH &&\n-\t\t\t   choosen_nfs_version != NFS_UNKOWN) {\n-\t\t\tnfs_state = STATE_MOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t} else {\n-\t\t\tnfs_state = STATE_LOOKUP_REQ;\n-\t\t\tnfs_send();\n-\t\t}\n-\t\tbreak;\n-\n-\tcase STATE_UMOUNT_REQ:\n-\t\treply = nfs_umountall_reply(pkt, len);\n-\t\tif (reply == -NFS_RPC_DROP) {\n-\t\t\tbreak;\n-\t\t} else if (reply == -NFS_RPC_ERR) {\n-\t\t\tdebug(\"*** ERROR: Cannot umount\\n\");\n-\t\t\tnet_set_state(NETLOOP_FAIL);\n-\t\t} else {\n-\t\t\tputs(\"\\ndone\\n\");\n-\t\t\tnet_set_state(nfs_download_state);\n-\t\t}\n-\t\tbreak;\n-\n-\tcase STATE_LOOKUP_REQ:\n-\t\treply = nfs_lookup_reply(pkt, len);\n-\t\tif (reply == -NFS_RPC_DROP) {\n-\t\t\tbreak;\n-\t\t} else if (reply == -NFS_RPC_ERR) {\n-\t\t\tputs(\"*** ERROR: File lookup fail\\n\");\n-\t\t\tnfs_state = STATE_UMOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t} else if (reply == -NFS_RPC_PROG_MISMATCH &&\n-\t\t\t   choosen_nfs_version != NFS_UNKOWN) {\n-\t\t\t/* umount */\n-\t\t\tnfs_state = STATE_UMOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t\t/* And retry with another supported version */\n-\t\t\tnfs_state = STATE_PRCLOOKUP_PROG_MOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t} else {\n-\t\t\tnfs_state = STATE_READ_REQ;\n-\t\t\tnfs_offset = 0;\n-\t\t\tnfs_len = NFS_READ_SIZE;\n-\t\t\tnfs_send();\n-\t\t}\n-\t\tbreak;\n-\n-\tcase STATE_READLINK_REQ:\n-\t\treply = nfs_readlink_reply(pkt, len);\n-\t\tif (reply == -NFS_RPC_DROP) {\n-\t\t\tbreak;\n-\t\t} else if (reply == -NFS_RPC_ERR) {\n-\t\t\tputs(\"*** ERROR: Symlink fail\\n\");\n-\t\t\tnfs_state = STATE_UMOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t} else {\n-\t\t\tdebug(\"Symlink --> %s\\n\", nfs_path);\n-\t\t\tnfs_filename = basename(nfs_path);\n-\t\t\tnfs_path     = dirname(nfs_path);\n-\n-\t\t\tnfs_state = STATE_MOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t}\n-\t\tbreak;\n-\n-\tcase STATE_READ_REQ:\n-\t\trlen = nfs_read_reply(pkt, len);\n-\t\tif (rlen == -NFS_RPC_DROP)\n-\t\t\tbreak;\n-\t\tnet_set_timeout_handler(nfs_timeout, nfs_timeout_handler);\n-\t\tif (rlen > 0) {\n-\t\t\tnfs_offset += rlen;\n-\t\t\tnfs_send();\n-\t\t} else if ((rlen == -NFSERR_ISDIR) || (rlen == -NFSERR_INVAL)) {\n-\t\t\t/* symbolic link */\n-\t\t\tnfs_state = STATE_READLINK_REQ;\n-\t\t\tnfs_send();\n-\t\t} else {\n-\t\t\tif (!rlen)\n-\t\t\t\tnfs_download_state = NETLOOP_SUCCESS;\n-\t\t\tif (rlen < 0)\n-\t\t\t\tdebug(\"NFS READ error (%d)\\n\", rlen);\n-\t\t\tnfs_state = STATE_UMOUNT_REQ;\n-\t\t\tnfs_send();\n-\t\t}\n-\t\tbreak;\n-\t}\n+\tnfs_pkt_recv(pkt, len);\n }\n \n void nfs_start(void)\n@@ -940,8 +118,8 @@ void nfs_start(void)\n \t\t       nfs_path);\n \t}\n \n-\tnfs_filename = basename(nfs_path);\n-\tnfs_path     = dirname(nfs_path);\n+\tnfs_filename = nfs_basename(nfs_path);\n+\tnfs_path     = nfs_dirname(nfs_path);\n \n \tprintf(\"Using %s device\\n\", eth_get_name());\n \ndiff --git a/net/nfs.h b/net/nfs.h\nindex 6bf1cb76bd58b0ca123f85d834355e30bf649811..0dd180ce2229ed6640ab8acb913f2876cc5e2772 100644\n--- a/net/nfs.h\n+++ b/net/nfs.h\n@@ -6,15 +6,6 @@\n #ifndef __NFS_H__\n #define __NFS_H__\n \n-#define SUNRPC_PORT     111\n-\n-#define PROG_PORTMAP    100000\n-#define PROG_NFS        100003\n-#define PROG_MOUNT      100005\n-\n-#define MSG_CALL        0\n-#define MSG_REPLY       1\n-\n #define PORTMAP_GETPORT 3\n \n #define MOUNT_ADDENTRY  1\n@@ -29,56 +20,6 @@\n #define NFS_FHSIZE      32\n #define NFS3_FHSIZE     64\n \n-#define NFSERR_PERM     1\n-#define NFSERR_NOENT    2\n-#define NFSERR_ACCES    13\n-#define NFSERR_ISDIR    21\n-#define NFSERR_INVAL    22\n-\n-/*\n- * Block size used for NFS read accesses.  A RPC reply packet (including  all\n- * headers) must fit within a single Ethernet frame to avoid fragmentation.\n- * However, if CONFIG_IP_DEFRAG is set, a bigger value could be used.  In any\n- * case, most NFS servers are optimized for a power of 2.\n- */\n-#define NFS_READ_SIZE\t1024\t/* biggest power of two that fits Ether frame */\n-#define NFS_MAX_ATTRS\t26\n-\n-/* Values for Accept State flag on RPC answers (See: rfc1831) */\n-enum rpc_accept_stat {\n-\tNFS_RPC_SUCCESS = 0,\t/* RPC executed successfully */\n-\tNFS_RPC_PROG_UNAVAIL = 1,\t/* remote hasn't exported program */\n-\tNFS_RPC_PROG_MISMATCH = 2,\t/* remote can't support version # */\n-\tNFS_RPC_PROC_UNAVAIL = 3,\t/* program can't support procedure */\n-\tNFS_RPC_GARBAGE_ARGS = 4,\t/* procedure can't decode params */\n-\tNFS_RPC_SYSTEM_ERR = 5\t/* errors like memory allocation failure */\n-};\n-\n-struct rpc_t {\n-\tunion {\n-\t\tuint8_t data[NFS_READ_SIZE + (6 + NFS_MAX_ATTRS) *\n-\t\t\tsizeof(uint32_t)];\n-\t\tstruct {\n-\t\t\tuint32_t id;\n-\t\t\tuint32_t type;\n-\t\t\tuint32_t rpcvers;\n-\t\t\tuint32_t prog;\n-\t\t\tuint32_t vers;\n-\t\t\tuint32_t proc;\n-\t\t\tuint32_t data[1];\n-\t\t} call;\n-\t\tstruct {\n-\t\t\tuint32_t id;\n-\t\t\tuint32_t type;\n-\t\t\tuint32_t rstatus;\n-\t\t\tuint32_t verifier;\n-\t\t\tuint32_t v2;\n-\t\t\tuint32_t astatus;\n-\t\t\tuint32_t data[NFS_READ_SIZE / sizeof(uint32_t) +\n-\t\t\t\tNFS_MAX_ATTRS];\n-\t\t} reply;\n-\t} u;\n-};\n void nfs_start(void);\t/* Begin NFS */\n \n /**********************************************************************/\n",
    "prefixes": [
        "v2",
        "4/6"
    ]
}