[PATCHv7 00/15] net/lwip: add lwip library for the network stack

Hello,
I'm sending v7, with all v6 comments getting fixed. The only thing left is a pointer to timeout callback which 2 applications use. I will rework this timeout in next v8. I started take a look at it, and want to fix this together with background applications support in v8.
changelog: v7: - more review fixes. - support of multiply eth devices, were "ethact" selects the active device. v6: - fixed review comments for v5 (thanks Ilias and Simon). - lwip is not under /net, so prior applying patch following commit is needed to create lwIP merge into U-Boot: git subtree add --prefix net/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash
v5: - fixed Iliases comments and split big patch on the small ones. You also need to issue command: git subtree add --prefix lib/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash Which will create merge commit of lwip library placing sources into lib/lwip/lwip-external directory. I do not send it a patch due to 1. merges are not friendly with git format-patch and 2. the source code of lwip is 78kb. v4: - tested with tests/py/ did some minor fixes (out of tree build, variables set after downloads). - accounted review comments for documentation. - implemented dns command - corrected wget command to not use serverip variable and use just url string. v3: - use lwip commands for ping,tftp,wget,dhcp if this patch applied. Drop CONFIG_LIB_LWIP_REPLACE_<COMMAND> option. - docs: use rst variant and drop references to RFC.
Maxim Uvarov (15): net/lwip: add doc/develop/net_lwip.rst net/lwip: integrate lwIP library net/lwip: implement dns cmd net/lwip: implement dhcp cmd net/lwip: implement tftp cmd net/lwip: implement wget cmd net/lwip: implement ping cmd net/lwip: add lwIP configuration net/lwip: implement lwIP port to U-Boot net/lwip: update .gitignore with lwIP net/lwip: connection between cmd and lwip apps net/lwip: replace original net commands with lwip net/lwip: split net.h to net.h, arp.h and eth.h net/lwip: drop old net/wget net/lwip/wget add port selection
boot/bootmeth_efi.c | 18 +- boot/bootmeth_pxe.c | 21 +- cmd/Makefile | 1 + cmd/net-lwip.c | 306 ++++++++++++++++++ cmd/net.c | 86 +---- cmd/pxe.c | 19 +- doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 76 +++++ include/net.h | 197 +----------- include/net/arp.h | 7 + include/net/eth.h | 190 +++++++++++ include/net/lwip.h | 73 +++++ include/net/ulwip.h | 76 +++++ include/net/wget.h | 22 -- net/Kconfig | 3 + net/Makefile | 2 +- net/eth-uclass.c | 8 + net/lwip/.gitignore | 8 + net/lwip/Kconfig | 55 ++++ net/lwip/Makefile | 72 +++++ net/lwip/apps/dhcp/lwip-dhcp.c | 62 ++++ net/lwip/apps/dns/lwip-dns.c | 46 +++ net/lwip/apps/http/Makefile | 13 + net/lwip/apps/http/lwip-wget.c | 134 ++++++++ net/lwip/apps/ping/Makefile | 11 + net/lwip/apps/ping/lwip_ping.c | 37 +++ net/lwip/apps/ping/lwip_ping.h | 15 + net/lwip/apps/ping/ping.h | 19 ++ net/lwip/apps/tftp/Makefile | 16 + net/lwip/apps/tftp/lwip-tftp.c | 124 ++++++++ net/lwip/lwipopts.h | 197 ++++++++++++ net/lwip/port/if.c | 343 ++++++++++++++++++++ net/lwip/port/include/arch/cc.h | 38 +++ net/lwip/port/include/arch/sys_arch.h | 10 + net/lwip/port/include/limits.h | 0 net/lwip/port/sys-arch.c | 13 + net/net.c | 26 +- net/wget.c | 440 -------------------------- 38 files changed, 2028 insertions(+), 757 deletions(-) create mode 100644 cmd/net-lwip.c create mode 100644 doc/develop/net_lwip.rst create mode 100644 include/net/arp.h create mode 100644 include/net/eth.h create mode 100644 include/net/lwip.h create mode 100644 include/net/ulwip.h delete mode 100644 include/net/wget.h create mode 100644 net/lwip/.gitignore create mode 100644 net/lwip/Kconfig create mode 100644 net/lwip/Makefile create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c create mode 100644 net/lwip/apps/dns/lwip-dns.c create mode 100644 net/lwip/apps/http/Makefile create mode 100644 net/lwip/apps/http/lwip-wget.c create mode 100644 net/lwip/apps/ping/Makefile create mode 100644 net/lwip/apps/ping/lwip_ping.c create mode 100644 net/lwip/apps/ping/lwip_ping.h create mode 100644 net/lwip/apps/ping/ping.h create mode 100644 net/lwip/apps/tftp/Makefile create mode 100644 net/lwip/apps/tftp/lwip-tftp.c create mode 100644 net/lwip/lwipopts.h create mode 100644 net/lwip/port/if.c create mode 100644 net/lwip/port/include/arch/cc.h create mode 100644 net/lwip/port/include/arch/sys_arch.h create mode 100644 net/lwip/port/include/limits.h create mode 100644 net/lwip/port/sys-arch.c delete mode 100644 net/wget.c

Add initial documentation of lwIP network IP stack integration to the U-Boot (net_lwip.rst).
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org Reviewed-by: Simon Glass sjg@chromium.org --- doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 doc/develop/net_lwip.rst
diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 5b230d0321..4764990f25 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -48,6 +48,7 @@ Implementation spl falcon uefi/index + net_lwip vbe version
diff --git a/doc/develop/net_lwip.rst b/doc/develop/net_lwip.rst new file mode 100644 index 0000000000..cd85de92a1 --- /dev/null +++ b/doc/develop/net_lwip.rst @@ -0,0 +1,76 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +LWIP IP stack intergation for U-Boot +==================================== + +Intro +----- + +LWIP is a library implementing network protocols, which is commonly used +on embedded devices. + +https://savannah.nongnu.org/projects/lwip/ + +LwIP license: +LwIP is licensed under a BSD-style license: http://lwip.wikia.com/wiki/License. + +Main features include: + +* Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE + +* DHCP client, DNS client (incl. mDNS hostname resolver), + AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3, private MIB support + & MIB compiler) + +* APIs: specialized APIs for enhanced performance, optional Berkeley-alike + socket API + +* Extended features: IP forwarding over multiple network interfaces, TCP + congestion control, RTT estimation and fast recovery/fast retransmit + +* Addon applications: HTTP(S) server, SNTP client, SMTP(S) client, ping, + NetBIOS nameserver, mDNS responder, MQTT client, TFTP server + +U-Boot implementation details +----------------------------- + +1. In general we can build lwIP as a library and link it against U-Boot or + compile it in the U-Boot tree in the same way as other U-Boot files. There + are few reasons why second variant was selected: lwIP is very customizable + with defines for features, memory size, types of allocation, some internal + types and platform specific code. It turned out easier to enable/disable + debug which is also done with defines, and is needed periodically. + +2. lwIP has 2 APIs - raw mode and sequential (as lwIP names it, or socket API + as we name it in Linux). For now only raw API is supported. + +In raw IP mode a callback function for RX path is registered and will be called +when packet is passed to the IP stack and is ready for the application. + +One example is the unmodified working ping example from lwip sources which +registered the callback: + +.. code-block:: c + + ping_pcb = raw_new(IP_PROTO_ICMP); + raw_recv(ping_pcb, ping_recv, NULL); <- ping_recv is app callback. + raw_bind(ping_pcb, IP_ADDR_ANY) + +3. Input and output + +RX packet path is injected to U-Boot eth_rx() polling loop and TX patch is in +eth_send() accordingly. That way we can leave the driver code unmodified and +consume packets once they are ready. So we do not touch any drivers code and +just eat packets when they are ready. + +U-Boot lwIP Applications +======================== + +.. kernel-doc:: include/net/lwip.h + :internal: + +lwIP API to control polling loop +================================ + +.. kernel-doc:: include/net/ulwip.h + :internal:

Hi Maxim,
On Tue, 22 Aug 2023 at 03:38, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Add initial documentation of lwIP network IP stack integration to the U-Boot (net_lwip.rst).
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org Reviewed-by: Simon Glass sjg@chromium.org
doc/develop/index.rst | 1 + doc/develop/net_lwip.rst | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 doc/develop/net_lwip.rst
diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 5b230d0321..4764990f25 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -48,6 +48,7 @@ Implementation spl falcon uefi/index
- net_lwip vbe version
diff --git a/doc/develop/net_lwip.rst b/doc/develop/net_lwip.rst new file mode 100644 index 0000000000..cd85de92a1 --- /dev/null +++ b/doc/develop/net_lwip.rst @@ -0,0 +1,76 @@ +.. SPDX-License-Identifier: GPL-2.0+
+LWIP IP stack intergation for U-Boot
spelling
+====================================
+Intro +-----
+LWIP is a library implementing network protocols, which is commonly used +on embedded devices.
+https://savannah.nongnu.org/projects/lwip/
+LwIP license: +LwIP is licensed under a BSD-style license: http://lwip.wikia.com/wiki/License.
+Main features include:
+* Protocols: IP, IPv6, ICMP, ND, MLD, UDP, TCP, IGMP, ARP, PPPoS, PPPoE
+* DHCP client, DNS client (incl. mDNS hostname resolver),
- AutoIP/APIPA (Zeroconf), SNMP agent (v1, v2c, v3, private MIB support
- & MIB compiler)
+* APIs: specialized APIs for enhanced performance, optional Berkeley-alike
- socket API
+* Extended features: IP forwarding over multiple network interfaces, TCP
- congestion control, RTT estimation and fast recovery/fast retransmit
+* Addon applications: HTTP(S) server, SNTP client, SMTP(S) client, ping,
- NetBIOS nameserver, mDNS responder, MQTT client, TFTP server
+U-Boot implementation details +-----------------------------
+1. In general we can build lwIP as a library and link it against U-Boot or
- compile it in the U-Boot tree in the same way as other U-Boot files. There
- are few reasons why second variant was selected: lwIP is very customizable
- with defines for features, memory size, types of allocation, some internal
- types and platform specific code. It turned out easier to enable/disable
- debug which is also done with defines, and is needed periodically.
+2. lwIP has 2 APIs - raw mode and sequential (as lwIP names it, or socket API
- as we name it in Linux). For now only raw API is supported.
+In raw IP mode a callback function for RX path is registered and will be called +when packet is passed to the IP stack and is ready for the application.
+One example is the unmodified working ping example from lwip sources which +registered the callback:
+.. code-block:: c
ping_pcb = raw_new(IP_PROTO_ICMP);
raw_recv(ping_pcb, ping_recv, NULL); <- ping_recv is app callback.
raw_bind(ping_pcb, IP_ADDR_ANY)
+3. Input and output
+RX packet path is injected to U-Boot eth_rx() polling loop and TX patch is in +eth_send() accordingly. That way we can leave the driver code unmodified and +consume packets once they are ready. So we do not touch any drivers code and +just eat packets when they are ready.
+U-Boot lwIP Applications +========================
+.. kernel-doc:: include/net/lwip.h
- :internal:
+lwIP API to control polling loop +================================
+.. kernel-doc:: include/net/ulwip.h
- :internal:
-- 2.30.2
Regards, Simon

Define Makefile and Kconfig to build lwIP inside the U-Boot. We compile lwIP the same as the main code, plus we can do optimization for size at compile time with disabling not needed debug asserts, or not used protocols. So we can tune lwIP configuration specially for U-Boot environments.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- net/Kconfig | 3 +++ net/Makefile | 1 + net/lwip/Kconfig | 55 +++++++++++++++++++++++++++++++++++++++ net/lwip/Makefile | 66 +++++++++++++++++++++++++++++++++++++++++++++++ net/net.c | 20 ++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 net/lwip/Kconfig create mode 100644 net/lwip/Makefile
diff --git a/net/Kconfig b/net/Kconfig index 4215889127..34c1e43c87 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,9 +5,12 @@ menuconfig NET bool "Networking support" default y + imply LWIP
if NET
+source net/lwip/Kconfig + config ARP_TIMEOUT int "Milliseconds before trying ARP again" default 5000 diff --git a/net/Makefile b/net/Makefile index 3e2d061338..61930c244e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o +obj-$(CONFIG_LWIP) += lwip/
# Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig new file mode 100644 index 0000000000..f07e26f7d9 --- /dev/null +++ b/net/lwip/Kconfig @@ -0,0 +1,55 @@ +menu "LWIP" +config LWIP + bool "Support LWIP library" + help + Enable the lwIP library code with + all dependencies (commands are implemented with lwIP + library. This option is automatically enabled if CONFIG_NET=y. + lwIP library (https://git.savannah.nongnu.org/git/lwip.git) provides + network stack and application code for U-Boot commands. + Please see doc/develop/net_lwip.rst for more details. + +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 by 16k. + +config LWIP_LIB_TCP + bool "tcp" + default y + help + Compile lwIP with TCP protocol support. + +config LWIP_LIB_UDP + bool "udp" + default y + help + Compile lwIP with UDP protocol support (needed for TFTP). + +config LWIP_LIB_DNS + bool "dns" + default y + help + Compile lwIP with DNS protocol support. + +config LWIP_LIB_DHCP + bool "dhcp" + default y + help + Compile lwIP with DHCP protocol support. + +config LWIP_LIB_LOOPBACK + bool "loopback" + help + Increases size by 1k. + Compile lwIP with loopback interface support. +endmenu + +endmenu diff --git a/net/lwip/Makefile b/net/lwip/Makefile new file mode 100644 index 0000000000..d1161bea78 --- /dev/null +++ b/net/lwip/Makefile @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + +LWIPDIR=lwip-external/src + +ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/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 diff --git a/net/net.c b/net/net.c index 43abbac7c3..7f868ee516 100644 --- a/net/net.c +++ b/net/net.c @@ -125,6 +125,7 @@ #endif #include "dhcpv6.h" #include "net_rand.h" +#include <net/ulwip.h>
/** BOOTP EXTENTIONS **/
@@ -452,7 +453,11 @@ int net_loop(enum proto_t protocol) #endif
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start"); +#if defined(CONFIG_LWIP) + if (!ulwip_enabled() || !ulwip_in_loop()) +#endif net_init(); + if (eth_is_on_demand_init()) { eth_halt(); eth_set_current(); @@ -649,6 +654,16 @@ restart: */ eth_rx();
+ if (IS_ENABLED(CONFIG_LWIP) && 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; + } + } /* * Abort if ctrl-c was pressed. */ @@ -1213,6 +1228,11 @@ void net_process_received_packet(uchar *in_packet, int len) if (len < ETHER_HDR_SIZE) return;
+ if (IS_ENABLED(CONFIG_LWIP) && ulwip_enabled()) { + ulwip_poll(); + return; + } + #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len);

