Message ID | 20230714142000.5534-3-maxim.uvarov@linaro.org |
---|---|
State | New |
Headers | show |
Series | net/lwip: add lwip library for the network stack | expand |
Hi Maxim, This is too much for a single patch review. Can you pleas split it in something that's easier to review and comment. For example, #1 add the lwip library only #2-#5 add ping, wget, tcp and ping Some random comments below as well. On Fri, Jul 14, 2023 at 08:19:57PM +0600, Maxim Uvarov wrote: > This commit adds lwip library for the U-boot network > stack. Supported commands: ping, tftp, dhcp and wget. > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> > --- > .gitignore | 9 + > boot/bootmeth_pxe.c | 2 +- > cmd/net.c | 48 +---- > cmd/pxe.c | 2 +- > include/net.h | 8 +- > lib/Kconfig | 2 + > lib/Makefile | 2 + > lib/lwip/Kconfig | 63 ++++++ > lib/lwip/Makefile | 101 ++++++++++ > lib/lwip/apps/dhcp/lwip-dhcp.c | 52 +++++ > lib/lwip/apps/http/lwip-wget.c | 74 +++++++ > lib/lwip/apps/ping/lwip_ping.c | 37 ++++ > lib/lwip/apps/ping/lwip_ping.h | 24 +++ > lib/lwip/apps/ping/ping.h | 35 ++++ > lib/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++++++ > lib/lwip/cmd-lwip.c | 269 ++++++++++++++++++++++++++ > lib/lwip/lwipopts.h | 203 +++++++++++++++++++ > lib/lwip/port/if.c | 260 +++++++++++++++++++++++++ > lib/lwip/port/include/arch/cc.h | 46 +++++ > lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ > lib/lwip/port/include/limits.h | 0 > lib/lwip/port/sys-arch.c | 20 ++ > lib/lwip/ulwip.h | 9 + > net/Kconfig | 1 + > net/net.c | 24 +++ > 25 files changed, 1430 insertions(+), 44 deletions(-) > create mode 100644 lib/lwip/Kconfig > create mode 100644 lib/lwip/Makefile > create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c > create mode 100644 lib/lwip/apps/http/lwip-wget.c > create mode 100644 lib/lwip/apps/ping/lwip_ping.c > create mode 100644 lib/lwip/apps/ping/lwip_ping.h > create mode 100644 lib/lwip/apps/ping/ping.h > create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c > create mode 100644 lib/lwip/cmd-lwip.c > create mode 100644 lib/lwip/lwipopts.h > create mode 100644 lib/lwip/port/if.c > create mode 100644 lib/lwip/port/include/arch/cc.h > create mode 100644 lib/lwip/port/include/arch/sys_arch.h > create mode 100644 lib/lwip/port/include/limits.h > create mode 100644 lib/lwip/port/sys-arch.c > create mode 100644 lib/lwip/ulwip.h > > diff --git a/.gitignore b/.gitignore > index eb769f144c..be3676c59e 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -104,3 +104,12 @@ __pycache__ > # pylint files > /pylint.cur > /pylint.out/ > + > +lib/lwip/lwip-external > +lib/lwip/apps/ping/ping.c > +lib/lwip/apps/http/http_client.c > +lib/lwip/apps/http/http_client.h > +lib/lwip/apps/tftp/tftp.c > +lib/lwip/apps/tftp/tftp_client.h > +lib/lwip/apps/tftp/tftp_common.h > +lib/lwip/apps/tftp/tftp_example.h > diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c > index e6992168c0..30331a9806 100644 > --- a/boot/bootmeth_pxe.c > +++ b/boot/bootmeth_pxe.c > @@ -118,7 +118,7 @@ static int distro_pxe_read_file(struct udevice *dev, struct bootflow *bflow, > tftp_argv[1] = file_addr; > tftp_argv[2] = (void *)file_path; > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > return -ENOENT; > ret = pxe_get_file_size(&size); > if (ret) > diff --git a/cmd/net.c b/cmd/net.c > index 0e9f200ca9..6d704fba86 100644 > --- a/cmd/net.c > +++ b/cmd/net.c > @@ -36,19 +36,9 @@ U_BOOT_CMD( > #endif > > #ifdef CONFIG_CMD_TFTPBOOT > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) > -{ > - int ret; > - > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); > - ret = netboot_common(TFTPGET, cmdtp, argc, argv); > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); > - return ret; > -} > - > #if IS_ENABLED(CONFIG_IPV6) > U_BOOT_CMD( > - tftpboot, 4, 1, do_tftpb, > + tftpboot, 4, 1, do_lwip_tftp, > "boot image via network using TFTP protocol\n" > "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " > "with [] brackets", > @@ -56,7 +46,7 @@ U_BOOT_CMD( > ); > #else > U_BOOT_CMD( > - tftpboot, 3, 1, do_tftpb, > + tftpboot, 3, 1, do_lwip_tftp, > "load file via network using TFTP protocol", > "[loadAddress] [[hostIPaddr:]bootfilename]" > ); > @@ -112,7 +102,7 @@ U_BOOT_CMD( > static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > char *const argv[]) > { > - return netboot_common(DHCP, cmdtp, argc, argv); > + return do_lwip_dhcp(); > } > > U_BOOT_CMD( > @@ -137,13 +127,11 @@ U_BOOT_CMD( > #endif > > #if defined(CONFIG_CMD_WGET) > -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) > -{ > - return netboot_common(WGET, cmdtp, argc, argv); > -} > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]); > > U_BOOT_CMD( > - wget, 3, 1, do_wget, > + wget, 3, 1, do_lwip_wget, I thought we agreed on keeping both the native u-boot stack and lwip until we can proove the later is useful. Do I remember this wrong? Same goes for all the other commands > "boot image via network using HTTP protocol", > "[loadAddress] [[hostIPaddr:]path and image name]" > ); > @@ -376,28 +364,10 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, > } > > #if defined(CONFIG_CMD_PING) > -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, > - char *const argv[]) > -{ > - if (argc < 2) > - return CMD_RET_USAGE; > - > - net_ping_ip = string_to_ip(argv[1]); > - if (net_ping_ip.s_addr == 0) > - return CMD_RET_USAGE; > - > - if (net_loop(PING) < 0) { > - printf("ping failed; host %s is not alive\n", argv[1]); > - return CMD_RET_FAILURE; > - } > - > - printf("host %s is alive\n", argv[1]); > - > - return CMD_RET_SUCCESS; > -} > - > +extern int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]); Why extern? Cant we define it properly as part of our header file? > U_BOOT_CMD( > - ping, 2, 1, do_ping, > + ping, 2, 1, do_lwip_ping, > "send ICMP ECHO_REQUEST to network host", > "pingAddress" > ); > diff --git a/cmd/pxe.c b/cmd/pxe.c > index db8e4697f2..bd4d6f5f2b 100644 > --- a/cmd/pxe.c > +++ b/cmd/pxe.c > @@ -33,7 +33,7 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path, > tftp_argv[1] = file_addr; > tftp_argv[2] = (void *)file_path; > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > return -ENOENT; > ret = pxe_get_file_size(sizep); > if (ret) > diff --git a/include/net.h b/include/net.h > index 1a99009959..6b573f3319 100644 > --- a/include/net.h > +++ b/include/net.h > @@ -54,8 +54,10 @@ struct in_addr { > __be32 s_addr; > }; > > +int do_lwip_dhcp(void); > + > /** > - * do_tftpb - Run the tftpboot command > + * do_lwip_tftp - Run the tftpboot command > * > * @cmdtp: Command information for tftpboot > * @flag: Command flags (CMD_FLAG_...) > @@ -63,7 +65,7 @@ struct in_addr { > * @argv: List of arguments > * Return: result (see enum command_ret_t) > */ > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); > > /** > * An incoming packet handler. > @@ -561,7 +563,7 @@ extern int net_restart_wrap; /* Tried all network devices */ > > enum proto_t { > BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, NETCONS, > - SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET > + SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET, LWIP > }; > > extern char net_boot_file_name[1024];/* Boot File name */ > diff --git a/lib/Kconfig b/lib/Kconfig > index 3c5a4ab386..7485a1f3bf 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates" > source lib/fwu_updates/Kconfig > > endmenu > + > +source lib/lwip/Kconfig > diff --git a/lib/Makefile b/lib/Makefile > index d77b33e7f4..3b80a41187 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -91,6 +91,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ > obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ > obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o > > +obj-y += lwip/ > + > ifdef CONFIG_SPL_BUILD > obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o > obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o > diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig > new file mode 100644 > index 0000000000..3688ac3305 > --- /dev/null > +++ b/lib/lwip/Kconfig > @@ -0,0 +1,63 @@ > +menu "LWIP" > +config LWIP_LIB > + bool "Support LWIP library" > + help > + Selecting this option will enable the LWIP library code. > + > +menu "LWIP options" > + > +config LWIP_LIB_DEBUG > + bool "enable debug" > + default n > + > +config LWIP_LIB_NOASSERT > + bool "disable asserts" > + default y > + help > + Disabling asserts reduces binary size on 16k. > + > +config LWIP_LIB_TCP You need some useful help entry on all of those. > + bool "tcp" > + default y > + > +config LWIP_LIB_UDP > + bool "udp" > + default y > + > +config LWIP_LIB_DNS > + bool "dns" > + default n > + > +config LWIP_LIB_DHCP > + bool "dhcp" > + default y > + > +config LWIP_LIB_LOOPBACK > + bool "loopback" > + help > + Increases size on 1k. > + > +config LWIP_LIB_SOCKET > + bool "socket API" > + > +config LWIP_LIB_NETCONN > + bool "netconn API" > + > +config LWIP_LIB_MEM_SIZE > + int "mem size" > + default 1600 > + range 1 4096 > + help > + MEM_SIZE: the size of the heap memory. If the application will send > + a lot of data that needs to be copied, this should be set high. > + > +config LWIP_LIB_PBUF_LINK_HLEN > + int "pbuf link hlen" > + default 14 > + range 4 1024 > + help > + PBUF_LINK_HLEN: the number of bytes that should be allocated for a > + link level header. The default is 14, the standard value for Ethernet. > +endmenu > + > +endmenu > diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile > new file mode 100644 > index 0000000000..e1a8a2a7b7 > --- /dev/null > +++ b/lib/lwip/Makefile > @@ -0,0 +1,101 @@ > +# SPDX-License-Identifier: GPL-2.0+ > +# > +# (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + > +LWIPDIR=lwip-external/src > + > +ccflags-y += -I$(srctree)/lib/lwip/port/include > +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip > + > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \ > + $(LWIPDIR)/core/def.o \ > + $(LWIPDIR)/core/dns.o \ > + $(LWIPDIR)/core/inet_chksum.o \ > + $(LWIPDIR)/core/ip.o \ > + $(LWIPDIR)/core/mem.o \ > + $(LWIPDIR)/core/memp.o \ > + $(LWIPDIR)/core/netif.o \ > + $(LWIPDIR)/core/pbuf.o \ > + $(LWIPDIR)/core/raw.o \ > + $(LWIPDIR)/core/stats.o \ > + $(LWIPDIR)/core/sys.o \ > + $(LWIPDIR)/core/altcp.o \ > + $(LWIPDIR)/core/altcp_alloc.o \ > + $(LWIPDIR)/core/altcp_tcp.o \ > + $(LWIPDIR)/core/tcp.o \ > + $(LWIPDIR)/core/tcp_in.o \ > + $(LWIPDIR)/core/tcp_out.o \ > + $(LWIPDIR)/core/timeouts.o \ > + $(LWIPDIR)/core/udp.o > + > +# IPv4 > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \ > + $(LWIPDIR)/core/ipv4/autoip.o \ > + $(LWIPDIR)/core/ipv4/dhcp.o \ > + $(LWIPDIR)/core/ipv4/etharp.o \ > + $(LWIPDIR)/core/ipv4/icmp.o \ > + $(LWIPDIR)/core/ipv4/igmp.o \ > + $(LWIPDIR)/core/ipv4/ip4_frag.o \ > + $(LWIPDIR)/core/ipv4/ip4.o \ > + $(LWIPDIR)/core/ipv4/ip4_addr.o > +# IPv6 > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \ > + $(LWIPDIR)/core/ipv6/ethip6.o \ > + $(LWIPDIR)/core/ipv6/icmp6.o \ > + $(LWIPDIR)/core/ipv6/inet6.o \ > + $(LWIPDIR)/core/ipv6/ip6.o \ > + $(LWIPDIR)/core/ipv6/ip6_addr.o \ > + $(LWIPDIR)/core/ipv6/ip6_frag.o \ > + $(LWIPDIR)/core/ipv6/mld6.o \ > + $(LWIPDIR)/core/ipv6/nd6.o > +# API > +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \ > + $(LWIPDIR)/api/api_msg.o \ > + $(LWIPDIR)/api/err.o \ > + $(LWIPDIR)/api/if_api.o \ > + $(LWIPDIR)/api/netbuf.o \ > + $(LWIPDIR)/api/netdb.o \ > + $(LWIPDIR)/api/netifapi.o \ > + $(LWIPDIR)/api/sockets.o \ > + $(LWIPDIR)/api/tcpip.o > + > +# Netdevs > +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o > + > +obj-$(CONFIG_NET) += port/if.o > +obj-$(CONFIG_NET) += port/sys-arch.o > + > +obj-$(CONFIG_NET) += cmd-lwip.o > + > + > +ccflags-y += -I$(srctree)/lib/lwip/apps/ping > +.PHONY: $(obj)/apps/ping/ping.c > +$(obj)/apps/ping/ping.o: $(obj)/apps/ping/ping.c > +$(obj)/apps/ping/ping.c: > + cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c $(obj)/apps/ping/ping.c > + > +obj-$(CONFIG_CMD_PING) += apps/ping/ping.o > +obj-$(CONFIG_CMD_PING) += apps/ping/lwip_ping.o > + > +$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c > +.PHONY: $(obj)/apps/http/http_client.c > +$(obj)/apps/http/http_client.c: > + cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c $(obj)/apps/http/http_client.c > + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/apps/http/http_client.h > + > +obj-$(CONFIG_CMD_WGET) += apps/http/http_client.o > +obj-$(CONFIG_CMD_WGET) += apps/http/lwip-wget.o > + > +ccflags-y += -I$(CURDIR)/lib/lwip/apps/tftp > +$(obj)/apps/tftp/tftp.o: $(obj)/apps/tftp/tftp.c > +.PHONY: $(obj)/apps/tftp/tftp.c > +$(obj)/apps/tftp/tftp.c: > + cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/apps/tftp/tftp.c > + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/apps/tftp/tftp_client.h > + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/apps/tftp/tftp_common.h > + cp $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/apps/tftp/tftp_example.h > + > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/tftp.o > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/lwip-tftp.o > + > +obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o > diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c b/lib/lwip/apps/dhcp/lwip-dhcp.c > new file mode 100644 > index 0000000000..2e4812c7dd > --- /dev/null > +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c > @@ -0,0 +1,52 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include <common.h> > +#include <command.h> > +#include <console.h> > + > +#include <lwip/dhcp.h> > +#include <lwip/prot/dhcp.h> > + > +#include "../../../lwip/ulwip.h" > + > +static struct dhcp dhcp; > +static bool dhcp_is_set; > +extern struct netif uboot_netif; Again why extern? I dont think it's sane to carry around the uboot_netif variable everytime we need to change a member. Instead we should functions doing that > + > +static int ulwip_dhcp_tmo(void) > +{ > + switch (dhcp.state) { > + case DHCP_STATE_BOUND: > + env_set("bootfile", dhcp.boot_file_name); > + env_set("ipaddr", ip4addr_ntoa(&dhcp.offered_ip_addr)); > + env_set("netmask", ip4addr_ntoa(&dhcp.offered_sn_mask)); > + env_set("serverip", ip4addr_ntoa(&dhcp.server_ip_addr)); > + printf("DHCP client bound to address %s\n", ip4addr_ntoa(&dhcp.offered_ip_addr)); > + break; > + default: > + return 0; > + } > + > + return 0; > +} The return value is always 0, why are we at least checking the result of env_set()? > + > +int ulwip_dhcp(void) > +{ > + int err; > + > + ulwip_set_tmo(ulwip_dhcp_tmo); > + > + if (!dhcp_is_set) { > + dhcp_set_struct(&uboot_netif, &dhcp); > + dhcp_is_set = true; > + } > + err = dhcp_start(&uboot_netif); > + if (err) > + printf("dhcp_start error %d\n", err); > + > + return err; > +} > diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c > new file mode 100644 > index 0000000000..0308b0b04a > --- /dev/null > +++ b/lib/lwip/apps/http/lwip-wget.c > @@ -0,0 +1,74 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include <common.h> > +#include <command.h> > +#include <console.h> > + > +#include "http_client.h" > +#include "../../../lwip/ulwip.h" > + > +static ulong daddr; > +static httpc_connection_t settings; > + > +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) > +{ > + struct pbuf *q; > + LWIP_UNUSED_ARG(err); > + > + if (!p) > + return ERR_BUF; > + > + for (q = p; q != NULL; q = q->next) { > + memcpy((void *)daddr, q->payload, q->len); > + printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); > + daddr += q->len; > + } > + altcp_recved(pcb, p->tot_len); > + pbuf_free(p); > + return ERR_OK; > +} > + > +static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, > + u32_t srv_res, err_t err) > +{ > + if (httpc_result == HTTPC_RESULT_OK) { > + printf("\n%d bytes successfully downloaded.\n", rx_content_len); > + env_set_ulong("filesize", rx_content_len); > + ulwip_exit(0); > + } else { > + printf("\nhttp eroror: %d\n", httpc_result); > + ulwip_exit(-1); > + } > +} > + > +int lwip_wget(ulong addr, char *url) > +{ > + err_t err; > + int port = 80; > + char *server_name; > + httpc_state_t *connection; > + > + daddr = addr; > + server_name = env_get("serverip"); > + if (!server_name) { > + printf("error: serverip variable has to be set\n"); > + return CMD_RET_FAILURE; > + } > + > + printf("downloading %s to addr 0x%lx\n", url, addr); > + memset(&settings, 0, sizeof(httpc_connection_t)); sizeof(settings) is preferred > + settings.result_fn = httpc_result; > + err = httpc_get_file_dns(server_name, port, url, &settings, > + httpc_recv, NULL, &connection); > + if (err != ERR_OK) { > + printf("httpc_init_connection failed\n"); > + return err; > + } > + > + env_set_hex("fileaddr", addr); > + return 0; > +} > diff --git a/lib/lwip/apps/ping/lwip_ping.c b/lib/lwip/apps/ping/lwip_ping.c > new file mode 100644 > index 0000000000..a05dc76326 > --- /dev/null > +++ b/lib/lwip/apps/ping/lwip_ping.c > @@ -0,0 +1,37 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include "lwip/opt.h" > +#include "lwip/ip_addr.h" > +#include "ping.h" > + > +#include "../../../lwip/ulwip.h" Please dont do this. Can't we just use -I or something and have this is a normal include path? > + > +static ip_addr_t ip_target; > + > +static int ulwip_ping_tmo(void) > +{ > + > + printf("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target)); > + return 0; > +} > + > +int lwip_ping_init(char *ping_addr) > +{ > + int err; > + > + err = ipaddr_aton(ping_addr, &ip_target); > + if (err == 0) { > + printf("wrong ping addr string \"%s\" \n", ping_addr); > + return -1; > + } > + > + ulwip_set_tmo(ulwip_ping_tmo); > + > + ping_init(&ip_target); > + > + return 0; > +} > diff --git a/lib/lwip/apps/ping/lwip_ping.h b/lib/lwip/apps/ping/lwip_ping.h > new file mode 100644 > index 0000000000..7f08095427 > --- /dev/null > +++ b/lib/lwip/apps/ping/lwip_ping.h > @@ -0,0 +1,24 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#ifndef LWIP_PING_H > +#define LWIP_PING_H > + > +#include <lwip/ip_addr.h> > + > +/** > + * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used > + */ > +#ifndef PING_USE_SOCKETS > +#define PING_USE_SOCKETS 0 > +#endif > + > +int lwip_ping_init(char *ping_addr); > + > +void ping_raw_init(void); > +void ping_send_now(void); > + > +#endif /* LWIP_PING_H */ > diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h > new file mode 100644 > index 0000000000..0dd4bd78c7 > --- /dev/null > +++ b/lib/lwip/apps/ping/ping.h > @@ -0,0 +1,35 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > + > +#include "../../../lwip/ulwip.h" > + > +#include "lwip/prot/ip4.h" > + > +#define ip4_print_parts(a, b, c, d) \ > + printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d); > + > +#define ip4_print(ipaddr) \ > + ip4_print_parts(\ > + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ > + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ > + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ > + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) > + > + > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ > +#define PING_RESULT(cond) { \ > + if (cond == 1) { \ > + printf("host "); \ > + ip4_print(addr); \ > + printf(" is alive\n"); \ > + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ > + ulwip_exit(0); \ > + } else { \ > + printf("ping failed; host "); \ > + ip4_print(addr); \ > + printf(" is not alive\n"); \ > + ulwip_exit(-1); \ > + } \ > + } while (0); > + > +#include "lwip/ip_addr.h" > +void ping_init(const ip_addr_t *ping_addr); > diff --git a/lib/lwip/apps/tftp/lwip-tftp.c b/lib/lwip/apps/tftp/lwip-tftp.c > new file mode 100644 > index 0000000000..511d82e600 > --- /dev/null > +++ b/lib/lwip/apps/tftp/lwip-tftp.c > @@ -0,0 +1,124 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include <common.h> > +#include <command.h> > +#include <console.h> > + > +#include "lwip/apps/tftp_client.h" > +#include "lwip/apps/tftp_server.h" > +#include <tftp_example.h> > + > +#include <string.h> > + > +#include "../../../lwip/ulwip.h" > + > +#if LWIP_UDP > + > +static ulong daddr; > +static ulong size; > + > +static void *tftp_open(const char *fname, const char *mode, u8_t is_write) > +{ > + LWIP_UNUSED_ARG(mode); > + return NULL; > +} > + > +static void tftp_close(void *handle) > +{ > + printf("\ndone\n"); > + printf("Bytes transferred = %ld (0x%lx hex)\n", size, size); > + > + env_set_ulong("filesize", size); > + ulwip_exit(0); > +} > + > +static int tftp_read(void *handle, void *buf, int bytes) > +{ > + return 0; > +} > + > +static int tftp_write(void *handle, struct pbuf *p) > +{ > + struct pbuf *q; > + > + for (q = p; q != NULL; q = q->next) { > + memcpy((void *)daddr, q->payload, q->len); > + /* printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); */ > + daddr += q->len; > + size += q->len; > + printf("#"); > + } > + > + return 0; > +} > + > +/* For TFTP client only */ > +static void tftp_error(void *handle, int err, const char *msg, int size) > +{ > + char message[100]; > + > + LWIP_UNUSED_ARG(handle); > + > + memset(message, 0, sizeof(message)); > + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size)); > + > + printf("TFTP error: %d (%s)", err, message); > +} > + > +static const struct tftp_context tftp = { > + tftp_open, > + tftp_close, > + tftp_read, > + tftp_write, > + tftp_error > +}; > + > +int lwip_tftp(ulong addr, char *fname) > +{ > + void *f = (void *)0x1; /*fake handle*/ > + err_t err; > + ip_addr_t srv; > + int ret; > + char *server_ip; > + > + if (!fname || addr == 0) > + return CMD_RET_FAILURE; > + > + size = 0; > + daddr = addr; > + server_ip = env_get("serverip"); > + if (!server_ip) { > + printf("error: serverip variable has to be set\n"); > + return CMD_RET_FAILURE; > + } > + > + ret = ipaddr_aton(server_ip, &srv); > + LWIP_ASSERT("ipaddr_aton failed", ret == 1); > + > + printf("TFTP from server %s; our IP address is %s\n", > + server_ip, env_get("ipaddr")); > + printf("Filename '%s'.\n", fname); > + printf("Load address: 0x%lx\n", daddr); > + printf("Loading:"); > + > + err = tftp_init_client(&tftp); > + if (!(err == ERR_OK || err == ERR_USE)) > + printf("tftp_init_client err: %d\n", err); > + > + err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET); > + /* might return different errors, like routing problems */ > + if (err != ERR_OK) { > + printf("tftp_get err=%d\n", err); > + } > + LWIP_ASSERT("tftp_get failed", err == ERR_OK); > + > + env_set_hex("fileaddr", addr); > + return err; > +} > +#else > +#error "UDP has to be supported" > +#endif /* LWIP_UDP */ > diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c > new file mode 100644 > index 0000000000..625c8c53b8 > --- /dev/null > +++ b/lib/lwip/cmd-lwip.c > @@ -0,0 +1,269 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org > + */ > + > +#include <common.h> > +#include <command.h> > +#include <console.h> > +#include <display_options.h> > +#include <memalign.h> > +#include <net.h> > +#include <image.h> > + > +#include "apps/ping/lwip_ping.h" > +#include "ulwip.h" > + > +extern int uboot_lwip_init(void); > +extern int uboot_lwip_loop_is_done(void); > + > +static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + printf("TBD: %s\n", __func__); > + return CMD_RET_SUCCESS; > +} > + > +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + if (!uboot_lwip_init()) > + return CMD_RET_SUCCESS; > + return CMD_RET_FAILURE; > +} > + > +static int lwip_empty_tmo(void) { return 0; }; > +int (*ulwip_tmo)(void) = lwip_empty_tmo; > +void ulwip_set_tmo(int (*tmo)(void)) > +{ > + ulwip_tmo = tmo; > +} > + > +static void ulwip_clear_tmo(void) > +{ > + ulwip_tmo = lwip_empty_tmo; > +} > + > +static void ulwip_timeout_handler(void) > +{ > + eth_halt(); > + ulwip_tmo(); > + net_set_state(NETLOOP_FAIL); /* we did not get the reply */ > + ulwip_loop_set(0); > +} > + > +static int ulwip_loop(void) > +{ > + ulwip_loop_set(1); > + if (net_loop(LWIP) < 0) { > + ulwip_loop_set(0); > + return CMD_RET_FAILURE; > + } > + ulwip_loop_set(0); > + return CMD_RET_SUCCESS; > +} > + > +#if defined(CONFIG_CMD_PING) > +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + if (argc < 2) { > + printf("argc = %d, error\n", argc); > + return CMD_RET_USAGE; > + } > + > + uboot_lwip_init(); > + > + eth_init(); /* activate u-boot eth dev */ > + > + printf("Using %s device\n", eth_get_name()); > + printf("pinging addr: %s\n", argv[1]); > + > + net_set_timeout_handler(1000UL, ulwip_timeout_handler); > + > + if (lwip_ping_init(argv[1])) { > + printf("ping init fail\n"); > + return CMD_RET_FAILURE; > + } > + > + ping_send_now(); > + > + return ulwip_loop(); > +} > +#endif /* CONFIG_CMD_PING */ > + > +#if defined(CONFIG_CMD_WGET) > +extern int lwip_wget(ulong addr, char *url); > + > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + char *url; > + > + if (argc < 2) { > + printf("argc = %d, error\n", argc); > + return CMD_RET_USAGE; > + } > + url = argv[1]; > + > + uboot_lwip_init(); > + > + eth_init(); /* activate u-boot eth dev */ > + > + lwip_wget(image_load_addr, url); > + > + return ulwip_loop(); > +} > +#endif > + > +#if defined(CONFIG_CMD_TFTPBOOT) > +extern int lwip_tftp(ulong addr, char *filename); > + > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + char *filename; > + ulong addr; > + char *end; > + int ret; > + > + switch (argc) { > + case 1: > + filename = env_get("bootfile"); > + break; > + case 2: > + /* > + * Only one arg - accept two forms: > + * Just load address, or just boot file name. The latter > + * form must be written in a format which can not be > + * mis-interpreted as a valid number. > + */ > + addr = hextoul(argv[1], &end); > + if (end == (argv[1] + strlen(argv[1]))) { > + image_load_addr = addr; > + filename = env_get("bootfile"); > + } else { > + filename = argv[1]; > + } > + break; > + case 3: > + image_load_addr = hextoul(argv[1], NULL); > + filename = argv[2]; > + break; > + default: > + return CMD_RET_USAGE; > + } > + > + uboot_lwip_init(); > + > + eth_init(); /* activate u-boot eth dev */ > + > + ret = lwip_tftp(image_load_addr, filename); > + if (ret) > + return ret; > + > + return ulwip_loop(); > +} > +#endif /* CONFIG_CMD_TFTPBOOT */ > + > +#if defined(CONFIG_CMD_DHCP) > +extern int ulwip_dhcp(void); > + > +int do_lwip_dhcp(void) > +{ > + int ret; > + char *filename; > + > + uboot_lwip_init(); > + > + ret = ulwip_dhcp(); > + > + net_set_timeout_handler(2000UL, ulwip_timeout_handler); > + > + ulwip_loop(); > + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { > + ulwip_clear_tmo(); > + > + filename = env_get("bootfile"); > + if (!filename) { > + printf("no bootfile\n"); > + return CMD_RET_FAILURE; > + } > + > + eth_init(); /* activate u-boot eth dev */ > + net_set_timeout_handler(20000UL, ulwip_timeout_handler); > + lwip_tftp(image_load_addr, filename); > + > + ret = ulwip_loop(); > + } > + > + return ret; > +} > + > +static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + return do_lwip_dhcp(); > +} > +#endif /* CONFIG_CMD_DHCP */ > + > +static struct cmd_tbl cmds[] = { > + U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""), > + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, > + "initialize lwip stack", ""), > +#if defined(CONFIG_CMD_LWIP_PING) > + U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, > + "send ICMP ECHO_REQUEST to network host", > + "pingAddress"), > +#endif > +#if defined(CONFIG_CMD_WGET) > + U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""), > +#endif > +#if defined(CONFIG_CMD_TFTPBOOT) > + U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp, > + "boot image via network using TFTP protocol\n", > + "[loadAddress] [[hostIPaddr:]bootfilename]"), > +#endif > +#if defined(CONFIG_CMD_DHCP) > + U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp, > + "boot image via network using DHCP/TFTP protocol", > + ""), > +#endif > +}; > + > +static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc, > + char *const argv[]) > +{ > + struct cmd_tbl *cp; > + > + cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds)); > + > + argc--; > + argv++; > + > + if (cp == NULL || argc > cp->maxargs) > + return CMD_RET_USAGE; > + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) > + return CMD_RET_SUCCESS; > + > + return cp->cmd(cmdtp, flag, argc, argv); > +} > + > +U_BOOT_CMD( > + lwip, 4, 1, do_ops, > + "LWIP sub system", > + "info - display info\n" > + "init - init LWIP\n" > + "ping addr - pingAddress\n" > + "wget http://IPadress/url/\n" > + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" > + "dhcp - boot image via network using DHCP/TFTP protocol\n" > + ); > + > +/* Old command kept for compatibility. Same as 'mmc info' */ > +U_BOOT_CMD( > + lwipinfo, 1, 0, do_lwip_info, > + "display LWIP info", > + "- display LWIP stack info" > +); > diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h > new file mode 100644 > index 0000000000..b943d7b9be > --- /dev/null > +++ b/lib/lwip/lwipopts.h > @@ -0,0 +1,203 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#ifndef LWIP_LWIPOPTS_H > +#define LWIP_LWIPOPTS_H > + > +#include "lwipopts.h" > + > +#if defined(CONFIG_LWIP_LIB_DEBUG) > +#define LWIP_DEBUG 1 > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON > +#define ETHARP_DEBUG LWIP_DBG_OFF > +#define NETIF_DEBUG LWIP_DBG_OFF > +#define PBUF_DEBUG LWIP_DBG_OFF > +#define API_LIB_DEBUG LWIP_DBG_OFF > +#define API_MSG_DEBUG LWIP_DBG_OFF > +#define SOCKETS_DEBUG LWIP_DBG_OFF > +#define ICMP_DEBUG LWIP_DBG_OFF > +#define IGMP_DEBUG LWIP_DBG_OFF > +#define INET_DEBUG LWIP_DBG_OFF > +#define IP_DEBUG LWIP_DBG_OFF > +#define IP_REASS_DEBUG LWIP_DBG_OFF > +#define RAW_DEBUG LWIP_DBG_OFF > +#define MEM_DEBUG LWIP_DBG_OFF > +#define MEMP_DEBUG LWIP_DBG_OFF > +#define SYS_DEBUG LWIP_DBG_OFF > +#define TIMERS_DEBUG LWIP_DBG_OFF > +#define TCP_DEBUG LWIP_DBG_OFF > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > +#define TCP_FR_DEBUG LWIP_DBG_OFF > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > +#define TCP_WND_DEBUG LWIP_DBG_OFF > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > +#define TCP_RST_DEBUG LWIP_DBG_OFF > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > +#define UDP_DEBUG LWIP_DBG_OFF > +#define TCPIP_DEBUG LWIP_DBG_OFF > +#define SLIP_DEBUG LWIP_DBG_OFF > +#define DHCP_DEBUG LWIP_DBG_ON > +#define AUTOIP_DEBUG LWIP_DBG_ON > +#define DNS_DEBUG LWIP_DBG_OFF > +#define IP6_DEBUG LWIP_DBG_OFF > +#define DHCP6_DEBUG LWIP_DBG_OFF > +#else > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF > +#define ETHARP_DEBUG LWIP_DBG_OFF > +#define NETIF_DEBUG LWIP_DBG_OFF > +#define PBUF_DEBUG LWIP_DBG_OFF > +#define API_LIB_DEBUG LWIP_DBG_OFF > +#define API_MSG_DEBUG LWIP_DBG_OFF > +#define SOCKETS_DEBUG LWIP_DBG_OFF > +#define ICMP_DEBUG LWIP_DBG_OFF > +#define IGMP_DEBUG LWIP_DBG_OFF > +#define INET_DEBUG LWIP_DBG_OFF > +#define IP_DEBUG LWIP_DBG_OFF > +#define IP_REASS_DEBUG LWIP_DBG_OFF > +#define RAW_DEBUG LWIP_DBG_OFF > +#define MEM_DEBUG LWIP_DBG_OFF > +#define MEMP_DEBUG LWIP_DBG_OFF > +#define SYS_DEBUG LWIP_DBG_OFF > +#define TIMERS_DEBUG LWIP_DBG_OFF > +#define TCP_DEBUG LWIP_DBG_OFF > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > +#define TCP_FR_DEBUG LWIP_DBG_OFF > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > +#define TCP_WND_DEBUG LWIP_DBG_OFF > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > +#define TCP_RST_DEBUG LWIP_DBG_OFF > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > +#define UDP_DEBUG LWIP_DBG_OFF > +#define TCPIP_DEBUG LWIP_DBG_OFF > +#define SLIP_DEBUG LWIP_DBG_OFF > +#define DHCP_DEBUG LWIP_DBG_OFF > +#define AUTOIP_DEBUG LWIP_DBG_OFF > +#define DNS_DEBUG LWIP_DBG_OFF > +#define IP6_DEBUG LWIP_DBG_OFF > +#define DHCP6_DEBUG LWIP_DBG_OFF > +#endif > +#define LWIP_TESTMODE 0 > + > +#if defined(CONFIG_LWIP_LIB_NOASSERT) > +#define LWIP_NOASSERT 1 > +#define LWIP_ASSERT(message, assertion) > +#endif > + > +#include "lwip/debug.h" > + > +#define SYS_LIGHTWEIGHT_PROT 0 > +#define NO_SYS 0 > + > +#define MEM_ALIGNMENT 1 > +#define MEM_SIZE CONFIG_LWIP_LIB_MEM_SIZE > + > +#define MEMP_NUM_PBUF 4 > +#define MEMP_NUM_RAW_PCB 2 > +#define MEMP_NUM_UDP_PCB 4 > +#define MEMP_NUM_TCP_PCB 2 > +#define MEMP_NUM_TCP_PCB_LISTEN 2 > +#define MEMP_NUM_TCP_SEG 16 > +#define MEMP_NUM_REASSDATA 1 > +#define MEMP_NUM_ARP_QUEUE 2 > +#define MEMP_NUM_SYS_TIMEOUT 4 > +#define MEMP_NUM_NETBUF 2 > +#define MEMP_NUM_NETCONN 32 > +#define MEMP_NUM_TCPIP_MSG_API 8 > +#define MEMP_NUM_TCPIP_MSG_INPKT 8 > +#define PBUF_POOL_SIZE 8 > + > +#define LWIP_ARP 1 > + > +#define IP_FORWARD 0 > +#define IP_OPTIONS_ALLOWED 1 > +#define IP_REASSEMBLY 1 > +#define IP_FRAG 1 > +#define IP_REASS_MAXAGE 3 > +#define IP_REASS_MAX_PBUFS 4 > +#define IP_FRAG_USES_STATIC_BUF 0 > + > +#define IP_DEFAULT_TTL 255 > + > +#define LWIP_ICMP 1 > + > +#define LWIP_RAW 1 > + > +#if defined(CONFIG_LWIP_LIB_DHCP) > +#define LWIP_DHCP 1 > +#define LWIP_DHCP_BOOTP_FILE 1 > +#else > +#define LWIP_DHCP 0 > +#endif > +#define LWIP_DHCP_DOES_ACD_CHECK 0 > + > +#define LWIP_AUTOIP 0 > + > +#define LWIP_SNMP 0 > + > +#define LWIP_IGMP 0 > + > +#if defined(CONFIG_LWIP_LIB_DNS) > +#define LWIP_DNS 1 > +#else > +#define LWIP_DNS 0 > +#endif > + > +#if defined(CONFIG_LWIP_LIB_TCP) > +#define LWIP_UDP 1 > +#else > +#define LWIP_UDP 0 > +#endif > + > +#if defined(CONFIG_LWIP_LIB_TCP) > +#define LWIP_TCP 1 > +#else > +#define LWIP_TCP 0 > +#endif > + > +#define LWIP_LISTEN_BACKLOG 0 > + > +#define PBUF_LINK_HLEN CONFIG_LWIP_LIB_PBUF_LINK_HLEN > +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN) > + > +#define LWIP_HAVE_LOOPIF 0 > + > +#if defined(CONFIG_LWIP_LIB_NETCONN) > +#define LWIP_NETCONN 1 > +#else > +#define LWIP_NETCONN 0 > +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 > +#endif > + > +#if defined(CONFIG_LWIP_LIB_SOCKET) > +#define LWIP_SOCKET 1 > + > +#define SO_REUSE 1 > +#else > +#define LWIP_SOCKET 0 > +#define SO_REUSE 0 > +#endif > + > +#define LWIP_STATS 0 > + > +#define PPP_SUPPORT 0 > + > +#define LWIP_TCPIP_CORE_LOCKING 0 > + > +#if defined(CONFIG_LWIP_LIB_LOOPBACK) > +#define LWIP_NETIF_LOOPBACK 1 > +#else > +#define LWIP_NETIF_LOOPBACK 0 > +#endif > +/* use malloc instead of pool */ > +#define MEMP_MEM_MALLOC 1 > +#define MEMP_MEM_INIT 1 > +#define MEM_LIBC_MALLOC 1 > + > +#endif /* LWIP_LWIPOPTS_H */ > diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c > new file mode 100644 > index 0000000000..37c02a451f > --- /dev/null > +++ b/lib/lwip/port/if.c > @@ -0,0 +1,260 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include <common.h> > +#include <command.h> > +extern int eth_init(void); /* net.h */ > +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* net.h */ > +extern struct in_addr net_ip; > +extern u8 net_ethaddr[6]; > + > +#include "lwip/debug.h" > +#include "lwip/arch.h" > +#include "netif/etharp.h" > +#include "lwip/stats.h" > +#include "lwip/def.h" > +#include "lwip/mem.h" > +#include "lwip/pbuf.h" > +#include "lwip/sys.h" > +#include "lwip/netif.h" > + > +#include "lwip/ip.h" > + > +#define IFNAME0 'e' > +#define IFNAME1 '0' > + > +static struct pbuf *low_level_input(struct netif *netif); > +static int uboot_net_use_lwip; > + > +int ulwip_enabled(void) > +{ > + return uboot_net_use_lwip; > +} > + > +/* 1 - in loop > + * 0 - no loop > + */ > +static int loop_lwip; > + > +/* ret 1 - in loop > + * 0 - no loop > + */ > +int ulwip_in_loop(void) > +{ > + return loop_lwip; > +} > + > +void ulwip_loop_set(int loop) > +{ > + loop_lwip = loop; > +} > + > +static int ulwip_app_err; > + > +void ulwip_exit(int err) > +{ > + ulwip_app_err = err; > + ulwip_loop_set(0); > +} > + > +int ulwip_app_get_err(void) > +{ > + return ulwip_app_err; > +} > + > +struct uboot_lwip_if { > +}; > + > +#if defined(CONFIG_CMD_DHCP) > +struct netif uboot_netif; > +#else > +static struct netif uboot_netif; > +#endif I am not sure I understand why this exists. If you want to change some some members of the struct from the dhcp code, why dont you create a function that resides here? > + > +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) > + > +extern uchar *net_rx_packet; > +extern int net_rx_packet_len; > + > +int uboot_lwip_poll(void) > +{ > + struct pbuf *p; > + int err; > + > + p = low_level_input(&uboot_netif); > + if (!p) { > + printf("error p = low_level_input = NULL\n"); > + return 0; > + } > + > + err = ethernet_input(p, &uboot_netif); > + if (err) > + printf("ip4_input err %d\n", err); > + > + return 0; > +} > + > +static struct pbuf *low_level_input(struct netif *netif) > +{ > + struct pbuf *p, *q; > + u16_t len = net_rx_packet_len; > + uchar *data = net_rx_packet; > + > +#if ETH_PAD_SIZE > + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ > +#endif > + > + /* We allocate a pbuf chain of pbufs from the pool. */ > + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); > + if (p) { > +#if ETH_PAD_SIZE > + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ > +#endif > + /* We iterate over the pbuf chain until we have read the entire > + * packet into the pbuf. > + */ > + for (q = p; q != NULL; q = q->next) { > + /* Read enough bytes to fill this pbuf in the chain. The > + * available data in the pbuf is given by the q->len > + * variable. > + * This does not necessarily have to be a memcpy, you can also preallocate > + * pbufs for a DMA-enabled MAC and after receiving truncate it to the > + * actually received size. In this case, ensure the tot_len member of the > + * pbuf is the sum of the chained pbuf len members. > + */ > + MEMCPY(q->payload, data, q->len); > + data += q->len; > + } > + //acknowledge that packet has been read(); > + > +#if ETH_PAD_SIZE > + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ > +#endif > + LINK_STATS_INC(link.recv); > + } else { > + //drop packet(); > + LINK_STATS_INC(link.memerr); > + LINK_STATS_INC(link.drop); > + } > + > + return p; > +} > + > +static int ethernetif_input(struct pbuf *p, struct netif *netif) > +{ > + struct ethernetif *ethernetif; > + > + ethernetif = netif->state; > + > + /* move received packet into a new pbuf */ > + p = low_level_input(netif); > + > + /* if no packet could be read, silently ignore this */ > + if (p) { > + /* pass all packets to ethernet_input, which decides what packets it supports */ > + if (netif->input(p, netif) != ERR_OK) { > + LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", __func__)); > + pbuf_free(p); > + p = NULL; > + } > + } > + return 0; > +} > + > +static err_t low_level_output(struct netif *netif, struct pbuf *p) > +{ > + int err; > + > + err = eth_send(p->payload, p->len); > + if (err != 0) { > + printf("eth_send error %d\n", err); > + return ERR_ABRT; > + } > + return ERR_OK; > +} > + > +err_t uboot_lwip_if_init(struct netif *netif) > +{ > + struct uboot_lwip_if *uif = (struct uboot_lwip_if *)malloc(sizeof(struct uboot_lwip_if)); > + > + if (!uif) { > + printf("uboot_lwip_if: out of memory\n"); > + return ERR_MEM; > + } > + netif->state = uif; > + > + netif->name[0] = IFNAME0; > + netif->name[1] = IFNAME1; > + > + netif->hwaddr_len = ETHARP_HWADDR_LEN; > + string_to_enetaddr(env_get("ethaddr"), netif->hwaddr); > +#if defined(CONFIG_LWIP_LIB_DEBUG) > + printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", > + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], > + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); > +#endif > + > +#if LWIP_IPV4 > + netif->output = etharp_output; > +#endif /* LWIP_IPV4 */ > +#if LWIP_IPV6 > + netif->output_ip6 = ethip6_output; > +#endif /* LWIP_IPV6 */ > + netif->linkoutput = low_level_output; > + netif->mtu = 1500; > + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; > + > + eth_init(); /* activate u-boot eth dev */ > + > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > + printf("Initialized LWIP stack\n"); > + } > + > + return ERR_OK; > +} > + > +int uboot_lwip_init(void) > +{ > + ip4_addr_t ipaddr, netmask, gw; > + > + if (uboot_net_use_lwip) > + return CMD_RET_SUCCESS; > + > + ip4_addr_set_zero(&gw); > + ip4_addr_set_zero(&ipaddr); > + ip4_addr_set_zero(&netmask); > + > + ipaddr_aton(env_get("ipaddr"), &ipaddr); > + ipaddr_aton(env_get("ipaddr"), &netmask); > + > + LWIP_PORT_INIT_NETMASK(&netmask); > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > + printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr)); > + printf(" GW: %s\n", ip4addr_ntoa(&gw)); > + printf(" mask: %s\n", ip4addr_ntoa(&netmask)); > + } > + > + if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw, > + &uboot_netif, uboot_lwip_if_init, ethernetif_input)) > + printf("err: netif_add failed!\n"); > + > + netif_set_up(&uboot_netif); > + netif_set_link_up(&uboot_netif); > +#if LWIP_IPV6 > + netif_create_ip6_linklocal_address(&uboot_netif, 1); > + printf(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0))); > +#endif /* LWIP_IPV6 */ > + > + uboot_net_use_lwip = 1; > + > + return CMD_RET_SUCCESS; > +} > + > +/* placeholder, not used now */ > +void uboot_lwip_destroy(void) > +{ > + uboot_net_use_lwip = 0; > +} > diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h > new file mode 100644 > index 0000000000..db30d7614e > --- /dev/null > +++ b/lib/lwip/port/include/arch/cc.h > @@ -0,0 +1,46 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#ifndef LWIP_ARCH_CC_H > +#define LWIP_ARCH_CC_H > + > +#include <linux/types.h> > +#include <linux/kernel.h> > + > +#define LWIP_ERRNO_INCLUDE <errno.h> > + > +#define LWIP_ERRNO_STDINCLUDE 1 > +#define LWIP_NO_UNISTD_H 1 > +#define LWIP_TIMEVAL_PRIVATE 1 > + > +extern unsigned int lwip_port_rand(void); > +#define LWIP_RAND() (lwip_port_rand()) > + > +/* different handling for unit test, normally not needed */ > +#ifdef LWIP_NOASSERT_ON_ERROR > +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ > + handler; }} while (0) > +#endif > + > +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS > + > +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ > + x, __LINE__, __FILE__); } while (0) > + > +static inline int atoi(const char *str) > +{ > + int r = 0; > + int i; > + > + for (i = 0; str[i] != '\0'; ++i) > + r = r * 10 + str[i] - '0'; > + > + return r; > +} > + > +#define LWIP_ERR_T int > + > +#endif /* LWIP_ARCH_CC_H */ > diff --git a/lib/lwip/port/include/arch/sys_arch.h b/lib/lwip/port/include/arch/sys_arch.h > new file mode 100644 > index 0000000000..8d95146275 > --- /dev/null > +++ b/lib/lwip/port/include/arch/sys_arch.h > @@ -0,0 +1,59 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#ifndef LWIP_ARCH_SYS_ARCH_H > +#define LWIP_ARCH_SYS_ARCH_H > + > +#include "lwip/opt.h" > +#include "lwip/arch.h" > +#include "lwip/err.h" > + > +#define ERR_NEED_SCHED 123 > + > +void sys_arch_msleep(u32_t delay_ms); > +#define sys_msleep(ms) sys_arch_msleep(ms) > + > +#if SYS_LIGHTWEIGHT_PROT > +typedef u32_t sys_prot_t; > +#endif /* SYS_LIGHTWEIGHT_PROT */ > + > +#include <errno.h> > + > +#define SYS_MBOX_NULL NULL > +#define SYS_SEM_NULL NULL > + > +typedef u32_t sys_prot_t; > + > +struct sys_sem; > +typedef struct sys_sem *sys_sem_t; > +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) > +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = NULL; }} while (0) > + > +/* let sys.h use binary semaphores for mutexes */ > +#define LWIP_COMPAT_MUTEX 1 > +#define LWIP_COMPAT_MUTEX_ALLOWED 1 > + > +struct sys_mbox; > +typedef struct sys_mbox *sys_mbox_t; > +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) > +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = NULL; }} while (0) > + > +struct sys_thread; > +typedef struct sys_thread *sys_thread_t; > + > +static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) > +{ > + return 0; > +}; > + > +static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) > +{ > + return 0; > +}; > + > +#define sys_sem_signal(s) > + > +#endif /* LWIP_ARCH_SYS_ARCH_H */ > diff --git a/lib/lwip/port/include/limits.h b/lib/lwip/port/include/limits.h > new file mode 100644 > index 0000000000..e69de29bb2 > diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c > new file mode 100644 > index 0000000000..609eeccf8c > --- /dev/null > +++ b/lib/lwip/port/sys-arch.c > @@ -0,0 +1,20 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > + */ > + > +#include <common.h> > +#include <rand.h> > +#include "lwip/opt.h" > + > +u32_t sys_now(void) > +{ > + return get_timer(0); > +} > + > +u32_t lwip_port_rand(void) > +{ > + return (u32_t)rand(); > +} > + > diff --git a/lib/lwip/ulwip.h b/lib/lwip/ulwip.h > new file mode 100644 > index 0000000000..11ca52aa1f > --- /dev/null > +++ b/lib/lwip/ulwip.h > @@ -0,0 +1,9 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > + > +int ulwip_enabled(void); > +int ulwip_in_loop(void); > +int ulwip_loop_set(int loop); > +int ulwip_exit(int err); > +int uboot_lwip_poll(void); > +int ulwip_app_get_err(void); > +void ulwip_set_tmo(int (*tmo)(void)); > diff --git a/net/Kconfig b/net/Kconfig > index a1ec3f8542..2c5d8b8aca 100644 > --- a/net/Kconfig > +++ b/net/Kconfig > @@ -5,6 +5,7 @@ > menuconfig NET > bool "Networking support" > default y > + select LWIP_LIB > > if NET > > diff --git a/net/net.c b/net/net.c > index 57da9bda85..3d9a2e798a 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -121,6 +121,7 @@ > #endif > #include <net/tcp.h> > #include <net/wget.h> > +#include "../lib/lwip/ulwip.h" > > /** BOOTP EXTENTIONS **/ > > @@ -438,7 +439,11 @@ int net_loop(enum proto_t protocol) > #endif > > bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); > +#if defined(CONFIG_LWIP_LIB) > + if (!ulwip_enabled() || !ulwip_in_loop()) > +#endif > net_init(); > + > if (eth_is_on_demand_init()) { > eth_halt(); > eth_set_current(); > @@ -619,6 +624,18 @@ restart: > */ > eth_rx(); > > +#if defined(CONFIG_LWIP_LIB) > + if (ulwip_enabled()) { > + net_set_state(NETLOOP_CONTINUE); > + if (!ulwip_in_loop()) { > + if (ulwip_app_get_err()) > + net_set_state(NETLOOP_FAIL); > + else > + net_set_state(NETLOOP_SUCCESS); > + goto done; > + } > + } > +#endif > /* > * Abort if ctrl-c was pressed. > */ > @@ -1177,6 +1194,13 @@ void net_process_received_packet(uchar *in_packet, int len) > if (len < ETHER_HDR_SIZE) > return; > > +#if defined(CONFIG_LWIP_LIB) > + if (ulwip_enabled()) { > + uboot_lwip_poll(); > + return; > + } > +#endif > + > #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) > if (push_packet) { > (*push_packet)(in_packet, len); > -- > 2.30.2 > Thanks /Ilias
On Thu, 27 Jul 2023 at 19:29, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote: > Hi Maxim, > > > This is too much for a single patch review. Can you pleas split it in > something that's easier to review and comment. > > For example, > #1 add the lwip library only > #2-#5 add ping, wget, tcp and ping > > Some random comments below as well. > > On Fri, Jul 14, 2023 at 08:19:57PM +0600, Maxim Uvarov wrote: > > This commit adds lwip library for the U-boot network > > stack. Supported commands: ping, tftp, dhcp and wget. > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> > > --- > > .gitignore | 9 + > > boot/bootmeth_pxe.c | 2 +- > > cmd/net.c | 48 +---- > > cmd/pxe.c | 2 +- > > include/net.h | 8 +- > > lib/Kconfig | 2 + > > lib/Makefile | 2 + > > lib/lwip/Kconfig | 63 ++++++ > > lib/lwip/Makefile | 101 ++++++++++ > > lib/lwip/apps/dhcp/lwip-dhcp.c | 52 +++++ > > lib/lwip/apps/http/lwip-wget.c | 74 +++++++ > > lib/lwip/apps/ping/lwip_ping.c | 37 ++++ > > lib/lwip/apps/ping/lwip_ping.h | 24 +++ > > lib/lwip/apps/ping/ping.h | 35 ++++ > > lib/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++++++ > > lib/lwip/cmd-lwip.c | 269 ++++++++++++++++++++++++++ > > lib/lwip/lwipopts.h | 203 +++++++++++++++++++ > > lib/lwip/port/if.c | 260 +++++++++++++++++++++++++ > > lib/lwip/port/include/arch/cc.h | 46 +++++ > > lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ > > lib/lwip/port/include/limits.h | 0 > > lib/lwip/port/sys-arch.c | 20 ++ > > lib/lwip/ulwip.h | 9 + > > net/Kconfig | 1 + > > net/net.c | 24 +++ > > 25 files changed, 1430 insertions(+), 44 deletions(-) > > create mode 100644 lib/lwip/Kconfig > > create mode 100644 lib/lwip/Makefile > > create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c > > create mode 100644 lib/lwip/apps/http/lwip-wget.c > > create mode 100644 lib/lwip/apps/ping/lwip_ping.c > > create mode 100644 lib/lwip/apps/ping/lwip_ping.h > > create mode 100644 lib/lwip/apps/ping/ping.h > > create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c > > create mode 100644 lib/lwip/cmd-lwip.c > > create mode 100644 lib/lwip/lwipopts.h > > create mode 100644 lib/lwip/port/if.c > > create mode 100644 lib/lwip/port/include/arch/cc.h > > create mode 100644 lib/lwip/port/include/arch/sys_arch.h > > create mode 100644 lib/lwip/port/include/limits.h > > create mode 100644 lib/lwip/port/sys-arch.c > > create mode 100644 lib/lwip/ulwip.h > > > > diff --git a/.gitignore b/.gitignore > > index eb769f144c..be3676c59e 100644 > > --- a/.gitignore > > +++ b/.gitignore > > @@ -104,3 +104,12 @@ __pycache__ > > # pylint files > > /pylint.cur > > /pylint.out/ > > + > > +lib/lwip/lwip-external > > +lib/lwip/apps/ping/ping.c > > +lib/lwip/apps/http/http_client.c > > +lib/lwip/apps/http/http_client.h > > +lib/lwip/apps/tftp/tftp.c > > +lib/lwip/apps/tftp/tftp_client.h > > +lib/lwip/apps/tftp/tftp_common.h > > +lib/lwip/apps/tftp/tftp_example.h > > diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c > > index e6992168c0..30331a9806 100644 > > --- a/boot/bootmeth_pxe.c > > +++ b/boot/bootmeth_pxe.c > > @@ -118,7 +118,7 @@ static int distro_pxe_read_file(struct udevice *dev, > struct bootflow *bflow, > > tftp_argv[1] = file_addr; > > tftp_argv[2] = (void *)file_path; > > > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > > return -ENOENT; > > ret = pxe_get_file_size(&size); > > if (ret) > > diff --git a/cmd/net.c b/cmd/net.c > > index 0e9f200ca9..6d704fba86 100644 > > --- a/cmd/net.c > > +++ b/cmd/net.c > > @@ -36,19 +36,9 @@ U_BOOT_CMD( > > #endif > > > > #ifdef CONFIG_CMD_TFTPBOOT > > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]) > > -{ > > - int ret; > > - > > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); > > - ret = netboot_common(TFTPGET, cmdtp, argc, argv); > > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); > > - return ret; > > -} > > - > > #if IS_ENABLED(CONFIG_IPV6) > > U_BOOT_CMD( > > - tftpboot, 4, 1, do_tftpb, > > + tftpboot, 4, 1, do_lwip_tftp, > > "boot image via network using TFTP protocol\n" > > "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " > > "with [] brackets", > > @@ -56,7 +46,7 @@ U_BOOT_CMD( > > ); > > #else > > U_BOOT_CMD( > > - tftpboot, 3, 1, do_tftpb, > > + tftpboot, 3, 1, do_lwip_tftp, > > "load file via network using TFTP protocol", > > "[loadAddress] [[hostIPaddr:]bootfilename]" > > ); > > @@ -112,7 +102,7 @@ U_BOOT_CMD( > > static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > > char *const argv[]) > > { > > - return netboot_common(DHCP, cmdtp, argc, argv); > > + return do_lwip_dhcp(); > > } > > > > U_BOOT_CMD( > > @@ -137,13 +127,11 @@ U_BOOT_CMD( > > #endif > > > > #if defined(CONFIG_CMD_WGET) > > -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * > const argv[]) > > -{ > > - return netboot_common(WGET, cmdtp, argc, argv); > > -} > > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]); > > > > U_BOOT_CMD( > > - wget, 3, 1, do_wget, > > + wget, 3, 1, do_lwip_wget, > > I thought we agreed on keeping both the native u-boot stack and lwip until > we can proove the later is useful. Do I remember this wrong? Same goes for > all the other commands > Ilias thanks for review, I will walk over all comments. Regarding this one in v3, there was a comment from Tom to switch to a new version for implemented comments. v3 had 3 modes 1 lwip disabled, original commands 2. lwip enabled, original command and "lwip <command>" 3. lwip replaces original commands and has "lwip <command>" For current v4 it's mode 3 only. <snip> So,, the spacing needs to be fixed up, and "default n" is the default when no "default" keyword is present. But here's the big change I want, if we enable LWIP it should replace the other commands. For debug / testing, it's OK for "lwip dhcp" to be how to run it, but since the goal is replacement, it needs to replace. I want to be able to do drop CONFIG_LWIP=y in my CI script and have all of my boards use LWIP for the normal networking tests so I can report back that things work, or that there's problems to sort out. Thanks! </snip> I agree if we can do good tests for lwip variants then more likely no need to support original commands. But I would like to see some consolidation here so I can account for that in updated patches. BR, Maxim. > > > "boot image via network using HTTP protocol", > > "[loadAddress] [[hostIPaddr:]path and image name]" > > ); > > @@ -376,28 +364,10 @@ static int netboot_common(enum proto_t proto, > struct cmd_tbl *cmdtp, int argc, > > } > > > > #if defined(CONFIG_CMD_PING) > > -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > - char *const argv[]) > > -{ > > - if (argc < 2) > > - return CMD_RET_USAGE; > > - > > - net_ping_ip = string_to_ip(argv[1]); > > - if (net_ping_ip.s_addr == 0) > > - return CMD_RET_USAGE; > > - > > - if (net_loop(PING) < 0) { > > - printf("ping failed; host %s is not alive\n", argv[1]); > > - return CMD_RET_FAILURE; > > - } > > - > > - printf("host %s is alive\n", argv[1]); > > - > > - return CMD_RET_SUCCESS; > > -} > > - > > +extern int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]); > > Why extern? Cant we define it properly as part of our header file? > > > U_BOOT_CMD( > > - ping, 2, 1, do_ping, > > + ping, 2, 1, do_lwip_ping, > > "send ICMP ECHO_REQUEST to network host", > > "pingAddress" > > ); > > diff --git a/cmd/pxe.c b/cmd/pxe.c > > index db8e4697f2..bd4d6f5f2b 100644 > > --- a/cmd/pxe.c > > +++ b/cmd/pxe.c > > @@ -33,7 +33,7 @@ static int do_get_tftp(struct pxe_context *ctx, const > char *file_path, > > tftp_argv[1] = file_addr; > > tftp_argv[2] = (void *)file_path; > > > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > > return -ENOENT; > > ret = pxe_get_file_size(sizep); > > if (ret) > > diff --git a/include/net.h b/include/net.h > > index 1a99009959..6b573f3319 100644 > > --- a/include/net.h > > +++ b/include/net.h > > @@ -54,8 +54,10 @@ struct in_addr { > > __be32 s_addr; > > }; > > > > +int do_lwip_dhcp(void); > > + > > /** > > - * do_tftpb - Run the tftpboot command > > + * do_lwip_tftp - Run the tftpboot command > > * > > * @cmdtp: Command information for tftpboot > > * @flag: Command flags (CMD_FLAG_...) > > @@ -63,7 +65,7 @@ struct in_addr { > > * @argv: List of arguments > > * Return: result (see enum command_ret_t) > > */ > > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]); > > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]); > > > > /** > > * An incoming packet handler. > > @@ -561,7 +563,7 @@ extern int net_restart_wrap; /* > Tried all network devices */ > > > > enum proto_t { > > BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, > NETCONS, > > - SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET > > + SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET, > LWIP > > }; > > > > extern char net_boot_file_name[1024];/* Boot File name */ > > diff --git a/lib/Kconfig b/lib/Kconfig > > index 3c5a4ab386..7485a1f3bf 100644 > > --- a/lib/Kconfig > > +++ b/lib/Kconfig > > @@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates" > > source lib/fwu_updates/Kconfig > > > > endmenu > > + > > +source lib/lwip/Kconfig > > diff --git a/lib/Makefile b/lib/Makefile > > index d77b33e7f4..3b80a41187 100644 > > --- a/lib/Makefile > > +++ b/lib/Makefile > > @@ -91,6 +91,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ > > obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ > > obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o > > > > +obj-y += lwip/ > > + > > ifdef CONFIG_SPL_BUILD > > obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o > > obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o > > diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig > > new file mode 100644 > > index 0000000000..3688ac3305 > > --- /dev/null > > +++ b/lib/lwip/Kconfig > > @@ -0,0 +1,63 @@ > > +menu "LWIP" > > +config LWIP_LIB > > + bool "Support LWIP library" > > + help > > + Selecting this option will enable the LWIP library code. > > + > > +menu "LWIP options" > > + > > +config LWIP_LIB_DEBUG > > + bool "enable debug" > > + default n > > + > > +config LWIP_LIB_NOASSERT > > + bool "disable asserts" > > + default y > > + help > > + Disabling asserts reduces binary size on 16k. > > + > > +config LWIP_LIB_TCP > > You need some useful help entry on all of those. > > > + bool "tcp" > > + default y > > + > > +config LWIP_LIB_UDP > > + bool "udp" > > + default y > > + > > +config LWIP_LIB_DNS > > + bool "dns" > > + default n > > + > > +config LWIP_LIB_DHCP > > + bool "dhcp" > > + default y > > + > > +config LWIP_LIB_LOOPBACK > > + bool "loopback" > > + help > > + Increases size on 1k. > > + > > +config LWIP_LIB_SOCKET > > + bool "socket API" > > + > > +config LWIP_LIB_NETCONN > > + bool "netconn API" > > + > > +config LWIP_LIB_MEM_SIZE > > + int "mem size" > > + default 1600 > > + range 1 4096 > > + help > > + MEM_SIZE: the size of the heap memory. If the application will > send > > + a lot of data that needs to be copied, this should be set high. > > + > > +config LWIP_LIB_PBUF_LINK_HLEN > > + int "pbuf link hlen" > > + default 14 > > + range 4 1024 > > + help > > + PBUF_LINK_HLEN: the number of bytes that should be allocated > for a > > + link level header. The default is 14, the standard value for > Ethernet. > > +endmenu > > + > > +endmenu > > diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile > > new file mode 100644 > > index 0000000000..e1a8a2a7b7 > > --- /dev/null > > +++ b/lib/lwip/Makefile > > @@ -0,0 +1,101 @@ > > +# SPDX-License-Identifier: GPL-2.0+ > > +# > > +# (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + > > +LWIPDIR=lwip-external/src > > + > > +ccflags-y += -I$(srctree)/lib/lwip/port/include > > +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include > -I$(srctree)/lib/lwip > > + > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \ > > + $(LWIPDIR)/core/def.o \ > > + $(LWIPDIR)/core/dns.o \ > > + $(LWIPDIR)/core/inet_chksum.o \ > > + $(LWIPDIR)/core/ip.o \ > > + $(LWIPDIR)/core/mem.o \ > > + $(LWIPDIR)/core/memp.o \ > > + $(LWIPDIR)/core/netif.o \ > > + $(LWIPDIR)/core/pbuf.o \ > > + $(LWIPDIR)/core/raw.o \ > > + $(LWIPDIR)/core/stats.o \ > > + $(LWIPDIR)/core/sys.o \ > > + $(LWIPDIR)/core/altcp.o \ > > + $(LWIPDIR)/core/altcp_alloc.o \ > > + $(LWIPDIR)/core/altcp_tcp.o \ > > + $(LWIPDIR)/core/tcp.o \ > > + $(LWIPDIR)/core/tcp_in.o \ > > + $(LWIPDIR)/core/tcp_out.o \ > > + $(LWIPDIR)/core/timeouts.o \ > > + $(LWIPDIR)/core/udp.o > > + > > +# IPv4 > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \ > > + $(LWIPDIR)/core/ipv4/autoip.o \ > > + $(LWIPDIR)/core/ipv4/dhcp.o \ > > + $(LWIPDIR)/core/ipv4/etharp.o \ > > + $(LWIPDIR)/core/ipv4/icmp.o \ > > + $(LWIPDIR)/core/ipv4/igmp.o \ > > + $(LWIPDIR)/core/ipv4/ip4_frag.o \ > > + $(LWIPDIR)/core/ipv4/ip4.o \ > > + $(LWIPDIR)/core/ipv4/ip4_addr.o > > +# IPv6 > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \ > > + $(LWIPDIR)/core/ipv6/ethip6.o \ > > + $(LWIPDIR)/core/ipv6/icmp6.o \ > > + $(LWIPDIR)/core/ipv6/inet6.o \ > > + $(LWIPDIR)/core/ipv6/ip6.o \ > > + $(LWIPDIR)/core/ipv6/ip6_addr.o \ > > + $(LWIPDIR)/core/ipv6/ip6_frag.o \ > > + $(LWIPDIR)/core/ipv6/mld6.o \ > > + $(LWIPDIR)/core/ipv6/nd6.o > > +# API > > +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \ > > + $(LWIPDIR)/api/api_msg.o \ > > + $(LWIPDIR)/api/err.o \ > > + $(LWIPDIR)/api/if_api.o \ > > + $(LWIPDIR)/api/netbuf.o \ > > + $(LWIPDIR)/api/netdb.o \ > > + $(LWIPDIR)/api/netifapi.o \ > > + $(LWIPDIR)/api/sockets.o \ > > + $(LWIPDIR)/api/tcpip.o > > + > > +# Netdevs > > +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o > > + > > +obj-$(CONFIG_NET) += port/if.o > > +obj-$(CONFIG_NET) += port/sys-arch.o > > + > > +obj-$(CONFIG_NET) += cmd-lwip.o > > + > > + > > +ccflags-y += -I$(srctree)/lib/lwip/apps/ping > > +.PHONY: $(obj)/apps/ping/ping.c > > +$(obj)/apps/ping/ping.o: $(obj)/apps/ping/ping.c > > +$(obj)/apps/ping/ping.c: > > + cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c > $(obj)/apps/ping/ping.c > > + > > +obj-$(CONFIG_CMD_PING) += apps/ping/ping.o > > +obj-$(CONFIG_CMD_PING) += apps/ping/lwip_ping.o > > + > > +$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c > > +.PHONY: $(obj)/apps/http/http_client.c > > +$(obj)/apps/http/http_client.c: > > + cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c > $(obj)/apps/http/http_client.c > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h > $(obj)/apps/http/http_client.h > > + > > +obj-$(CONFIG_CMD_WGET) += apps/http/http_client.o > > +obj-$(CONFIG_CMD_WGET) += apps/http/lwip-wget.o > > + > > +ccflags-y += -I$(CURDIR)/lib/lwip/apps/tftp > > +$(obj)/apps/tftp/tftp.o: $(obj)/apps/tftp/tftp.c > > +.PHONY: $(obj)/apps/tftp/tftp.c > > +$(obj)/apps/tftp/tftp.c: > > + cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c > $(obj)/apps/tftp/tftp.c > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h > $(obj)/apps/tftp/tftp_client.h > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h > $(obj)/apps/tftp/tftp_common.h > > + cp > $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h > $(obj)/apps/tftp/tftp_example.h > > + > > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/tftp.o > > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/lwip-tftp.o > > + > > +obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o > > diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c > b/lib/lwip/apps/dhcp/lwip-dhcp.c > > new file mode 100644 > > index 0000000000..2e4812c7dd > > --- /dev/null > > +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c > > @@ -0,0 +1,52 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include <lwip/dhcp.h> > > +#include <lwip/prot/dhcp.h> > > + > > +#include "../../../lwip/ulwip.h" > > + > > +static struct dhcp dhcp; > > +static bool dhcp_is_set; > > +extern struct netif uboot_netif; > > Again why extern? I dont think it's sane to carry around the uboot_netif > variable everytime we need to change a member. Instead we should functions > doing that > > > + > > +static int ulwip_dhcp_tmo(void) > > +{ > > + switch (dhcp.state) { > > + case DHCP_STATE_BOUND: > > + env_set("bootfile", dhcp.boot_file_name); > > + env_set("ipaddr", ip4addr_ntoa(&dhcp.offered_ip_addr)); > > + env_set("netmask", ip4addr_ntoa(&dhcp.offered_sn_mask)); > > + env_set("serverip", ip4addr_ntoa(&dhcp.server_ip_addr)); > > + printf("DHCP client bound to address %s\n", > ip4addr_ntoa(&dhcp.offered_ip_addr)); > > + break; > > + default: > > + return 0; > > + } > > + > > + return 0; > > +} > > The return value is always 0, why are we at least checking the result of > env_set()? > > > + > > +int ulwip_dhcp(void) > > +{ > > + int err; > > + > > + ulwip_set_tmo(ulwip_dhcp_tmo); > > + > > + if (!dhcp_is_set) { > > + dhcp_set_struct(&uboot_netif, &dhcp); > > + dhcp_is_set = true; > > + } > > + err = dhcp_start(&uboot_netif); > > + if (err) > > + printf("dhcp_start error %d\n", err); > > + > > + return err; > > +} > > diff --git a/lib/lwip/apps/http/lwip-wget.c > b/lib/lwip/apps/http/lwip-wget.c > > new file mode 100644 > > index 0000000000..0308b0b04a > > --- /dev/null > > +++ b/lib/lwip/apps/http/lwip-wget.c > > @@ -0,0 +1,74 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include "http_client.h" > > +#include "../../../lwip/ulwip.h" > > + > > +static ulong daddr; > > +static httpc_connection_t settings; > > + > > +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf > *p, err_t err) > > +{ > > + struct pbuf *q; > > + LWIP_UNUSED_ARG(err); > > + > > + if (!p) > > + return ERR_BUF; > > + > > + for (q = p; q != NULL; q = q->next) { > > + memcpy((void *)daddr, q->payload, q->len); > > + printf("downloaded chunk size %d, to addr 0x%lx\n", > q->len, daddr); > > + daddr += q->len; > > + } > > + altcp_recved(pcb, p->tot_len); > > + pbuf_free(p); > > + return ERR_OK; > > +} > > + > > +static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t > rx_content_len, > > + u32_t srv_res, err_t err) > > +{ > > + if (httpc_result == HTTPC_RESULT_OK) { > > + printf("\n%d bytes successfully downloaded.\n", > rx_content_len); > > + env_set_ulong("filesize", rx_content_len); > > + ulwip_exit(0); > > + } else { > > + printf("\nhttp eroror: %d\n", httpc_result); > > + ulwip_exit(-1); > > + } > > +} > > + > > +int lwip_wget(ulong addr, char *url) > > +{ > > + err_t err; > > + int port = 80; > > + char *server_name; > > + httpc_state_t *connection; > > + > > + daddr = addr; > > + server_name = env_get("serverip"); > > + if (!server_name) { > > + printf("error: serverip variable has to be set\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + printf("downloading %s to addr 0x%lx\n", url, addr); > > + memset(&settings, 0, sizeof(httpc_connection_t)); > > sizeof(settings) is preferred > > > + settings.result_fn = httpc_result; > > + err = httpc_get_file_dns(server_name, port, url, &settings, > > + httpc_recv, NULL, &connection); > > + if (err != ERR_OK) { > > + printf("httpc_init_connection failed\n"); > > + return err; > > + } > > + > > + env_set_hex("fileaddr", addr); > > + return 0; > > +} > > diff --git a/lib/lwip/apps/ping/lwip_ping.c > b/lib/lwip/apps/ping/lwip_ping.c > > new file mode 100644 > > index 0000000000..a05dc76326 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/lwip_ping.c > > @@ -0,0 +1,37 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include "lwip/opt.h" > > +#include "lwip/ip_addr.h" > > +#include "ping.h" > > + > > +#include "../../../lwip/ulwip.h" > > Please dont do this. Can't we just use -I or something and have this is a > normal include path? > > > + > > +static ip_addr_t ip_target; > > + > > +static int ulwip_ping_tmo(void) > > +{ > > + > > + printf("ping failed; host %s is not alive\n", > ipaddr_ntoa(&ip_target)); > > + return 0; > > +} > > + > > +int lwip_ping_init(char *ping_addr) > > +{ > > + int err; > > + > > + err = ipaddr_aton(ping_addr, &ip_target); > > + if (err == 0) { > > + printf("wrong ping addr string \"%s\" \n", ping_addr); > > + return -1; > > + } > > + > > + ulwip_set_tmo(ulwip_ping_tmo); > > + > > + ping_init(&ip_target); > > + > > + return 0; > > +} > > diff --git a/lib/lwip/apps/ping/lwip_ping.h > b/lib/lwip/apps/ping/lwip_ping.h > > new file mode 100644 > > index 0000000000..7f08095427 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/lwip_ping.h > > @@ -0,0 +1,24 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_PING_H > > +#define LWIP_PING_H > > + > > +#include <lwip/ip_addr.h> > > + > > +/** > > + * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is > used > > + */ > > +#ifndef PING_USE_SOCKETS > > +#define PING_USE_SOCKETS 0 > > +#endif > > + > > +int lwip_ping_init(char *ping_addr); > > + > > +void ping_raw_init(void); > > +void ping_send_now(void); > > + > > +#endif /* LWIP_PING_H */ > > diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h > > new file mode 100644 > > index 0000000000..0dd4bd78c7 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/ping.h > > @@ -0,0 +1,35 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +#include "../../../lwip/ulwip.h" > > + > > +#include "lwip/prot/ip4.h" > > + > > +#define ip4_print_parts(a, b, c, d) \ > > + printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d); > > + > > +#define ip4_print(ipaddr) \ > > + ip4_print_parts(\ > > + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : > 0)) > > + > > + > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ > > +#define PING_RESULT(cond) { \ > > + if (cond == 1) { \ > > + printf("host "); \ > > + ip4_print(addr); \ > > + printf(" is alive\n"); \ > > + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ > > + ulwip_exit(0); \ > > + } else { \ > > + printf("ping failed; host "); \ > > + ip4_print(addr); \ > > + printf(" is not alive\n"); \ > > + ulwip_exit(-1); \ > > + } \ > > + } while (0); > > + > > +#include "lwip/ip_addr.h" > > +void ping_init(const ip_addr_t *ping_addr); > > diff --git a/lib/lwip/apps/tftp/lwip-tftp.c > b/lib/lwip/apps/tftp/lwip-tftp.c > > new file mode 100644 > > index 0000000000..511d82e600 > > --- /dev/null > > +++ b/lib/lwip/apps/tftp/lwip-tftp.c > > @@ -0,0 +1,124 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include "lwip/apps/tftp_client.h" > > +#include "lwip/apps/tftp_server.h" > > +#include <tftp_example.h> > > + > > +#include <string.h> > > + > > +#include "../../../lwip/ulwip.h" > > + > > +#if LWIP_UDP > > + > > +static ulong daddr; > > +static ulong size; > > + > > +static void *tftp_open(const char *fname, const char *mode, u8_t > is_write) > > +{ > > + LWIP_UNUSED_ARG(mode); > > + return NULL; > > +} > > + > > +static void tftp_close(void *handle) > > +{ > > + printf("\ndone\n"); > > + printf("Bytes transferred = %ld (0x%lx hex)\n", size, size); > > + > > + env_set_ulong("filesize", size); > > + ulwip_exit(0); > > +} > > + > > +static int tftp_read(void *handle, void *buf, int bytes) > > +{ > > + return 0; > > +} > > + > > +static int tftp_write(void *handle, struct pbuf *p) > > +{ > > + struct pbuf *q; > > + > > + for (q = p; q != NULL; q = q->next) { > > + memcpy((void *)daddr, q->payload, q->len); > > + /* printf("downloaded chunk size %d, to addr 0x%lx\n", > q->len, daddr); */ > > + daddr += q->len; > > + size += q->len; > > + printf("#"); > > + } > > + > > + return 0; > > +} > > + > > +/* For TFTP client only */ > > +static void tftp_error(void *handle, int err, const char *msg, int size) > > +{ > > + char message[100]; > > + > > + LWIP_UNUSED_ARG(handle); > > + > > + memset(message, 0, sizeof(message)); > > + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size)); > > + > > + printf("TFTP error: %d (%s)", err, message); > > +} > > + > > +static const struct tftp_context tftp = { > > + tftp_open, > > + tftp_close, > > + tftp_read, > > + tftp_write, > > + tftp_error > > +}; > > + > > +int lwip_tftp(ulong addr, char *fname) > > +{ > > + void *f = (void *)0x1; /*fake handle*/ > > + err_t err; > > + ip_addr_t srv; > > + int ret; > > + char *server_ip; > > + > > + if (!fname || addr == 0) > > + return CMD_RET_FAILURE; > > + > > + size = 0; > > + daddr = addr; > > + server_ip = env_get("serverip"); > > + if (!server_ip) { > > + printf("error: serverip variable has to be set\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + ret = ipaddr_aton(server_ip, &srv); > > + LWIP_ASSERT("ipaddr_aton failed", ret == 1); > > + > > + printf("TFTP from server %s; our IP address is %s\n", > > + server_ip, env_get("ipaddr")); > > + printf("Filename '%s'.\n", fname); > > + printf("Load address: 0x%lx\n", daddr); > > + printf("Loading:"); > > + > > + err = tftp_init_client(&tftp); > > + if (!(err == ERR_OK || err == ERR_USE)) > > + printf("tftp_init_client err: %d\n", err); > > + > > + err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET); > > + /* might return different errors, like routing problems */ > > + if (err != ERR_OK) { > > + printf("tftp_get err=%d\n", err); > > + } > > + LWIP_ASSERT("tftp_get failed", err == ERR_OK); > > + > > + env_set_hex("fileaddr", addr); > > + return err; > > +} > > +#else > > +#error "UDP has to be supported" > > +#endif /* LWIP_UDP */ > > diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c > > new file mode 100644 > > index 0000000000..625c8c53b8 > > --- /dev/null > > +++ b/lib/lwip/cmd-lwip.c > > @@ -0,0 +1,269 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > +#include <display_options.h> > > +#include <memalign.h> > > +#include <net.h> > > +#include <image.h> > > + > > +#include "apps/ping/lwip_ping.h" > > +#include "ulwip.h" > > + > > +extern int uboot_lwip_init(void); > > +extern int uboot_lwip_loop_is_done(void); > > + > > +static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + printf("TBD: %s\n", __func__); > > + return CMD_RET_SUCCESS; > > +} > > + > > +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + if (!uboot_lwip_init()) > > + return CMD_RET_SUCCESS; > > + return CMD_RET_FAILURE; > > +} > > + > > +static int lwip_empty_tmo(void) { return 0; }; > > +int (*ulwip_tmo)(void) = lwip_empty_tmo; > > +void ulwip_set_tmo(int (*tmo)(void)) > > +{ > > + ulwip_tmo = tmo; > > +} > > + > > +static void ulwip_clear_tmo(void) > > +{ > > + ulwip_tmo = lwip_empty_tmo; > > +} > > + > > +static void ulwip_timeout_handler(void) > > +{ > > + eth_halt(); > > + ulwip_tmo(); > > + net_set_state(NETLOOP_FAIL); /* we did not get the reply */ > > + ulwip_loop_set(0); > > +} > > + > > +static int ulwip_loop(void) > > +{ > > + ulwip_loop_set(1); > > + if (net_loop(LWIP) < 0) { > > + ulwip_loop_set(0); > > + return CMD_RET_FAILURE; > > + } > > + ulwip_loop_set(0); > > + return CMD_RET_SUCCESS; > > +} > > + > > +#if defined(CONFIG_CMD_PING) > > +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + if (argc < 2) { > > + printf("argc = %d, error\n", argc); > > + return CMD_RET_USAGE; > > + } > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + printf("Using %s device\n", eth_get_name()); > > + printf("pinging addr: %s\n", argv[1]); > > + > > + net_set_timeout_handler(1000UL, ulwip_timeout_handler); > > + > > + if (lwip_ping_init(argv[1])) { > > + printf("ping init fail\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + ping_send_now(); > > + > > + return ulwip_loop(); > > +} > > +#endif /* CONFIG_CMD_PING */ > > + > > +#if defined(CONFIG_CMD_WGET) > > +extern int lwip_wget(ulong addr, char *url); > > + > > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + char *url; > > + > > + if (argc < 2) { > > + printf("argc = %d, error\n", argc); > > + return CMD_RET_USAGE; > > + } > > + url = argv[1]; > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + lwip_wget(image_load_addr, url); > > + > > + return ulwip_loop(); > > +} > > +#endif > > + > > +#if defined(CONFIG_CMD_TFTPBOOT) > > +extern int lwip_tftp(ulong addr, char *filename); > > + > > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + char *filename; > > + ulong addr; > > + char *end; > > + int ret; > > + > > + switch (argc) { > > + case 1: > > + filename = env_get("bootfile"); > > + break; > > + case 2: > > + /* > > + * Only one arg - accept two forms: > > + * Just load address, or just boot file name. The latter > > + * form must be written in a format which can not be > > + * mis-interpreted as a valid number. > > + */ > > + addr = hextoul(argv[1], &end); > > + if (end == (argv[1] + strlen(argv[1]))) { > > + image_load_addr = addr; > > + filename = env_get("bootfile"); > > + } else { > > + filename = argv[1]; > > + } > > + break; > > + case 3: > > + image_load_addr = hextoul(argv[1], NULL); > > + filename = argv[2]; > > + break; > > + default: > > + return CMD_RET_USAGE; > > + } > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + ret = lwip_tftp(image_load_addr, filename); > > + if (ret) > > + return ret; > > + > > + return ulwip_loop(); > > +} > > +#endif /* CONFIG_CMD_TFTPBOOT */ > > + > > +#if defined(CONFIG_CMD_DHCP) > > +extern int ulwip_dhcp(void); > > + > > +int do_lwip_dhcp(void) > > +{ > > + int ret; > > + char *filename; > > + > > + uboot_lwip_init(); > > + > > + ret = ulwip_dhcp(); > > + > > + net_set_timeout_handler(2000UL, ulwip_timeout_handler); > > + > > + ulwip_loop(); > > + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { > > + ulwip_clear_tmo(); > > + > > + filename = env_get("bootfile"); > > + if (!filename) { > > + printf("no bootfile\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + eth_init(); /* activate u-boot eth dev */ > > + net_set_timeout_handler(20000UL, ulwip_timeout_handler); > > + lwip_tftp(image_load_addr, filename); > > + > > + ret = ulwip_loop(); > > + } > > + > > + return ret; > > +} > > + > > +static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + return do_lwip_dhcp(); > > +} > > +#endif /* CONFIG_CMD_DHCP */ > > + > > +static struct cmd_tbl cmds[] = { > > + U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""), > > + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, > > + "initialize lwip stack", ""), > > +#if defined(CONFIG_CMD_LWIP_PING) > > + U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, > > + "send ICMP ECHO_REQUEST to network host", > > + "pingAddress"), > > +#endif > > +#if defined(CONFIG_CMD_WGET) > > + U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""), > > +#endif > > +#if defined(CONFIG_CMD_TFTPBOOT) > > + U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp, > > + "boot image via network using TFTP protocol\n", > > + "[loadAddress] [[hostIPaddr:]bootfilename]"), > > +#endif > > +#if defined(CONFIG_CMD_DHCP) > > + U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp, > > + "boot image via network using DHCP/TFTP protocol", > > + ""), > > +#endif > > +}; > > + > > +static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + struct cmd_tbl *cp; > > + > > + cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds)); > > + > > + argc--; > > + argv++; > > + > > + if (cp == NULL || argc > cp->maxargs) > > + return CMD_RET_USAGE; > > + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) > > + return CMD_RET_SUCCESS; > > + > > + return cp->cmd(cmdtp, flag, argc, argv); > > +} > > + > > +U_BOOT_CMD( > > + lwip, 4, 1, do_ops, > > + "LWIP sub system", > > + "info - display info\n" > > + "init - init LWIP\n" > > + "ping addr - pingAddress\n" > > + "wget http://IPadress/url/\n" > > + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" > > + "dhcp - boot image via network using DHCP/TFTP protocol\n" > > + ); > > + > > +/* Old command kept for compatibility. Same as 'mmc info' */ > > +U_BOOT_CMD( > > + lwipinfo, 1, 0, do_lwip_info, > > + "display LWIP info", > > + "- display LWIP stack info" > > +); > > diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h > > new file mode 100644 > > index 0000000000..b943d7b9be > > --- /dev/null > > +++ b/lib/lwip/lwipopts.h > > @@ -0,0 +1,203 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_LWIPOPTS_H > > +#define LWIP_LWIPOPTS_H > > + > > +#include "lwipopts.h" > > + > > +#if defined(CONFIG_LWIP_LIB_DEBUG) > > +#define LWIP_DEBUG 1 > > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > > +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON > > +#define ETHARP_DEBUG LWIP_DBG_OFF > > +#define NETIF_DEBUG LWIP_DBG_OFF > > +#define PBUF_DEBUG LWIP_DBG_OFF > > +#define API_LIB_DEBUG LWIP_DBG_OFF > > +#define API_MSG_DEBUG LWIP_DBG_OFF > > +#define SOCKETS_DEBUG LWIP_DBG_OFF > > +#define ICMP_DEBUG LWIP_DBG_OFF > > +#define IGMP_DEBUG LWIP_DBG_OFF > > +#define INET_DEBUG LWIP_DBG_OFF > > +#define IP_DEBUG LWIP_DBG_OFF > > +#define IP_REASS_DEBUG LWIP_DBG_OFF > > +#define RAW_DEBUG LWIP_DBG_OFF > > +#define MEM_DEBUG LWIP_DBG_OFF > > +#define MEMP_DEBUG LWIP_DBG_OFF > > +#define SYS_DEBUG LWIP_DBG_OFF > > +#define TIMERS_DEBUG LWIP_DBG_OFF > > +#define TCP_DEBUG LWIP_DBG_OFF > > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_FR_DEBUG LWIP_DBG_OFF > > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > > +#define TCP_WND_DEBUG LWIP_DBG_OFF > > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_RST_DEBUG LWIP_DBG_OFF > > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > > +#define UDP_DEBUG LWIP_DBG_OFF > > +#define TCPIP_DEBUG LWIP_DBG_OFF > > +#define SLIP_DEBUG LWIP_DBG_OFF > > +#define DHCP_DEBUG LWIP_DBG_ON > > +#define AUTOIP_DEBUG LWIP_DBG_ON > > +#define DNS_DEBUG LWIP_DBG_OFF > > +#define IP6_DEBUG LWIP_DBG_OFF > > +#define DHCP6_DEBUG LWIP_DBG_OFF > > +#else > > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > > +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF > > +#define ETHARP_DEBUG LWIP_DBG_OFF > > +#define NETIF_DEBUG LWIP_DBG_OFF > > +#define PBUF_DEBUG LWIP_DBG_OFF > > +#define API_LIB_DEBUG LWIP_DBG_OFF > > +#define API_MSG_DEBUG LWIP_DBG_OFF > > +#define SOCKETS_DEBUG LWIP_DBG_OFF > > +#define ICMP_DEBUG LWIP_DBG_OFF > > +#define IGMP_DEBUG LWIP_DBG_OFF > > +#define INET_DEBUG LWIP_DBG_OFF > > +#define IP_DEBUG LWIP_DBG_OFF > > +#define IP_REASS_DEBUG LWIP_DBG_OFF > > +#define RAW_DEBUG LWIP_DBG_OFF > > +#define MEM_DEBUG LWIP_DBG_OFF > > +#define MEMP_DEBUG LWIP_DBG_OFF > > +#define SYS_DEBUG LWIP_DBG_OFF > > +#define TIMERS_DEBUG LWIP_DBG_OFF > > +#define TCP_DEBUG LWIP_DBG_OFF > > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_FR_DEBUG LWIP_DBG_OFF > > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > > +#define TCP_WND_DEBUG LWIP_DBG_OFF > > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_RST_DEBUG LWIP_DBG_OFF > > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > > +#define UDP_DEBUG LWIP_DBG_OFF > > +#define TCPIP_DEBUG LWIP_DBG_OFF > > +#define SLIP_DEBUG LWIP_DBG_OFF > > +#define DHCP_DEBUG LWIP_DBG_OFF > > +#define AUTOIP_DEBUG LWIP_DBG_OFF > > +#define DNS_DEBUG LWIP_DBG_OFF > > +#define IP6_DEBUG LWIP_DBG_OFF > > +#define DHCP6_DEBUG LWIP_DBG_OFF > > +#endif > > +#define LWIP_TESTMODE 0 > > + > > +#if defined(CONFIG_LWIP_LIB_NOASSERT) > > +#define LWIP_NOASSERT 1 > > +#define LWIP_ASSERT(message, assertion) > > +#endif > > + > > +#include "lwip/debug.h" > > + > > +#define SYS_LIGHTWEIGHT_PROT 0 > > +#define NO_SYS 0 > > + > > +#define MEM_ALIGNMENT 1 > > +#define MEM_SIZE CONFIG_LWIP_LIB_MEM_SIZE > > + > > +#define MEMP_NUM_PBUF 4 > > +#define MEMP_NUM_RAW_PCB 2 > > +#define MEMP_NUM_UDP_PCB 4 > > +#define MEMP_NUM_TCP_PCB 2 > > +#define MEMP_NUM_TCP_PCB_LISTEN 2 > > +#define MEMP_NUM_TCP_SEG 16 > > +#define MEMP_NUM_REASSDATA 1 > > +#define MEMP_NUM_ARP_QUEUE 2 > > +#define MEMP_NUM_SYS_TIMEOUT 4 > > +#define MEMP_NUM_NETBUF 2 > > +#define MEMP_NUM_NETCONN 32 > > +#define MEMP_NUM_TCPIP_MSG_API 8 > > +#define MEMP_NUM_TCPIP_MSG_INPKT 8 > > +#define PBUF_POOL_SIZE 8 > > + > > +#define LWIP_ARP 1 > > + > > +#define IP_FORWARD 0 > > +#define IP_OPTIONS_ALLOWED 1 > > +#define IP_REASSEMBLY 1 > > +#define IP_FRAG 1 > > +#define IP_REASS_MAXAGE 3 > > +#define IP_REASS_MAX_PBUFS 4 > > +#define IP_FRAG_USES_STATIC_BUF 0 > > + > > +#define IP_DEFAULT_TTL 255 > > + > > +#define LWIP_ICMP 1 > > + > > +#define LWIP_RAW 1 > > + > > +#if defined(CONFIG_LWIP_LIB_DHCP) > > +#define LWIP_DHCP 1 > > +#define LWIP_DHCP_BOOTP_FILE 1 > > +#else > > +#define LWIP_DHCP 0 > > +#endif > > +#define LWIP_DHCP_DOES_ACD_CHECK 0 > > + > > +#define LWIP_AUTOIP 0 > > + > > +#define LWIP_SNMP 0 > > + > > +#define LWIP_IGMP 0 > > + > > +#if defined(CONFIG_LWIP_LIB_DNS) > > +#define LWIP_DNS 1 > > +#else > > +#define LWIP_DNS 0 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_TCP) > > +#define LWIP_UDP 1 > > +#else > > +#define LWIP_UDP 0 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_TCP) > > +#define LWIP_TCP 1 > > +#else > > +#define LWIP_TCP 0 > > +#endif > > + > > +#define LWIP_LISTEN_BACKLOG 0 > > + > > +#define PBUF_LINK_HLEN CONFIG_LWIP_LIB_PBUF_LINK_HLEN > > +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + > 40 + PBUF_LINK_HLEN) > > + > > +#define LWIP_HAVE_LOOPIF 0 > > + > > +#if defined(CONFIG_LWIP_LIB_NETCONN) > > +#define LWIP_NETCONN 1 > > +#else > > +#define LWIP_NETCONN 0 > > +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_SOCKET) > > +#define LWIP_SOCKET 1 > > + > > +#define SO_REUSE 1 > > +#else > > +#define LWIP_SOCKET 0 > > +#define SO_REUSE 0 > > +#endif > > + > > +#define LWIP_STATS 0 > > + > > +#define PPP_SUPPORT 0 > > + > > +#define LWIP_TCPIP_CORE_LOCKING 0 > > + > > +#if defined(CONFIG_LWIP_LIB_LOOPBACK) > > +#define LWIP_NETIF_LOOPBACK 1 > > +#else > > +#define LWIP_NETIF_LOOPBACK 0 > > +#endif > > +/* use malloc instead of pool */ > > +#define MEMP_MEM_MALLOC 1 > > +#define MEMP_MEM_INIT 1 > > +#define MEM_LIBC_MALLOC 1 > > + > > +#endif /* LWIP_LWIPOPTS_H */ > > diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c > > new file mode 100644 > > index 0000000000..37c02a451f > > --- /dev/null > > +++ b/lib/lwip/port/if.c > > @@ -0,0 +1,260 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +extern int eth_init(void); /* net.h */ > > +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* > net.h */ > > +extern struct in_addr net_ip; > > +extern u8 net_ethaddr[6]; > > + > > +#include "lwip/debug.h" > > +#include "lwip/arch.h" > > +#include "netif/etharp.h" > > +#include "lwip/stats.h" > > +#include "lwip/def.h" > > +#include "lwip/mem.h" > > +#include "lwip/pbuf.h" > > +#include "lwip/sys.h" > > +#include "lwip/netif.h" > > + > > +#include "lwip/ip.h" > > + > > +#define IFNAME0 'e' > > +#define IFNAME1 '0' > > + > > +static struct pbuf *low_level_input(struct netif *netif); > > +static int uboot_net_use_lwip; > > + > > +int ulwip_enabled(void) > > +{ > > + return uboot_net_use_lwip; > > +} > > + > > +/* 1 - in loop > > + * 0 - no loop > > + */ > > +static int loop_lwip; > > + > > +/* ret 1 - in loop > > + * 0 - no loop > > + */ > > +int ulwip_in_loop(void) > > +{ > > + return loop_lwip; > > +} > > + > > +void ulwip_loop_set(int loop) > > +{ > > + loop_lwip = loop; > > +} > > + > > +static int ulwip_app_err; > > + > > +void ulwip_exit(int err) > > +{ > > + ulwip_app_err = err; > > + ulwip_loop_set(0); > > +} > > + > > +int ulwip_app_get_err(void) > > +{ > > + return ulwip_app_err; > > +} > > + > > +struct uboot_lwip_if { > > +}; > > + > > +#if defined(CONFIG_CMD_DHCP) > > +struct netif uboot_netif; > > +#else > > +static struct netif uboot_netif; > > +#endif > > I am not sure I understand why this exists. If you want to change some > some members of the struct from the dhcp code, why dont you create a > function that resides here? > > > + > > +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) > > + > > +extern uchar *net_rx_packet; > > +extern int net_rx_packet_len; > > + > > +int uboot_lwip_poll(void) > > +{ > > + struct pbuf *p; > > + int err; > > + > > + p = low_level_input(&uboot_netif); > > + if (!p) { > > + printf("error p = low_level_input = NULL\n"); > > + return 0; > > + } > > + > > + err = ethernet_input(p, &uboot_netif); > > + if (err) > > + printf("ip4_input err %d\n", err); > > + > > + return 0; > > +} > > + > > +static struct pbuf *low_level_input(struct netif *netif) > > +{ > > + struct pbuf *p, *q; > > + u16_t len = net_rx_packet_len; > > + uchar *data = net_rx_packet; > > + > > +#if ETH_PAD_SIZE > > + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ > > +#endif > > + > > + /* We allocate a pbuf chain of pbufs from the pool. */ > > + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); > > + if (p) { > > +#if ETH_PAD_SIZE > > + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding > word */ > > +#endif > > + /* We iterate over the pbuf chain until we have read the > entire > > + * packet into the pbuf. > > + */ > > + for (q = p; q != NULL; q = q->next) { > > + /* Read enough bytes to fill this pbuf in the > chain. The > > + * available data in the pbuf is given by the > q->len > > + * variable. > > + * This does not necessarily have to be a memcpy, > you can also preallocate > > + * pbufs for a DMA-enabled MAC and after receiving > truncate it to the > > + * actually received size. In this case, ensure > the tot_len member of the > > + * pbuf is the sum of the chained pbuf len members. > > + */ > > + MEMCPY(q->payload, data, q->len); > > + data += q->len; > > + } > > + //acknowledge that packet has been read(); > > + > > +#if ETH_PAD_SIZE > > + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding > word */ > > +#endif > > + LINK_STATS_INC(link.recv); > > + } else { > > + //drop packet(); > > + LINK_STATS_INC(link.memerr); > > + LINK_STATS_INC(link.drop); > > + } > > + > > + return p; > > +} > > + > > +static int ethernetif_input(struct pbuf *p, struct netif *netif) > > +{ > > + struct ethernetif *ethernetif; > > + > > + ethernetif = netif->state; > > + > > + /* move received packet into a new pbuf */ > > + p = low_level_input(netif); > > + > > + /* if no packet could be read, silently ignore this */ > > + if (p) { > > + /* pass all packets to ethernet_input, which decides what > packets it supports */ > > + if (netif->input(p, netif) != ERR_OK) { > > + LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", > __func__)); > > + pbuf_free(p); > > + p = NULL; > > + } > > + } > > + return 0; > > +} > > + > > +static err_t low_level_output(struct netif *netif, struct pbuf *p) > > +{ > > + int err; > > + > > + err = eth_send(p->payload, p->len); > > + if (err != 0) { > > + printf("eth_send error %d\n", err); > > + return ERR_ABRT; > > + } > > + return ERR_OK; > > +} > > + > > +err_t uboot_lwip_if_init(struct netif *netif) > > +{ > > + struct uboot_lwip_if *uif = (struct uboot_lwip_if > *)malloc(sizeof(struct uboot_lwip_if)); > > + > > + if (!uif) { > > + printf("uboot_lwip_if: out of memory\n"); > > + return ERR_MEM; > > + } > > + netif->state = uif; > > + > > + netif->name[0] = IFNAME0; > > + netif->name[1] = IFNAME1; > > + > > + netif->hwaddr_len = ETHARP_HWADDR_LEN; > > + string_to_enetaddr(env_get("ethaddr"), netif->hwaddr); > > +#if defined(CONFIG_LWIP_LIB_DEBUG) > > + printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", > > + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], > > + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); > > +#endif > > + > > +#if LWIP_IPV4 > > + netif->output = etharp_output; > > +#endif /* LWIP_IPV4 */ > > +#if LWIP_IPV6 > > + netif->output_ip6 = ethip6_output; > > +#endif /* LWIP_IPV6 */ > > + netif->linkoutput = low_level_output; > > + netif->mtu = 1500; > > + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | > NETIF_FLAG_LINK_UP; > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > > + printf("Initialized LWIP stack\n"); > > + } > > + > > + return ERR_OK; > > +} > > + > > +int uboot_lwip_init(void) > > +{ > > + ip4_addr_t ipaddr, netmask, gw; > > + > > + if (uboot_net_use_lwip) > > + return CMD_RET_SUCCESS; > > + > > + ip4_addr_set_zero(&gw); > > + ip4_addr_set_zero(&ipaddr); > > + ip4_addr_set_zero(&netmask); > > + > > + ipaddr_aton(env_get("ipaddr"), &ipaddr); > > + ipaddr_aton(env_get("ipaddr"), &netmask); > > + > > + LWIP_PORT_INIT_NETMASK(&netmask); > > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > > + printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr)); > > + printf(" GW: %s\n", ip4addr_ntoa(&gw)); > > + printf(" mask: %s\n", ip4addr_ntoa(&netmask)); > > + } > > + > > + if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw, > > + &uboot_netif, uboot_lwip_if_init, ethernetif_input)) > > + printf("err: netif_add failed!\n"); > > + > > + netif_set_up(&uboot_netif); > > + netif_set_link_up(&uboot_netif); > > +#if LWIP_IPV6 > > + netif_create_ip6_linklocal_address(&uboot_netif, 1); > > + printf(" IPv6: %s\n", > ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0))); > > +#endif /* LWIP_IPV6 */ > > + > > + uboot_net_use_lwip = 1; > > + > > + return CMD_RET_SUCCESS; > > +} > > + > > +/* placeholder, not used now */ > > +void uboot_lwip_destroy(void) > > +{ > > + uboot_net_use_lwip = 0; > > +} > > diff --git a/lib/lwip/port/include/arch/cc.h > b/lib/lwip/port/include/arch/cc.h > > new file mode 100644 > > index 0000000000..db30d7614e > > --- /dev/null > > +++ b/lib/lwip/port/include/arch/cc.h > > @@ -0,0 +1,46 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_ARCH_CC_H > > +#define LWIP_ARCH_CC_H > > + > > +#include <linux/types.h> > > +#include <linux/kernel.h> > > + > > +#define LWIP_ERRNO_INCLUDE <errno.h> > > + > > +#define LWIP_ERRNO_STDINCLUDE 1 > > +#define LWIP_NO_UNISTD_H 1 > > +#define LWIP_TIMEVAL_PRIVATE 1 > > + > > +extern unsigned int lwip_port_rand(void); > > +#define LWIP_RAND() (lwip_port_rand()) > > + > > +/* different handling for unit test, normally not needed */ > > +#ifdef LWIP_NOASSERT_ON_ERROR > > +#define LWIP_ERROR(message, expression, handler) do { if > (!(expression)) { \ > > + handler; }} while (0) > > +#endif > > + > > +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS > > + > > +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at > line %d in %s\n", \ > > + x, __LINE__, __FILE__); } while (0) > > + > > +static inline int atoi(const char *str) > > +{ > > + int r = 0; > > + int i; > > + > > + for (i = 0; str[i] != '\0'; ++i) > > + r = r * 10 + str[i] - '0'; > > + > > + return r; > > +} > > + > > +#define LWIP_ERR_T int > > + > > +#endif /* LWIP_ARCH_CC_H */ > > diff --git a/lib/lwip/port/include/arch/sys_arch.h > b/lib/lwip/port/include/arch/sys_arch.h > > new file mode 100644 > > index 0000000000..8d95146275 > > --- /dev/null > > +++ b/lib/lwip/port/include/arch/sys_arch.h > > @@ -0,0 +1,59 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_ARCH_SYS_ARCH_H > > +#define LWIP_ARCH_SYS_ARCH_H > > + > > +#include "lwip/opt.h" > > +#include "lwip/arch.h" > > +#include "lwip/err.h" > > + > > +#define ERR_NEED_SCHED 123 > > + > > +void sys_arch_msleep(u32_t delay_ms); > > +#define sys_msleep(ms) sys_arch_msleep(ms) > > + > > +#if SYS_LIGHTWEIGHT_PROT > > +typedef u32_t sys_prot_t; > > +#endif /* SYS_LIGHTWEIGHT_PROT */ > > + > > +#include <errno.h> > > + > > +#define SYS_MBOX_NULL NULL > > +#define SYS_SEM_NULL NULL > > + > > +typedef u32_t sys_prot_t; > > + > > +struct sys_sem; > > +typedef struct sys_sem *sys_sem_t; > > +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) > > +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = > NULL; }} while (0) > > + > > +/* let sys.h use binary semaphores for mutexes */ > > +#define LWIP_COMPAT_MUTEX 1 > > +#define LWIP_COMPAT_MUTEX_ALLOWED 1 > > + > > +struct sys_mbox; > > +typedef struct sys_mbox *sys_mbox_t; > > +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) > > +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = > NULL; }} while (0) > > + > > +struct sys_thread; > > +typedef struct sys_thread *sys_thread_t; > > + > > +static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) > > +{ > > + return 0; > > +}; > > + > > +static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) > > +{ > > + return 0; > > +}; > > + > > +#define sys_sem_signal(s) > > + > > +#endif /* LWIP_ARCH_SYS_ARCH_H */ > > diff --git a/lib/lwip/port/include/limits.h > b/lib/lwip/port/include/limits.h > > new file mode 100644 > > index 0000000000..e69de29bb2 > > diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c > > new file mode 100644 > > index 0000000000..609eeccf8c > > --- /dev/null > > +++ b/lib/lwip/port/sys-arch.c > > @@ -0,0 +1,20 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <rand.h> > > +#include "lwip/opt.h" > > + > > +u32_t sys_now(void) > > +{ > > + return get_timer(0); > > +} > > + > > +u32_t lwip_port_rand(void) > > +{ > > + return (u32_t)rand(); > > +} > > + > > diff --git a/lib/lwip/ulwip.h b/lib/lwip/ulwip.h > > new file mode 100644 > > index 0000000000..11ca52aa1f > > --- /dev/null > > +++ b/lib/lwip/ulwip.h > > @@ -0,0 +1,9 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +int ulwip_enabled(void); > > +int ulwip_in_loop(void); > > +int ulwip_loop_set(int loop); > > +int ulwip_exit(int err); > > +int uboot_lwip_poll(void); > > +int ulwip_app_get_err(void); > > +void ulwip_set_tmo(int (*tmo)(void)); > > diff --git a/net/Kconfig b/net/Kconfig > > index a1ec3f8542..2c5d8b8aca 100644 > > --- a/net/Kconfig > > +++ b/net/Kconfig > > @@ -5,6 +5,7 @@ > > menuconfig NET > > bool "Networking support" > > default y > > + select LWIP_LIB > > > > if NET > > > > diff --git a/net/net.c b/net/net.c > > index 57da9bda85..3d9a2e798a 100644 > > --- a/net/net.c > > +++ b/net/net.c > > @@ -121,6 +121,7 @@ > > #endif > > #include <net/tcp.h> > > #include <net/wget.h> > > +#include "../lib/lwip/ulwip.h" > > > > /** BOOTP EXTENTIONS **/ > > > > @@ -438,7 +439,11 @@ int net_loop(enum proto_t protocol) > > #endif > > > > bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); > > +#if defined(CONFIG_LWIP_LIB) > > + if (!ulwip_enabled() || !ulwip_in_loop()) > > +#endif > > net_init(); > > + > > if (eth_is_on_demand_init()) { > > eth_halt(); > > eth_set_current(); > > @@ -619,6 +624,18 @@ restart: > > */ > > eth_rx(); > > > > +#if defined(CONFIG_LWIP_LIB) > > + if (ulwip_enabled()) { > > + net_set_state(NETLOOP_CONTINUE); > > + if (!ulwip_in_loop()) { > > + if (ulwip_app_get_err()) > > + net_set_state(NETLOOP_FAIL); > > + else > > + net_set_state(NETLOOP_SUCCESS); > > + goto done; > > + } > > + } > > +#endif > > /* > > * Abort if ctrl-c was pressed. > > */ > > @@ -1177,6 +1194,13 @@ void net_process_received_packet(uchar > *in_packet, int len) > > if (len < ETHER_HDR_SIZE) > > return; > > > > +#if defined(CONFIG_LWIP_LIB) > > + if (ulwip_enabled()) { > > + uboot_lwip_poll(); > > + return; > > + } > > +#endif > > + > > #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) > > if (push_packet) { > > (*push_packet)(in_packet, len); > > -- > > 2.30.2 > > > > Thanks > /Ilias >
On Thu, 27 Jul 2023 at 19:29, Ilias Apalodimas <ilias.apalodimas@linaro.org> wrote: > Hi Maxim, > > > This is too much for a single patch review. Can you pleas split it in > something that's easier to review and comment. > > For example, > #1 add the lwip library only > #2-#5 add ping, wget, tcp and ping > > Some random comments below as well. > > On Fri, Jul 14, 2023 at 08:19:57PM +0600, Maxim Uvarov wrote: > > This commit adds lwip library for the U-boot network > > stack. Supported commands: ping, tftp, dhcp and wget. > > > > Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> > > --- > > .gitignore | 9 + > > boot/bootmeth_pxe.c | 2 +- > > cmd/net.c | 48 +---- > > cmd/pxe.c | 2 +- > > include/net.h | 8 +- > > lib/Kconfig | 2 + > > lib/Makefile | 2 + > > lib/lwip/Kconfig | 63 ++++++ > > lib/lwip/Makefile | 101 ++++++++++ > > lib/lwip/apps/dhcp/lwip-dhcp.c | 52 +++++ > > lib/lwip/apps/http/lwip-wget.c | 74 +++++++ > > lib/lwip/apps/ping/lwip_ping.c | 37 ++++ > > lib/lwip/apps/ping/lwip_ping.h | 24 +++ > > lib/lwip/apps/ping/ping.h | 35 ++++ > > lib/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++++++ > > lib/lwip/cmd-lwip.c | 269 ++++++++++++++++++++++++++ > > lib/lwip/lwipopts.h | 203 +++++++++++++++++++ > > lib/lwip/port/if.c | 260 +++++++++++++++++++++++++ > > lib/lwip/port/include/arch/cc.h | 46 +++++ > > lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ > > lib/lwip/port/include/limits.h | 0 > > lib/lwip/port/sys-arch.c | 20 ++ > > lib/lwip/ulwip.h | 9 + > > net/Kconfig | 1 + > > net/net.c | 24 +++ > > 25 files changed, 1430 insertions(+), 44 deletions(-) > > create mode 100644 lib/lwip/Kconfig > > create mode 100644 lib/lwip/Makefile > > create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c > > create mode 100644 lib/lwip/apps/http/lwip-wget.c > > create mode 100644 lib/lwip/apps/ping/lwip_ping.c > > create mode 100644 lib/lwip/apps/ping/lwip_ping.h > > create mode 100644 lib/lwip/apps/ping/ping.h > > create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c > > create mode 100644 lib/lwip/cmd-lwip.c > > create mode 100644 lib/lwip/lwipopts.h > > create mode 100644 lib/lwip/port/if.c > > create mode 100644 lib/lwip/port/include/arch/cc.h > > create mode 100644 lib/lwip/port/include/arch/sys_arch.h > > create mode 100644 lib/lwip/port/include/limits.h > > create mode 100644 lib/lwip/port/sys-arch.c > > create mode 100644 lib/lwip/ulwip.h > > > > diff --git a/.gitignore b/.gitignore > > index eb769f144c..be3676c59e 100644 > > --- a/.gitignore > > +++ b/.gitignore > > @@ -104,3 +104,12 @@ __pycache__ > > # pylint files > > /pylint.cur > > /pylint.out/ > > + > > +lib/lwip/lwip-external > > +lib/lwip/apps/ping/ping.c > > +lib/lwip/apps/http/http_client.c > > +lib/lwip/apps/http/http_client.h > > +lib/lwip/apps/tftp/tftp.c > > +lib/lwip/apps/tftp/tftp_client.h > > +lib/lwip/apps/tftp/tftp_common.h > > +lib/lwip/apps/tftp/tftp_example.h > > diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c > > index e6992168c0..30331a9806 100644 > > --- a/boot/bootmeth_pxe.c > > +++ b/boot/bootmeth_pxe.c > > @@ -118,7 +118,7 @@ static int distro_pxe_read_file(struct udevice *dev, > struct bootflow *bflow, > > tftp_argv[1] = file_addr; > > tftp_argv[2] = (void *)file_path; > > > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > > return -ENOENT; > > ret = pxe_get_file_size(&size); > > if (ret) > > diff --git a/cmd/net.c b/cmd/net.c > > index 0e9f200ca9..6d704fba86 100644 > > --- a/cmd/net.c > > +++ b/cmd/net.c > > @@ -36,19 +36,9 @@ U_BOOT_CMD( > > #endif > > > > #ifdef CONFIG_CMD_TFTPBOOT > > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]) > > -{ > > - int ret; > > - > > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); > > - ret = netboot_common(TFTPGET, cmdtp, argc, argv); > > - bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); > > - return ret; > > -} > > - > > #if IS_ENABLED(CONFIG_IPV6) > > U_BOOT_CMD( > > - tftpboot, 4, 1, do_tftpb, > > + tftpboot, 4, 1, do_lwip_tftp, > > "boot image via network using TFTP protocol\n" > > "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " > > "with [] brackets", > > @@ -56,7 +46,7 @@ U_BOOT_CMD( > > ); > > #else > > U_BOOT_CMD( > > - tftpboot, 3, 1, do_tftpb, > > + tftpboot, 3, 1, do_lwip_tftp, > > "load file via network using TFTP protocol", > > "[loadAddress] [[hostIPaddr:]bootfilename]" > > ); > > @@ -112,7 +102,7 @@ U_BOOT_CMD( > > static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > > char *const argv[]) > > { > > - return netboot_common(DHCP, cmdtp, argc, argv); > > + return do_lwip_dhcp(); > > } > > > > U_BOOT_CMD( > > @@ -137,13 +127,11 @@ U_BOOT_CMD( > > #endif > > > > #if defined(CONFIG_CMD_WGET) > > -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * > const argv[]) > > -{ > > - return netboot_common(WGET, cmdtp, argc, argv); > > -} > > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]); > > > > U_BOOT_CMD( > > - wget, 3, 1, do_wget, > > + wget, 3, 1, do_lwip_wget, > > I thought we agreed on keeping both the native u-boot stack and lwip until > we can proove the later is useful. Do I remember this wrong? Same goes for > all the other commands > > > "boot image via network using HTTP protocol", > > "[loadAddress] [[hostIPaddr:]path and image name]" > > ); > > @@ -376,28 +364,10 @@ static int netboot_common(enum proto_t proto, > struct cmd_tbl *cmdtp, int argc, > > } > > > > #if defined(CONFIG_CMD_PING) > > -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > - char *const argv[]) > > -{ > > - if (argc < 2) > > - return CMD_RET_USAGE; > > - > > - net_ping_ip = string_to_ip(argv[1]); > > - if (net_ping_ip.s_addr == 0) > > - return CMD_RET_USAGE; > > - > > - if (net_loop(PING) < 0) { > > - printf("ping failed; host %s is not alive\n", argv[1]); > > - return CMD_RET_FAILURE; > > - } > > - > > - printf("host %s is alive\n", argv[1]); > > - > > - return CMD_RET_SUCCESS; > > -} > > - > > +extern int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]); > > Why extern? Cant we define it properly as part of our header file? > > > U_BOOT_CMD( > > - ping, 2, 1, do_ping, > > + ping, 2, 1, do_lwip_ping, > > "send ICMP ECHO_REQUEST to network host", > > "pingAddress" > > ); > > diff --git a/cmd/pxe.c b/cmd/pxe.c > > index db8e4697f2..bd4d6f5f2b 100644 > > --- a/cmd/pxe.c > > +++ b/cmd/pxe.c > > @@ -33,7 +33,7 @@ static int do_get_tftp(struct pxe_context *ctx, const > char *file_path, > > tftp_argv[1] = file_addr; > > tftp_argv[2] = (void *)file_path; > > > > - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) > > + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) > > return -ENOENT; > > ret = pxe_get_file_size(sizep); > > if (ret) > > diff --git a/include/net.h b/include/net.h > > index 1a99009959..6b573f3319 100644 > > --- a/include/net.h > > +++ b/include/net.h > > @@ -54,8 +54,10 @@ struct in_addr { > > __be32 s_addr; > > }; > > > > +int do_lwip_dhcp(void); > > + > > /** > > - * do_tftpb - Run the tftpboot command > > + * do_lwip_tftp - Run the tftpboot command > > * > > * @cmdtp: Command information for tftpboot > > * @flag: Command flags (CMD_FLAG_...) > > @@ -63,7 +65,7 @@ struct in_addr { > > * @argv: List of arguments > > * Return: result (see enum command_ret_t) > > */ > > -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]); > > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const > argv[]); > > > > /** > > * An incoming packet handler. > > @@ -561,7 +563,7 @@ extern int net_restart_wrap; /* > Tried all network devices */ > > > > enum proto_t { > > BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, > NETCONS, > > - SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET > > + SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET, > LWIP > > }; > > > > extern char net_boot_file_name[1024];/* Boot File name */ > > diff --git a/lib/Kconfig b/lib/Kconfig > > index 3c5a4ab386..7485a1f3bf 100644 > > --- a/lib/Kconfig > > +++ b/lib/Kconfig > > @@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates" > > source lib/fwu_updates/Kconfig > > > > endmenu > > + > > +source lib/lwip/Kconfig > > diff --git a/lib/Makefile b/lib/Makefile > > index d77b33e7f4..3b80a41187 100644 > > --- a/lib/Makefile > > +++ b/lib/Makefile > > @@ -91,6 +91,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ > > obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ > > obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o > > > > +obj-y += lwip/ > > + > > ifdef CONFIG_SPL_BUILD > > obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o > > obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o > > diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig > > new file mode 100644 > > index 0000000000..3688ac3305 > > --- /dev/null > > +++ b/lib/lwip/Kconfig > > @@ -0,0 +1,63 @@ > > +menu "LWIP" > > +config LWIP_LIB > > + bool "Support LWIP library" > > + help > > + Selecting this option will enable the LWIP library code. > > + > > +menu "LWIP options" > > + > > +config LWIP_LIB_DEBUG > > + bool "enable debug" > > + default n > > + > > +config LWIP_LIB_NOASSERT > > + bool "disable asserts" > > + default y > > + help > > + Disabling asserts reduces binary size on 16k. > > + > > +config LWIP_LIB_TCP > > You need some useful help entry on all of those. > > > + bool "tcp" > > + default y > > + > > +config LWIP_LIB_UDP > > + bool "udp" > > + default y > > + > > +config LWIP_LIB_DNS > > + bool "dns" > > + default n > > + > > +config LWIP_LIB_DHCP > > + bool "dhcp" > > + default y > > + > > +config LWIP_LIB_LOOPBACK > > + bool "loopback" > > + help > > + Increases size on 1k. > > + > > +config LWIP_LIB_SOCKET > > + bool "socket API" > > + > > +config LWIP_LIB_NETCONN > > + bool "netconn API" > > + > > +config LWIP_LIB_MEM_SIZE > > + int "mem size" > > + default 1600 > > + range 1 4096 > > + help > > + MEM_SIZE: the size of the heap memory. If the application will > send > > + a lot of data that needs to be copied, this should be set high. > > + > > +config LWIP_LIB_PBUF_LINK_HLEN > > + int "pbuf link hlen" > > + default 14 > > + range 4 1024 > > + help > > + PBUF_LINK_HLEN: the number of bytes that should be allocated > for a > > + link level header. The default is 14, the standard value for > Ethernet. > > +endmenu > > + > > +endmenu > > diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile > > new file mode 100644 > > index 0000000000..e1a8a2a7b7 > > --- /dev/null > > +++ b/lib/lwip/Makefile > > @@ -0,0 +1,101 @@ > > +# SPDX-License-Identifier: GPL-2.0+ > > +# > > +# (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + > > +LWIPDIR=lwip-external/src > > + > > +ccflags-y += -I$(srctree)/lib/lwip/port/include > > +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include > -I$(srctree)/lib/lwip > > + > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \ > > + $(LWIPDIR)/core/def.o \ > > + $(LWIPDIR)/core/dns.o \ > > + $(LWIPDIR)/core/inet_chksum.o \ > > + $(LWIPDIR)/core/ip.o \ > > + $(LWIPDIR)/core/mem.o \ > > + $(LWIPDIR)/core/memp.o \ > > + $(LWIPDIR)/core/netif.o \ > > + $(LWIPDIR)/core/pbuf.o \ > > + $(LWIPDIR)/core/raw.o \ > > + $(LWIPDIR)/core/stats.o \ > > + $(LWIPDIR)/core/sys.o \ > > + $(LWIPDIR)/core/altcp.o \ > > + $(LWIPDIR)/core/altcp_alloc.o \ > > + $(LWIPDIR)/core/altcp_tcp.o \ > > + $(LWIPDIR)/core/tcp.o \ > > + $(LWIPDIR)/core/tcp_in.o \ > > + $(LWIPDIR)/core/tcp_out.o \ > > + $(LWIPDIR)/core/timeouts.o \ > > + $(LWIPDIR)/core/udp.o > > + > > +# IPv4 > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \ > > + $(LWIPDIR)/core/ipv4/autoip.o \ > > + $(LWIPDIR)/core/ipv4/dhcp.o \ > > + $(LWIPDIR)/core/ipv4/etharp.o \ > > + $(LWIPDIR)/core/ipv4/icmp.o \ > > + $(LWIPDIR)/core/ipv4/igmp.o \ > > + $(LWIPDIR)/core/ipv4/ip4_frag.o \ > > + $(LWIPDIR)/core/ipv4/ip4.o \ > > + $(LWIPDIR)/core/ipv4/ip4_addr.o > > +# IPv6 > > +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \ > > + $(LWIPDIR)/core/ipv6/ethip6.o \ > > + $(LWIPDIR)/core/ipv6/icmp6.o \ > > + $(LWIPDIR)/core/ipv6/inet6.o \ > > + $(LWIPDIR)/core/ipv6/ip6.o \ > > + $(LWIPDIR)/core/ipv6/ip6_addr.o \ > > + $(LWIPDIR)/core/ipv6/ip6_frag.o \ > > + $(LWIPDIR)/core/ipv6/mld6.o \ > > + $(LWIPDIR)/core/ipv6/nd6.o > > +# API > > +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \ > > + $(LWIPDIR)/api/api_msg.o \ > > + $(LWIPDIR)/api/err.o \ > > + $(LWIPDIR)/api/if_api.o \ > > + $(LWIPDIR)/api/netbuf.o \ > > + $(LWIPDIR)/api/netdb.o \ > > + $(LWIPDIR)/api/netifapi.o \ > > + $(LWIPDIR)/api/sockets.o \ > > + $(LWIPDIR)/api/tcpip.o > > + > > +# Netdevs > > +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o > > + > > +obj-$(CONFIG_NET) += port/if.o > > +obj-$(CONFIG_NET) += port/sys-arch.o > > + > > +obj-$(CONFIG_NET) += cmd-lwip.o > > + > > + > > +ccflags-y += -I$(srctree)/lib/lwip/apps/ping > > +.PHONY: $(obj)/apps/ping/ping.c > > +$(obj)/apps/ping/ping.o: $(obj)/apps/ping/ping.c > > +$(obj)/apps/ping/ping.c: > > + cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c > $(obj)/apps/ping/ping.c > > + > > +obj-$(CONFIG_CMD_PING) += apps/ping/ping.o > > +obj-$(CONFIG_CMD_PING) += apps/ping/lwip_ping.o > > + > > +$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c > > +.PHONY: $(obj)/apps/http/http_client.c > > +$(obj)/apps/http/http_client.c: > > + cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c > $(obj)/apps/http/http_client.c > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h > $(obj)/apps/http/http_client.h > > + > > +obj-$(CONFIG_CMD_WGET) += apps/http/http_client.o > > +obj-$(CONFIG_CMD_WGET) += apps/http/lwip-wget.o > > + > > +ccflags-y += -I$(CURDIR)/lib/lwip/apps/tftp > > +$(obj)/apps/tftp/tftp.o: $(obj)/apps/tftp/tftp.c > > +.PHONY: $(obj)/apps/tftp/tftp.c > > +$(obj)/apps/tftp/tftp.c: > > + cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c > $(obj)/apps/tftp/tftp.c > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h > $(obj)/apps/tftp/tftp_client.h > > + cp > $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h > $(obj)/apps/tftp/tftp_common.h > > + cp > $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h > $(obj)/apps/tftp/tftp_example.h > > + > > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/tftp.o > > +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/lwip-tftp.o > > + > > +obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o > > diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c > b/lib/lwip/apps/dhcp/lwip-dhcp.c > > new file mode 100644 > > index 0000000000..2e4812c7dd > > --- /dev/null > > +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c > > @@ -0,0 +1,52 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include <lwip/dhcp.h> > > +#include <lwip/prot/dhcp.h> > > + > > +#include "../../../lwip/ulwip.h" > > + > > +static struct dhcp dhcp; > > +static bool dhcp_is_set; > > +extern struct netif uboot_netif; > > Again why extern? I dont think it's sane to carry around the uboot_netif > variable everytime we need to change a member. Instead we should functions > doing that > yes, netif_get_by_index(1) can be used to get a default pointer to netif. Changed that. > > > + > > +static int ulwip_dhcp_tmo(void) > > +{ > > + switch (dhcp.state) { > > + case DHCP_STATE_BOUND: > > + env_set("bootfile", dhcp.boot_file_name); > > + env_set("ipaddr", ip4addr_ntoa(&dhcp.offered_ip_addr)); > > + env_set("netmask", ip4addr_ntoa(&dhcp.offered_sn_mask)); > > + env_set("serverip", ip4addr_ntoa(&dhcp.server_ip_addr)); > > + printf("DHCP client bound to address %s\n", > ip4addr_ntoa(&dhcp.offered_ip_addr)); > > + break; > > + default: > > + return 0; > > + } > > + > > + return 0; > > +} > > The return value is always 0, why are we at least checking the result of > env_set()? > > Yes, thanks I did not check the error path here. Actually this chunk will be changed when lwip will have a callback for changing states. That is in progress. But for now I just registered a timeout to check if the state was changed. > > + > > +int ulwip_dhcp(void) > > +{ > > + int err; > > + > > + ulwip_set_tmo(ulwip_dhcp_tmo); > > + > > + if (!dhcp_is_set) { > > + dhcp_set_struct(&uboot_netif, &dhcp); > > + dhcp_is_set = true; > > + } > > + err = dhcp_start(&uboot_netif); > > + if (err) > > + printf("dhcp_start error %d\n", err); > > + > > + return err; > > +} > > diff --git a/lib/lwip/apps/http/lwip-wget.c > b/lib/lwip/apps/http/lwip-wget.c > > new file mode 100644 > > index 0000000000..0308b0b04a > > --- /dev/null > > +++ b/lib/lwip/apps/http/lwip-wget.c > > @@ -0,0 +1,74 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include "http_client.h" > > +#include "../../../lwip/ulwip.h" > > + > > +static ulong daddr; > > +static httpc_connection_t settings; > > + > > +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf > *p, err_t err) > > +{ > > + struct pbuf *q; > > + LWIP_UNUSED_ARG(err); > > + > > + if (!p) > > + return ERR_BUF; > > + > > + for (q = p; q != NULL; q = q->next) { > > + memcpy((void *)daddr, q->payload, q->len); > > + printf("downloaded chunk size %d, to addr 0x%lx\n", > q->len, daddr); > > + daddr += q->len; > > + } > > + altcp_recved(pcb, p->tot_len); > > + pbuf_free(p); > > + return ERR_OK; > > +} > > + > > +static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t > rx_content_len, > > + u32_t srv_res, err_t err) > > +{ > > + if (httpc_result == HTTPC_RESULT_OK) { > > + printf("\n%d bytes successfully downloaded.\n", > rx_content_len); > > + env_set_ulong("filesize", rx_content_len); > > + ulwip_exit(0); > > + } else { > > + printf("\nhttp eroror: %d\n", httpc_result); > > + ulwip_exit(-1); > > + } > > +} > > + > > +int lwip_wget(ulong addr, char *url) > > +{ > > + err_t err; > > + int port = 80; > > + char *server_name; > > + httpc_state_t *connection; > > + > > + daddr = addr; > > + server_name = env_get("serverip"); > > + if (!server_name) { > > + printf("error: serverip variable has to be set\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + printf("downloading %s to addr 0x%lx\n", url, addr); > > + memset(&settings, 0, sizeof(httpc_connection_t)); > > sizeof(settings) is preferred > > ok > > + settings.result_fn = httpc_result; > > + err = httpc_get_file_dns(server_name, port, url, &settings, > > + httpc_recv, NULL, &connection); > > + if (err != ERR_OK) { > > + printf("httpc_init_connection failed\n"); > > + return err; > > + } > > + > > + env_set_hex("fileaddr", addr); > > + return 0; > > +} > > diff --git a/lib/lwip/apps/ping/lwip_ping.c > b/lib/lwip/apps/ping/lwip_ping.c > > new file mode 100644 > > index 0000000000..a05dc76326 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/lwip_ping.c > > @@ -0,0 +1,37 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include "lwip/opt.h" > > +#include "lwip/ip_addr.h" > > +#include "ping.h" > > + > > +#include "../../../lwip/ulwip.h" > > Please dont do this. Can't we just use -I or something and have this is a > normal include path? > > simple <ulwip.h> can be used. fixed. > > + > > +static ip_addr_t ip_target; > > + > > +static int ulwip_ping_tmo(void) > > +{ > > + > > + printf("ping failed; host %s is not alive\n", > ipaddr_ntoa(&ip_target)); > > + return 0; > > +} > > + > > +int lwip_ping_init(char *ping_addr) > > +{ > > + int err; > > + > > + err = ipaddr_aton(ping_addr, &ip_target); > > + if (err == 0) { > > + printf("wrong ping addr string \"%s\" \n", ping_addr); > > + return -1; > > + } > > + > > + ulwip_set_tmo(ulwip_ping_tmo); > > + > > + ping_init(&ip_target); > > + > > + return 0; > > +} > > diff --git a/lib/lwip/apps/ping/lwip_ping.h > b/lib/lwip/apps/ping/lwip_ping.h > > new file mode 100644 > > index 0000000000..7f08095427 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/lwip_ping.h > > @@ -0,0 +1,24 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_PING_H > > +#define LWIP_PING_H > > + > > +#include <lwip/ip_addr.h> > > + > > +/** > > + * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is > used > > + */ > > +#ifndef PING_USE_SOCKETS > > +#define PING_USE_SOCKETS 0 > > +#endif > > + > > +int lwip_ping_init(char *ping_addr); > > + > > +void ping_raw_init(void); > > +void ping_send_now(void); > > + > > +#endif /* LWIP_PING_H */ > > diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h > > new file mode 100644 > > index 0000000000..0dd4bd78c7 > > --- /dev/null > > +++ b/lib/lwip/apps/ping/ping.h > > @@ -0,0 +1,35 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +#include "../../../lwip/ulwip.h" > > + > > +#include "lwip/prot/ip4.h" > > + > > +#define ip4_print_parts(a, b, c, d) \ > > + printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d); > > + > > +#define ip4_print(ipaddr) \ > > + ip4_print_parts(\ > > + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : > 0), \ > > + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : > 0)) > > + > > + > > +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ > > +#define PING_RESULT(cond) { \ > > + if (cond == 1) { \ > > + printf("host "); \ > > + ip4_print(addr); \ > > + printf(" is alive\n"); \ > > + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ > > + ulwip_exit(0); \ > > + } else { \ > > + printf("ping failed; host "); \ > > + ip4_print(addr); \ > > + printf(" is not alive\n"); \ > > + ulwip_exit(-1); \ > > + } \ > > + } while (0); > > + > > +#include "lwip/ip_addr.h" > > +void ping_init(const ip_addr_t *ping_addr); > > diff --git a/lib/lwip/apps/tftp/lwip-tftp.c > b/lib/lwip/apps/tftp/lwip-tftp.c > > new file mode 100644 > > index 0000000000..511d82e600 > > --- /dev/null > > +++ b/lib/lwip/apps/tftp/lwip-tftp.c > > @@ -0,0 +1,124 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > + > > +#include "lwip/apps/tftp_client.h" > > +#include "lwip/apps/tftp_server.h" > > +#include <tftp_example.h> > > + > > +#include <string.h> > > + > > +#include "../../../lwip/ulwip.h" > > + > > +#if LWIP_UDP > > + > > +static ulong daddr; > > +static ulong size; > > + > > +static void *tftp_open(const char *fname, const char *mode, u8_t > is_write) > > +{ > > + LWIP_UNUSED_ARG(mode); > > + return NULL; > > +} > > + > > +static void tftp_close(void *handle) > > +{ > > + printf("\ndone\n"); > > + printf("Bytes transferred = %ld (0x%lx hex)\n", size, size); > > + > > + env_set_ulong("filesize", size); > > + ulwip_exit(0); > > +} > > + > > +static int tftp_read(void *handle, void *buf, int bytes) > > +{ > > + return 0; > > +} > > + > > +static int tftp_write(void *handle, struct pbuf *p) > > +{ > > + struct pbuf *q; > > + > > + for (q = p; q != NULL; q = q->next) { > > + memcpy((void *)daddr, q->payload, q->len); > > + /* printf("downloaded chunk size %d, to addr 0x%lx\n", > q->len, daddr); */ > > + daddr += q->len; > > + size += q->len; > > + printf("#"); > > + } > > + > > + return 0; > > +} > > + > > +/* For TFTP client only */ > > +static void tftp_error(void *handle, int err, const char *msg, int size) > > +{ > > + char message[100]; > > + > > + LWIP_UNUSED_ARG(handle); > > + > > + memset(message, 0, sizeof(message)); > > + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size)); > > + > > + printf("TFTP error: %d (%s)", err, message); > > +} > > + > > +static const struct tftp_context tftp = { > > + tftp_open, > > + tftp_close, > > + tftp_read, > > + tftp_write, > > + tftp_error > > +}; > > + > > +int lwip_tftp(ulong addr, char *fname) > > +{ > > + void *f = (void *)0x1; /*fake handle*/ > > + err_t err; > > + ip_addr_t srv; > > + int ret; > > + char *server_ip; > > + > > + if (!fname || addr == 0) > > + return CMD_RET_FAILURE; > > + > > + size = 0; > > + daddr = addr; > > + server_ip = env_get("serverip"); > > + if (!server_ip) { > > + printf("error: serverip variable has to be set\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + ret = ipaddr_aton(server_ip, &srv); > > + LWIP_ASSERT("ipaddr_aton failed", ret == 1); > > + > > + printf("TFTP from server %s; our IP address is %s\n", > > + server_ip, env_get("ipaddr")); > > + printf("Filename '%s'.\n", fname); > > + printf("Load address: 0x%lx\n", daddr); > > + printf("Loading:"); > > + > > + err = tftp_init_client(&tftp); > > + if (!(err == ERR_OK || err == ERR_USE)) > > + printf("tftp_init_client err: %d\n", err); > > + > > + err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET); > > + /* might return different errors, like routing problems */ > > + if (err != ERR_OK) { > > + printf("tftp_get err=%d\n", err); > > + } > > + LWIP_ASSERT("tftp_get failed", err == ERR_OK); > > + > > + env_set_hex("fileaddr", addr); > > + return err; > > +} > > +#else > > +#error "UDP has to be supported" > > +#endif /* LWIP_UDP */ > > diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c > > new file mode 100644 > > index 0000000000..625c8c53b8 > > --- /dev/null > > +++ b/lib/lwip/cmd-lwip.c > > @@ -0,0 +1,269 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +#include <console.h> > > +#include <display_options.h> > > +#include <memalign.h> > > +#include <net.h> > > +#include <image.h> > > + > > +#include "apps/ping/lwip_ping.h" > > +#include "ulwip.h" > > + > > +extern int uboot_lwip_init(void); > > +extern int uboot_lwip_loop_is_done(void); > > + > > +static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + printf("TBD: %s\n", __func__); > > + return CMD_RET_SUCCESS; > > +} > > + > > +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + if (!uboot_lwip_init()) > > + return CMD_RET_SUCCESS; > > + return CMD_RET_FAILURE; > > +} > > + > > +static int lwip_empty_tmo(void) { return 0; }; > > +int (*ulwip_tmo)(void) = lwip_empty_tmo; > > +void ulwip_set_tmo(int (*tmo)(void)) > > +{ > > + ulwip_tmo = tmo; > > +} > > + > > +static void ulwip_clear_tmo(void) > > +{ > > + ulwip_tmo = lwip_empty_tmo; > > +} > > + > > +static void ulwip_timeout_handler(void) > > +{ > > + eth_halt(); > > + ulwip_tmo(); > > + net_set_state(NETLOOP_FAIL); /* we did not get the reply */ > > + ulwip_loop_set(0); > > +} > > + > > +static int ulwip_loop(void) > > +{ > > + ulwip_loop_set(1); > > + if (net_loop(LWIP) < 0) { > > + ulwip_loop_set(0); > > + return CMD_RET_FAILURE; > > + } > > + ulwip_loop_set(0); > > + return CMD_RET_SUCCESS; > > +} > > + > > +#if defined(CONFIG_CMD_PING) > > +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + if (argc < 2) { > > + printf("argc = %d, error\n", argc); > > + return CMD_RET_USAGE; > > + } > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + printf("Using %s device\n", eth_get_name()); > > + printf("pinging addr: %s\n", argv[1]); > > + > > + net_set_timeout_handler(1000UL, ulwip_timeout_handler); > > + > > + if (lwip_ping_init(argv[1])) { > > + printf("ping init fail\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + ping_send_now(); > > + > > + return ulwip_loop(); > > +} > > +#endif /* CONFIG_CMD_PING */ > > + > > +#if defined(CONFIG_CMD_WGET) > > +extern int lwip_wget(ulong addr, char *url); > > + > > +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + char *url; > > + > > + if (argc < 2) { > > + printf("argc = %d, error\n", argc); > > + return CMD_RET_USAGE; > > + } > > + url = argv[1]; > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + lwip_wget(image_load_addr, url); > > + > > + return ulwip_loop(); > > +} > > +#endif > > + > > +#if defined(CONFIG_CMD_TFTPBOOT) > > +extern int lwip_tftp(ulong addr, char *filename); > > + > > +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + char *filename; > > + ulong addr; > > + char *end; > > + int ret; > > + > > + switch (argc) { > > + case 1: > > + filename = env_get("bootfile"); > > + break; > > + case 2: > > + /* > > + * Only one arg - accept two forms: > > + * Just load address, or just boot file name. The latter > > + * form must be written in a format which can not be > > + * mis-interpreted as a valid number. > > + */ > > + addr = hextoul(argv[1], &end); > > + if (end == (argv[1] + strlen(argv[1]))) { > > + image_load_addr = addr; > > + filename = env_get("bootfile"); > > + } else { > > + filename = argv[1]; > > + } > > + break; > > + case 3: > > + image_load_addr = hextoul(argv[1], NULL); > > + filename = argv[2]; > > + break; > > + default: > > + return CMD_RET_USAGE; > > + } > > + > > + uboot_lwip_init(); > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + ret = lwip_tftp(image_load_addr, filename); > > + if (ret) > > + return ret; > > + > > + return ulwip_loop(); > > +} > > +#endif /* CONFIG_CMD_TFTPBOOT */ > > + > > +#if defined(CONFIG_CMD_DHCP) > > +extern int ulwip_dhcp(void); > > + > > +int do_lwip_dhcp(void) > > +{ > > + int ret; > > + char *filename; > > + > > + uboot_lwip_init(); > > + > > + ret = ulwip_dhcp(); > > + > > + net_set_timeout_handler(2000UL, ulwip_timeout_handler); > > + > > + ulwip_loop(); > > + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { > > + ulwip_clear_tmo(); > > + > > + filename = env_get("bootfile"); > > + if (!filename) { > > + printf("no bootfile\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + eth_init(); /* activate u-boot eth dev */ > > + net_set_timeout_handler(20000UL, ulwip_timeout_handler); > > + lwip_tftp(image_load_addr, filename); > > + > > + ret = ulwip_loop(); > > + } > > + > > + return ret; > > +} > > + > > +static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + return do_lwip_dhcp(); > > +} > > +#endif /* CONFIG_CMD_DHCP */ > > + > > +static struct cmd_tbl cmds[] = { > > + U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""), > > + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, > > + "initialize lwip stack", ""), > > +#if defined(CONFIG_CMD_LWIP_PING) > > + U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, > > + "send ICMP ECHO_REQUEST to network host", > > + "pingAddress"), > > +#endif > > +#if defined(CONFIG_CMD_WGET) > > + U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""), > > +#endif > > +#if defined(CONFIG_CMD_TFTPBOOT) > > + U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp, > > + "boot image via network using TFTP protocol\n", > > + "[loadAddress] [[hostIPaddr:]bootfilename]"), > > +#endif > > +#if defined(CONFIG_CMD_DHCP) > > + U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp, > > + "boot image via network using DHCP/TFTP protocol", > > + ""), > > +#endif > > +}; > > + > > +static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc, > > + char *const argv[]) > > +{ > > + struct cmd_tbl *cp; > > + > > + cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds)); > > + > > + argc--; > > + argv++; > > + > > + if (cp == NULL || argc > cp->maxargs) > > + return CMD_RET_USAGE; > > + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) > > + return CMD_RET_SUCCESS; > > + > > + return cp->cmd(cmdtp, flag, argc, argv); > > +} > > + > > +U_BOOT_CMD( > > + lwip, 4, 1, do_ops, > > + "LWIP sub system", > > + "info - display info\n" > > + "init - init LWIP\n" > > + "ping addr - pingAddress\n" > > + "wget http://IPadress/url/\n" > > + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" > > + "dhcp - boot image via network using DHCP/TFTP protocol\n" > > + ); > > + > > +/* Old command kept for compatibility. Same as 'mmc info' */ > > +U_BOOT_CMD( > > + lwipinfo, 1, 0, do_lwip_info, > > + "display LWIP info", > > + "- display LWIP stack info" > > +); > > diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h > > new file mode 100644 > > index 0000000000..b943d7b9be > > --- /dev/null > > +++ b/lib/lwip/lwipopts.h > > @@ -0,0 +1,203 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_LWIPOPTS_H > > +#define LWIP_LWIPOPTS_H > > + > > +#include "lwipopts.h" > > + > > +#if defined(CONFIG_LWIP_LIB_DEBUG) > > +#define LWIP_DEBUG 1 > > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > > +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON > > +#define ETHARP_DEBUG LWIP_DBG_OFF > > +#define NETIF_DEBUG LWIP_DBG_OFF > > +#define PBUF_DEBUG LWIP_DBG_OFF > > +#define API_LIB_DEBUG LWIP_DBG_OFF > > +#define API_MSG_DEBUG LWIP_DBG_OFF > > +#define SOCKETS_DEBUG LWIP_DBG_OFF > > +#define ICMP_DEBUG LWIP_DBG_OFF > > +#define IGMP_DEBUG LWIP_DBG_OFF > > +#define INET_DEBUG LWIP_DBG_OFF > > +#define IP_DEBUG LWIP_DBG_OFF > > +#define IP_REASS_DEBUG LWIP_DBG_OFF > > +#define RAW_DEBUG LWIP_DBG_OFF > > +#define MEM_DEBUG LWIP_DBG_OFF > > +#define MEMP_DEBUG LWIP_DBG_OFF > > +#define SYS_DEBUG LWIP_DBG_OFF > > +#define TIMERS_DEBUG LWIP_DBG_OFF > > +#define TCP_DEBUG LWIP_DBG_OFF > > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_FR_DEBUG LWIP_DBG_OFF > > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > > +#define TCP_WND_DEBUG LWIP_DBG_OFF > > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_RST_DEBUG LWIP_DBG_OFF > > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > > +#define UDP_DEBUG LWIP_DBG_OFF > > +#define TCPIP_DEBUG LWIP_DBG_OFF > > +#define SLIP_DEBUG LWIP_DBG_OFF > > +#define DHCP_DEBUG LWIP_DBG_ON > > +#define AUTOIP_DEBUG LWIP_DBG_ON > > +#define DNS_DEBUG LWIP_DBG_OFF > > +#define IP6_DEBUG LWIP_DBG_OFF > > +#define DHCP6_DEBUG LWIP_DBG_OFF > > +#else > > +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL > > +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF > > +#define ETHARP_DEBUG LWIP_DBG_OFF > > +#define NETIF_DEBUG LWIP_DBG_OFF > > +#define PBUF_DEBUG LWIP_DBG_OFF > > +#define API_LIB_DEBUG LWIP_DBG_OFF > > +#define API_MSG_DEBUG LWIP_DBG_OFF > > +#define SOCKETS_DEBUG LWIP_DBG_OFF > > +#define ICMP_DEBUG LWIP_DBG_OFF > > +#define IGMP_DEBUG LWIP_DBG_OFF > > +#define INET_DEBUG LWIP_DBG_OFF > > +#define IP_DEBUG LWIP_DBG_OFF > > +#define IP_REASS_DEBUG LWIP_DBG_OFF > > +#define RAW_DEBUG LWIP_DBG_OFF > > +#define MEM_DEBUG LWIP_DBG_OFF > > +#define MEMP_DEBUG LWIP_DBG_OFF > > +#define SYS_DEBUG LWIP_DBG_OFF > > +#define TIMERS_DEBUG LWIP_DBG_OFF > > +#define TCP_DEBUG LWIP_DBG_OFF > > +#define TCP_INPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_FR_DEBUG LWIP_DBG_OFF > > +#define TCP_RTO_DEBUG LWIP_DBG_OFF > > +#define TCP_CWND_DEBUG LWIP_DBG_OFF > > +#define TCP_WND_DEBUG LWIP_DBG_OFF > > +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF > > +#define TCP_RST_DEBUG LWIP_DBG_OFF > > +#define TCP_QLEN_DEBUG LWIP_DBG_OFF > > +#define UDP_DEBUG LWIP_DBG_OFF > > +#define TCPIP_DEBUG LWIP_DBG_OFF > > +#define SLIP_DEBUG LWIP_DBG_OFF > > +#define DHCP_DEBUG LWIP_DBG_OFF > > +#define AUTOIP_DEBUG LWIP_DBG_OFF > > +#define DNS_DEBUG LWIP_DBG_OFF > > +#define IP6_DEBUG LWIP_DBG_OFF > > +#define DHCP6_DEBUG LWIP_DBG_OFF > > +#endif > > +#define LWIP_TESTMODE 0 > > + > > +#if defined(CONFIG_LWIP_LIB_NOASSERT) > > +#define LWIP_NOASSERT 1 > > +#define LWIP_ASSERT(message, assertion) > > +#endif > > + > > +#include "lwip/debug.h" > > + > > +#define SYS_LIGHTWEIGHT_PROT 0 > > +#define NO_SYS 0 > > + > > +#define MEM_ALIGNMENT 1 > > +#define MEM_SIZE CONFIG_LWIP_LIB_MEM_SIZE > > + > > +#define MEMP_NUM_PBUF 4 > > +#define MEMP_NUM_RAW_PCB 2 > > +#define MEMP_NUM_UDP_PCB 4 > > +#define MEMP_NUM_TCP_PCB 2 > > +#define MEMP_NUM_TCP_PCB_LISTEN 2 > > +#define MEMP_NUM_TCP_SEG 16 > > +#define MEMP_NUM_REASSDATA 1 > > +#define MEMP_NUM_ARP_QUEUE 2 > > +#define MEMP_NUM_SYS_TIMEOUT 4 > > +#define MEMP_NUM_NETBUF 2 > > +#define MEMP_NUM_NETCONN 32 > > +#define MEMP_NUM_TCPIP_MSG_API 8 > > +#define MEMP_NUM_TCPIP_MSG_INPKT 8 > > +#define PBUF_POOL_SIZE 8 > > + > > +#define LWIP_ARP 1 > > + > > +#define IP_FORWARD 0 > > +#define IP_OPTIONS_ALLOWED 1 > > +#define IP_REASSEMBLY 1 > > +#define IP_FRAG 1 > > +#define IP_REASS_MAXAGE 3 > > +#define IP_REASS_MAX_PBUFS 4 > > +#define IP_FRAG_USES_STATIC_BUF 0 > > + > > +#define IP_DEFAULT_TTL 255 > > + > > +#define LWIP_ICMP 1 > > + > > +#define LWIP_RAW 1 > > + > > +#if defined(CONFIG_LWIP_LIB_DHCP) > > +#define LWIP_DHCP 1 > > +#define LWIP_DHCP_BOOTP_FILE 1 > > +#else > > +#define LWIP_DHCP 0 > > +#endif > > +#define LWIP_DHCP_DOES_ACD_CHECK 0 > > + > > +#define LWIP_AUTOIP 0 > > + > > +#define LWIP_SNMP 0 > > + > > +#define LWIP_IGMP 0 > > + > > +#if defined(CONFIG_LWIP_LIB_DNS) > > +#define LWIP_DNS 1 > > +#else > > +#define LWIP_DNS 0 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_TCP) > > +#define LWIP_UDP 1 > > +#else > > +#define LWIP_UDP 0 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_TCP) > > +#define LWIP_TCP 1 > > +#else > > +#define LWIP_TCP 0 > > +#endif > > + > > +#define LWIP_LISTEN_BACKLOG 0 > > + > > +#define PBUF_LINK_HLEN CONFIG_LWIP_LIB_PBUF_LINK_HLEN > > +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + > 40 + PBUF_LINK_HLEN) > > + > > +#define LWIP_HAVE_LOOPIF 0 > > + > > +#if defined(CONFIG_LWIP_LIB_NETCONN) > > +#define LWIP_NETCONN 1 > > +#else > > +#define LWIP_NETCONN 0 > > +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 > > +#endif > > + > > +#if defined(CONFIG_LWIP_LIB_SOCKET) > > +#define LWIP_SOCKET 1 > > + > > +#define SO_REUSE 1 > > +#else > > +#define LWIP_SOCKET 0 > > +#define SO_REUSE 0 > > +#endif > > + > > +#define LWIP_STATS 0 > > + > > +#define PPP_SUPPORT 0 > > + > > +#define LWIP_TCPIP_CORE_LOCKING 0 > > + > > +#if defined(CONFIG_LWIP_LIB_LOOPBACK) > > +#define LWIP_NETIF_LOOPBACK 1 > > +#else > > +#define LWIP_NETIF_LOOPBACK 0 > > +#endif > > +/* use malloc instead of pool */ > > +#define MEMP_MEM_MALLOC 1 > > +#define MEMP_MEM_INIT 1 > > +#define MEM_LIBC_MALLOC 1 > > + > > +#endif /* LWIP_LWIPOPTS_H */ > > diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c > > new file mode 100644 > > index 0000000000..37c02a451f > > --- /dev/null > > +++ b/lib/lwip/port/if.c > > @@ -0,0 +1,260 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <command.h> > > +extern int eth_init(void); /* net.h */ > > +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* > net.h */ > > +extern struct in_addr net_ip; > > +extern u8 net_ethaddr[6]; > > + > > +#include "lwip/debug.h" > > +#include "lwip/arch.h" > > +#include "netif/etharp.h" > > +#include "lwip/stats.h" > > +#include "lwip/def.h" > > +#include "lwip/mem.h" > > +#include "lwip/pbuf.h" > > +#include "lwip/sys.h" > > +#include "lwip/netif.h" > > + > > +#include "lwip/ip.h" > > + > > +#define IFNAME0 'e' > > +#define IFNAME1 '0' > > + > > +static struct pbuf *low_level_input(struct netif *netif); > > +static int uboot_net_use_lwip; > > + > > +int ulwip_enabled(void) > > +{ > > + return uboot_net_use_lwip; > > +} > > + > > +/* 1 - in loop > > + * 0 - no loop > > + */ > > +static int loop_lwip; > > + > > +/* ret 1 - in loop > > + * 0 - no loop > > + */ > > +int ulwip_in_loop(void) > > +{ > > + return loop_lwip; > > +} > > + > > +void ulwip_loop_set(int loop) > > +{ > > + loop_lwip = loop; > > +} > > + > > +static int ulwip_app_err; > > + > > +void ulwip_exit(int err) > > +{ > > + ulwip_app_err = err; > > + ulwip_loop_set(0); > > +} > > + > > +int ulwip_app_get_err(void) > > +{ > > + return ulwip_app_err; > > +} > > + > > +struct uboot_lwip_if { > > +}; > > + > > +#if defined(CONFIG_CMD_DHCP) > > +struct netif uboot_netif; > > +#else > > +static struct netif uboot_netif; > > +#endif > > I am not sure I understand why this exists. If you want to change some > some members of the struct from the dhcp code, why dont you create a > function that resides here? > > ok. changed to use a helper function to get netif pointer. > > + > > +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) > > + > > +extern uchar *net_rx_packet; > > +extern int net_rx_packet_len; > > + > > +int uboot_lwip_poll(void) > > +{ > > + struct pbuf *p; > > + int err; > > + > > + p = low_level_input(&uboot_netif); > > + if (!p) { > > + printf("error p = low_level_input = NULL\n"); > > + return 0; > > + } > > + > > + err = ethernet_input(p, &uboot_netif); > > + if (err) > > + printf("ip4_input err %d\n", err); > > + > > + return 0; > > +} > > + > > +static struct pbuf *low_level_input(struct netif *netif) > > +{ > > + struct pbuf *p, *q; > > + u16_t len = net_rx_packet_len; > > + uchar *data = net_rx_packet; > > + > > +#if ETH_PAD_SIZE > > + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ > > +#endif > > + > > + /* We allocate a pbuf chain of pbufs from the pool. */ > > + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); > > + if (p) { > > +#if ETH_PAD_SIZE > > + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding > word */ > > +#endif > > + /* We iterate over the pbuf chain until we have read the > entire > > + * packet into the pbuf. > > + */ > > + for (q = p; q != NULL; q = q->next) { > > + /* Read enough bytes to fill this pbuf in the > chain. The > > + * available data in the pbuf is given by the > q->len > > + * variable. > > + * This does not necessarily have to be a memcpy, > you can also preallocate > > + * pbufs for a DMA-enabled MAC and after receiving > truncate it to the > > + * actually received size. In this case, ensure > the tot_len member of the > > + * pbuf is the sum of the chained pbuf len members. > > + */ > > + MEMCPY(q->payload, data, q->len); > > + data += q->len; > > + } > > + //acknowledge that packet has been read(); > > + > > +#if ETH_PAD_SIZE > > + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding > word */ > > +#endif > > + LINK_STATS_INC(link.recv); > > + } else { > > + //drop packet(); > > + LINK_STATS_INC(link.memerr); > > + LINK_STATS_INC(link.drop); > > + } > > + > > + return p; > > +} > > + > > +static int ethernetif_input(struct pbuf *p, struct netif *netif) > > +{ > > + struct ethernetif *ethernetif; > > + > > + ethernetif = netif->state; > > + > > + /* move received packet into a new pbuf */ > > + p = low_level_input(netif); > > + > > + /* if no packet could be read, silently ignore this */ > > + if (p) { > > + /* pass all packets to ethernet_input, which decides what > packets it supports */ > > + if (netif->input(p, netif) != ERR_OK) { > > + LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", > __func__)); > > + pbuf_free(p); > > + p = NULL; > > + } > > + } > > + return 0; > > +} > > + > > +static err_t low_level_output(struct netif *netif, struct pbuf *p) > > +{ > > + int err; > > + > > + err = eth_send(p->payload, p->len); > > + if (err != 0) { > > + printf("eth_send error %d\n", err); > > + return ERR_ABRT; > > + } > > + return ERR_OK; > > +} > > + > > +err_t uboot_lwip_if_init(struct netif *netif) > > +{ > > + struct uboot_lwip_if *uif = (struct uboot_lwip_if > *)malloc(sizeof(struct uboot_lwip_if)); > > + > > + if (!uif) { > > + printf("uboot_lwip_if: out of memory\n"); > > + return ERR_MEM; > > + } > > + netif->state = uif; > > + > > + netif->name[0] = IFNAME0; > > + netif->name[1] = IFNAME1; > > + > > + netif->hwaddr_len = ETHARP_HWADDR_LEN; > > + string_to_enetaddr(env_get("ethaddr"), netif->hwaddr); > > +#if defined(CONFIG_LWIP_LIB_DEBUG) > > + printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", > > + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], > > + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); > > +#endif > > + > > +#if LWIP_IPV4 > > + netif->output = etharp_output; > > +#endif /* LWIP_IPV4 */ > > +#if LWIP_IPV6 > > + netif->output_ip6 = ethip6_output; > > +#endif /* LWIP_IPV6 */ > > + netif->linkoutput = low_level_output; > > + netif->mtu = 1500; > > + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | > NETIF_FLAG_LINK_UP; > > + > > + eth_init(); /* activate u-boot eth dev */ > > + > > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > > + printf("Initialized LWIP stack\n"); > > + } > > + > > + return ERR_OK; > > +} > > + > > +int uboot_lwip_init(void) > > +{ > > + ip4_addr_t ipaddr, netmask, gw; > > + > > + if (uboot_net_use_lwip) > > + return CMD_RET_SUCCESS; > > + > > + ip4_addr_set_zero(&gw); > > + ip4_addr_set_zero(&ipaddr); > > + ip4_addr_set_zero(&netmask); > > + > > + ipaddr_aton(env_get("ipaddr"), &ipaddr); > > + ipaddr_aton(env_get("ipaddr"), &netmask); > > + > > + LWIP_PORT_INIT_NETMASK(&netmask); > > + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { > > + printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr)); > > + printf(" GW: %s\n", ip4addr_ntoa(&gw)); > > + printf(" mask: %s\n", ip4addr_ntoa(&netmask)); > > + } > > + > > + if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw, > > + &uboot_netif, uboot_lwip_if_init, ethernetif_input)) > > + printf("err: netif_add failed!\n"); > > + > > + netif_set_up(&uboot_netif); > > + netif_set_link_up(&uboot_netif); > > +#if LWIP_IPV6 > > + netif_create_ip6_linklocal_address(&uboot_netif, 1); > > + printf(" IPv6: %s\n", > ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0))); > > +#endif /* LWIP_IPV6 */ > > + > > + uboot_net_use_lwip = 1; > > + > > + return CMD_RET_SUCCESS; > > +} > > + > > +/* placeholder, not used now */ > > +void uboot_lwip_destroy(void) > > +{ > > + uboot_net_use_lwip = 0; > > +} > > diff --git a/lib/lwip/port/include/arch/cc.h > b/lib/lwip/port/include/arch/cc.h > > new file mode 100644 > > index 0000000000..db30d7614e > > --- /dev/null > > +++ b/lib/lwip/port/include/arch/cc.h > > @@ -0,0 +1,46 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_ARCH_CC_H > > +#define LWIP_ARCH_CC_H > > + > > +#include <linux/types.h> > > +#include <linux/kernel.h> > > + > > +#define LWIP_ERRNO_INCLUDE <errno.h> > > + > > +#define LWIP_ERRNO_STDINCLUDE 1 > > +#define LWIP_NO_UNISTD_H 1 > > +#define LWIP_TIMEVAL_PRIVATE 1 > > + > > +extern unsigned int lwip_port_rand(void); > > +#define LWIP_RAND() (lwip_port_rand()) > > + > > +/* different handling for unit test, normally not needed */ > > +#ifdef LWIP_NOASSERT_ON_ERROR > > +#define LWIP_ERROR(message, expression, handler) do { if > (!(expression)) { \ > > + handler; }} while (0) > > +#endif > > + > > +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS > > + > > +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at > line %d in %s\n", \ > > + x, __LINE__, __FILE__); } while (0) > > + > > +static inline int atoi(const char *str) > > +{ > > + int r = 0; > > + int i; > > + > > + for (i = 0; str[i] != '\0'; ++i) > > + r = r * 10 + str[i] - '0'; > > + > > + return r; > > +} > > + > > +#define LWIP_ERR_T int > > + > > +#endif /* LWIP_ARCH_CC_H */ > > diff --git a/lib/lwip/port/include/arch/sys_arch.h > b/lib/lwip/port/include/arch/sys_arch.h > > new file mode 100644 > > index 0000000000..8d95146275 > > --- /dev/null > > +++ b/lib/lwip/port/include/arch/sys_arch.h > > @@ -0,0 +1,59 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#ifndef LWIP_ARCH_SYS_ARCH_H > > +#define LWIP_ARCH_SYS_ARCH_H > > + > > +#include "lwip/opt.h" > > +#include "lwip/arch.h" > > +#include "lwip/err.h" > > + > > +#define ERR_NEED_SCHED 123 > > + > > +void sys_arch_msleep(u32_t delay_ms); > > +#define sys_msleep(ms) sys_arch_msleep(ms) > > + > > +#if SYS_LIGHTWEIGHT_PROT > > +typedef u32_t sys_prot_t; > > +#endif /* SYS_LIGHTWEIGHT_PROT */ > > + > > +#include <errno.h> > > + > > +#define SYS_MBOX_NULL NULL > > +#define SYS_SEM_NULL NULL > > + > > +typedef u32_t sys_prot_t; > > + > > +struct sys_sem; > > +typedef struct sys_sem *sys_sem_t; > > +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) > > +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = > NULL; }} while (0) > > + > > +/* let sys.h use binary semaphores for mutexes */ > > +#define LWIP_COMPAT_MUTEX 1 > > +#define LWIP_COMPAT_MUTEX_ALLOWED 1 > > + > > +struct sys_mbox; > > +typedef struct sys_mbox *sys_mbox_t; > > +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) > > +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = > NULL; }} while (0) > > + > > +struct sys_thread; > > +typedef struct sys_thread *sys_thread_t; > > + > > +static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) > > +{ > > + return 0; > > +}; > > + > > +static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) > > +{ > > + return 0; > > +}; > > + > > +#define sys_sem_signal(s) > > + > > +#endif /* LWIP_ARCH_SYS_ARCH_H */ > > diff --git a/lib/lwip/port/include/limits.h > b/lib/lwip/port/include/limits.h > > new file mode 100644 > > index 0000000000..e69de29bb2 > > diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c > > new file mode 100644 > > index 0000000000..609eeccf8c > > --- /dev/null > > +++ b/lib/lwip/port/sys-arch.c > > @@ -0,0 +1,20 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/* > > + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> > > + */ > > + > > +#include <common.h> > > +#include <rand.h> > > +#include "lwip/opt.h" > > + > > +u32_t sys_now(void) > > +{ > > + return get_timer(0); > > +} > > + > > +u32_t lwip_port_rand(void) > > +{ > > + return (u32_t)rand(); > > +} > > + > > diff --git a/lib/lwip/ulwip.h b/lib/lwip/ulwip.h > > new file mode 100644 > > index 0000000000..11ca52aa1f > > --- /dev/null > > +++ b/lib/lwip/ulwip.h > > @@ -0,0 +1,9 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > + > > +int ulwip_enabled(void); > > +int ulwip_in_loop(void); > > +int ulwip_loop_set(int loop); > > +int ulwip_exit(int err); > > +int uboot_lwip_poll(void); > > +int ulwip_app_get_err(void); > > +void ulwip_set_tmo(int (*tmo)(void)); > > diff --git a/net/Kconfig b/net/Kconfig > > index a1ec3f8542..2c5d8b8aca 100644 > > --- a/net/Kconfig > > +++ b/net/Kconfig > > @@ -5,6 +5,7 @@ > > menuconfig NET > > bool "Networking support" > > default y > > + select LWIP_LIB > > > > if NET > > > > diff --git a/net/net.c b/net/net.c > > index 57da9bda85..3d9a2e798a 100644 > > --- a/net/net.c > > +++ b/net/net.c > > @@ -121,6 +121,7 @@ > > #endif > > #include <net/tcp.h> > > #include <net/wget.h> > > +#include "../lib/lwip/ulwip.h" > > > > /** BOOTP EXTENTIONS **/ > > > > @@ -438,7 +439,11 @@ int net_loop(enum proto_t protocol) > > #endif > > > > bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); > > +#if defined(CONFIG_LWIP_LIB) > > + if (!ulwip_enabled() || !ulwip_in_loop()) > > +#endif > > net_init(); > > + > > if (eth_is_on_demand_init()) { > > eth_halt(); > > eth_set_current(); > > @@ -619,6 +624,18 @@ restart: > > */ > > eth_rx(); > > > > +#if defined(CONFIG_LWIP_LIB) > > + if (ulwip_enabled()) { > > + net_set_state(NETLOOP_CONTINUE); > > + if (!ulwip_in_loop()) { > > + if (ulwip_app_get_err()) > > + net_set_state(NETLOOP_FAIL); > > + else > > + net_set_state(NETLOOP_SUCCESS); > > + goto done; > > + } > > + } > > +#endif > > /* > > * Abort if ctrl-c was pressed. > > */ > > @@ -1177,6 +1194,13 @@ void net_process_received_packet(uchar > *in_packet, int len) > > if (len < ETHER_HDR_SIZE) > > return; > > > > +#if defined(CONFIG_LWIP_LIB) > > + if (ulwip_enabled()) { > > + uboot_lwip_poll(); > > + return; > > + } > > +#endif > > + > > #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) > > if (push_packet) { > > (*push_packet)(in_packet, len); > > -- > > 2.30.2 > > > > Thanks > /Ilias > Agree that the patch is really huge. And it's even complex to navigate over the comments. I will split it into smaller changs. What I also worry about is IPv6 support which theoretically exists and is supported by lwip, but I did not test it. Because of original commands have IPv5 it will be good to not break working code. BR, Maxim.
diff --git a/.gitignore b/.gitignore index eb769f144c..be3676c59e 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,12 @@ __pycache__ # pylint files /pylint.cur /pylint.out/ + +lib/lwip/lwip-external +lib/lwip/apps/ping/ping.c +lib/lwip/apps/http/http_client.c +lib/lwip/apps/http/http_client.h +lib/lwip/apps/tftp/tftp.c +lib/lwip/apps/tftp/tftp_client.h +lib/lwip/apps/tftp/tftp_common.h +lib/lwip/apps/tftp/tftp_example.h diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index e6992168c0..30331a9806 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -118,7 +118,7 @@ static int distro_pxe_read_file(struct udevice *dev, struct bootflow *bflow, tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path; - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(&size); if (ret) diff --git a/cmd/net.c b/cmd/net.c index 0e9f200ca9..6d704fba86 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -36,19 +36,9 @@ U_BOOT_CMD( #endif #ifdef CONFIG_CMD_TFTPBOOT -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - int ret; - - bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); - ret = netboot_common(TFTPGET, cmdtp, argc, argv); - bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); - return ret; -} - #if IS_ENABLED(CONFIG_IPV6) U_BOOT_CMD( - tftpboot, 4, 1, do_tftpb, + tftpboot, 4, 1, do_lwip_tftp, "boot image via network using TFTP protocol\n" "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " "with [] brackets", @@ -56,7 +46,7 @@ U_BOOT_CMD( ); #else U_BOOT_CMD( - tftpboot, 3, 1, do_tftpb, + tftpboot, 3, 1, do_lwip_tftp, "load file via network using TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]" ); @@ -112,7 +102,7 @@ U_BOOT_CMD( static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - return netboot_common(DHCP, cmdtp, argc, argv); + return do_lwip_dhcp(); } U_BOOT_CMD( @@ -137,13 +127,11 @@ U_BOOT_CMD( #endif #if defined(CONFIG_CMD_WGET) -static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) -{ - return netboot_common(WGET, cmdtp, argc, argv); -} +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); U_BOOT_CMD( - wget, 3, 1, do_wget, + wget, 3, 1, do_lwip_wget, "boot image via network using HTTP protocol", "[loadAddress] [[hostIPaddr:]path and image name]" ); @@ -376,28 +364,10 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, } #if defined(CONFIG_CMD_PING) -static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (argc < 2) - return CMD_RET_USAGE; - - net_ping_ip = string_to_ip(argv[1]); - if (net_ping_ip.s_addr == 0) - return CMD_RET_USAGE; - - if (net_loop(PING) < 0) { - printf("ping failed; host %s is not alive\n", argv[1]); - return CMD_RET_FAILURE; - } - - printf("host %s is alive\n", argv[1]); - - return CMD_RET_SUCCESS; -} - +extern int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); U_BOOT_CMD( - ping, 2, 1, do_ping, + ping, 2, 1, do_lwip_ping, "send ICMP ECHO_REQUEST to network host", "pingAddress" ); diff --git a/cmd/pxe.c b/cmd/pxe.c index db8e4697f2..bd4d6f5f2b 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -33,7 +33,7 @@ static int do_get_tftp(struct pxe_context *ctx, const char *file_path, tftp_argv[1] = file_addr; tftp_argv[2] = (void *)file_path; - if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) + if (do_lwip_tftp(ctx->cmdtp, 0, 3, tftp_argv)) return -ENOENT; ret = pxe_get_file_size(sizep); if (ret) diff --git a/include/net.h b/include/net.h index 1a99009959..6b573f3319 100644 --- a/include/net.h +++ b/include/net.h @@ -54,8 +54,10 @@ struct in_addr { __be32 s_addr; }; +int do_lwip_dhcp(void); + /** - * do_tftpb - Run the tftpboot command + * do_lwip_tftp - Run the tftpboot command * * @cmdtp: Command information for tftpboot * @flag: Command flags (CMD_FLAG_...) @@ -63,7 +65,7 @@ struct in_addr { * @argv: List of arguments * Return: result (see enum command_ret_t) */ -int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); /** * An incoming packet handler. @@ -561,7 +563,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, NETCONS, - SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET + SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET, LWIP }; extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/lib/Kconfig b/lib/Kconfig index 3c5a4ab386..7485a1f3bf 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates" source lib/fwu_updates/Kconfig endmenu + +source lib/lwip/Kconfig diff --git a/lib/Makefile b/lib/Makefile index d77b33e7f4..3b80a41187 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -91,6 +91,8 @@ obj-$(CONFIG_LIBAVB) += libavb/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o +obj-y += lwip/ + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig new file mode 100644 index 0000000000..3688ac3305 --- /dev/null +++ b/lib/lwip/Kconfig @@ -0,0 +1,63 @@ +menu "LWIP" +config LWIP_LIB + bool "Support LWIP library" + help + Selecting this option will enable the LWIP library code. + +menu "LWIP options" + +config LWIP_LIB_DEBUG + bool "enable debug" + default n + +config LWIP_LIB_NOASSERT + bool "disable asserts" + default y + help + Disabling asserts reduces binary size on 16k. + +config LWIP_LIB_TCP + bool "tcp" + default y + +config LWIP_LIB_UDP + bool "udp" + default y + +config LWIP_LIB_DNS + bool "dns" + default n + +config LWIP_LIB_DHCP + bool "dhcp" + default y + +config LWIP_LIB_LOOPBACK + bool "loopback" + help + Increases size on 1k. + +config LWIP_LIB_SOCKET + bool "socket API" + +config LWIP_LIB_NETCONN + bool "netconn API" + +config LWIP_LIB_MEM_SIZE + int "mem size" + default 1600 + range 1 4096 + help + MEM_SIZE: the size of the heap memory. If the application will send + a lot of data that needs to be copied, this should be set high. + +config LWIP_LIB_PBUF_LINK_HLEN + int "pbuf link hlen" + default 14 + range 4 1024 + help + PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. The default is 14, the standard value for Ethernet. +endmenu + +endmenu diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile new file mode 100644 index 0000000000..e1a8a2a7b7 --- /dev/null +++ b/lib/lwip/Makefile @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + +LWIPDIR=lwip-external/src + +ccflags-y += -I$(srctree)/lib/lwip/port/include +ccflags-y += -I$(srctree)/lib/lwip/lwip-external/src/include -I$(srctree)/lib/lwip + +obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \ + $(LWIPDIR)/core/def.o \ + $(LWIPDIR)/core/dns.o \ + $(LWIPDIR)/core/inet_chksum.o \ + $(LWIPDIR)/core/ip.o \ + $(LWIPDIR)/core/mem.o \ + $(LWIPDIR)/core/memp.o \ + $(LWIPDIR)/core/netif.o \ + $(LWIPDIR)/core/pbuf.o \ + $(LWIPDIR)/core/raw.o \ + $(LWIPDIR)/core/stats.o \ + $(LWIPDIR)/core/sys.o \ + $(LWIPDIR)/core/altcp.o \ + $(LWIPDIR)/core/altcp_alloc.o \ + $(LWIPDIR)/core/altcp_tcp.o \ + $(LWIPDIR)/core/tcp.o \ + $(LWIPDIR)/core/tcp_in.o \ + $(LWIPDIR)/core/tcp_out.o \ + $(LWIPDIR)/core/timeouts.o \ + $(LWIPDIR)/core/udp.o + +# IPv4 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv4/acd.o \ + $(LWIPDIR)/core/ipv4/autoip.o \ + $(LWIPDIR)/core/ipv4/dhcp.o \ + $(LWIPDIR)/core/ipv4/etharp.o \ + $(LWIPDIR)/core/ipv4/icmp.o \ + $(LWIPDIR)/core/ipv4/igmp.o \ + $(LWIPDIR)/core/ipv4/ip4_frag.o \ + $(LWIPDIR)/core/ipv4/ip4.o \ + $(LWIPDIR)/core/ipv4/ip4_addr.o +# IPv6 +obj-$(CONFIG_NET) += $(LWIPDIR)/core/ipv6/dhcp6.o \ + $(LWIPDIR)/core/ipv6/ethip6.o \ + $(LWIPDIR)/core/ipv6/icmp6.o \ + $(LWIPDIR)/core/ipv6/inet6.o \ + $(LWIPDIR)/core/ipv6/ip6.o \ + $(LWIPDIR)/core/ipv6/ip6_addr.o \ + $(LWIPDIR)/core/ipv6/ip6_frag.o \ + $(LWIPDIR)/core/ipv6/mld6.o \ + $(LWIPDIR)/core/ipv6/nd6.o +# API +obj-$(CONFIG_NET) += $(LWIPDIR)/api/api_lib.o \ + $(LWIPDIR)/api/api_msg.o \ + $(LWIPDIR)/api/err.o \ + $(LWIPDIR)/api/if_api.o \ + $(LWIPDIR)/api/netbuf.o \ + $(LWIPDIR)/api/netdb.o \ + $(LWIPDIR)/api/netifapi.o \ + $(LWIPDIR)/api/sockets.o \ + $(LWIPDIR)/api/tcpip.o + +# Netdevs +obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o + +obj-$(CONFIG_NET) += port/if.o +obj-$(CONFIG_NET) += port/sys-arch.o + +obj-$(CONFIG_NET) += cmd-lwip.o + + +ccflags-y += -I$(srctree)/lib/lwip/apps/ping +.PHONY: $(obj)/apps/ping/ping.c +$(obj)/apps/ping/ping.o: $(obj)/apps/ping/ping.c +$(obj)/apps/ping/ping.c: + cp $(srctree)/lib/lwip/lwip-external/contrib/apps/ping/ping.c $(obj)/apps/ping/ping.c + +obj-$(CONFIG_CMD_PING) += apps/ping/ping.o +obj-$(CONFIG_CMD_PING) += apps/ping/lwip_ping.o + +$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c +.PHONY: $(obj)/apps/http/http_client.c +$(obj)/apps/http/http_client.c: + cp $(srctree)/lib/lwip/lwip-external/src/apps/http/http_client.c $(obj)/apps/http/http_client.c + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/apps/http/http_client.h + +obj-$(CONFIG_CMD_WGET) += apps/http/http_client.o +obj-$(CONFIG_CMD_WGET) += apps/http/lwip-wget.o + +ccflags-y += -I$(CURDIR)/lib/lwip/apps/tftp +$(obj)/apps/tftp/tftp.o: $(obj)/apps/tftp/tftp.c +.PHONY: $(obj)/apps/tftp/tftp.c +$(obj)/apps/tftp/tftp.c: + cp $(srctree)/lib/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/apps/tftp/tftp.c + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/apps/tftp/tftp_client.h + cp $(srctree)/lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/apps/tftp/tftp_common.h + cp $(srctree)/lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/apps/tftp/tftp_example.h + +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/lwip-tftp.o + +obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c b/lib/lwip/apps/dhcp/lwip-dhcp.c new file mode 100644 index 0000000000..2e4812c7dd --- /dev/null +++ b/lib/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include <lwip/dhcp.h> +#include <lwip/prot/dhcp.h> + +#include "../../../lwip/ulwip.h" + +static struct dhcp dhcp; +static bool dhcp_is_set; +extern struct netif uboot_netif; + +static int ulwip_dhcp_tmo(void) +{ + switch (dhcp.state) { + case DHCP_STATE_BOUND: + env_set("bootfile", dhcp.boot_file_name); + env_set("ipaddr", ip4addr_ntoa(&dhcp.offered_ip_addr)); + env_set("netmask", ip4addr_ntoa(&dhcp.offered_sn_mask)); + env_set("serverip", ip4addr_ntoa(&dhcp.server_ip_addr)); + printf("DHCP client bound to address %s\n", ip4addr_ntoa(&dhcp.offered_ip_addr)); + break; + default: + return 0; + } + + return 0; +} + +int ulwip_dhcp(void) +{ + int err; + + ulwip_set_tmo(ulwip_dhcp_tmo); + + if (!dhcp_is_set) { + dhcp_set_struct(&uboot_netif, &dhcp); + dhcp_is_set = true; + } + err = dhcp_start(&uboot_netif); + if (err) + printf("dhcp_start error %d\n", err); + + return err; +} diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c new file mode 100644 index 0000000000..0308b0b04a --- /dev/null +++ b/lib/lwip/apps/http/lwip-wget.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include "http_client.h" +#include "../../../lwip/ulwip.h" + +static ulong daddr; +static httpc_connection_t settings; + +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct pbuf *q; + LWIP_UNUSED_ARG(err); + + if (!p) + return ERR_BUF; + + for (q = p; q != NULL; q = q->next) { + memcpy((void *)daddr, q->payload, q->len); + printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); + daddr += q->len; + } + altcp_recved(pcb, p->tot_len); + pbuf_free(p); + return ERR_OK; +} + +static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, + u32_t srv_res, err_t err) +{ + if (httpc_result == HTTPC_RESULT_OK) { + printf("\n%d bytes successfully downloaded.\n", rx_content_len); + env_set_ulong("filesize", rx_content_len); + ulwip_exit(0); + } else { + printf("\nhttp eroror: %d\n", httpc_result); + ulwip_exit(-1); + } +} + +int lwip_wget(ulong addr, char *url) +{ + err_t err; + int port = 80; + char *server_name; + httpc_state_t *connection; + + daddr = addr; + server_name = env_get("serverip"); + if (!server_name) { + printf("error: serverip variable has to be set\n"); + return CMD_RET_FAILURE; + } + + printf("downloading %s to addr 0x%lx\n", url, addr); + memset(&settings, 0, sizeof(httpc_connection_t)); + settings.result_fn = httpc_result; + err = httpc_get_file_dns(server_name, port, url, &settings, + httpc_recv, NULL, &connection); + if (err != ERR_OK) { + printf("httpc_init_connection failed\n"); + return err; + } + + env_set_hex("fileaddr", addr); + return 0; +} diff --git a/lib/lwip/apps/ping/lwip_ping.c b/lib/lwip/apps/ping/lwip_ping.c new file mode 100644 index 0000000000..a05dc76326 --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "ping.h" + +#include "../../../lwip/ulwip.h" + +static ip_addr_t ip_target; + +static int ulwip_ping_tmo(void) +{ + + printf("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target)); + return 0; +} + +int lwip_ping_init(char *ping_addr) +{ + int err; + + err = ipaddr_aton(ping_addr, &ip_target); + if (err == 0) { + printf("wrong ping addr string \"%s\" \n", ping_addr); + return -1; + } + + ulwip_set_tmo(ulwip_ping_tmo); + + ping_init(&ip_target); + + return 0; +} diff --git a/lib/lwip/apps/ping/lwip_ping.h b/lib/lwip/apps/ping/lwip_ping.h new file mode 100644 index 0000000000..7f08095427 --- /dev/null +++ b/lib/lwip/apps/ping/lwip_ping.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#ifndef LWIP_PING_H +#define LWIP_PING_H + +#include <lwip/ip_addr.h> + +/** + * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used + */ +#ifndef PING_USE_SOCKETS +#define PING_USE_SOCKETS 0 +#endif + +int lwip_ping_init(char *ping_addr); + +void ping_raw_init(void); +void ping_send_now(void); + +#endif /* LWIP_PING_H */ diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h new file mode 100644 index 0000000000..0dd4bd78c7 --- /dev/null +++ b/lib/lwip/apps/ping/ping.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include "../../../lwip/ulwip.h" + +#include "lwip/prot/ip4.h" + +#define ip4_print_parts(a, b, c, d) \ + printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d); + +#define ip4_print(ipaddr) \ + ip4_print_parts(\ + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) + + +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ +#define PING_RESULT(cond) { \ + if (cond == 1) { \ + printf("host "); \ + ip4_print(addr); \ + printf(" is alive\n"); \ + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ + ulwip_exit(0); \ + } else { \ + printf("ping failed; host "); \ + ip4_print(addr); \ + printf(" is not alive\n"); \ + ulwip_exit(-1); \ + } \ + } while (0); + +#include "lwip/ip_addr.h" +void ping_init(const ip_addr_t *ping_addr); diff --git a/lib/lwip/apps/tftp/lwip-tftp.c b/lib/lwip/apps/tftp/lwip-tftp.c new file mode 100644 index 0000000000..511d82e600 --- /dev/null +++ b/lib/lwip/apps/tftp/lwip-tftp.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include <common.h> +#include <command.h> +#include <console.h> + +#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h> + +#include <string.h> + +#include "../../../lwip/ulwip.h" + +#if LWIP_UDP + +static ulong daddr; +static ulong size; + +static void *tftp_open(const char *fname, const char *mode, u8_t is_write) +{ + LWIP_UNUSED_ARG(mode); + return NULL; +} + +static void tftp_close(void *handle) +{ + printf("\ndone\n"); + printf("Bytes transferred = %ld (0x%lx hex)\n", size, size); + + env_set_ulong("filesize", size); + ulwip_exit(0); +} + +static int tftp_read(void *handle, void *buf, int bytes) +{ + return 0; +} + +static int tftp_write(void *handle, struct pbuf *p) +{ + struct pbuf *q; + + for (q = p; q != NULL; q = q->next) { + memcpy((void *)daddr, q->payload, q->len); + /* printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, daddr); */ + daddr += q->len; + size += q->len; + printf("#"); + } + + return 0; +} + +/* For TFTP client only */ +static void tftp_error(void *handle, int err, const char *msg, int size) +{ + char message[100]; + + LWIP_UNUSED_ARG(handle); + + memset(message, 0, sizeof(message)); + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size)); + + printf("TFTP error: %d (%s)", err, message); +} + +static const struct tftp_context tftp = { + tftp_open, + tftp_close, + tftp_read, + tftp_write, + tftp_error +}; + +int lwip_tftp(ulong addr, char *fname) +{ + void *f = (void *)0x1; /*fake handle*/ + err_t err; + ip_addr_t srv; + int ret; + char *server_ip; + + if (!fname || addr == 0) + return CMD_RET_FAILURE; + + size = 0; + daddr = addr; + server_ip = env_get("serverip"); + if (!server_ip) { + printf("error: serverip variable has to be set\n"); + return CMD_RET_FAILURE; + } + + ret = ipaddr_aton(server_ip, &srv); + LWIP_ASSERT("ipaddr_aton failed", ret == 1); + + printf("TFTP from server %s; our IP address is %s\n", + server_ip, env_get("ipaddr")); + printf("Filename '%s'.\n", fname); + printf("Load address: 0x%lx\n", daddr); + printf("Loading:"); + + err = tftp_init_client(&tftp); + if (!(err == ERR_OK || err == ERR_USE)) + printf("tftp_init_client err: %d\n", err); + + err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET); + /* might return different errors, like routing problems */ + if (err != ERR_OK) { + printf("tftp_get err=%d\n", err); + } + LWIP_ASSERT("tftp_get failed", err == ERR_OK); + + env_set_hex("fileaddr", addr); + return err; +} +#else +#error "UDP has to be supported" +#endif /* LWIP_UDP */ diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c new file mode 100644 index 0000000000..625c8c53b8 --- /dev/null +++ b/lib/lwip/cmd-lwip.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <console.h> +#include <display_options.h> +#include <memalign.h> +#include <net.h> +#include <image.h> + +#include "apps/ping/lwip_ping.h" +#include "ulwip.h" + +extern int uboot_lwip_init(void); +extern int uboot_lwip_loop_is_done(void); + +static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + printf("TBD: %s\n", __func__); + return CMD_RET_SUCCESS; +} + +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (!uboot_lwip_init()) + return CMD_RET_SUCCESS; + return CMD_RET_FAILURE; +} + +static int lwip_empty_tmo(void) { return 0; }; +int (*ulwip_tmo)(void) = lwip_empty_tmo; +void ulwip_set_tmo(int (*tmo)(void)) +{ + ulwip_tmo = tmo; +} + +static void ulwip_clear_tmo(void) +{ + ulwip_tmo = lwip_empty_tmo; +} + +static void ulwip_timeout_handler(void) +{ + eth_halt(); + ulwip_tmo(); + net_set_state(NETLOOP_FAIL); /* we did not get the reply */ + ulwip_loop_set(0); +} + +static int ulwip_loop(void) +{ + ulwip_loop_set(1); + if (net_loop(LWIP) < 0) { + ulwip_loop_set(0); + return CMD_RET_FAILURE; + } + ulwip_loop_set(0); + return CMD_RET_SUCCESS; +} + +#if defined(CONFIG_CMD_PING) +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc < 2) { + printf("argc = %d, error\n", argc); + return CMD_RET_USAGE; + } + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + printf("Using %s device\n", eth_get_name()); + printf("pinging addr: %s\n", argv[1]); + + net_set_timeout_handler(1000UL, ulwip_timeout_handler); + + if (lwip_ping_init(argv[1])) { + printf("ping init fail\n"); + return CMD_RET_FAILURE; + } + + ping_send_now(); + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_PING */ + +#if defined(CONFIG_CMD_WGET) +extern int lwip_wget(ulong addr, char *url); + +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *url; + + if (argc < 2) { + printf("argc = %d, error\n", argc); + return CMD_RET_USAGE; + } + url = argv[1]; + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + lwip_wget(image_load_addr, url); + + return ulwip_loop(); +} +#endif + +#if defined(CONFIG_CMD_TFTPBOOT) +extern int lwip_tftp(ulong addr, char *filename); + +int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *filename; + ulong addr; + char *end; + int ret; + + switch (argc) { + case 1: + filename = env_get("bootfile"); + break; + case 2: + /* + * Only one arg - accept two forms: + * Just load address, or just boot file name. The latter + * form must be written in a format which can not be + * mis-interpreted as a valid number. + */ + addr = hextoul(argv[1], &end); + if (end == (argv[1] + strlen(argv[1]))) { + image_load_addr = addr; + filename = env_get("bootfile"); + } else { + filename = argv[1]; + } + break; + case 3: + image_load_addr = hextoul(argv[1], NULL); + filename = argv[2]; + break; + default: + return CMD_RET_USAGE; + } + + uboot_lwip_init(); + + eth_init(); /* activate u-boot eth dev */ + + ret = lwip_tftp(image_load_addr, filename); + if (ret) + return ret; + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_TFTPBOOT */ + +#if defined(CONFIG_CMD_DHCP) +extern int ulwip_dhcp(void); + +int do_lwip_dhcp(void) +{ + int ret; + char *filename; + + uboot_lwip_init(); + + ret = ulwip_dhcp(); + + net_set_timeout_handler(2000UL, ulwip_timeout_handler); + + ulwip_loop(); + if (IS_ENABLED(CONFIG_CMD_TFTPBOOT)) { + ulwip_clear_tmo(); + + filename = env_get("bootfile"); + if (!filename) { + printf("no bootfile\n"); + return CMD_RET_FAILURE; + } + + eth_init(); /* activate u-boot eth dev */ + net_set_timeout_handler(20000UL, ulwip_timeout_handler); + lwip_tftp(image_load_addr, filename); + + ret = ulwip_loop(); + } + + return ret; +} + +static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return do_lwip_dhcp(); +} +#endif /* CONFIG_CMD_DHCP */ + +static struct cmd_tbl cmds[] = { + U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""), + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, + "initialize lwip stack", ""), +#if defined(CONFIG_CMD_LWIP_PING) + U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, + "send ICMP ECHO_REQUEST to network host", + "pingAddress"), +#endif +#if defined(CONFIG_CMD_WGET) + U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""), +#endif +#if defined(CONFIG_CMD_TFTPBOOT) + U_BOOT_CMD_MKENT(tftp, 3, 0, do_lwip_tftp, + "boot image via network using TFTP protocol\n", + "[loadAddress] [[hostIPaddr:]bootfilename]"), +#endif +#if defined(CONFIG_CMD_DHCP) + U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp, + "boot image via network using DHCP/TFTP protocol", + ""), +#endif +}; + +static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *cp; + + cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds)); + + argc--; + argv++; + + if (cp == NULL || argc > cp->maxargs) + return CMD_RET_USAGE; + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) + return CMD_RET_SUCCESS; + + return cp->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD( + lwip, 4, 1, do_ops, + "LWIP sub system", + "info - display info\n" + "init - init LWIP\n" + "ping addr - pingAddress\n" + "wget http://IPadress/url/\n" + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" + "dhcp - boot image via network using DHCP/TFTP protocol\n" + ); + +/* Old command kept for compatibility. Same as 'mmc info' */ +U_BOOT_CMD( + lwipinfo, 1, 0, do_lwip_info, + "display LWIP info", + "- display LWIP stack info" +); diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h new file mode 100644 index 0000000000..b943d7b9be --- /dev/null +++ b/lib/lwip/lwipopts.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#include "lwipopts.h" + +#if defined(CONFIG_LWIP_LIB_DEBUG) +#define LWIP_DEBUG 1 +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define IGMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_ON +#define AUTOIP_DEBUG LWIP_DBG_ON +#define DNS_DEBUG LWIP_DBG_OFF +#define IP6_DEBUG LWIP_DBG_OFF +#define DHCP6_DEBUG LWIP_DBG_OFF +#else +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define IGMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF +#define AUTOIP_DEBUG LWIP_DBG_OFF +#define DNS_DEBUG LWIP_DBG_OFF +#define IP6_DEBUG LWIP_DBG_OFF +#define DHCP6_DEBUG LWIP_DBG_OFF +#endif +#define LWIP_TESTMODE 0 + +#if defined(CONFIG_LWIP_LIB_NOASSERT) +#define LWIP_NOASSERT 1 +#define LWIP_ASSERT(message, assertion) +#endif + +#include "lwip/debug.h" + +#define SYS_LIGHTWEIGHT_PROT 0 +#define NO_SYS 0 + +#define MEM_ALIGNMENT 1 +#define MEM_SIZE CONFIG_LWIP_LIB_MEM_SIZE + +#define MEMP_NUM_PBUF 4 +#define MEMP_NUM_RAW_PCB 2 +#define MEMP_NUM_UDP_PCB 4 +#define MEMP_NUM_TCP_PCB 2 +#define MEMP_NUM_TCP_PCB_LISTEN 2 +#define MEMP_NUM_TCP_SEG 16 +#define MEMP_NUM_REASSDATA 1 +#define MEMP_NUM_ARP_QUEUE 2 +#define MEMP_NUM_SYS_TIMEOUT 4 +#define MEMP_NUM_NETBUF 2 +#define MEMP_NUM_NETCONN 32 +#define MEMP_NUM_TCPIP_MSG_API 8 +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#define PBUF_POOL_SIZE 8 + +#define LWIP_ARP 1 + +#define IP_FORWARD 0 +#define IP_OPTIONS_ALLOWED 1 +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define IP_REASS_MAXAGE 3 +#define IP_REASS_MAX_PBUFS 4 +#define IP_FRAG_USES_STATIC_BUF 0 + +#define IP_DEFAULT_TTL 255 + +#define LWIP_ICMP 1 + +#define LWIP_RAW 1 + +#if defined(CONFIG_LWIP_LIB_DHCP) +#define LWIP_DHCP 1 +#define LWIP_DHCP_BOOTP_FILE 1 +#else +#define LWIP_DHCP 0 +#endif +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#define LWIP_AUTOIP 0 + +#define LWIP_SNMP 0 + +#define LWIP_IGMP 0 + +#if defined(CONFIG_LWIP_LIB_DNS) +#define LWIP_DNS 1 +#else +#define LWIP_DNS 0 +#endif + +#if defined(CONFIG_LWIP_LIB_TCP) +#define LWIP_UDP 1 +#else +#define LWIP_UDP 0 +#endif + +#if defined(CONFIG_LWIP_LIB_TCP) +#define LWIP_TCP 1 +#else +#define LWIP_TCP 0 +#endif + +#define LWIP_LISTEN_BACKLOG 0 + +#define PBUF_LINK_HLEN CONFIG_LWIP_LIB_PBUF_LINK_HLEN +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN) + +#define LWIP_HAVE_LOOPIF 0 + +#if defined(CONFIG_LWIP_LIB_NETCONN) +#define LWIP_NETCONN 1 +#else +#define LWIP_NETCONN 0 +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 +#endif + +#if defined(CONFIG_LWIP_LIB_SOCKET) +#define LWIP_SOCKET 1 + +#define SO_REUSE 1 +#else +#define LWIP_SOCKET 0 +#define SO_REUSE 0 +#endif + +#define LWIP_STATS 0 + +#define PPP_SUPPORT 0 + +#define LWIP_TCPIP_CORE_LOCKING 0 + +#if defined(CONFIG_LWIP_LIB_LOOPBACK) +#define LWIP_NETIF_LOOPBACK 1 +#else +#define LWIP_NETIF_LOOPBACK 0 +#endif +/* use malloc instead of pool */ +#define MEMP_MEM_MALLOC 1 +#define MEMP_MEM_INIT 1 +#define MEM_LIBC_MALLOC 1 + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c new file mode 100644 index 0000000000..37c02a451f --- /dev/null +++ b/lib/lwip/port/if.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include <common.h> +#include <command.h> +extern int eth_init(void); /* net.h */ +extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* net.h */ +extern struct in_addr net_ip; +extern u8 net_ethaddr[6]; + +#include "lwip/debug.h" +#include "lwip/arch.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h" + +#include "lwip/ip.h" + +#define IFNAME0 'e' +#define IFNAME1 '0' + +static struct pbuf *low_level_input(struct netif *netif); +static int uboot_net_use_lwip; + +int ulwip_enabled(void) +{ + return uboot_net_use_lwip; +} + +/* 1 - in loop + * 0 - no loop + */ +static int loop_lwip; + +/* ret 1 - in loop + * 0 - no loop + */ +int ulwip_in_loop(void) +{ + return loop_lwip; +} + +void ulwip_loop_set(int loop) +{ + loop_lwip = loop; +} + +static int ulwip_app_err; + +void ulwip_exit(int err) +{ + ulwip_app_err = err; + ulwip_loop_set(0); +} + +int ulwip_app_get_err(void) +{ + return ulwip_app_err; +} + +struct uboot_lwip_if { +}; + +#if defined(CONFIG_CMD_DHCP) +struct netif uboot_netif; +#else +static struct netif uboot_netif; +#endif + +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) + +extern uchar *net_rx_packet; +extern int net_rx_packet_len; + +int uboot_lwip_poll(void) +{ + struct pbuf *p; + int err; + + p = low_level_input(&uboot_netif); + if (!p) { + printf("error p = low_level_input = NULL\n"); + return 0; + } + + err = ethernet_input(p, &uboot_netif); + if (err) + printf("ip4_input err %d\n", err); + + return 0; +} + +static struct pbuf *low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len = net_rx_packet_len; + uchar *data = net_rx_packet; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p) { +#if ETH_PAD_SIZE + pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ +#endif + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. + */ + for (q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + MEMCPY(q->payload, data, q->len); + data += q->len; + } + //acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + LINK_STATS_INC(link.recv); + } else { + //drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +static int ethernetif_input(struct pbuf *p, struct netif *netif) +{ + struct ethernetif *ethernetif; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* if no packet could be read, silently ignore this */ + if (p) { + /* pass all packets to ethernet_input, which decides what packets it supports */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", __func__)); + pbuf_free(p); + p = NULL; + } + } + return 0; +} + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + int err; + + err = eth_send(p->payload, p->len); + if (err != 0) { + printf("eth_send error %d\n", err); + return ERR_ABRT; + } + return ERR_OK; +} + +err_t uboot_lwip_if_init(struct netif *netif) +{ + struct uboot_lwip_if *uif = (struct uboot_lwip_if *)malloc(sizeof(struct uboot_lwip_if)); + + if (!uif) { + printf("uboot_lwip_if: out of memory\n"); + return ERR_MEM; + } + netif->state = uif; + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + + netif->hwaddr_len = ETHARP_HWADDR_LEN; + string_to_enetaddr(env_get("ethaddr"), netif->hwaddr); +#if defined(CONFIG_LWIP_LIB_DEBUG) + printf(" MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], + netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]); +#endif + +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + eth_init(); /* activate u-boot eth dev */ + + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + printf("Initialized LWIP stack\n"); + } + + return ERR_OK; +} + +int uboot_lwip_init(void) +{ + ip4_addr_t ipaddr, netmask, gw; + + if (uboot_net_use_lwip) + return CMD_RET_SUCCESS; + + ip4_addr_set_zero(&gw); + ip4_addr_set_zero(&ipaddr); + ip4_addr_set_zero(&netmask); + + ipaddr_aton(env_get("ipaddr"), &ipaddr); + ipaddr_aton(env_get("ipaddr"), &netmask); + + LWIP_PORT_INIT_NETMASK(&netmask); + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr)); + printf(" GW: %s\n", ip4addr_ntoa(&gw)); + printf(" mask: %s\n", ip4addr_ntoa(&netmask)); + } + + if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw, + &uboot_netif, uboot_lwip_if_init, ethernetif_input)) + printf("err: netif_add failed!\n"); + + netif_set_up(&uboot_netif); + netif_set_link_up(&uboot_netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&uboot_netif, 1); + printf(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0))); +#endif /* LWIP_IPV6 */ + + uboot_net_use_lwip = 1; + + return CMD_RET_SUCCESS; +} + +/* placeholder, not used now */ +void uboot_lwip_destroy(void) +{ + uboot_net_use_lwip = 0; +} diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h new file mode 100644 index 0000000000..db30d7614e --- /dev/null +++ b/lib/lwip/port/include/arch/cc.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#ifndef LWIP_ARCH_CC_H +#define LWIP_ARCH_CC_H + +#include <linux/types.h> +#include <linux/kernel.h> + +#define LWIP_ERRNO_INCLUDE <errno.h> + +#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1 + +extern unsigned int lwip_port_rand(void); +#define LWIP_RAND() (lwip_port_rand()) + +/* different handling for unit test, normally not needed */ +#ifdef LWIP_NOASSERT_ON_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + handler; }} while (0) +#endif + +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS + +#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ + x, __LINE__, __FILE__); } while (0) + +static inline int atoi(const char *str) +{ + int r = 0; + int i; + + for (i = 0; str[i] != '\0'; ++i) + r = r * 10 + str[i] - '0'; + + return r; +} + +#define LWIP_ERR_T int + +#endif /* LWIP_ARCH_CC_H */ diff --git a/lib/lwip/port/include/arch/sys_arch.h b/lib/lwip/port/include/arch/sys_arch.h new file mode 100644 index 0000000000..8d95146275 --- /dev/null +++ b/lib/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#include "lwip/opt.h" +#include "lwip/arch.h" +#include "lwip/err.h" + +#define ERR_NEED_SCHED 123 + +void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms) + +#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#include <errno.h> + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +typedef u32_t sys_prot_t; + +struct sys_sem; +typedef struct sys_sem *sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = NULL; }} while (0) + +/* let sys.h use binary semaphores for mutexes */ +#define LWIP_COMPAT_MUTEX 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1 + +struct sys_mbox; +typedef struct sys_mbox *sys_mbox_t; +#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) +#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = NULL; }} while (0) + +struct sys_thread; +typedef struct sys_thread *sys_thread_t; + +static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + return 0; +}; + +static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + return 0; +}; + +#define sys_sem_signal(s) + +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/lib/lwip/port/include/limits.h b/lib/lwip/port/include/limits.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c new file mode 100644 index 0000000000..609eeccf8c --- /dev/null +++ b/lib/lwip/port/sys-arch.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org> + */ + +#include <common.h> +#include <rand.h> +#include "lwip/opt.h" + +u32_t sys_now(void) +{ + return get_timer(0); +} + +u32_t lwip_port_rand(void) +{ + return (u32_t)rand(); +} + diff --git a/lib/lwip/ulwip.h b/lib/lwip/ulwip.h new file mode 100644 index 0000000000..11ca52aa1f --- /dev/null +++ b/lib/lwip/ulwip.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +int ulwip_enabled(void); +int ulwip_in_loop(void); +int ulwip_loop_set(int loop); +int ulwip_exit(int err); +int uboot_lwip_poll(void); +int ulwip_app_get_err(void); +void ulwip_set_tmo(int (*tmo)(void)); diff --git a/net/Kconfig b/net/Kconfig index a1ec3f8542..2c5d8b8aca 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,6 +5,7 @@ menuconfig NET bool "Networking support" default y + select LWIP_LIB if NET diff --git a/net/net.c b/net/net.c index 57da9bda85..3d9a2e798a 100644 --- a/net/net.c +++ b/net/net.c @@ -121,6 +121,7 @@ #endif #include <net/tcp.h> #include <net/wget.h> +#include "../lib/lwip/ulwip.h" /** BOOTP EXTENTIONS **/ @@ -438,7 +439,11 @@ int net_loop(enum proto_t protocol) #endif bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); +#if defined(CONFIG_LWIP_LIB) + if (!ulwip_enabled() || !ulwip_in_loop()) +#endif net_init(); + if (eth_is_on_demand_init()) { eth_halt(); eth_set_current(); @@ -619,6 +624,18 @@ restart: */ eth_rx(); +#if defined(CONFIG_LWIP_LIB) + if (ulwip_enabled()) { + net_set_state(NETLOOP_CONTINUE); + if (!ulwip_in_loop()) { + if (ulwip_app_get_err()) + net_set_state(NETLOOP_FAIL); + else + net_set_state(NETLOOP_SUCCESS); + goto done; + } + } +#endif /* * Abort if ctrl-c was pressed. */ @@ -1177,6 +1194,13 @@ void net_process_received_packet(uchar *in_packet, int len) if (len < ETHER_HDR_SIZE) return; +#if defined(CONFIG_LWIP_LIB) + if (ulwip_enabled()) { + uboot_lwip_poll(); + return; + } +#endif + #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len);
This commit adds lwip library for the U-boot network stack. Supported commands: ping, tftp, dhcp and wget. Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> --- .gitignore | 9 + boot/bootmeth_pxe.c | 2 +- cmd/net.c | 48 +---- cmd/pxe.c | 2 +- include/net.h | 8 +- lib/Kconfig | 2 + lib/Makefile | 2 + lib/lwip/Kconfig | 63 ++++++ lib/lwip/Makefile | 101 ++++++++++ lib/lwip/apps/dhcp/lwip-dhcp.c | 52 +++++ lib/lwip/apps/http/lwip-wget.c | 74 +++++++ lib/lwip/apps/ping/lwip_ping.c | 37 ++++ lib/lwip/apps/ping/lwip_ping.h | 24 +++ lib/lwip/apps/ping/ping.h | 35 ++++ lib/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++++++ lib/lwip/cmd-lwip.c | 269 ++++++++++++++++++++++++++ lib/lwip/lwipopts.h | 203 +++++++++++++++++++ lib/lwip/port/if.c | 260 +++++++++++++++++++++++++ lib/lwip/port/include/arch/cc.h | 46 +++++ lib/lwip/port/include/arch/sys_arch.h | 59 ++++++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 20 ++ lib/lwip/ulwip.h | 9 + net/Kconfig | 1 + net/net.c | 24 +++ 25 files changed, 1430 insertions(+), 44 deletions(-) create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c create mode 100644 lib/lwip/apps/http/lwip-wget.c create mode 100644 lib/lwip/apps/ping/lwip_ping.c create mode 100644 lib/lwip/apps/ping/lwip_ping.h create mode 100644 lib/lwip/apps/ping/ping.h create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c create mode 100644 lib/lwip/cmd-lwip.c create mode 100644 lib/lwip/lwipopts.h create mode 100644 lib/lwip/port/if.c create mode 100644 lib/lwip/port/include/arch/cc.h create mode 100644 lib/lwip/port/include/arch/sys_arch.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c create mode 100644 lib/lwip/ulwip.h