On 08/07/2026 21:31, James Hilliard wrote:
> The legacy network stack supports tftpsrv, which listens for an
> incoming TFTP write request and receives the first file into memory.
> Despite the old command help wording, the command returns after
> receiving the file and does not boot it automatically.
> 
> The lwIP stack already builds the lwIP TFTP application, but only wires
> it up for client-side tftpboot. Add a lwIP tftpsrv command and
> implement the server path with tftp_init_server(). Reuse the existing
> lwIP TFTP write callback and memory copy path so LMB checks, progress
> output, filesize/fileaddr updates and EFI bootdev handling stay
> consistent with tftpboot.
> 
> Track receive timeout and write-failure state around the lwIP callbacks
> so a stalled or rejected receive is not reported as a successful close.
> 
> Move CMD_TFTPSRV out of the legacy-only Kconfig block so it can be
> enabled with either network stack. Update the command help text and add
> usage documentation for the receive-only behavior.
> 
> Add pytest coverage for tftpsrv using a generated host file and curl's
> TFTP upload support. Enable the command in qemu_arm64_lwip_defconfig so
> the test can be run with the existing lwIP QEMU build when the boardenv
> provides env__net_tftpsrv_file.
> 
> Signed-off-by: James Hilliard <[email protected]>
> ---
> Changes v3 -> v4:
>   - Match lwIP TFTP filename length with legacy TFTP
>   - Keep the server transfer context on the stack
>   - Use the existing net_lwip_eth_stop() helper after tftpsrv exits
> 
> Changes v2 -> v3:
>   - Use an explicit TFTPSRV_LISTEN_TIMEOUT_MS value
>   - Allocate the server transfer context dynamically
>   - Halt the lwIP Ethernet device after tftpsrv exits
> 
> Changes v1 -> v2:
>   - Add tftpsrv usage documentation  (suggested by Quentin Schulz)
>   - Add tftpsrv pytest coverage  (suggested by Quentin Schulz)
>   - Enable CMD_TFTPSRV in qemu_arm64_lwip_defconfig
>   - Allow tftpsrv pytest coverage to use an explicit upload URL
>   - Keep tftpsrv pytest coverage gated by env__net_tftpsrv_file
>   - Clarify that tftpsrv returns after receiving instead of booting
>   - Update legacy and lwIP command help text for receive-only behavior
> ---
>  cmd/Kconfig                       |  14 ++-
>  cmd/lwip/Makefile                 |   1 +
>  cmd/lwip/tftpsrv.c                |  11 ++
>  cmd/net.c                         |   4 +-
>  configs/qemu_arm64_lwip_defconfig |   1 +
>  doc/usage/cmd/tftpsrv.rst         |  73 ++++++++++++
>  include/net-lwip.h                |   1 +
>  lib/lwip/u-boot/lwipopts.h        |  11 ++
>  net/lwip/tftp.c                   | 188 +++++++++++++++++++++++++++++-
>  test/py/tests/test_net.py         |  94 +++++++++++++++
>  10 files changed, 385 insertions(+), 13 deletions(-)
>  create mode 100644 cmd/lwip/tftpsrv.c
>  create mode 100644 doc/usage/cmd/tftpsrv.rst
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index ca1039f6a03..c9a6c7c33a2 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -2134,12 +2134,6 @@ config CMD_TFTPPUT
>       help
>         TFTP put command, for uploading files to a server
>  
> -config CMD_TFTPSRV
> -     bool "tftpsrv"
> -     depends on CMD_TFTPBOOT
> -     help
> -       Act as a TFTP server and boot the first received file
> -
>  config NET_TFTP_VARS
>       bool "Control TFTP timeout and count through environment"
>       depends on CMD_TFTPBOOT
> @@ -2286,6 +2280,14 @@ config CMD_TFTPBOOT
>       help
>         tftpboot - load file via network using TFTP protocol
>  
> +config CMD_TFTPSRV
> +     bool "tftpsrv"
> +     depends on CMD_TFTPBOOT
> +     help
> +       Act as a TFTP server and receive the first incoming file into
> +       memory. The command returns successfully after the transfer so
> +       boot scripts can boot the received image from the load address.
> +
>  config CMD_WGET
>       bool "wget"
>       default y if SANDBOX || ARCH_QEMU
> diff --git a/cmd/lwip/Makefile b/cmd/lwip/Makefile
> index 90df1f5511c..245683a9672 100644
> --- a/cmd/lwip/Makefile
> +++ b/cmd/lwip/Makefile
> @@ -4,4 +4,5 @@ obj-$(CONFIG_CMD_NFS) += nfs.o
>  obj-$(CONFIG_CMD_PING) += ping.o
>  obj-$(CONFIG_CMD_SNTP) += sntp.o
>  obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
> +obj-$(CONFIG_CMD_TFTPSRV) += tftpsrv.o
>  obj-$(CONFIG_CMD_WGET) += wget.o
> diff --git a/cmd/lwip/tftpsrv.c b/cmd/lwip/tftpsrv.c
> new file mode 100644
> index 00000000000..6370c900489
> --- /dev/null
> +++ b/cmd/lwip/tftpsrv.c
> @@ -0,0 +1,11 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <command.h>
> +#include <net.h>
> +
> +U_BOOT_CMD(tftpsrv, 2, 1, do_tftpsrv,
> +        "act as a TFTP server and receive the first file",
> +        "[loadAddress]\n"
> +        "Listen for an incoming TFTP transfer and receive a file into 
> memory.\n"
> +        "The transfer is aborted if a transfer has not been started after\n"
> +        "about 50 seconds or if Ctrl-C is pressed.");
> diff --git a/cmd/net.c b/cmd/net.c
> index f6f556f36ae..0f0b2386d87 100644
> --- a/cmd/net.c
> +++ b/cmd/net.c
> @@ -89,9 +89,9 @@ static int do_tftpsrv(struct cmd_tbl *cmdtp, int flag, int 
> argc,
>  
>  U_BOOT_CMD(
>       tftpsrv,        2,      1,      do_tftpsrv,
> -     "act as a TFTP server and boot the first received file",
> +     "act as a TFTP server and receive the first file",
>       "[loadAddress]\n"
> -     "Listen for an incoming TFTP transfer, receive a file and boot it.\n"
> +     "Listen for an incoming TFTP transfer and receive a file into memory.\n"
>       "The transfer is aborted if a transfer has not been started after\n"
>       "about 50 seconds or if Ctrl-C is pressed."
>  );
> diff --git a/configs/qemu_arm64_lwip_defconfig 
> b/configs/qemu_arm64_lwip_defconfig
> index a974970c3d3..06ed5a131db 100644
> --- a/configs/qemu_arm64_lwip_defconfig
> +++ b/configs/qemu_arm64_lwip_defconfig
> @@ -7,6 +7,7 @@ CONFIG_NET_LWIP=y
>  CONFIG_CMD_DNS=y
>  CONFIG_CMD_NFS=y
>  CONFIG_CMD_SNTP=y
> +CONFIG_CMD_TFTPSRV=y
>  CONFIG_CMD_WGET=y
>  CONFIG_EFI_HTTP_BOOT=y
>  CONFIG_WGET_HTTPS=y
> diff --git a/doc/usage/cmd/tftpsrv.rst b/doc/usage/cmd/tftpsrv.rst
> new file mode 100644
> index 00000000000..597a2f3a8bd
> --- /dev/null
> +++ b/doc/usage/cmd/tftpsrv.rst
> @@ -0,0 +1,73 @@
> +.. SPDX-License-Identifier: GPL-2.0+:

Extra ':' character. No need to respin, I can remove it when taking
the patch.

Reviewed-by: Jerome Forissier <[email protected]>

Thanks,
-- 
Jerome

Reply via email to