Hi Maxim,
On Tue, 22 Aug 2023 at 03:38, Maxim Uvarov maxim.uvarov@linaro.org wrote:
Define Makefile and Kconfig to build lwIP inside the U-Boot. We compile lwIP the same as the main code, plus we can do optimization for size at compile time with disabling not needed debug asserts, or not used protocols. So we can tune lwIP configuration specially for U-Boot environments.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
net/Kconfig | 3 +++ net/Makefile | 1 + net/lwip/Kconfig | 55 +++++++++++++++++++++++++++++++++++++++ net/lwip/Makefile | 66 +++++++++++++++++++++++++++++++++++++++++++++++ net/net.c | 20 ++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 net/lwip/Kconfig create mode 100644 net/lwip/Makefile
diff --git a/net/Kconfig b/net/Kconfig index 4215889127..34c1e43c87 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,9 +5,12 @@ menuconfig NET bool "Networking support" default y
imply LWIP
if NET
+source net/lwip/Kconfig
config ARP_TIMEOUT int "Milliseconds before trying ARP again" default 5000 diff --git a/net/Makefile b/net/Makefile index 3e2d061338..61930c244e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o +obj-$(CONFIG_LWIP) += lwip/
# Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig new file mode 100644 index 0000000000..f07e26f7d9 --- /dev/null +++ b/net/lwip/Kconfig @@ -0,0 +1,55 @@ +menu "LWIP" +config LWIP
bool "Support LWIP library"
help
Enable the lwIP library code with
all dependencies (commands are implemented with lwIP
library. This option is automatically enabled if CONFIG_NET=y.
lwIP library (https://git.savannah.nongnu.org/git/lwip.git) provides
network stack and application code for U-Boot commands.
Please see doc/develop/net_lwip.rst for more details.
+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 by 16k.
+config LWIP_LIB_TCP
bool "tcp"
default y
help
Compile lwIP with TCP protocol support.
+config LWIP_LIB_UDP
bool "udp"
default y
help
Compile lwIP with UDP protocol support (needed for TFTP).
+config LWIP_LIB_DNS
bool "dns"
default y
help
Compile lwIP with DNS protocol support.
+config LWIP_LIB_DHCP
bool "dhcp"
default y
help
Compile lwIP with DHCP protocol support.
+config LWIP_LIB_LOOPBACK
bool "loopback"
help
Increases size by 1k.
Compile lwIP with loopback interface support.
+endmenu
+endmenu diff --git a/net/lwip/Makefile b/net/lwip/Makefile new file mode 100644 index 0000000000..d1161bea78 --- /dev/null +++ b/net/lwip/Makefile @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org
+LWIPDIR=lwip-external/src
+ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip
+obj-$(CONFIG_NET) += $(LWIPDIR)/core/init.o \
$(LWIPDIR)/core/def.o \
Can we drop the LWIPDIR things? It should use the directory anyway
$(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 diff --git a/net/net.c b/net/net.c index 43abbac7c3..7f868ee516 100644 --- a/net/net.c +++ b/net/net.c @@ -125,6 +125,7 @@ #endif #include "dhcpv6.h" #include "net_rand.h" +#include <net/ulwip.h>
/** BOOTP EXTENTIONS **/
@@ -452,7 +453,11 @@ int net_loop(enum proto_t protocol) #endif
bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
+#if defined(CONFIG_LWIP)
if (!ulwip_enabled() || !ulwip_in_loop())
+#endif
Let's try not to add any #if things in your patches.
net_init();
if (eth_is_on_demand_init()) { eth_halt(); eth_set_current();
@@ -649,6 +654,16 @@ restart: */ eth_rx();
if (IS_ENABLED(CONFIG_LWIP) && 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;
}
} /* * Abort if ctrl-c was pressed. */
@@ -1213,6 +1228,11 @@ void net_process_received_packet(uchar *in_packet, int len) if (len < ETHER_HDR_SIZE) return;
if (IS_ENABLED(CONFIG_LWIP) && ulwip_enabled()) {
ulwip_poll();
return;
}
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) if (push_packet) { (*push_packet)(in_packet, len); -- 2.30.2
Regards, Simon

út 22. 8. 2023 v 11:38 odesílatel Maxim Uvarov maxim.uvarov@linaro.org napsal:
Define Makefile and Kconfig to build lwIP inside the U-Boot. We compile lwIP the same as the main code, plus we can do optimization for size at compile time with disabling not needed debug asserts, or not used protocols. So we can tune lwIP configuration specially for U-Boot environments.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
net/Kconfig | 3 +++ net/Makefile | 1 + net/lwip/Kconfig | 55 +++++++++++++++++++++++++++++++++++++++ net/lwip/Makefile | 66 +++++++++++++++++++++++++++++++++++++++++++++++ net/net.c | 20 ++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 net/lwip/Kconfig create mode 100644 net/lwip/Makefile
diff --git a/net/Kconfig b/net/Kconfig index 4215889127..34c1e43c87 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -5,9 +5,12 @@ menuconfig NET bool "Networking support" default y
imply LWIP
if NET
+source net/lwip/Kconfig
config ARP_TIMEOUT int "Milliseconds before trying ARP again" default 5000 diff --git a/net/Makefile b/net/Makefile index 3e2d061338..61930c244e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_CMD_WGET) += wget.o +obj-$(CONFIG_LWIP) += lwip/
# Disable this warning as it is triggered by: # sprintf(buf, index ? "foo%d" : "foo", index) diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig new file mode 100644 index 0000000000..f07e26f7d9 --- /dev/null +++ b/net/lwip/Kconfig @@ -0,0 +1,55 @@ +menu "LWIP" +config LWIP
bool "Support LWIP library"
help
Enable the lwIP library code with
all dependencies (commands are implemented with lwIP
library. This option is automatically enabled if CONFIG_NET=y.
lwIP library (https://git.savannah.nongnu.org/git/lwip.git) provides
network stack and application code for U-Boot commands.
Please see doc/develop/net_lwip.rst for more details.
+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 by 16k.
+config LWIP_LIB_TCP
bool "tcp"
default y
Please check tab/space in this file. Below you have the same issues.
Thanks, Michal

U-Boot recently got support for an alternative network stack using LWIP. Replace dns command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 19 +++++++++++++++ net/lwip/Makefile | 2 ++ net/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 include/net/lwip.h create mode 100644 net/lwip/apps/dns/lwip-dns.c
diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..cda896d062 --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); + +/** + * ulwip_dns() - creates the DNS request to resolve a domain host name + * + * This function creates the DNS request to resolve a domain host name. Function + * can return immediately if previous request was cached or it might require + * entering the polling loop for a request to a remote server. + * + * @name: dns name to resolve + * @varname: (optional) U-Boot variable name to store the result + * Returns: ERR_OK(0) for fetching entry from the cache + * ERR_INPROGRESS(-5) success, can go to the polling loop + * Other value < 0, if error + */ +int ulwip_dns(char *name, char *varname); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index d1161bea78..6d2c00605b 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o + +obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dns/lwip-dns.c b/net/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..6e205c1153 --- /dev/null +++ b/net/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// 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/dns.h> +#include <lwip/ip_addr.h> + +#include <net/ulwip.h> + +static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + char *varname = (char *)callback_arg; + + if (varname) + env_set(varname, ip4addr_ntoa(ipaddr)); + + log_info("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr)); + ulwip_exit(0); +} + +int ulwip_dns(char *name, char *varname) +{ + int err; + ip_addr_t ipaddr; /* not used */ + ip_addr_t dns1; + ip_addr_t dns2; + + ipaddr_aton(env_get("dnsip"), &dns1); + ipaddr_aton(env_get("dnsip2"), &dns2); + + dns_init(); + dns_setserver(0, &dns1); + dns_setserver(1, &dns2); + + err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname); + if (err == ERR_OK) + dns_found_cb(name, &ipaddr, varname); + + return err; +}

Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace dns command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 19 +++++++++++++++ net/lwip/Makefile | 2 ++ net/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 include/net/lwip.h create mode 100644 net/lwip/apps/dns/lwip-dns.c
diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..cda896d062 --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
Please make sure you comment all exported functions, including the return value.
+/**
- ulwip_dns() - creates the DNS request to resolve a domain host name
- This function creates the DNS request to resolve a domain host name. Function
- can return immediately if previous request was cached or it might require
- entering the polling loop for a request to a remote server.
- @name: dns name to resolve
- @varname: (optional) U-Boot variable name to store the result
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
+int ulwip_dns(char *name, char *varname); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index d1161bea78..6d2c00605b 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dns/lwip-dns.c b/net/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..6e205c1153 --- /dev/null +++ b/net/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// 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/dns.h> +#include <lwip/ip_addr.h>
+#include <net/ulwip.h>
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{
char *varname = (char *)callback_arg;
if (varname)
env_set(varname, ip4addr_ntoa(ipaddr));
log_info("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr));
ulwip_exit(0);
+}
+int ulwip_dns(char *name, char *varname) +{
int err;
ip_addr_t ipaddr; /* not used */
ip_addr_t dns1;
ip_addr_t dns2;
ipaddr_aton(env_get("dnsip"), &dns1);
ipaddr_aton(env_get("dnsip2"), &dns2);
What if the env_get() fails? Won't that return NULL?
dns_init();
dns_setserver(0, &dns1);
dns_setserver(1, &dns2);
Can either of these fail?
Please be very attentive to error-checking.
err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
if (err == ERR_OK)
Is that 0? If so, then if (err) is better
dns_found_cb(name, &ipaddr, varname);
return err;
I am not sure what that is, but will review it when you add the header comments.
+}
2.30.2
Regards, Simon

On Wed, 23 Aug 2023 at 00:58, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace dns command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 19 +++++++++++++++ net/lwip/Makefile | 2 ++ net/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 include/net/lwip.h create mode 100644 net/lwip/apps/dns/lwip-dns.c
diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..cda896d062 --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
Please make sure you comment all exported functions, including the return value.
+/**
- ulwip_dns() - creates the DNS request to resolve a domain host name
- This function creates the DNS request to resolve a domain host name.
Function
- can return immediately if previous request was cached or it might
require
- entering the polling loop for a request to a remote server.
- @name: dns name to resolve
- @varname: (optional) U-Boot variable name to store the result
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
here.
+int ulwip_dns(char *name, char *varname); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index d1161bea78..6d2c00605b 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dns/lwip-dns.c b/net/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..6e205c1153 --- /dev/null +++ b/net/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// 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/dns.h> +#include <lwip/ip_addr.h>
+#include <net/ulwip.h>
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr,
void *callback_arg)
+{
char *varname = (char *)callback_arg;
if (varname)
env_set(varname, ip4addr_ntoa(ipaddr));
log_info("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr));
ulwip_exit(0);
+}
+int ulwip_dns(char *name, char *varname) +{
int err;
ip_addr_t ipaddr; /* not used */
ip_addr_t dns1;
ip_addr_t dns2;
ipaddr_aton(env_get("dnsip"), &dns1);
ipaddr_aton(env_get("dnsip2"), &dns2);
What if the env_get() fails? Won't that return NULL?
all of these functions will not crash, they have null check. You can set dnsip or dnsip2 or both. If both are not set then dns cmd will not look up anything. We can exit earlier here, but that is a common case and nothing bad if we make code simpler and exit a little bit later.
dns_init();
dns_setserver(0, &dns1);
dns_setserver(1, &dns2);
Can either of these fail?
Please be very attentive to error-checking.
All above functions are void. But they have LWIP_ASSERT() for sanity checks in some places.
err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
if (err == ERR_OK)
Is that 0? If so, then if (err) is better
dns_gethostbyname() returns ERR_OK which is defined net/lwip/lwip-external/src/include/lwip/err.h. Yes it's defined to 0 and maybe always will be defined to 0. But that may change. And I would keep the check against the same return macro that the function does.
dns_found_cb(name, &ipaddr, varname);
return err;
I am not sure what that is, but will review it when you add the header comments.
In the header file of this function is an explanation. It's above in this
patch: + * Returns: ERR_OK(0) for fetching entry from the cache + * ERR_INPROGRESS(-5) success, can go to the polling loop + * Other value < 0, if error + */
+}
2.30.2
Regards, Simon

Hi Maxim,
On Fri, 1 Sept 2023 at 08:49, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Wed, 23 Aug 2023 at 00:58, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace dns command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 19 +++++++++++++++ net/lwip/Makefile | 2 ++ net/lwip/apps/dns/lwip-dns.c | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 include/net/lwip.h create mode 100644 net/lwip/apps/dns/lwip-dns.c
diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..cda896d062 --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
Please make sure you comment all exported functions, including the return value.
+/**
- ulwip_dns() - creates the DNS request to resolve a domain host name
- This function creates the DNS request to resolve a domain host name. Function
- can return immediately if previous request was cached or it might require
- entering the polling loop for a request to a remote server.
- @name: dns name to resolve
- @varname: (optional) U-Boot variable name to store the result
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
here.
That seems to be a different function?
+int ulwip_dns(char *name, char *varname);
This one has no comment?
diff --git a/net/lwip/Makefile b/net/lwip/Makefile index d1161bea78..6d2c00605b 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dns/lwip-dns.c b/net/lwip/apps/dns/lwip-dns.c new file mode 100644 index 0000000000..6e205c1153 --- /dev/null +++ b/net/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// 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/dns.h> +#include <lwip/ip_addr.h>
+#include <net/ulwip.h>
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{
char *varname = (char *)callback_arg;
if (varname)
env_set(varname, ip4addr_ntoa(ipaddr));
That can fail
log_info("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr));
ulwip_exit(0);
+}
+int ulwip_dns(char *name, char *varname) +{
int err;
ip_addr_t ipaddr; /* not used */
ip_addr_t dns1;
ip_addr_t dns2;
ipaddr_aton(env_get("dnsip"), &dns1);
ipaddr_aton(env_get("dnsip2"), &dns2);
What if the env_get() fails? Won't that return NULL?
all of these functions will not crash, they have null check. You can set dnsip or dnsip2 or both. If both are not set then dns cmd will not look up anything. We can exit earlier here, but that is a common case and nothing bad if we make code simpler and exit a little bit later.
OK but I cannot see where the error is returned?
dns_init();
dns_setserver(0, &dns1);
dns_setserver(1, &dns2);
Can either of these fail?
Please be very attentive to error-checking.
All above functions are void. But they have LWIP_ASSERT() for sanity checks in some places.
err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
if (err == ERR_OK)
Is that 0? If so, then if (err) is better
dns_gethostbyname() returns ERR_OK which is defined net/lwip/lwip-external/src/include/lwip/err.h. Yes it's defined to 0 and maybe always will be defined to 0. But that may change. And I would keep the check against the same return macro that the function does.
I cannot imagine it changing.
dns_found_cb(name, &ipaddr, varname);
return err;
I am not sure what that is, but will review it when you add the header comments.
In the header file of this function is an explanation. It's above in this patch:
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
OK, so what I am getting at is trying to understand the error conversion. It seems that lwip uses different numbering from U-Boot/Linux, so we need to do a conversion somewhere?
Regards, Simon

On Sat, 2 Sept 2023 at 06:09, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Fri, 1 Sept 2023 at 08:49, Maxim Uvarov maxim.uvarov@linaro.org wrote:
On Wed, 23 Aug 2023 at 00:58, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org
wrote:
U-Boot recently got support for an alternative network stack using
LWIP.
Replace dns command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 19 +++++++++++++++ net/lwip/Makefile | 2 ++ net/lwip/apps/dns/lwip-dns.c | 46
++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+) create mode 100644 include/net/lwip.h create mode 100644 net/lwip/apps/dns/lwip-dns.c
diff --git a/include/net/lwip.h b/include/net/lwip.h new file mode 100644 index 0000000000..cda896d062 --- /dev/null +++ b/include/net/lwip.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */
+int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]);
Please make sure you comment all exported functions, including the
return value.
+/**
- ulwip_dns() - creates the DNS request to resolve a domain host
name
- This function creates the DNS request to resolve a domain host
name. Function
- can return immediately if previous request was cached or it might
require
- entering the polling loop for a request to a remote server.
- @name: dns name to resolve
- @varname: (optional) U-Boot variable name to store the result
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
here.
That seems to be a different function?
+int ulwip_dns(char *name, char *varname);
This one has no comment?
diff --git a/net/lwip/Makefile b/net/lwip/Makefile index d1161bea78..6d2c00605b 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -64,3 +64,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o
obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dns/lwip-dns.c
b/net/lwip/apps/dns/lwip-dns.c
new file mode 100644 index 0000000000..6e205c1153 --- /dev/null +++ b/net/lwip/apps/dns/lwip-dns.c @@ -0,0 +1,46 @@ +// 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/dns.h> +#include <lwip/ip_addr.h>
+#include <net/ulwip.h>
+static void dns_found_cb(const char *name, const ip_addr_t *ipaddr,
void *callback_arg)
+{
char *varname = (char *)callback_arg;
if (varname)
env_set(varname, ip4addr_ntoa(ipaddr));
That can fail
yea, will add a check.
log_info("resolved %s to %s\n", name, ip4addr_ntoa(ipaddr));
ulwip_exit(0);
+}
+int ulwip_dns(char *name, char *varname) +{
int err;
ip_addr_t ipaddr; /* not used */
ip_addr_t dns1;
ip_addr_t dns2;
ipaddr_aton(env_get("dnsip"), &dns1);
ipaddr_aton(env_get("dnsip2"), &dns2);
What if the env_get() fails? Won't that return NULL?
all of these functions will not crash, they have null check. You can set
dnsip or dnsip2 or both. If both are not set then dns cmd will not look up anything.
We can exit earlier here, but that is a common case and nothing bad if
we make code simpler and exit a little bit later.
OK but I cannot see where the error is returned?
I will add more checks. dns_gethostbyname() will return an error if dns were set wrongly. But I will also add more checks here to be clear for other people also.
dns_init();
dns_setserver(0, &dns1);
dns_setserver(1, &dns2);
Can either of these fail?
Please be very attentive to error-checking.
All above functions are void. But they have LWIP_ASSERT() for sanity
checks in some places.
err = dns_gethostbyname(name, &ipaddr, dns_found_cb, varname);
if (err == ERR_OK)
Is that 0? If so, then if (err) is better
dns_gethostbyname() returns ERR_OK which is defined
net/lwip/lwip-external/src/include/lwip/err.h.
Yes it's defined to 0 and maybe always will be defined to 0. But that
may change. And I would keep
the check against the same return macro that the function does.
I cannot imagine it changing.
dns_found_cb(name, &ipaddr, varname);
return err;
I am not sure what that is, but will review it when you add the header
comments.
In the header file of this function is an explanation. It's above in
this patch:
- Returns: ERR_OK(0) for fetching entry from the cache
ERR_INPROGRESS(-5) success, can go to the polling loop
Other value < 0, if error
- */
OK, so what I am getting at is trying to understand the error conversion. It seems that lwip uses different numbering from U-Boot/Linux, so we need to do a conversion somewhere?
Regards, Simon
Yes, that is exactly what happens here. Lwip ERR_INPROGRESS(-5) might be U-boot: #define EINPROGRESS 115 /* Operation now in progress */
I can do a conversion here with some comments to make it more clear.

U-Boot recently got support for an alternative network stack using LWIP. Replace dhcp command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 12 +++++++ net/lwip/Makefile | 1 + net/lwip/apps/dhcp/lwip-dhcp.c | 62 ++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index cda896d062..240ebba354 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -17,3 +17,15 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, * Other value < 0, if error */ int ulwip_dns(char *name, char *varname); + +/** + * ulwip_dhcp() - create the DHCP request to obtain IP address. + * + * This function creates the DHCP request to obtain IP address. If DHCP server + * returns file name, this file will be downloaded with tftp. After this + * function you need to invoke the polling loop to process network communication. + * + * Returns: 0 if success + * Other value < 0, if error +*/ +int ulwip_dhcp(void); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 6d2c00605b..59323fb325 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dhcp/lwip-dhcp.c b/net/lwip/apps/dhcp/lwip-dhcp.c new file mode 100644 index 0000000000..cce1e367f9 --- /dev/null +++ b/net/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,62 @@ +// 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 <net/eth.h> +#include <net/ulwip.h> + +static struct dhcp dhcp; + +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 -1; + } + + return 0; +} + +int ulwip_dhcp(void) +{ + int err; + struct netif *netif; + int eth_idx; + + eth_idx = eth_get_dev_index(); + if (eth_idx < 0) { + log_err("no eth idx\n"); + return -1; + } + + netif = netif_get_by_index(eth_idx + 1); + if (!netif) + return -1; + + ulwip_set_tmo(ulwip_dhcp_tmo); + + if (!netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) + dhcp_set_struct(netif, &dhcp); + + err = dhcp_start(netif); + if (err) + log_err("dhcp_start error %d\n", err); + + return err; +}

Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace dhcp command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 12 +++++++ net/lwip/Makefile | 1 + net/lwip/apps/dhcp/lwip-dhcp.c | 62 ++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index cda896d062..240ebba354 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -17,3 +17,15 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc,
Other value < 0, if error
*/ int ulwip_dns(char *name, char *varname);
+/**
- ulwip_dhcp() - create the DHCP request to obtain IP address.
- This function creates the DHCP request to obtain IP address. If DHCP server
- returns file name, this file will be downloaded with tftp. After this
- function you need to invoke the polling loop to process network communication.
- Returns: 0 if success
Other value < 0, if error
So this is an errno value from errno.h ?
+*/ +int ulwip_dhcp(void); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 6d2c00605b..59323fb325 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dhcp/lwip-dhcp.c b/net/lwip/apps/dhcp/lwip-dhcp.c new file mode 100644 index 0000000000..cce1e367f9 --- /dev/null +++ b/net/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,62 @@ +// 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 <net/eth.h> +#include <net/ulwip.h>
+static struct dhcp dhcp;
Can we keep the state in the uclass?
+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));
Please check errors throughout your patches.
printf("DHCP client bound to address %s\n", ip4addr_ntoa(&dhcp.offered_ip_addr));
break;
default:
return -1;
}
return 0;
+}
+int ulwip_dhcp(void) +{
int err;
struct netif *netif;
int eth_idx;
eth_idx = eth_get_dev_index();
if (eth_idx < 0) {
log_err("no eth idx\n");
return -1;
That is -EPERM...please use a suitable error, perhaps -ENOENT?
}
netif = netif_get_by_index(eth_idx + 1);
if (!netif)
return -1;
ulwip_set_tmo(ulwip_dhcp_tmo);
if (!netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
dhcp_set_struct(netif, &dhcp);
err = dhcp_start(netif);
if (err)
log_err("dhcp_start error %d\n", err);
Ideally the caller would print the errors. We try to have commands do that, since then it allows silent running for things which want it. It also helps with code size.
return err;
+}
2.30.2
Regards, Simon

On Wed, 23 Aug 2023 at 00:58, Simon Glass sjg@google.com wrote:
Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace dhcp command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 12 +++++++ net/lwip/Makefile | 1 + net/lwip/apps/dhcp/lwip-dhcp.c | 62 ++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 net/lwip/apps/dhcp/lwip-dhcp.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index cda896d062..240ebba354 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -17,3 +17,15 @@ int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int
argc,
Other value < 0, if error
*/ int ulwip_dns(char *name, char *varname);
+/**
- ulwip_dhcp() - create the DHCP request to obtain IP address.
- This function creates the DHCP request to obtain IP address. If DHCP
server
- returns file name, this file will be downloaded with tftp. After
this
- function you need to invoke the polling loop to process network
communication.
- Returns: 0 if success
Other value < 0, if error
So this is an errno value from errno.h ?
No. In this version it's what lwip returned. I can replace it with: return dhcp_start(netif) ? 0 : -EPERM; to not provide on upper layer lwip internal things.
+*/ +int ulwip_dhcp(void); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 6d2c00605b..59323fb325 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -65,4 +65,5 @@ obj-$(CONFIG_NET) += $(LWIPDIR)/netif/ethernet.o obj-$(CONFIG_NET) += port/if.o obj-$(CONFIG_NET) += port/sys-arch.o
+obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o diff --git a/net/lwip/apps/dhcp/lwip-dhcp.c
b/net/lwip/apps/dhcp/lwip-dhcp.c
new file mode 100644 index 0000000000..cce1e367f9 --- /dev/null +++ b/net/lwip/apps/dhcp/lwip-dhcp.c @@ -0,0 +1,62 @@ +// 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 <net/eth.h> +#include <net/ulwip.h>
+static struct dhcp dhcp;
Can we keep the state in the uclass?
I found a good way to avoid this static. If dhcp_set_struct() is not called this struct is malloced, later it can be accessed as code bellow.
+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));
Please check errors throughout your patches. Use the netif_get_client_data() as in code bellow and do not pass
yep.
printf("DHCP client bound to address %s\n",
ip4addr_ntoa(&dhcp.offered_ip_addr));
break;
default:
return -1;
}
return 0;
+}
+int ulwip_dhcp(void) +{
int err;
struct netif *netif;
int eth_idx;
eth_idx = eth_get_dev_index();
if (eth_idx < 0) {
log_err("no eth idx\n");
return -1;
That is -EPERM...please use a suitable error, perhaps -ENOENT?
}
netif = netif_get_by_index(eth_idx + 1);
if (!netif)
return -1;
ulwip_set_tmo(ulwip_dhcp_tmo);
if (!netif_get_client_data(netif,
LWIP_NETIF_CLIENT_DATA_INDEX_DHCP))
dhcp_set_struct(netif, &dhcp);
err = dhcp_start(netif);
if (err)
log_err("dhcp_start error %d\n", err);
Ideally the caller would print the errors. We try to have commands do that, since then it allows silent running for things which want it. It also helps with code size.
ok.
return err;
+}
2.30.2
Regards, Simon

U-Boot recently got support for an alternative network stack using LWIP. Replace tftp command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 14 +++- net/lwip/Makefile | 1 + net/lwip/apps/tftp/Makefile | 16 +++++ net/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 net/lwip/apps/tftp/Makefile create mode 100644 net/lwip/apps/tftp/lwip-tftp.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index 240ebba354..14a65470ee 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -28,4 +28,16 @@ int ulwip_dns(char *name, char *varname); * Returns: 0 if success * Other value < 0, if error */ -int ulwip_dhcp(void); + +/** + * ulwip_tftp() - load file with tftp + * + * Load file with tftp to specific address + * + * @addr: Address to store downloaded file + * @filename: File name on remote tftp server to download + * + * + * Returns: 0 if success, !0 if error + */ +int ulwip_tftp(ulong addr, const char *filename); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 59323fb325..0337d82cf5 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ diff --git a/net/lwip/apps/tftp/Makefile b/net/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..0e50fcad45 --- /dev/null +++ b/net/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@ + +ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip +ccflags-y += -I$(obj) + +$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c: + cp $(srctree)/net/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/tftp.c + cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h + cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h + cp $(srctree)/net/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h + +obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o + diff --git a/net/lwip/apps/tftp/lwip-tftp.c b/net/lwip/apps/tftp/lwip-tftp.c new file mode 100644 index 0000000000..e6e4883de8 --- /dev/null +++ b/net/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 <bootstage.h> + +#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h" +#include <tftp_example.h> + +#include <string.h> + +#include <net/ulwip.h> + +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) +{ + log_info("\ndone\n"); + log_info("Bytes transferred = %ld (0x%lx hex)\n", size, size); + + bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done"); + 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); + daddr += q->len; + size += q->len; + log_info("#"); + } + + return 0; +} + +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)); + + log_info("TFTP error: %d (%s)", err, message); +} + +static const struct tftp_context tftp = { + tftp_open, + tftp_close, + tftp_read, + tftp_write, + tftp_error +}; + +int ulwip_tftp(ulong addr, char *fname) +{ + void *f = (void *)0x1; /* unused fake file 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) { + log_err("error: serverip variable has to be set\n"); + return CMD_RET_FAILURE; + } + + ret = ipaddr_aton(server_ip, &srv); + if (!ret) { + log_err("error: ipaddr_aton\n"); + return CMD_RET_FAILURE; + } + + log_info("TFTP from server %s; our IP address is %s\n", + server_ip, env_get("ipaddr")); + log_info("Filename '%s'.\n", fname); + log_info("Load address: 0x%lx\n", daddr); + log_info("Loading:"); + + bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start"); + + err = tftp_init_client(&tftp); + if (!(err == ERR_OK || err == ERR_USE)) + log_err("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) { + log_err("tftp_get err=%d\n", err); + return CMD_RET_FAILURE; + } + + env_set_hex("fileaddr", addr); + return err; +}

Hi Maxim,
On Tue, 22 Aug 2023 at 03:39, Maxim Uvarov maxim.uvarov@linaro.org wrote:
U-Boot recently got support for an alternative network stack using LWIP. Replace tftp command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
include/net/lwip.h | 14 +++- net/lwip/Makefile | 1 + net/lwip/apps/tftp/Makefile | 16 +++++ net/lwip/apps/tftp/lwip-tftp.c | 124 +++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 net/lwip/apps/tftp/Makefile create mode 100644 net/lwip/apps/tftp/lwip-tftp.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index 240ebba354..14a65470ee 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -28,4 +28,16 @@ int ulwip_dns(char *name, char *varname);
- Returns: 0 if success
Other value < 0, if error
*/ -int ulwip_dhcp(void);
+/**
- ulwip_tftp() - load file with tftp
- Load file with tftp to specific address
- @addr: Address to store downloaded file
- @filename: File name on remote tftp server to download
- Returns: 0 if success, !0 if error
- */
+int ulwip_tftp(ulong addr, const char *filename);
Does this load it, or initiate the load? When will this function return?
Please check your return values too. I believe they should all return errno values, so -ve on error, rather than !0
diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 59323fb325..0337d82cf5 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/
We should separate the CMD configs from the functionality, i.e. I should be able to have CONFIG_TFTPBOOT but not CONFIG_CMD_TFTPBOOT. For standard boot, we need to be able to boot without CONFIG_CMDLINE enabled.
This merging of CMD and functionality CONFIG options has historically been a problem in U-Boot, but it is mostly tidied up now.
diff --git a/net/lwip/apps/tftp/Makefile b/net/lwip/apps/tftp/Makefile new file mode 100644 index 0000000000..0e50fcad45 --- /dev/null +++ b/net/lwip/apps/tftp/Makefile @@ -0,0 +1,16 @@
+ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip +ccflags-y += -I$(obj)
Should we move this to
+$(obj)/tftp.o: $(obj)/tftp.c +.PHONY: $(obj)/tftp.c +$(obj)/tftp.c:
cp $(srctree)/net/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/tftp.c
cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_client.h $(obj)/tftp_client.h
cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/tftp_common.h $(obj)/tftp_common.h
cp $(srctree)/net/lwip/lwip-external/contrib/examples/tftp/tftp_example.h $(obj)/tftp_example.h
What is going on here?
+obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o +obj-$(CONFIG_CMD_TFTPBOOT) += lwip-tftp.o
diff --git a/net/lwip/apps/tftp/lwip-tftp.c b/net/lwip/apps/tftp/lwip-tftp.c new file mode 100644 index 0000000000..e6e4883de8 --- /dev/null +++ b/net/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 <bootstage.h>
+#include "lwip/apps/tftp_client.h" +#include "lwip/apps/tftp_server.h"
Can we add a -I to the top-level Makefile so we can use #include <ttfp_client.h> ?
+#include <tftp_example.h>
+#include <string.h>
Should go up the top
+#include <net/ulwip.h>
+static ulong daddr; +static ulong size;
Again please see if you can keep your state together rather than sprinkling it around static vars.
+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) +{
log_info("\ndone\n");
log_info("Bytes transferred = %ld (0x%lx hex)\n", size, size);
bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
env_set_ulong("filesize", size);
Error check...
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);
daddr += q->len;
size += q->len;
log_info("#");
}
return 0;
+}
+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));
what is MEMCPY() ?
log_info("TFTP error: %d (%s)", err, message);
+}
+static const struct tftp_context tftp = {
tftp_open,
tftp_close,
tftp_read,
tftp_write,
tftp_error
+};
+int ulwip_tftp(ulong addr, char *fname) +{
void *f = (void *)0x1; /* unused fake file 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) {
log_err("error: serverip variable has to be set\n");
return CMD_RET_FAILURE;
}
ret = ipaddr_aton(server_ip, &srv);
if (!ret) {
log_err("error: ipaddr_aton\n");
return CMD_RET_FAILURE;
}
log_info("TFTP from server %s; our IP address is %s\n",
server_ip, env_get("ipaddr"));
log_info("Filename '%s'.\n", fname);
log_info("Load address: 0x%lx\n", daddr);
log_info("Loading:");
bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
err = tftp_init_client(&tftp);
if (!(err == ERR_OK || err == ERR_USE))
log_err("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) {
log_err("tftp_get err=%d\n", err);
return CMD_RET_FAILURE;
}
env_set_hex("fileaddr", addr);
return err;
+}
2.30.2
I'm going to stop at this patch...
Regards, Simon

U-Boot recently got support for an alternative network stack using LWIP. Replace wget command with the LWIP variant while keeping the output and error messages identical.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 15 +++++ net/lwip/Makefile | 1 + net/lwip/apps/http/Makefile | 13 ++++ net/lwip/apps/http/lwip-wget.c | 111 +++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 net/lwip/apps/http/Makefile create mode 100644 net/lwip/apps/http/lwip-wget.c
diff --git a/include/net/lwip.h b/include/net/lwip.h index 14a65470ee..724f68b148 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -28,6 +28,7 @@ int ulwip_dns(char *name, char *varname); * Returns: 0 if success * Other value < 0, if error */ +int ulwip_dhcp(void);
/** * ulwip_tftp() - load file with tftp @@ -41,3 +42,17 @@ int ulwip_dns(char *name, char *varname); * Returns: 0 if success, !0 if error */ int ulwip_tftp(ulong addr, const char *filename); + +/** + * ulwip_wget() - creates the HTTP request to download file + * + * This function creates the HTTP request to download file from url to the address + * specified in parameters. After this function you need to invoke the polling + * loop to process network communication. + * + * + * @addr: start address to download result + * @url: url in format http://host/url + * Returns: 0 for success, !0 if error +*/ +int ulwip_wget(ulong addr, char *url); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 0337d82cf5..4c6df94807 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_NET) += port/sys-arch.o obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ +obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/net/lwip/apps/http/Makefile b/net/lwip/apps/http/Makefile new file mode 100644 index 0000000000..3e92b0ef1b --- /dev/null +++ b/net/lwip/apps/http/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip +ccflags-y += -I$(obj) + +$(obj)/http_clinet.o: $(obj)/http_client.c +.PHONY: $(obj)/http_client.c +$(obj)/http_client.c: + cp $(srctree)/net/lwip/lwip-external/src/apps/http/http_client.c $(obj)/http_client.c + cp $(srctree)/net/lwip/lwip-external/src/include/lwip/apps/http_client.h $(obj)/http_client.h + +obj-$(CONFIG_CMD_WGET) += http_client.o +obj-$(CONFIG_CMD_WGET) += lwip-wget.o + diff --git a/net/lwip/apps/http/lwip-wget.c b/net/lwip/apps/http/lwip-wget.c new file mode 100644 index 0000000000..a9bb29e156 --- /dev/null +++ b/net/lwip/apps/http/lwip-wget.c @@ -0,0 +1,111 @@ +// 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 <vsprintf.h> + +#include "http_client.h" +#include <net/ulwip.h> + +static ulong daddr; +static httpc_connection_t settings; + +#define SERVER_NAME_SIZE 200 +#define HTTP_PORT_DEFAULT 80 + +static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf, + err_t unused_err) +{ + struct pbuf *buf; + + if (!pbuf) + return ERR_BUF; + + for (buf = pbuf; buf != NULL; buf = buf->next) { + memcpy((void *)daddr, buf->payload, buf->len); + log_debug("downloaded chunk size %d, to addr 0x%lx\n", + buf->len, daddr); + daddr += buf->len; + } + + altcp_recved(pcb, pbuf->tot_len); + pbuf_free(pbuf); + 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) { + log_info("\n%d bytes successfully downloaded.\n", rx_content_len); + env_set_ulong("filesize", rx_content_len); + ulwip_exit(0); + } else { + log_err("\nhttp eroror: %d\n", httpc_result); + ulwip_exit(-1); + } +} + +/* http://hostname:port/url */ +static int parse_url(char *url, char *host, u16 *port) +{ + char *p, *pp; + + p = strstr(url, "http://"); + if (!p) { + printf("err: no http://!%5Cn"); + return -1; + } + + p += strlen("http://"); + + /* parse hostname */ + pp = strchr(p, '/'); + if (!pp) { + printf("wrong url\n"); + return -2; + } + + if (pp - p >= SERVER_NAME_SIZE) + return -3; + + memcpy(host, p, pp - p); + host[pp - p + 1] = '\0'; + *port = HTTP_PORT_DEFAULT; + + return 0; +} + +int ulwip_wget(ulong addr, char *url) +{ + err_t err; + u16 port; + char server_name[SERVER_NAME_SIZE]; + httpc_state_t *connection; + + daddr = addr; + + err = parse_url(url, server_name, &port); + if (err) { + log_err("error parse_url\n"); + return -1; + } + + log_info("downloading %s to addr 0x%lx\n", url, addr); + memset(&settings, 0, sizeof(settings)); + settings.result_fn = httpc_result; + err = httpc_get_file_dns(server_name, port, url, &settings, + httpc_recv, NULL, &connection); + if (err != ERR_OK) { + log_err("httpc_init_connection failed\n"); + return err; + } + + env_set_hex("fileaddr", addr); + return 0; +}

U-Boot recently got support for an alternative network stack using LWIP. Replace ping command with the LWIP variant while keeping the output and error messages identical. ping uses lwIP contrib/apps/ping/ping.c code.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 15 ++++++++++++++ net/lwip/Makefile | 1 + net/lwip/apps/ping/Makefile | 11 ++++++++++ net/lwip/apps/ping/lwip_ping.c | 37 ++++++++++++++++++++++++++++++++++ net/lwip/apps/ping/lwip_ping.h | 15 ++++++++++++++ net/lwip/apps/ping/ping.h | 19 +++++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 net/lwip/apps/ping/Makefile create mode 100644 net/lwip/apps/ping/lwip_ping.c create mode 100644 net/lwip/apps/ping/lwip_ping.h create mode 100644 net/lwip/apps/ping/ping.h
diff --git a/include/net/lwip.h b/include/net/lwip.h index 724f68b148..aa82d71715 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -2,6 +2,8 @@
int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]);
/** * ulwip_dns() - creates the DNS request to resolve a domain host name @@ -56,3 +58,16 @@ int ulwip_tftp(ulong addr, const char *filename); * Returns: 0 for success, !0 if error */ int ulwip_wget(ulong addr, char *url); + +/** + * ulwip_ping - create the ping request + * + * This function creates the ping for address provided in parameters. + * After this function you need to invoke the polling + * loop to process network communication. + * + * + * @ping_addr: IP address to ping + * Returns: 0 for success, !0 if error +*/ +int ulwip_ping(char *ping_addr); diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 4c6df94807..8b3e843426 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -67,5 +67,6 @@ obj-$(CONFIG_NET) += port/sys-arch.o
obj-$(CONFIG_CMD_DHCP) += apps/dhcp/lwip-dhcp.o obj-$(CONFIG_CMD_DNS) += apps/dns/lwip-dns.o +obj-$(CONFIG_CMD_PING) += apps/ping/ obj-$(CONFIG_CMD_TFTPBOOT) += apps/tftp/ obj-$(CONFIG_CMD_WGET) += apps/http/ diff --git a/net/lwip/apps/ping/Makefile b/net/lwip/apps/ping/Makefile new file mode 100644 index 0000000000..dc63feb7b5 --- /dev/null +++ b/net/lwip/apps/ping/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -I$(srctree)/net/lwip/port/include +ccflags-y += -I$(srctree)/net/lwip/lwip-external/src/include -I$(srctree)/net/lwip +ccflags-y += -I$(obj) + +.PHONY: $(obj)/ping.c +$(obj)/ping.o: $(obj)/ping.c +$(obj)/ping.c: + cp $(srctree)/net/lwip/lwip-external/contrib/apps/ping/ping.c $(obj)/ping.c + +obj-$(CONFIG_CMD_PING) += ping.o +obj-$(CONFIG_CMD_PING) += lwip_ping.o diff --git a/net/lwip/apps/ping/lwip_ping.c b/net/lwip/apps/ping/lwip_ping.c new file mode 100644 index 0000000000..a2fe58f5e9 --- /dev/null +++ b/net/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_ping.h" + +static ip_addr_t ip_target; + +static int ulwip_ping_tmo(void) +{ + + log_err("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target)); + return 1; +} + +int ulwip_ping(char *ping_addr) +{ + int err; + + err = ipaddr_aton(ping_addr, &ip_target); + if (!err) { + log_err("Invalid ip address\n"); + return -1; + } + + ulwip_set_tmo(ulwip_ping_tmo); + + ping_init(&ip_target); + ping_send_now(); + + return 0; +} diff --git a/net/lwip/apps/ping/lwip_ping.h b/net/lwip/apps/ping/lwip_ping.h new file mode 100644 index 0000000000..0374f07d9e --- /dev/null +++ b/net/lwip/apps/ping/lwip_ping.h @@ -0,0 +1,15 @@ +/* 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> + +void ping_raw_init(void); +void ping_send_now(void); + +#endif /* LWIP_PING_H */ diff --git a/net/lwip/apps/ping/ping.h b/net/lwip/apps/ping/ping.h new file mode 100644 index 0000000000..006a18c658 --- /dev/null +++ b/net/lwip/apps/ping/ping.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <net/ulwip.h> +#include "lwip/ip_addr.h" + +#define LWIP_DEBUG 1 /* ping_time is under ifdef*/ +#define PING_RESULT(cond) { \ + if (cond == 1) { \ + printf("host %s a alive\n", ipaddr_ntoa(addr)); \ + printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \ + ulwip_exit(0); \ + } else { \ + printf("ping failed; host %s in not alive\n",\ + ipaddr_ntoa(addr)); \ + ulwip_exit(-1); \ + } \ + } while (0); + +void ping_init(const ip_addr_t *ping_addr);

lwip configuration can be tuned with header file.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- net/lwip/lwipopts.h | 197 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 net/lwip/lwipopts.h
diff --git a/net/lwip/lwipopts.h b/net/lwip/lwipopts.h new file mode 100644 index 0000000000..dec7638cd4 --- /dev/null +++ b/net/lwip/lwipopts.h @@ -0,0 +1,197 @@ +/* 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_ON +#define NETIF_DEBUG LWIP_DBG_ON +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_ON +#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_ON +#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_ON +#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 1 + +#define LWIP_IPV6 0 + +#define MEM_ALIGNMENT 1 +#define MEM_SIZE 1600 + +#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 ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 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 14 +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_HLEN) + +#define LWIP_HAVE_LOOPIF 0 + +#define LWIP_NETCONN 0 +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1 + +#define LWIP_SOCKET 0 +#define SO_REUSE 0 + +#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 */

Implement port of lwIP stack to the U-Boot. lwIP is well known full IP stack which provides wide functionality, various examples, API closer to linux userland. Rich debug printing and possibility to run lwIP apps under linux make it easier to develop and debug apps. U-Boot implementation keeps the original file structure widely used for lwIP ports. (i.e. port/if.c port/sys-arch.c). That should allow us to easy port apps to or from U-Boot. Multiply ethernet devices are supported and "ethact" env variable chooses the active device. Having a rich IP stack inside U-Boot will allow us to have such applications as http or https clients.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- net/eth-uclass.c | 8 + net/lwip/port/if.c | 343 ++++++++++++++++++++++++++ net/lwip/port/include/arch/cc.h | 38 +++ net/lwip/port/include/arch/sys_arch.h | 10 + net/lwip/port/include/limits.h | 0 net/lwip/port/sys-arch.c | 13 + 6 files changed, 412 insertions(+) create mode 100644 net/lwip/port/if.c create mode 100644 net/lwip/port/include/arch/cc.h create mode 100644 net/lwip/port/include/arch/sys_arch.h create mode 100644 net/lwip/port/include/limits.h create mode 100644 net/lwip/port/sys-arch.c
diff --git a/net/eth-uclass.c b/net/eth-uclass.c index c393600fab..6625f6d8a5 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR; struct eth_device_priv { enum eth_state_t state; bool running; + ulwip ulwip; };
/** @@ -347,6 +348,13 @@ int eth_init(void) return ret; }
+struct ulwip *eth_lwip_priv(struct udevice *current) +{ + struct eth_device_priv *priv = dev_get_uclass_priv(current); + + return &priv->ulwip; +} + void eth_halt(void) { struct udevice *current; diff --git a/net/lwip/port/if.c b/net/lwip/port/if.c new file mode 100644 index 0000000000..17842a9bc3 --- /dev/null +++ b/net/lwip/port/if.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include <command.h> +#include <net/eth.h> +#include <dm/device.h> +#include <dm/uclass-id.h> +#include <dm/uclass.h> +#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/ethip6.h" + +#include "lwip/ip.h" + +/* + * MAC_ADDR_STRLEN: length of mac address string + */ +#define MAC_ADDR_STRLEN 17 + +int ulwip_enabled(void) +{ + struct udevice *udev; + struct ulwip *ulwip; + + udev = eth_get_dev(); + if (!udev) + return 0; + + ulwip = eth_lwip_priv(udev); + return ulwip->init_done; +} + +int ulwip_in_loop(void) +{ + struct udevice *udev; + struct ulwip *ulwip; + + udev = eth_get_dev(); + if (!udev) + return 0; + + ulwip = eth_lwip_priv(udev); + return ulwip->loop; +} + +void ulwip_loop_set(int loop) +{ + struct udevice *udev; + struct ulwip *ulwip; + + udev = eth_get_dev(); + if (!udev) + return; + + ulwip = eth_lwip_priv(udev); + ulwip->loop = loop; +} + +void ulwip_exit(int err) +{ + struct udevice *udev; + struct ulwip *ulwip; + + udev = eth_get_dev(); + if (!udev) + return; + + ulwip = eth_lwip_priv(udev); + ulwip->loop = 0; + ulwip->err = err; +} + +int ulwip_app_get_err(void) +{ + struct udevice *udev; + struct ulwip *ulwip; + + udev = eth_get_dev(); + if (!udev) + return 0; + + ulwip = eth_lwip_priv(udev); + return ulwip->err; +} + +typedef struct { +} ulwip_if_t; + +static struct pbuf *low_level_input(void) +{ + struct pbuf *p, *q; + u16_t len = net_rx_packet_len; + uchar *data = net_rx_packet; + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (!p) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + return NULL; + } + + /* 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; + } + + LINK_STATS_INC(link.recv); + + return p; +} + +void ulwip_poll(void) +{ + struct pbuf *p; + int err; + struct netif *netif; + int eth_idx; + + eth_idx = eth_get_dev_index(); + if (eth_idx < 0) { + log_err("no eth idx\n"); + return; + } + + netif = netif_get_by_index(eth_idx + 1); + if (!netif) { + log_err("!netif\n"); + return; + } + + p = low_level_input(); + if (!p) { + log_err("no mem\n"); + return; + } + + /* ethernet_input always returns ERR_OK */ + err = ethernet_input(p, netif); + if (err) + log_err("ip4_input err %d\n", err); + + return; +} + +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(); + + /* 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; + + /* switch dev to active state */ + eth_init_state_only(); + + err = eth_send(p->payload, p->len); + if (err) { + log_err("eth_send error %d\n", err); + return ERR_ABRT; + } + return ERR_OK; +} + +err_t ulwip_if_init(struct netif *netif) +{ + ulwip_if_t *uif; + struct ulwip *ulwip; + + uif = malloc(sizeof(ulwip_if_t)); + if (!uif) { + log_err("uif: out of memory\n"); + return ERR_MEM; + } + netif->state = uif; + +#if defined(CONFIG_LWIP_LIB_DEBUG) + log_info(" 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]); + log_info(" NAME: %s\n", netif->name); +#endif +#if LWIP_IPV4 + netif->output = etharp_output; +#endif +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif + + netif->linkoutput = low_level_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + ulwip = eth_lwip_priv(eth_get_dev()); + ulwip->init_done = 1; + + return ERR_OK; +} + +int ulwip_init(void) +{ + ip4_addr_t ipaddr, netmask, gw; + struct netif *unetif; + struct ulwip *ulwip; + struct udevice *udev; + int ret; + unsigned char env_enetaddr[ARP_HLEN]; + const struct udevice *dev; + struct uclass *uc; + + ret = eth_init(); + if (ret) { + log_err("eth_init error %d\n", ret); + return ERR_IF; + } + + udev = eth_get_dev(); + if (!udev) { + log_err("no active eth device\n"); + return ERR_IF; + } + + eth_set_current(); + + ulwip = eth_lwip_priv(udev); + if (ulwip->init_done) { + log_info("init already done for %s\n", udev->name); + return CMD_RET_SUCCESS; + } + + uclass_id_foreach_dev(UCLASS_ETH, dev, uc) { + char ipstr[IP4ADDR_STRLEN_MAX]; + char maskstr[IP4ADDR_STRLEN_MAX]; + char gwstr[IP4ADDR_STRLEN_MAX]; + char hwstr[MAC_ADDR_STRLEN]; + + eth_env_get_enetaddr_by_index("eth", dev_seq(dev), env_enetaddr); + log_info("eth%d: %s %pM %s\n", dev_seq(dev), dev->name, env_enetaddr, + udev == dev ? "active" : ""); + + unetif = malloc(sizeof(struct netif)); + if (!unetif) + return ERR_MEM; + memset(unetif, 0, sizeof(struct netif)); + + ip4_addr_set_zero(&gw); + ip4_addr_set_zero(&ipaddr); + ip4_addr_set_zero(&netmask); + + if (dev_seq(dev) == 0) { + snprintf(ipstr, IP4ADDR_STRLEN_MAX, "ipaddr"); + snprintf(maskstr, IP4ADDR_STRLEN_MAX, "netmask"); + snprintf(gwstr, IP4ADDR_STRLEN_MAX, "gw"); + } else { + snprintf(ipstr, IP4ADDR_STRLEN_MAX, "ipaddr%d", dev_seq(dev)); + snprintf(maskstr, IP4ADDR_STRLEN_MAX, "netmask%d", dev_seq(dev)); + snprintf(gwstr, IP4ADDR_STRLEN_MAX, "gw%d", dev_seq(dev)); + } + snprintf(hwstr, MAC_ADDR_STRLEN, "%pM", env_enetaddr); + snprintf(unetif->name, 2, "%d", dev_seq(dev)); + + string_to_enetaddr(hwstr, unetif->hwaddr); + unetif->hwaddr_len = ETHARP_HWADDR_LEN; + + ipaddr_aton(env_get(ipstr), &ipaddr); + ipaddr_aton(env_get(maskstr), &netmask); + + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + log_info("Starting lwIP\n "); + log_info(" netdev: %s\n", dev->name); + log_info(" IP: %s\n", ip4addr_ntoa(&ipaddr)); + log_info(" GW: %s\n", ip4addr_ntoa(&gw)); + log_info(" mask: %s\n", ip4addr_ntoa(&netmask)); + } + +#if LWIP_IPV6 +#define MAC_FROM_48_BIT 1 + netif_create_ip6_linklocal_address(unetif, MAC_FROM_48_BIT); + log_info(" IPv6: %s\n", ip6addr_ntoa(netif_ip6_addr(unetif, 0))); +#endif /* LWIP_IPV6 */ + + if (!netif_add(unetif, &ipaddr, &netmask, &gw, + unetif, ulwip_if_init, ethernetif_input)) { + log_err("err: netif_add failed!\n"); + free(unetif); + return ERR_IF; + } + + netif_set_up(unetif); + netif_set_link_up(unetif); + } + + if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) { + log_info("Initialized LWIP stack\n"); + } + return CMD_RET_SUCCESS; +} + +/* placeholder, not used now */ +void ulwip_destroy(void) +{ +} diff --git a/net/lwip/port/include/arch/cc.h b/net/lwip/port/include/arch/cc.h new file mode 100644 index 0000000000..23fd51c308 --- /dev/null +++ b/net/lwip/port/include/arch/cc.h @@ -0,0 +1,38 @@ +/* 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> +#include <vsprintf.h> +#include <rand.h> + +#define LWIP_ERRNO_INCLUDE <errno.h> + +#define LWIP_ERRNO_STDINCLUDE 1 +#define LWIP_NO_UNISTD_H 1 +#define LWIP_TIMEVAL_PRIVATE 1 + +#define LWIP_RAND() ((u32_t)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) + +#define atoi(str) (int)dectoul(str, NULL) + +#define LWIP_ERR_T int + +#endif /* LWIP_ARCH_CC_H */ diff --git a/net/lwip/port/include/arch/sys_arch.h b/net/lwip/port/include/arch/sys_arch.h new file mode 100644 index 0000000000..87a3fb66d1 --- /dev/null +++ b/net/lwip/port/include/arch/sys_arch.h @@ -0,0 +1,10 @@ +/* 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 + +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/net/lwip/port/include/limits.h b/net/lwip/port/include/limits.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/net/lwip/port/sys-arch.c b/net/lwip/port/sys-arch.c new file mode 100644 index 0000000000..68476d16e8 --- /dev/null +++ b/net/lwip/port/sys-arch.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * (C) Copyright 2023 Linaro Ltd. maxim.uvarov@linaro.org + */ + +#include <common.h> +#include "lwip/opt.h" + +u32_t sys_now(void) +{ + return get_timer(0); +}

ignore lwIP library code and reused files from the lwIP.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- net/lwip/.gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 net/lwip/.gitignore
diff --git a/net/lwip/.gitignore b/net/lwip/.gitignore new file mode 100644 index 0000000000..7b5dacce90 --- /dev/null +++ b/net/lwip/.gitignore @@ -0,0 +1,8 @@ +lwip-external +apps/ping/ping.c +apps/http/http_client.c +apps/http/http_client.h +apps/tftp/tftp.c +apps/tftp/tftp_client.h +apps/tftp/tftp_common.h +apps/tftp/tftp_example.h

Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- cmd/Makefile | 1 + cmd/net-lwip.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 cmd/net-lwip.c
diff --git a/cmd/Makefile b/cmd/Makefile index 9bebf321c3..6ab6b16aab 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -128,6 +128,7 @@ endif obj-$(CONFIG_CMD_MUX) += mux.o obj-$(CONFIG_CMD_NAND) += nand.o obj-$(CONFIG_CMD_NET) += net.o +obj-$(CONFIG_CMD_NET) += net-lwip.o obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o obj-$(CONFIG_CMD_ONENAND) += onenand.o obj-$(CONFIG_CMD_OSD) += osd.o diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c new file mode 100644 index 0000000000..46fe4f091f --- /dev/null +++ b/cmd/net-lwip.c @@ -0,0 +1,306 @@ +// 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 "net/lwip.h" +#include "net/ulwip.h" + +static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (!ulwip_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); +} + +int ulwip_loop(void) +{ + int ret = CMD_RET_FAILURE; + + ulwip_loop_set(1); + if (!net_loop(LWIP)) + ret = CMD_RET_SUCCESS; + ulwip_loop_set(0); + return ret; +} + +#if defined(CONFIG_CMD_PING) +int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + if (argc < 2) { + printf("argc = %d, error\n", argc); + return CMD_RET_USAGE; + } + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + printf("Using %s device\n", eth_get_name()); + printf("pinging addr: %s\n", argv[1]); + + net_set_timeout_handler(1000UL, ulwip_timeout_handler); + + if (ulwip_ping(argv[1])) { + printf("ping init fail\n"); + return CMD_RET_FAILURE; + } + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_PING */ + +#if defined(CONFIG_CMD_WGET) +int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *url; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + url = argv[1]; + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + ret = ulwip_wget(image_load_addr, url); + if (ret) { + log_err("lwip_wget err %d\n", ret); + return CMD_RET_FAILURE; + } + + + return ulwip_loop(); +} +#endif + +#if defined(CONFIG_CMD_TFTPBOOT) +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; + } + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + ret = ulwip_tftp(image_load_addr, filename); + if (ret) + return ret; + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_TFTPBOOT */ + +#if defined(CONFIG_CMD_DHCP) +int do_lwip_dhcp(void) +{ + int ret; + char *filename; + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + 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) { + log_notice("no bootfile\n"); + return CMD_RET_SUCCESS; + } + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + net_set_timeout_handler(20000UL, ulwip_timeout_handler); + ulwip_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 */ + +#if defined(CONFIG_CMD_DNS) +int do_lwip_dns(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + char *name; + char *varname; + int LWIP_ERR_INPROGRESS = -5; /* lwip/err.h */ + + if (argc == 1) + return CMD_RET_USAGE; + + name = argv[1]; + + if (argc == 3) + varname = argv[2]; + else + varname = NULL; + + ret = ulwip_init(); + if (ret) { + log_err("ulwip_init err %d\n", ret); + return CMD_RET_FAILURE; + } + + ret = ulwip_dns(name, varname); + if (ret == 0) + return CMD_RET_SUCCESS; + if (ret != LWIP_ERR_INPROGRESS) + return CMD_RET_FAILURE; + + net_set_timeout_handler(1000UL, ulwip_timeout_handler); + + return ulwip_loop(); +} +#endif /* CONFIG_CMD_DNS */ + +static struct cmd_tbl cmds[] = { + U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, + "initialize lwip stack", ""), +#if defined(CONFIG_CMD_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 +#if defined(CONFIG_CMD_DNS) + U_BOOT_CMD_MKENT(dns, 3, 0, do_lwip_dns, + "lookup dns name [and store address at variable]", + ""), +#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", + "init - init LWIP\n" + "ping addr - pingAddress\n" + "wget http://IPadress/url/%5Cn" + "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n" + "dhcp - boot image via network using DHCP/TFTP protocol\n" + );

Replace original commands: ping, tftp, dhcp and wget.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- boot/bootmeth_efi.c | 18 +++++++--- boot/bootmeth_pxe.c | 21 ++++++----- cmd/net.c | 86 +++++---------------------------------------- cmd/pxe.c | 19 +++++----- include/net.h | 8 +++-- include/net/ulwip.h | 76 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 103 deletions(-) create mode 100644 include/net/ulwip.h
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index ae936c8daa..52399d627c 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -20,6 +20,8 @@ #include <mapmem.h> #include <mmc.h> #include <net.h> +#include <net/lwip.h> +#include <net/ulwip.h> #include <pxe_utils.h> #include <linux/sizes.h>
@@ -319,9 +321,7 @@ static int distro_efi_try_bootflow_files(struct udevice *dev,
static int distro_efi_read_bootflow_net(struct bootflow *bflow) { - char file_addr[17], fname[256]; - char *tftp_argv[] = {"tftp", file_addr, fname, NULL}; - struct cmd_tbl cmdtp = {}; /* dummy */ + char fname[256]; const char *addr_str, *fdt_addr_str; int ret, arch, size; ulong addr, fdt_addr; @@ -368,7 +368,6 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!fdt_addr_str) return log_msg_ret("fdt", -EINVAL); fdt_addr = hextoul(fdt_addr_str, NULL); - sprintf(file_addr, "%lx", fdt_addr);
/* We only allow the first prefix with PXE */ ret = distro_efi_get_fdt_name(fname, sizeof(fname), 0); @@ -379,7 +378,16 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) if (!bflow->fdt_fname) return log_msg_ret("fil", -ENOMEM);
- if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) { + ret = ulwip_init(); + if (ret) + return log_msg_ret("ulwip_init", ret); + + ret = ulwip_tftp(fdt_addr, fname); + if (ret) + return log_msg_ret("ulwip_tftp", ret); + + ret = ulwip_loop(); + if (!ret) { bflow->fdt_size = env_get_hex("filesize", 0); bflow->fdt_addr = fdt_addr; } else { diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index 8d489a11aa..fc6aabaa18 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -21,6 +21,8 @@ #include <mapmem.h> #include <mmc.h> #include <net.h> +#include <net/ulwip.h> +#include <net/lwip.h> #include <pxe_utils.h>
static int extlinux_pxe_getfile(struct pxe_context *ctx, const char *file_path, @@ -116,18 +118,21 @@ static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow, const char *file_path, ulong addr, ulong *sizep) { - char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; - struct pxe_context *ctx = dev_get_priv(dev); - char file_addr[17]; ulong size; int ret;
- sprintf(file_addr, "%lx", addr); - tftp_argv[1] = file_addr; - tftp_argv[2] = (void *)file_path; + ret = ulwip_init(); + if (ret) + return log_msg_ret("ulwip_init", ret); + + ret = ulwip_tftp(addr, file_path); + if (ret) + return log_msg_ret("ulwip_tftp", ret); + + ret = ulwip_loop(); + if (ret) + return log_msg_ret("ulwip_loop", ret);
- if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) - return -ENOENT; ret = pxe_get_file_size(&size); if (ret) return log_msg_ret("tftp", ret); diff --git a/cmd/net.c b/cmd/net.c index d407d8320a..dc5a114309 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -22,6 +22,7 @@ #include <net/udp.h> #include <net/sntp.h> #include <net/ncsi.h> +#include <net/lwip.h>
static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
@@ -40,19 +41,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", @@ -60,7 +51,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]" ); @@ -139,7 +130,7 @@ U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6, 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( @@ -196,13 +187,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]" ); @@ -456,28 +445,8 @@ 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; -} - U_BOOT_CMD( - ping, 2, 1, do_ping, + ping, 2, 1, do_lwip_ping, "send ICMP ECHO_REQUEST to network host", "pingAddress" ); @@ -601,45 +570,8 @@ U_BOOT_CMD( #endif
#if defined(CONFIG_CMD_DNS) -int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - if (argc == 1) - return CMD_RET_USAGE; - - /* - * We should check for a valid hostname: - * - Each label must be between 1 and 63 characters long - * - the entire hostname has a maximum of 255 characters - * - only the ASCII letters 'a' through 'z' (case-insensitive), - * the digits '0' through '9', and the hyphen - * - cannot begin or end with a hyphen - * - no other symbols, punctuation characters, or blank spaces are - * permitted - * but hey - this is a minimalist implmentation, so only check length - * and let the name server deal with things. - */ - if (strlen(argv[1]) >= 255) { - printf("dns error: hostname too long\n"); - return CMD_RET_FAILURE; - } - - net_dns_resolve = argv[1]; - - if (argc == 3) - net_dns_env_var = argv[2]; - else - net_dns_env_var = NULL; - - if (net_loop(DNS) < 0) { - printf("dns lookup of %s failed, check setup\n", argv[1]); - return CMD_RET_FAILURE; - } - - return CMD_RET_SUCCESS; -} - U_BOOT_CMD( - dns, 3, 1, do_dns, + dns, 3, 1, do_lwip_dns, "lookup the IP of a hostname", "hostname [envvar]" ); diff --git a/cmd/pxe.c b/cmd/pxe.c index 677142520b..d44df428d2 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -8,6 +8,7 @@ #include <command.h> #include <fs.h> #include <net.h> +#include <net/lwip.h> #include <net6.h> #include <malloc.h>
@@ -29,21 +30,19 @@ const char *pxe_default_paths[] = { static int do_get_tftp(struct pxe_context *ctx, const char *file_path, char *file_addr, ulong *sizep) { - char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; + ulong addr; + char *end; int ret; - int num_args;
- tftp_argv[1] = file_addr; - tftp_argv[2] = (void *)file_path; + addr = hextoul(file_addr, &end); + if (ctx->use_ipv6) { - tftp_argv[3] = USE_IP6_CMD_PARAM; - num_args = 4; - } else { - num_args = 3; + /* @todo: check and fix me, here */ }
- if (do_tftpb(ctx->cmdtp, 0, num_args, tftp_argv)) - return -ENOENT; + ret = ulwip_tftp(addr, file_path); + if (ret) + return log_msg_ret("tftp", ret);
ret = pxe_get_file_size(sizep); if (ret) diff --git a/include/net.h b/include/net.h index e254df7d7f..de7baeb121 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[]);
/** * dhcp_run() - Run DHCP on the current ethernet device @@ -514,7 +516,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP, - WOL, UDP, NCSI, WGET, RS + WOL, UDP, NCSI, WGET, RS, LWIP };
extern char net_boot_file_name[1024];/* Boot File name */ diff --git a/include/net/ulwip.h b/include/net/ulwip.h new file mode 100644 index 0000000000..e2a54bdce5 --- /dev/null +++ b/include/net/ulwip.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/** + * ulwip_init() - initialize lwIP network stack + * + * @return 0 if success, !0 if error + */ +int ulwip_init(void); + +/** + * ulwip_enabled() - check if lwIP network stack was initialized + * + * @return 1 lwip initialized, 0 if not yet initialized + */ +int ulwip_enabled(void); + +/** + * ulwip_in_loop() - lwIP controls packet net loop + * + * @return 1 lwIP owns packet loop, 0 lwip does not own packet loop + */ +int ulwip_in_loop(void); + +/** + * ulwip_loop_set() - make loop to be used by lwIP + * + * Function is used to make lwIP control network pool. + * + * @loop: 1. Rx packets go to lwIP 2. Rx packets go to the original stack. + */ +void ulwip_loop_set(int loop); + +/** + * ulwip_exit() - exit from lwIP with a return code + * + * Exit from lwIP application back to the U-Boot with specific error code. + * + * @err: Error code to return + */ +void ulwip_exit(int err); + +/** + * ulwip_poll() - polling function to feed lwIP with ethernet packet + * + * Function takes network packet and passes it to lwIP network stack + */ +void ulwip_poll(void); + +/** + * ulwip_app_get_err() - return error code from lwIP application + * + * @return error code + */ +int ulwip_app_get_err(void); + +/** + * ulwip_set_tmo() - set application timeout function to trap lwIP application + * + * lwIP cmd compatibility code does initialization for application then gives + * control to the packet loop. To keep ability for control return code and + * application state after application work special handler can be registered + * with this call. + * + * @tmo: Function to call if timeout happen. + */ +void ulwip_set_tmo(int (*tmo)(void)); + +/** + * ulwip_loop() - enter to packet polling loop + * + * When lwIP application did it's initialization stage, then it needs to enter + * to packet polling loop to grab rx packets. + * + * Returns: 0 if success, !0 if error + */ +int ulwip_loop(void);

current net.h has ethernet and protocol definitions. Protocol definitions overlap with lwIP protocol definitions and net.h can not be included from lwIP code. Splitting on logical blocks makes that work.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net.h | 189 +-------------------------------------------- include/net/arp.h | 7 ++ include/net/eth.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 185 deletions(-) create mode 100644 include/net/arp.h create mode 100644 include/net/eth.h
diff --git a/include/net.h b/include/net.h index de7baeb121..780c51fab9 100644 --- a/include/net.h +++ b/include/net.h @@ -20,6 +20,7 @@ #include <time.h> #include <linux/if_ether.h> #include <rand.h> +#include <net/arp.h>
struct bd_info; struct cmd_tbl; @@ -30,25 +31,6 @@ struct udevice; #define DEBUG_NET_PKT 0 /* Packets on info on the network at large */ #define DEBUG_INT_STATE 0 /* Internal network state changes */
-/* - * The number of receive packet buffers, and the required packet buffer - * alignment in memory. - * - */ -#define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER -#define PKTALIGN ARCH_DMA_MINALIGN - -/* Number of packets processed together */ -#define ETH_PACKETS_BATCH_RECV 32 - -/* ARP hardware address length */ -#define ARP_HLEN 6 -/* - * The size of a MAC address in string form, each digit requires two chars - * and five separator characters to form '00:00:00:00:00:00'. - */ -#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1) - /* IPv4 addresses are always 32 bits in size */ struct in_addr { __be32 s_addr; @@ -112,150 +94,7 @@ typedef void rxhand_icmp_f(unsigned type, unsigned code, unsigned dport, */ typedef void thand_f(void);
-enum eth_state_t { - ETH_STATE_INIT, - ETH_STATE_PASSIVE, - ETH_STATE_ACTIVE -}; - -/** - * struct eth_pdata - Platform data for Ethernet MAC controllers - * - * @iobase: The base address of the hardware registers - * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env - * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_... - * @max_speed: Maximum speed of Ethernet connection supported by MAC - * @priv_pdata: device specific plat - */ -struct eth_pdata { - phys_addr_t iobase; - unsigned char enetaddr[ARP_HLEN]; - int phy_interface; - int max_speed; - void *priv_pdata; -}; - -enum eth_recv_flags { - /* - * Check hardware device for new packets (otherwise only return those - * which are already in the memory buffer ready to process) - */ - ETH_RECV_CHECK_DEVICE = 1 << 0, -}; - -/** - * struct eth_ops - functions of Ethernet MAC controllers - * - * start: Prepare the hardware to send and receive packets - * send: Send the bytes passed in "packet" as a packet on the wire - * recv: Check if the hardware received a packet. If so, set the pointer to the - * packet buffer in the packetp parameter. If not, return an error or 0 to - * indicate that the hardware receive FIFO is empty. If 0 is returned, the - * network stack will not process the empty packet, but free_pkt() will be - * called if supplied - * free_pkt: Give the driver an opportunity to manage its packet buffer memory - * when the network stack is finished processing it. This will only be - * called when no error was returned from recv - optional - * stop: Stop the hardware from looking for packets - may be called even if - * state == PASSIVE - * mcast: Join or leave a multicast group (for TFTP) - optional - * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux - * on some platforms like ARM). This function expects the - * eth_pdata::enetaddr field to be populated. The method can - * return -ENOSYS to indicate that this is not implemented for - this hardware - optional. - * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a - * ROM on the board. This is how the driver should expose it - * to the network stack. This function should fill in the - * eth_pdata::enetaddr field - optional - * set_promisc: Enable or Disable promiscuous mode - * get_sset_count: Number of statistics counters - * get_string: Names of the statistic counters - * get_stats: The values of the statistic counters - */ -struct eth_ops { - int (*start)(struct udevice *dev); - int (*send)(struct udevice *dev, void *packet, int length); - int (*recv)(struct udevice *dev, int flags, uchar **packetp); - int (*free_pkt)(struct udevice *dev, uchar *packet, int length); - void (*stop)(struct udevice *dev); - int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join); - int (*write_hwaddr)(struct udevice *dev); - int (*read_rom_hwaddr)(struct udevice *dev); - int (*set_promisc)(struct udevice *dev, bool enable); - int (*get_sset_count)(struct udevice *dev); - void (*get_strings)(struct udevice *dev, u8 *data); - void (*get_stats)(struct udevice *dev, u64 *data); -}; - -#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) - -struct udevice *eth_get_dev(void); /* get the current device */ -/* - * The devname can be either an exact name given by the driver or device tree - * or it can be an alias of the form "eth%d" - */ -struct udevice *eth_get_dev_by_name(const char *devname); -unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ - -/* Used only when NetConsole is enabled */ -int eth_is_active(struct udevice *dev); /* Test device for active state */ -int eth_init_state_only(void); /* Set active state */ -void eth_halt_state_only(void); /* Set passive state */ - -int eth_initialize(void); /* Initialize network subsystem */ -void eth_try_another(int first_restart); /* Change the device */ -void eth_set_current(void); /* set nterface to ethcur var */ - -int eth_get_dev_index(void); /* get the device index */ - -/** - * eth_env_set_enetaddr_by_index() - set the MAC address environment variable - * - * This sets up an environment variable with the given MAC address (@enetaddr). - * The environment variable to be set is defined by <@base_name><@index>addr. - * If @index is 0 it is omitted. For common Ethernet this means ethaddr, - * eth1addr, etc. - * - * @base_name: Base name for variable, typically "eth" - * @index: Index of interface being updated (>=0) - * @enetaddr: Pointer to MAC address to put into the variable - * Return: 0 if OK, other value on error - */ -int eth_env_set_enetaddr_by_index(const char *base_name, int index, - uchar *enetaddr); - - -/* - * Initialize USB ethernet device with CONFIG_DM_ETH - * Returns: - * 0 is success, non-zero is error status. - */ -int usb_ether_init(void); - -/* - * Get the hardware address for an ethernet interface . - * Args: - * base_name - base name for device (normally "eth") - * index - device index number (0 for first) - * enetaddr - returns 6 byte hardware address - * Returns: - * Return true if the address is valid. - */ -int eth_env_get_enetaddr_by_index(const char *base_name, int index, - uchar *enetaddr); - -int eth_init(void); /* Initialize the device */ -int eth_send(void *packet, int length); /* Send a packet */ - -#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) -int eth_receive(void *packet, int length); /* Receive a packet*/ -extern void (*push_packet)(void *packet, int length); -#endif -int eth_rx(void); /* Check for received packets */ -void eth_halt(void); /* stop SCC */ -const char *eth_get_name(void); /* get name of current device */ -int eth_mcast_join(struct in_addr mcast_addr, int join); +#include <net/eth.h>
/**********************************************************************/ /* @@ -495,16 +334,6 @@ extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */ /* Indicates whether the pxe path prefix / config file was specified in dhcp option */ extern char *pxelinux_configfile; /** END OF BOOTP EXTENTIONS **/ -extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */ -extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */ -extern struct in_addr net_ip; /* Our IP addr (0 = unknown) */ -extern struct in_addr net_server_ip; /* Server IP addr (0 = unknown) */ -extern uchar *net_tx_packet; /* THE transmit packet */ -extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */ -extern uchar *net_rx_packet; /* Current receive packet */ -extern int net_rx_packet_len; /* Current rx packet length */ -extern const u8 net_bcast_ethaddr[ARP_HLEN]; /* Ethernet broadcast address */ -extern const u8 net_null_ethaddr[ARP_HLEN];
#define VLAN_NONE 4095 /* untagged */ #define VLAN_IDMASK 0x0fff /* mask of valid vlan id */ @@ -557,6 +386,8 @@ extern struct in_addr net_ntp_server; /* the ip address to NTP */ extern int net_ntp_time_offset; /* offset time from UTC */ #endif
+int eth_mcast_join(struct in_addr mcast_addr, int join); + /* Initialize the network adapter */ int net_init(void); int net_loop(enum proto_t); @@ -827,18 +658,6 @@ static inline void net_random_ethaddr(uchar *addr) addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ }
-/** - * string_to_enetaddr() - Parse a MAC address - * - * Convert a string MAC address - * - * Implemented in lib/net_utils.c (built unconditionally) - * - * @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit - * hex value - * @enetaddr: Place to put MAC address (6 bytes) - */ -void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
/* Convert an IP address to a string */ void ip_to_string(struct in_addr x, char *s); diff --git a/include/net/arp.h b/include/net/arp.h new file mode 100644 index 0000000000..f614f0ef78 --- /dev/null +++ b/include/net/arp.h @@ -0,0 +1,7 @@ +/* ARP hardware address length */ +#define ARP_HLEN 6 +/* + * The size of a MAC address in string form, each digit requires two chars + * and five separator characters to form '00:00:00:00:00:00'. + */ +#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1) diff --git a/include/net/eth.h b/include/net/eth.h new file mode 100644 index 0000000000..17552bca81 --- /dev/null +++ b/include/net/eth.h @@ -0,0 +1,190 @@ +#include <net/arp.h> + +struct udevice; + +enum eth_state_t { + ETH_STATE_INIT, + ETH_STATE_PASSIVE, + ETH_STATE_ACTIVE +}; + +/** + * struct eth_pdata - Platform data for Ethernet MAC controllers + * + * @iobase: The base address of the hardware registers + * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env + * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_... + * @max_speed: Maximum speed of Ethernet connection supported by MAC + * @priv_pdata: device specific plat + */ +struct eth_pdata { + phys_addr_t iobase; + unsigned char enetaddr[ARP_HLEN]; + int phy_interface; + int max_speed; + void *priv_pdata; +}; + +enum eth_recv_flags { + /* + * Check hardware device for new packets (otherwise only return those + * which are already in the memory buffer ready to process) + */ + ETH_RECV_CHECK_DEVICE = 1 << 0, +}; + +/** + * struct eth_ops - functions of Ethernet MAC controllers + * + * start: Prepare the hardware to send and receive packets + * send: Send the bytes passed in "packet" as a packet on the wire + * recv: Check if the hardware received a packet. If so, set the pointer to the + * packet buffer in the packetp parameter. If not, return an error or 0 to + * indicate that the hardware receive FIFO is empty. If 0 is returned, the + * network stack will not process the empty packet, but free_pkt() will be + * called if supplied + * free_pkt: Give the driver an opportunity to manage its packet buffer memory + * when the network stack is finished processing it. This will only be + * called when no error was returned from recv - optional + * stop: Stop the hardware from looking for packets - may be called even if + * state == PASSIVE + * mcast: Join or leave a multicast group (for TFTP) - optional + * write_hwaddr: Write a MAC address to the hardware (used to pass it to Linux + * on some platforms like ARM). This function expects the + * eth_pdata::enetaddr field to be populated. The method can + * return -ENOSYS to indicate that this is not implemented for + this hardware - optional. + * read_rom_hwaddr: Some devices have a backup of the MAC address stored in a + * ROM on the board. This is how the driver should expose it + * to the network stack. This function should fill in the + * eth_pdata::enetaddr field - optional + * set_promisc: Enable or Disable promiscuous mode + * get_sset_count: Number of statistics counters + * get_string: Names of the statistic counters + * get_stats: The values of the statistic counters + */ +struct eth_ops { + int (*start)(struct udevice *dev); + int (*send)(struct udevice *dev, void *packet, int length); + int (*recv)(struct udevice *dev, int flags, uchar **packetp); + int (*free_pkt)(struct udevice *dev, uchar *packet, int length); + void (*stop)(struct udevice *dev); + int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join); + int (*write_hwaddr)(struct udevice *dev); + int (*read_rom_hwaddr)(struct udevice *dev); + int (*set_promisc)(struct udevice *dev, bool enable); + int (*get_sset_count)(struct udevice *dev); + void (*get_strings)(struct udevice *dev, u8 *data); + void (*get_stats)(struct udevice *dev, u64 *data); +}; + +#define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) + +struct udevice *eth_get_dev(void); /* get the current device */ +/* + * The devname can be either an exact name given by the driver or device tree + * or it can be an alias of the form "eth%d" + */ +struct udevice *eth_get_dev_by_name(const char *devname); +unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ + +/* Used only when NetConsole is enabled */ +int eth_is_active(struct udevice *dev); /* Test device for active state */ +int eth_init_state_only(void); /* Set active state */ +void eth_halt_state_only(void); /* Set passive state */ + +int eth_initialize(void); /* Initialize network subsystem */ +void eth_try_another(int first_restart); /* Change the device */ +void eth_set_current(void); /* set nterface to ethcur var */ + +int eth_get_dev_index(void); /* get the device index */ + +/** + * eth_env_set_enetaddr_by_index() - set the MAC address environment variable + * + * This sets up an environment variable with the given MAC address (@enetaddr). + * The environment variable to be set is defined by <@base_name><@index>addr. + * If @index is 0 it is omitted. For common Ethernet this means ethaddr, + * eth1addr, etc. + * + * @base_name: Base name for variable, typically "eth" + * @index: Index of interface being updated (>=0) + * @enetaddr: Pointer to MAC address to put into the variable + * Return: 0 if OK, other value on error + */ +int eth_env_set_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr); + + +/* + * Initialize USB ethernet device with CONFIG_DM_ETH + * Returns: + * 0 is success, non-zero is error status. + */ +int usb_ether_init(void); + +/* + * Get the hardware address for an ethernet interface . + * Args: + * base_name - base name for device (normally "eth") + * index - device index number (0 for first) + * enetaddr - returns 6 byte hardware address + * Returns: + * Return true if the address is valid. + */ +int eth_env_get_enetaddr_by_index(const char *base_name, int index, + uchar *enetaddr); + +int eth_init(void); /* Initialize the device */ +int eth_send(void *packet, int length); /* Send a packet */ + +#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER) +int eth_receive(void *packet, int length); /* Receive a packet*/ +extern void (*push_packet)(void *packet, int length); +#endif +int eth_rx(void); /* Check for received packets */ +void eth_halt(void); /* stop SCC */ +const char *eth_get_name(void); /* get name of current device */ + +/* + * The number of receive packet buffers, and the required packet buffer + * alignment in memory. + * + */ +#define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER +#define PKTALIGN ARCH_DMA_MINALIGN + +/* Number of packets processed together */ +#define ETH_PACKETS_BATCH_RECV 32 + +extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */ +extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */ +extern struct in_addr net_ip; /* Our IP addr (0 = unknown) */ +extern struct in_addr net_server_ip; /* Server IP addr (0 = unknown) */ +extern uchar *net_tx_packet; /* THE transmit packet */ +extern uchar *net_rx_packets[PKTBUFSRX]; /* Receive packets */ +extern uchar *net_rx_packet; /* Current receive packet */ +extern int net_rx_packet_len; /* Current rx packet length */ +extern const u8 net_bcast_ethaddr[ARP_HLEN]; /* Ethernet broadcast address */ +extern const u8 net_null_ethaddr[ARP_HLEN]; + +/** + * string_to_enetaddr() - Parse a MAC address + * + * Convert a string MAC address + * + * Implemented in lib/net_utils.c (built unconditionally) + * + * @addr: MAC address in aa:bb:cc:dd:ee:ff format, where each part is a 2-digit + * hex value + * @enetaddr: Place to put MAC address (6 bytes) + */ +void string_to_enetaddr(const char *addr, uint8_t *enetaddr); + +typedef struct ulwip { + bool loop; + int err; + bool init_done; +} ulwip; + +struct ulwip *eth_lwip_priv(struct udevice *current);

After which to lwip variants of working apps we need to drop old code with all dependencies. This commit drop old wget command files.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/wget.h | 22 --- net/Makefile | 1 - net/net.c | 6 - net/wget.c | 440 --------------------------------------------- 4 files changed, 469 deletions(-) delete mode 100644 include/net/wget.h delete mode 100644 net/wget.c
diff --git a/include/net/wget.h b/include/net/wget.h deleted file mode 100644 index da0920de11..0000000000 --- a/include/net/wget.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Duncan Hare Copyright 2017 - */ - -/** - * wget_start() - begin wget - */ -void wget_start(void); - -enum wget_state { - WGET_CLOSED, - WGET_CONNECTING, - WGET_CONNECTED, - WGET_TRANSFERRING, - WGET_TRANSFERRED -}; - -#define DEBUG_WGET 0 /* Set to 1 for debug messages */ -#define SERVER_PORT 80 -#define WGET_RETRY_COUNT 30 -#define WGET_TIMEOUT 2000UL diff --git a/net/Makefile b/net/Makefile index 61930c244e..eda21f988a 100644 --- a/net/Makefile +++ b/net/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o -obj-$(CONFIG_CMD_WGET) += wget.o obj-$(CONFIG_LWIP) += lwip/
# Disable this warning as it is triggered by: diff --git a/net/net.c b/net/net.c index 7f868ee516..38d34ed5f4 100644 --- a/net/net.c +++ b/net/net.c @@ -109,7 +109,6 @@ #include <linux/compiler.h> #include <test/test.h> #include <net/tcp.h> -#include <net/wget.h> #include "arp.h" #include "bootp.h" #include "cdp.h" @@ -566,11 +565,6 @@ restart: nfs_start(); break; #endif -#if defined(CONFIG_CMD_WGET) - case WGET: - wget_start(); - break; -#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/wget.c b/net/wget.c deleted file mode 100644 index 2dbfeb1a1d..0000000000 --- a/net/wget.c +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * WGET/HTTP support driver based on U-BOOT's nfs.c - * Copyright Duncan Hare dh@synoia.com 2017 - */ - -#include <command.h> -#include <common.h> -#include <display_options.h> -#include <env.h> -#include <image.h> -#include <mapmem.h> -#include <net.h> -#include <net/tcp.h> -#include <net/wget.h> - -static const char bootfile1[] = "GET "; -static const char bootfile3[] = " HTTP/1.0\r\n\r\n"; -static const char http_eom[] = "\r\n\r\n"; -static const char http_ok[] = "200"; -static const char content_len[] = "Content-Length"; -static const char linefeed[] = "\r\n"; -static struct in_addr web_server_ip; -static int our_port; -static int wget_timeout_count; - -struct pkt_qd { - uchar *pkt; - unsigned int tcp_seq_num; - unsigned int len; -}; - -/* - * This is a control structure for out of order packets received. - * The actual packet bufers are in the kernel space, and are - * expected to be overwritten by the downloaded image. - */ -static struct pkt_qd pkt_q[PKTBUFSRX / 4]; -static int pkt_q_idx; -static unsigned long content_length; -static unsigned int packets; - -static unsigned int initial_data_seq_num; - -static enum wget_state current_wget_state; - -static char *image_url; -static unsigned int wget_timeout = WGET_TIMEOUT; - -static enum net_loop_state wget_loop_state; - -/* Timeout retry parameters */ -static u8 retry_action; /* actions for TCP retry */ -static unsigned int retry_tcp_ack_num; /* TCP retry acknowledge number*/ -static unsigned int retry_tcp_seq_num; /* TCP retry sequence number */ -static int retry_len; /* TCP retry length */ - -/** - * store_block() - store block in memory - * @src: source of data - * @offset: offset - * @len: length - */ -static inline int store_block(uchar *src, unsigned int offset, unsigned int len) -{ - ulong newsize = offset + len; - uchar *ptr; - - ptr = map_sysmem(image_load_addr + offset, len); - memcpy(ptr, src, len); - unmap_sysmem(ptr); - - if (net_boot_file_size < (offset + len)) - net_boot_file_size = newsize; - - return 0; -} - -/** - * wget_send_stored() - wget response dispatcher - * - * WARNING, This, and only this, is the place in wget.c where - * SEQUENCE NUMBERS are swapped between incoming (RX) - * and outgoing (TX). - * Procedure wget_handler() is correct for RX traffic. - */ -static void wget_send_stored(void) -{ - u8 action = retry_action; - int len = retry_len; - unsigned int tcp_ack_num = retry_tcp_seq_num + (len == 0 ? 1 : len); - unsigned int tcp_seq_num = retry_tcp_ack_num; - uchar *ptr, *offset; - - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: send SYN\n"); - current_wget_state = WGET_CONNECTING; - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - packets = 0; - break; - case WGET_CONNECTING: - pkt_q_idx = 0; - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - - ptr = net_tx_packet + net_eth_hdr_size() + - IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2; - offset = ptr; - - memcpy(offset, &bootfile1, strlen(bootfile1)); - offset += strlen(bootfile1); - - memcpy(offset, image_url, strlen(image_url)); - offset += strlen(image_url); - - memcpy(offset, &bootfile3, strlen(bootfile3)); - offset += strlen(bootfile3); - net_send_tcp_packet((offset - ptr), SERVER_PORT, our_port, - TCP_PUSH, tcp_seq_num, tcp_ack_num); - current_wget_state = WGET_CONNECTED; - break; - case WGET_CONNECTED: - case WGET_TRANSFERRING: - case WGET_TRANSFERRED: - net_send_tcp_packet(0, SERVER_PORT, our_port, action, - tcp_seq_num, tcp_ack_num); - break; - } -} - -static void wget_send(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len) -{ - retry_action = action; - retry_tcp_ack_num = tcp_ack_num; - retry_tcp_seq_num = tcp_seq_num; - retry_len = len; - - wget_send_stored(); -} - -void wget_fail(char *error_message, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, u8 action) -{ - printf("wget: Transfer Fail - %s\n", error_message); - net_set_timeout_handler(0, NULL); - wget_send(action, tcp_seq_num, tcp_ack_num, 0); -} - -void wget_success(u8 action, unsigned int tcp_seq_num, - unsigned int tcp_ack_num, int len, int packets) -{ - printf("Packets received %d, Transfer Successful\n", packets); - wget_send(action, tcp_seq_num, tcp_ack_num, len); -} - -/* - * Interfaces of U-BOOT - */ -static void wget_timeout_handler(void) -{ - if (++wget_timeout_count > WGET_RETRY_COUNT) { - puts("\nRetry count exceeded; starting again\n"); - wget_send(TCP_RST, 0, 0, 0); - net_start_again(); - } else { - puts("T "); - net_set_timeout_handler(wget_timeout + - WGET_TIMEOUT * wget_timeout_count, - wget_timeout_handler); - wget_send_stored(); - } -} - -#define PKT_QUEUE_OFFSET 0x20000 -#define PKT_QUEUE_PACKET_SIZE 0x800 - -static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, - u8 action, unsigned int tcp_ack_num, unsigned int len) -{ - uchar *pkt_in_q; - char *pos; - int hlen, i; - uchar *ptr1; - - pkt[len] = '\0'; - pos = strstr((char *)pkt, http_eom); - - if (!pos) { - debug_cond(DEBUG_WGET, - "wget: Connected, data before Header %p\n", pkt); - pkt_in_q = (void *)image_load_addr + PKT_QUEUE_OFFSET + - (pkt_q_idx * PKT_QUEUE_PACKET_SIZE); - - ptr1 = map_sysmem((phys_addr_t)pkt_in_q, len); - memcpy(ptr1, pkt, len); - unmap_sysmem(ptr1); - - pkt_q[pkt_q_idx].pkt = pkt_in_q; - pkt_q[pkt_q_idx].tcp_seq_num = tcp_seq_num; - pkt_q[pkt_q_idx].len = len; - pkt_q_idx++; - } else { - debug_cond(DEBUG_WGET, "wget: Connected HTTP Header %p\n", pkt); - /* sizeof(http_eom) - 1 is the string length of (http_eom) */ - hlen = pos - (char *)pkt + sizeof(http_eom) - 1; - pos = strstr((char *)pkt, linefeed); - if (pos > 0) - i = pos - (char *)pkt; - else - i = hlen; - printf("%.*s", i, pkt); - - current_wget_state = WGET_TRANSFERRING; - - if (strstr((char *)pkt, http_ok) == 0) { - debug_cond(DEBUG_WGET, - "wget: Connected Bad Xfer\n"); - initial_data_seq_num = tcp_seq_num + hlen; - wget_loop_state = NETLOOP_FAIL; - wget_send(action, tcp_seq_num, tcp_ack_num, len); - } else { - debug_cond(DEBUG_WGET, - "wget: Connctd pkt %p hlen %x\n", - pkt, hlen); - initial_data_seq_num = tcp_seq_num + hlen; - - pos = strstr((char *)pkt, content_len); - if (!pos) { - content_length = -1; - } else { - pos += sizeof(content_len) + 2; - strict_strtoul(pos, 10, &content_length); - debug_cond(DEBUG_WGET, - "wget: Connected Len %lu\n", - content_length); - } - - net_boot_file_size = 0; - - if (len > hlen) - store_block(pkt + hlen, 0, len - hlen); - - debug_cond(DEBUG_WGET, - "wget: Connected Pkt %p hlen %x\n", - pkt, hlen); - - for (i = 0; i < pkt_q_idx; i++) { - ptr1 = map_sysmem( - (phys_addr_t)(pkt_q[i].pkt), - pkt_q[i].len); - store_block(ptr1, - pkt_q[i].tcp_seq_num - - initial_data_seq_num, - pkt_q[i].len); - unmap_sysmem(ptr1); - debug_cond(DEBUG_WGET, - "wget: Connctd pkt Q %p len %x\n", - pkt_q[i].pkt, pkt_q[i].len); - } - } - } - wget_send(action, tcp_seq_num, tcp_ack_num, len); -} - -/** - * wget_handler() - TCP handler of wget - * @pkt: pointer to the application packet - * @dport: destination TCP port - * @sip: source IP address - * @sport: source TCP port - * @tcp_seq_num: TCP sequential number - * @tcp_ack_num: TCP acknowledgment number - * @action: TCP action (SYN, ACK, FIN, etc) - * @len: packet length - * - * In the "application push" invocation, the TCP header with all - * its information is pointed to by the packet pointer. - */ -static void wget_handler(uchar *pkt, u16 dport, - struct in_addr sip, u16 sport, - u32 tcp_seq_num, u32 tcp_ack_num, - u8 action, unsigned int len) -{ - enum tcp_state wget_tcp_state = tcp_get_tcp_state(); - - net_set_timeout_handler(wget_timeout, wget_timeout_handler); - packets++; - - switch (current_wget_state) { - case WGET_CLOSED: - debug_cond(DEBUG_WGET, "wget: Handler: Error!, State wrong\n"); - break; - case WGET_CONNECTING: - debug_cond(DEBUG_WGET, - "wget: Connecting In len=%x, Seq=%u, Ack=%u\n", - len, tcp_seq_num, tcp_ack_num); - if (!len) { - if (wget_tcp_state == TCP_ESTABLISHED) { - debug_cond(DEBUG_WGET, - "wget: Cting, send, len=%x\n", len); - wget_send(action, tcp_seq_num, tcp_ack_num, - len); - } else { - printf("%.*s", len, pkt); - wget_fail("wget: Handler Connected Fail\n", - tcp_seq_num, tcp_ack_num, action); - } - } - break; - case WGET_CONNECTED: - debug_cond(DEBUG_WGET, "wget: Connected seq=%u, len=%x\n", - tcp_seq_num, len); - if (!len) { - wget_fail("Image not found, no data returned\n", - tcp_seq_num, tcp_ack_num, action); - } else { - wget_connected(pkt, tcp_seq_num, action, tcp_ack_num, len); - } - break; - case WGET_TRANSFERRING: - debug_cond(DEBUG_WGET, - "wget: Transferring, seq=%x, ack=%x,len=%x\n", - tcp_seq_num, tcp_ack_num, len); - - if (tcp_seq_num >= initial_data_seq_num && - store_block(pkt, tcp_seq_num - initial_data_seq_num, - len) != 0) { - wget_fail("wget: store error\n", - tcp_seq_num, tcp_ack_num, action); - return; - } - - switch (wget_tcp_state) { - case TCP_FIN_WAIT_2: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, len); - fallthrough; - case TCP_SYN_SENT: - case TCP_SYN_RECEIVED: - case TCP_CLOSING: - case TCP_FIN_WAIT_1: - case TCP_CLOSED: - net_set_state(NETLOOP_FAIL); - break; - case TCP_ESTABLISHED: - wget_send(TCP_ACK, tcp_seq_num, tcp_ack_num, - len); - wget_loop_state = NETLOOP_SUCCESS; - break; - case TCP_CLOSE_WAIT: /* End of transfer */ - current_wget_state = WGET_TRANSFERRED; - wget_send(action | TCP_ACK | TCP_FIN, - tcp_seq_num, tcp_ack_num, len); - break; - } - break; - case WGET_TRANSFERRED: - printf("Packets received %d, Transfer Successful\n", packets); - net_set_state(wget_loop_state); - break; - } -} - -#define RANDOM_PORT_START 1024 -#define RANDOM_PORT_RANGE 0x4000 - -/** - * random_port() - make port a little random (1024-17407) - * - * Return: random port number from 1024 to 17407 - * - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -static unsigned int random_port(void) -{ - return RANDOM_PORT_START + (get_timer(0) % RANDOM_PORT_RANGE); -} - -#define BLOCKSIZE 512 - -void wget_start(void) -{ - image_url = strchr(net_boot_file_name, ':'); - if (image_url > 0) { - web_server_ip = string_to_ip(net_boot_file_name); - ++image_url; - net_server_ip = web_server_ip; - } else { - web_server_ip = net_server_ip; - image_url = net_boot_file_name; - } - - debug_cond(DEBUG_WGET, - "wget: Transfer HTTP Server %pI4; our IP %pI4\n", - &web_server_ip, &net_ip); - - /* Check if we need to send across this subnet */ - if (net_gateway.s_addr && net_netmask.s_addr) { - struct in_addr our_net; - struct in_addr server_net; - - our_net.s_addr = net_ip.s_addr & net_netmask.s_addr; - server_net.s_addr = net_server_ip.s_addr & net_netmask.s_addr; - if (our_net.s_addr != server_net.s_addr) - debug_cond(DEBUG_WGET, - "wget: sending through gateway %pI4", - &net_gateway); - } - debug_cond(DEBUG_WGET, "URL '%s'\n", image_url); - - if (net_boot_file_expected_size_in_blocks) { - debug_cond(DEBUG_WGET, "wget: Size is 0x%x Bytes = ", - net_boot_file_expected_size_in_blocks * BLOCKSIZE); - print_size(net_boot_file_expected_size_in_blocks * BLOCKSIZE, - ""); - } - debug_cond(DEBUG_WGET, - "\nwget:Load address: 0x%lx\nLoading: *\b", image_load_addr); - - net_set_timeout_handler(wget_timeout, wget_timeout_handler); - tcp_set_tcp_handler(wget_handler); - - wget_timeout_count = 0; - current_wget_state = WGET_CLOSED; - - our_port = random_port(); - - /* - * Zero out server ether to force arp resolution in case - * the server ip for the previous u-boot command, for example dns - * is not the same as the web server ip. - */ - - memset(net_server_ethaddr, 0, 6); - - wget_send(TCP_SYN, 0, 0, 0); -}

Allow to specify HTTP port instead of just using default for wget command.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org --- include/net/lwip.h | 2 +- net/lwip/apps/http/lwip-wget.c | 45 +++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/include/net/lwip.h b/include/net/lwip.h index aa82d71715..c66551a14c 100644 --- a/include/net/lwip.h +++ b/include/net/lwip.h @@ -54,7 +54,7 @@ int ulwip_tftp(ulong addr, const char *filename); * * * @addr: start address to download result - * @url: url in format http://host/url + * @url: url in format http://host%5B:port%5D/url * Returns: 0 for success, !0 if error */ int ulwip_wget(ulong addr, char *url); diff --git a/net/lwip/apps/http/lwip-wget.c b/net/lwip/apps/http/lwip-wget.c index a9bb29e156..01aa146b13 100644 --- a/net/lwip/apps/http/lwip-wget.c +++ b/net/lwip/apps/http/lwip-wget.c @@ -65,19 +65,42 @@ static int parse_url(char *url, char *host, u16 *port) p += strlen("http://");
/* parse hostname */ - pp = strchr(p, '/'); - if (!pp) { - printf("wrong url\n"); - return -2; + pp = strchr(p, ':'); + if (pp) { +#define PORT_STR_SIZE 5 + char portstr[PORT_STR_SIZE]; + + if (pp - p >= SERVER_NAME_SIZE) + return -2; + memcpy(host, p, pp - p); + host[pp - p + 1] = '\0'; + + p = pp + 1; + pp = strchr(p, '/'); + if (!pp) { + printf("wrong url\n"); + return -3; + } + + if (pp - p >= PORT_STR_SIZE) + return -4; + memcpy(portstr, p, pp - p); + portstr[pp - p] = '\0'; + *port = (u16)dectoul(portstr, NULL); + } else { + pp = strchr(p, '/'); + if (!pp) { + printf("wrong url\n"); + return -5; + } + + if (pp - p >= SERVER_NAME_SIZE) + return -6; + memcpy(host, p, pp - p); + host[pp - p + 1] = '\0'; + *port = HTTP_PORT_DEFAULT; }
- if (pp - p >= SERVER_NAME_SIZE) - return -3; - - memcpy(host, p, pp - p); - host[pp - p + 1] = '\0'; - *port = HTTP_PORT_DEFAULT; - return 0; }

Hi,
út 22. 8. 2023 v 11:38 odesílatel Maxim Uvarov maxim.uvarov@linaro.org napsal:
Hello,
I'm sending v7, with all v6 comments getting fixed. The only thing left is a pointer to timeout callback which 2 applications use. I will rework this timeout in next v8. I started take a look at it, and want to fix this together with background applications support in v8.
changelog: v7: - more review fixes. - support of multiply eth devices, were "ethact" selects the active device. v6: - fixed review comments for v5 (thanks Ilias and Simon). - lwip is not under /net, so prior applying patch following commit is needed to create lwIP merge into U-Boot: git subtree add --prefix net/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash
I think you should integrate it via .gitmodules as is done for example in qemu.
The next part. I tried to use buildmain to build the whole series and I am getting a lot of errors. You should fix pretty much all of these errors to make sure that the tree is bisectable.
Thanks, Michal
[u-boot](lwip)$ ./tools/buildman/buildman -C -b `git rev-parse --abbrev-ref HEAD` xilinx_zynqmp_virt -o /run/shm/ -sSed Summary of 18 commits for 1 boards (1 thread, 12 jobs per thread) 01: Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-usb aarch64: w+ xilinx_zynqmp_virt +===================== WARNING ====================== +This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate +to binman instead, to avoid the proliferation of +arch-specific scripts with no tests. +==================================================== 02: net/lwip: add doc/develop/net_lwip.rst 03: net/lwip: integrate lwIP library aarch64: + xilinx_zynqmp_virt -===================== WARNING ====================== -This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate -to binman instead, to avoid the proliferation of -arch-specific scripts with no tests. -==================================================== +make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. +make[2]: *** [../scripts/Makefile.build:397: net/lwip] Error 2 +../net/net.c:128:23: fatal error: net/ulwip.h: No such file or directory + #include <net/ulwip.h> + ^ +compilation terminated. +make[2]: *** [../scripts/Makefile.build:256: net/net.o] Error 1 +make[1]: *** [Makefile:1857: net] Error 2 +make: *** [Makefile:177: sub-make] Error 2 04: net/lwip: implement dns cmd -make[2]: *** [../scripts/Makefile.build:256: net/net.o] Error 1 +make[2]: *** [../scripts/Makefile.build:257: net/net.o] Error 1 05: net/lwip: implement dhcp cmd 06: net/lwip: implement tftp cmd +cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory +make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory + #include "lwip/apps/tftp_client.h" + ^ +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 07: net/lwip: implement wget cmd 08: net/lwip: implement ping cmd +cp: cannot stat '../net/lwip/lwip-external/contrib/apps/ping/ping.c': No such file or directory +make[4]: *** [../net/lwip/apps/ping/Makefile:8: net/lwip/apps/ping/ping.c] Error 1 +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory + #include "lwip/opt.h" + ^ +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/ping] Error 2 09: net/lwip: add lwIP configuration 10: net/lwip: implement lwIP port to U-Boot -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory - #include "lwip/opt.h" - ^ -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory - #include "lwip/apps/tftp_client.h" - ^ -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +../net/eth-uclass.c:35:2: error: unknown type name ‘ulwip’ + ulwip ulwip; + ^~~~~ + return &priv->ulwip; + ^~~~~~~~~~~~ +make[2]: *** [../scripts/Makefile.build:257: net/eth-uclass.o] Error 1 w+../net/eth-uclass.c: In function ‘eth_lwip_priv’: w+../net/eth-uclass.c:355:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types] 11: net/lwip: update .gitignore with lwIP +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory + #include "lwip/opt.h" + ^ +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory + #include "lwip/apps/tftp_client.h" + ^ +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 12: net/lwip: connection between cmd and lwip apps -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory - #include "lwip/opt.h" - ^ -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory - #include "lwip/apps/tftp_client.h" - ^ -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +../cmd/net-lwip.c:16:23: fatal error: net/ulwip.h: No such file or directory + #include "net/ulwip.h" +make[2]: *** [../scripts/Makefile.build:257: cmd/net-lwip.o] Error 1 +make[1]: *** [Makefile:1857: cmd] Error 2 13: net/lwip: replace original net commands with lwip -make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. -cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory -make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 -../cmd/net-lwip.c:16:23: fatal error: net/ulwip.h: No such file or directory - #include "net/ulwip.h" - ^ -compilation terminated. -make[2]: *** [../scripts/Makefile.build:257: cmd/net-lwip.o] Error 1 -make[1]: *** [Makefile:1857: cmd] Error 2 -make[2]: *** [../scripts/Makefile.build:257: net/eth-uclass.o] Error 1 -../net/net.c:128:23: fatal error: net/ulwip.h: No such file or directory - #include <net/ulwip.h> -make[2]: *** [../scripts/Makefile.build:257: net/net.o] Error 1 +make[2]: *** [../scripts/Makefile.build:256: net/eth-uclass.o] Error 1 14: net/lwip: split net.h to net.h, arp.h and eth.h -../net/eth-uclass.c:35:2: error: unknown type name ‘ulwip’ - ulwip ulwip; - ^~~~~ - return &priv->ulwip; - ^~~~~~~~~~~~ -make[2]: *** [../scripts/Makefile.build:256: net/eth-uclass.o] Error 1 w-../net/eth-uclass.c: In function ‘eth_lwip_priv’: w-../net/eth-uclass.c:355:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types] 15: net/lwip: drop old net/wget +make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. +cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory +make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory + #include "lwip/opt.h" + ^ +compilation terminated. +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory + #include "lwip/apps/tftp_client.h" + ^ +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 16: net/lwip/wget add port selection 17: Squashed 'net/lwip/lwip-external/' content from commit 84fde1ebbfe3 -make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. -cp: cannot stat '../net/lwip/lwip-external/contrib/apps/ping/ping.c': No such file or directory -make[4]: *** [../net/lwip/apps/ping/Makefile:8: net/lwip/apps/ping/ping.c] Error 1 -cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory -make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory - #include "lwip/opt.h" - ^ -compilation terminated. -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/ping] Error 2 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory - #include "lwip/apps/tftp_client.h" - ^ -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 -make[2]: *** [../scripts/Makefile.build:397: net/lwip] Error 2 -make[1]: *** [Makefile:1857: net] Error 2 -make: *** [Makefile:177: sub-make] Error 2 +make: *** No rule to make target 'xilinx_zynqmp_virt_defconfig'. Stop. 18: Merge commit 'c773d79082011e8d77cd4b125c07a84b8348af39' as 'net/lwip/lwip-external' aarch64: w+ xilinx_zynqmp_virt -make: *** No rule to make target 'xilinx_zynqmp_virt_defconfig'. Stop. +===================== WARNING ====================== +This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate +to binman instead, to avoid the proliferation of +arch-specific scripts with no tests. +====================================================

On Thu, 7 Sept 2023 at 21:21, Michal Simek monstr@monstr.eu wrote:
Hi,
út 22. 8. 2023 v 11:38 odesílatel Maxim Uvarov maxim.uvarov@linaro.org napsal:
Hello,
I'm sending v7, with all v6 comments getting fixed. The only thing left
is a pointer
to timeout callback which 2 applications use. I will rework this timeout in next v8. I started take a look at it, and want to fix this together with background applications support in v8.
changelog: v7: - more review fixes. - support of multiply eth devices, were "ethact" selects the active device. v6: - fixed review comments for v5 (thanks Ilias and Simon). - lwip is not under /net, so prior applying patch following commit is needed to create lwIP merge into U-Boot: git subtree add --prefix net/lwip/lwip-external
https://git.savannah.nongnu.org/git/lwip.git master --squash
I think you should integrate it via .gitmodules as is done for example in qemu.
The next part. I tried to use buildmain to build the whole series and I am getting a lot of errors. You should fix pretty much all of these errors to make sure that the tree is bisectable.
Thanks, Michal
Hello Michal, the first version was with .gitmodules. To run buildman you need to create a subtree commit with the above line first, and only then run buildman for patches. And I think these series of patches are not friendly with sequential per patch builds. It's split into logical pieces for easier review.
From the log below I can say that subtree commit was not created. lwIP
library files are missing in your set up.
BR, Maxim.
[u-boot](lwip)$ ./tools/buildman/buildman -C -b `git rev-parse --abbrev-ref HEAD` xilinx_zynqmp_virt -o /run/shm/ -sSed Summary of 18 commits for 1 boards (1 thread, 12 jobs per thread) 01: Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-usb aarch64: w+ xilinx_zynqmp_virt +===================== WARNING ====================== +This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate +to binman instead, to avoid the proliferation of +arch-specific scripts with no tests. +==================================================== 02: net/lwip: add doc/develop/net_lwip.rst 03: net/lwip: integrate lwIP library aarch64: + xilinx_zynqmp_virt -===================== WARNING ====================== -This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate -to binman instead, to avoid the proliferation of
-arch-specific scripts with no tests.
+make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. +make[2]: *** [../scripts/Makefile.build:397: net/lwip] Error 2 +../net/net.c:128:23: fatal error: net/ulwip.h: No such file or directory
- #include <net/ulwip.h>
^
+compilation terminated. +make[2]: *** [../scripts/Makefile.build:256: net/net.o] Error 1 +make[1]: *** [Makefile:1857: net] Error 2 +make: *** [Makefile:177: sub-make] Error 2 04: net/lwip: implement dns cmd -make[2]: *** [../scripts/Makefile.build:256: net/net.o] Error 1 +make[2]: *** [../scripts/Makefile.build:257: net/net.o] Error 1 05: net/lwip: implement dhcp cmd 06: net/lwip: implement tftp cmd +cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory +make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
+make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 07: net/lwip: implement wget cmd 08: net/lwip: implement ping cmd +cp: cannot stat '../net/lwip/lwip-external/contrib/apps/ping/ping.c': No such file or directory +make[4]: *** [../net/lwip/apps/ping/Makefile:8: net/lwip/apps/ping/ping.c] Error 1 +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
+make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/ping] Error 2 09: net/lwip: add lwIP configuration 10: net/lwip: implement lwIP port to U-Boot -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
-make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
-make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +../net/eth-uclass.c:35:2: error: unknown type name ‘ulwip’
- ulwip ulwip;
- ^~~~~
- return &priv->ulwip;
^~~~~~~~~~~~
+make[2]: *** [../scripts/Makefile.build:257: net/eth-uclass.o] Error 1 w+../net/eth-uclass.c: In function ‘eth_lwip_priv’: w+../net/eth-uclass.c:355:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types] 11: net/lwip: update .gitignore with lwIP +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
+make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
+make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 12: net/lwip: connection between cmd and lwip apps -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
-make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
-make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +../cmd/net-lwip.c:16:23: fatal error: net/ulwip.h: No such file or directory
- #include "net/ulwip.h"
+make[2]: *** [../scripts/Makefile.build:257: cmd/net-lwip.o] Error 1 +make[1]: *** [Makefile:1857: cmd] Error 2 13: net/lwip: replace original net commands with lwip -make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. -cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory -make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 -../cmd/net-lwip.c:16:23: fatal error: net/ulwip.h: No such file or directory
- #include "net/ulwip.h"
^
-compilation terminated. -make[2]: *** [../scripts/Makefile.build:257: cmd/net-lwip.o] Error 1 -make[1]: *** [Makefile:1857: cmd] Error 2 -make[2]: *** [../scripts/Makefile.build:257: net/eth-uclass.o] Error 1 -../net/net.c:128:23: fatal error: net/ulwip.h: No such file or directory
- #include <net/ulwip.h>
-make[2]: *** [../scripts/Makefile.build:257: net/net.o] Error 1 +make[2]: *** [../scripts/Makefile.build:256: net/eth-uclass.o] Error 1 14: net/lwip: split net.h to net.h, arp.h and eth.h -../net/eth-uclass.c:35:2: error: unknown type name ‘ulwip’
- ulwip ulwip;
- ^~~~~
- return &priv->ulwip;
^~~~~~~~~~~~
-make[2]: *** [../scripts/Makefile.build:256: net/eth-uclass.o] Error 1 w-../net/eth-uclass.c: In function ‘eth_lwip_priv’: w-../net/eth-uclass.c:355:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types] 15: net/lwip: drop old net/wget +make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. +cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory +make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 +../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
+compilation terminated. +make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 +../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
+make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 +make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 16: net/lwip/wget add port selection 17: Squashed 'net/lwip/lwip-external/' content from commit 84fde1ebbfe3 -make[3]: *** No rule to make target 'net/lwip/lwip-external/src/core/init.o', needed by 'net/lwip/built-in.o'. Stop. -cp: cannot stat '../net/lwip/lwip-external/contrib/apps/ping/ping.c': No such file or directory -make[4]: *** [../net/lwip/apps/ping/Makefile:8: net/lwip/apps/ping/ping.c] Error 1 -cp: cannot stat '../net/lwip/lwip-external/src/apps/tftp/tftp.c': No such file or directory -make[4]: *** [../net/lwip/apps/tftp/Makefile:9: net/lwip/apps/tftp/tftp.c] Error 1 -../net/lwip/apps/ping/lwip_ping.c:7:22: fatal error: lwip/opt.h: No such file or directory
- #include "lwip/opt.h"
^
-compilation terminated. -make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/ping/lwip_ping.o] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/ping] Error 2 -../net/lwip/apps/tftp/lwip-tftp.c:12:35: fatal error: lwip/apps/tftp_client.h: No such file or directory
- #include "lwip/apps/tftp_client.h"
^
-make[4]: *** [../scripts/Makefile.build:257: net/lwip/apps/tftp/lwip-tftp.o] Error 1 -make[3]: *** [../scripts/Makefile.build:397: net/lwip/apps/tftp] Error 2 -make[2]: *** [../scripts/Makefile.build:397: net/lwip] Error 2 -make[1]: *** [Makefile:1857: net] Error 2 -make: *** [Makefile:177: sub-make] Error 2 +make: *** No rule to make target 'xilinx_zynqmp_virt_defconfig'. Stop. 18: Merge commit 'c773d79082011e8d77cd4b125c07a84b8348af39' as 'net/lwip/lwip-external' aarch64: w+ xilinx_zynqmp_virt -make: *** No rule to make target 'xilinx_zynqmp_virt_defconfig'. Stop. +===================== WARNING ====================== +This board uses CONFIG_SPL_FIT_GENERATOR. Please migrate +to binman instead, to avoid the proliferation of +arch-specific scripts with no tests. +====================================================

On Thu, Sep 07, 2023 at 05:21:18PM +0200, Michal Simek wrote:
Hi,
út 22. 8. 2023 v 11:38 odesílatel Maxim Uvarov maxim.uvarov@linaro.org napsal:
Hello,
I'm sending v7, with all v6 comments getting fixed. The only thing left is a pointer to timeout callback which 2 applications use. I will rework this timeout in next v8. I started take a look at it, and want to fix this together with background applications support in v8.
changelog: v7: - more review fixes. - support of multiply eth devices, were "ethact" selects the active device. v6: - fixed review comments for v5 (thanks Ilias and Simon). - lwip is not under /net, so prior applying patch following commit is needed to create lwIP merge into U-Boot: git subtree add --prefix net/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash
I think you should integrate it via .gitmodules as is done for example in qemu.
I _think_ I am leaning towards subtree, but it sounds like we need to make the initial build easier, perhaps some Makefile logic to see we haven't added, and then do what's needed?

On 9/7/23 21:23, Tom Rini wrote:
On Thu, Sep 07, 2023 at 05:21:18PM +0200, Michal Simek wrote:
Hi,
út 22. 8. 2023 v 11:38 odesílatel Maxim Uvarov maxim.uvarov@linaro.org napsal:
Hello,
I'm sending v7, with all v6 comments getting fixed. The only thing left is a pointer to timeout callback which 2 applications use. I will rework this timeout in next v8. I started take a look at it, and want to fix this together with background applications support in v8.
changelog: v7: - more review fixes. - support of multiply eth devices, were "ethact" selects the active device. v6: - fixed review comments for v5 (thanks Ilias and Simon). - lwip is not under /net, so prior applying patch following commit is needed to create lwIP merge into U-Boot: git subtree add --prefix net/lwip/lwip-external https://git.savannah.nongnu.org/git/lwip.git master --squash
I think you should integrate it via .gitmodules as is done for example in qemu.
I _think_ I am leaning towards subtree, but it sounds like we need to make the initial build easier, perhaps some Makefile logic to see we haven't added, and then do what's needed?
Definitely it has to solved without any manual step. And this is enabled by default for all platforms. I pretty much think that it should be disabled now and when tested properly it can become default y.
Thanks, Michal
participants (6)
-
Maxim Uvarov
-
Michal Simek
-
Michal Simek
-
Simon Glass
-
Simon Glass
-
Tom Rini