lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] [PATCHv2 3/3] net/lwip: add lwip library for the network st


From: Maxim Uvarov
Subject: [lwip-devel] [PATCHv2 3/3] net/lwip: add lwip library for the network stack
Date: Thu, 29 Jun 2023 18:34:30 +0600

This commit adds lwip library for the U-boot network
stack. Supported commands: ping, tftp, dhcp and wget.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
---
 .gitignore                            |   9 +
 cmd/net.c                             |  38 +++-
 include/net.h                         |   2 +-
 lib/Kconfig                           |   2 +
 lib/Makefile                          |   2 +
 lib/lwip/Kconfig                      | 108 ++++++++++
 lib/lwip/Makefile                     |  98 +++++++++
 lib/lwip/apps/dhcp/lwip-dhcp.c        |  52 +++++
 lib/lwip/apps/http/lwip-wget.c        |  71 +++++++
 lib/lwip/apps/ping/lwip_ping.c        |  37 ++++
 lib/lwip/apps/ping/lwip_ping.h        |  24 +++
 lib/lwip/apps/ping/ping.h             |  35 ++++
 lib/lwip/apps/tftp/lwip-tftp.c        | 121 +++++++++++
 lib/lwip/cmd-lwip.c                   | 276 ++++++++++++++++++++++++++
 lib/lwip/lwipopts.h                   | 203 +++++++++++++++++++
 lib/lwip/port/if.c                    | 260 ++++++++++++++++++++++++
 lib/lwip/port/include/arch/cc.h       |  46 +++++
 lib/lwip/port/include/arch/sys_arch.h |  59 ++++++
 lib/lwip/port/include/limits.h        |   0
 lib/lwip/port/sys-arch.c              |  20 ++
 lib/lwip/ulwip.h                      |   9 +
 net/eth-uclass.c                      |   4 +-
 net/net.c                             |  25 +++
 23 files changed, 1496 insertions(+), 5 deletions(-)
 create mode 100644 lib/lwip/Kconfig
 create mode 100644 lib/lwip/Makefile
 create mode 100644 lib/lwip/apps/dhcp/lwip-dhcp.c
 create mode 100644 lib/lwip/apps/http/lwip-wget.c
 create mode 100644 lib/lwip/apps/ping/lwip_ping.c
 create mode 100644 lib/lwip/apps/ping/lwip_ping.h
 create mode 100644 lib/lwip/apps/ping/ping.h
 create mode 100644 lib/lwip/apps/tftp/lwip-tftp.c
 create mode 100644 lib/lwip/cmd-lwip.c
 create mode 100644 lib/lwip/lwipopts.h
 create mode 100644 lib/lwip/port/if.c
 create mode 100644 lib/lwip/port/include/arch/cc.h
 create mode 100644 lib/lwip/port/include/arch/sys_arch.h
 create mode 100644 lib/lwip/port/include/limits.h
 create mode 100644 lib/lwip/port/sys-arch.c
 create mode 100644 lib/lwip/ulwip.h

diff --git a/.gitignore b/.gitignore
index eb769f144c..be3676c59e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,3 +104,12 @@ __pycache__
 # pylint files
 /pylint.cur
 /pylint.out/
+
+lib/lwip/lwip-external
+lib/lwip/apps/ping/ping.c
+lib/lwip/apps/http/http_client.c
+lib/lwip/apps/http/http_client.h
+lib/lwip/apps/tftp/tftp.c
+lib/lwip/apps/tftp/tftp_client.h
+lib/lwip/apps/tftp/tftp_common.h
+lib/lwip/apps/tftp/tftp_example.h
diff --git a/cmd/net.c b/cmd/net.c
index 0e9f200ca9..5b3dfd6c7e 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -36,6 +36,10 @@ U_BOOT_CMD(
 #endif
 
 #ifdef CONFIG_CMD_TFTPBOOT
+#if defined(CONFIG_CMD_LWIP_REPLACE_TFTP)
+int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc,
+                char *const argv[]);
+#endif
 int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        int ret;
@@ -56,7 +60,12 @@ U_BOOT_CMD(
 );
 #else
 U_BOOT_CMD(
-       tftpboot,       3,      1,      do_tftpb,
+       tftpboot,       3,      1,
+#if defined(CONFIG_CMD_LWIP_REPLACE_TFTP)
+       do_lwip_tftp,
+#else
+       do_tftpb,
+#endif
        "load file via network using TFTP protocol",
        "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
@@ -112,7 +121,11 @@ U_BOOT_CMD(
 static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
                   char *const argv[])
 {
+#if defined(CONFIG_CMD_LWIP_REPLACE_DHCP)
+       return do_lwip_dhcp();
+#else
        return netboot_common(DHCP, cmdtp, argc, argv);
+#endif
 }
 
 U_BOOT_CMD(
@@ -137,13 +150,22 @@ U_BOOT_CMD(
 #endif
 
 #if defined(CONFIG_CMD_WGET)
+#if defined(CONFIG_CMD_LWIP_REPLACE_WGET)
+int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
+                char *const argv[])
+#endif
 static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const 
argv[])
 {
        return netboot_common(WGET, cmdtp, argc, argv);
 }
 
 U_BOOT_CMD(
-       wget,   3,      1,      do_wget,
+       wget,   3,      1,
+#if defined(CONFIG_CMD_LWIP_REPLACE_WGET)
+       do_lwip_wget,
+#else
+       do_wget,
+#endif
        "boot image via network using HTTP protocol",
        "[loadAddress] [[hostIPaddr:]path and image name]"
 );
@@ -376,6 +398,10 @@ static int netboot_common(enum proto_t proto, struct 
cmd_tbl *cmdtp, int argc,
 }
 
 #if defined(CONFIG_CMD_PING)
+#if defined(CONFIG_CMD_LWIP_REPLACE_PING)
+extern int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
+                       char *const argv[]);
+#else
 static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
                   char *const argv[])
 {
@@ -395,9 +421,15 @@ static int do_ping(struct cmd_tbl *cmdtp, int flag, int 
argc,
 
        return CMD_RET_SUCCESS;
 }
+#endif
 
 U_BOOT_CMD(
-       ping,   2,      1,      do_ping,
+       ping,   2,      1,
+#if defined(CONFIG_CMD_LWIP_REPLACE_PING)
+       do_lwip_ping,
+#else
+       do_ping,
+#endif
        "send ICMP ECHO_REQUEST to network host",
        "pingAddress"
 );
diff --git a/include/net.h b/include/net.h
index 1a99009959..8622983597 100644
--- a/include/net.h
+++ b/include/net.h
@@ -561,7 +561,7 @@ extern int          net_restart_wrap;       /* Tried all 
network devices */
 
 enum proto_t {
        BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP, NETCONS,
-       SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET
+       SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI, WGET, LWIP
 };
 
 extern char    net_boot_file_name[1024];/* Boot File name */
diff --git a/lib/Kconfig b/lib/Kconfig
index 3c5a4ab386..7485a1f3bf 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates"
 source lib/fwu_updates/Kconfig
 
 endmenu
+
+source lib/lwip/Kconfig
diff --git a/lib/Makefile b/lib/Makefile
index d77b33e7f4..3b80a41187 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -91,6 +91,8 @@ obj-$(CONFIG_LIBAVB) += libavb/
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
 obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o
 
+obj-y += lwip/
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16-ccitt.o
 obj-$(CONFIG_$(SPL_TPL_)HASH) += crc16-ccitt.o
diff --git a/lib/lwip/Kconfig b/lib/lwip/Kconfig
new file mode 100644
index 0000000000..80d540ba54
--- /dev/null
+++ b/lib/lwip/Kconfig
@@ -0,0 +1,108 @@
+menu "LWIP"
+config LWIP_LIB
+       bool "Support LWIP library"
+       help
+         Selecting this option will enable the shared LWIP library code.
+
+menu "LWIP options"
+config LWIP_LIB_DEBUG
+       bool "enable debug"
+       default n
+config LWIP_LIB_NOASSERT
+       bool "disable asserts"
+       default y
+       help
+           Disabling asserts reduces binary size on 16k.
+config LWIP_LIB_TCP
+        bool "tcp"
+        default y
+config LWIP_LIB_UDP
+        bool "udp"
+        default y
+config LWIP_LIB_DNS
+        bool "dns"
+        default n
+config LWIP_LIB_DHCP
+        bool "dhcp"
+        default y
+
+config LWIP_LIB_LOOPBACK
+        bool "loopback"
+        default n
+        help
+          Increases size on 1k.
+config LWIP_LIB_SOCKET
+        bool "socket API"
+        default n
+config LWIP_LIB_NETCONN
+        bool "netconn API"
+        default n
+config LWIP_LIB_MEM_SIZE
+       int "mem size"
+       default 1600
+       range 1 4096
+       help
+           MEM_SIZE: the size of the heap memory. If the application will send
+           a lot of data that needs to be copied, this should be set high.
+
+config LWIP_LIB_PBUF_LINK_HLEN
+        int "pbuf link hlen"
+        default 14
+        range 4 1024
+        help
+          PBUF_LINK_HLEN: the number of bytes that should be allocated for a
+           link level header. The default is 14, the standard value for 
Ethernet.
+endmenu
+
+config CMD_LWIP
+        bool "lwip cmd"
+        default y
+       depends on LWIP_LIB
+        help
+          lwip networking command.
+
+config CMD_LWIP_PING
+        bool "ping"
+        default y
+       depends on CMD_LWIP
+        help
+          lwip ping command.
+
+config CMD_LWIP_REPLACE_PING
+        bool "replace original ping command"
+        default n
+
+config CMD_LWIP_WGET
+        bool "wget"
+        default y
+       depends on CMD_LWIP
+        help
+          lwip wget command.
+
+config CMD_LWIP_REPLACE_WGET
+       bool "replace original wget command"
+       default n
+
+config CMD_LWIP_TFTP
+        bool "tftp"
+        default y
+       depends on CMD_LWIP
+        help
+          lwip tftp command.
+
+config CMD_LWIP_REPLACE_TFTP
+       bool "replace original tftp command"
+       default n
+
+config CMD_LWIP_DHCP
+        bool "dhcp"
+        default y
+       depends on CMD_LWIP
+       depends on LWIP_LIB_DHCP
+        help
+          lwip dhcp command.
+
+config CMD_LWIP_REPLACE_DHCP
+       bool "replace original dhcp command"
+       default n
+endmenu
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
new file mode 100644
index 0000000000..6f68eb04ed
--- /dev/null
+++ b/lib/lwip/Makefile
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+
+LWIPDIR=lwip-external/src
+
+ccflags-y += -I$(CURDIR)/lib/lwip/port/include
+ccflags-y += -I$(CURDIR)/lib/lwip/lwip-external/src/include 
-I$(CURDIR)/lib/lwip
+
+obj-$(CONFIG_LWIP_LIB) += $(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_LWIP_LIB) += $(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_LWIP_LIB) += $(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_LWIP_LIB) += $(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_LWIP_LIB) += $(LWIPDIR)/netif/ethernet.o
+
+obj-$(CONFIG_LWIP_LIB) += port/if.o
+obj-$(CONFIG_LWIP_LIB) += port/sys-arch.o
+
+obj-$(CONFIG_CMD_LWIP) += cmd-lwip.o
+
+.PHONY: $(obj)/apps/ping/ping.c
+$(obj)/apps/ping/ping.o: $(obj)/apps/ping/ping.c
+$(obj)/apps/ping/ping.c:
+       cp ./lib/lwip/lwip-external/contrib/apps/ping/ping.c 
$(obj)/apps/ping/ping.c
+
+obj-$(CONFIG_CMD_LWIP) += apps/ping/ping.o
+obj-$(CONFIG_CMD_LWIP) += apps/ping/lwip_ping.o
+
+$(obj)/apps/http/http_clinet.o: $(obj)/apps/http/http_client.c
+.PHONY: $(obj)/apps/http/http_client.c
+$(obj)/apps/http/http_client.c:
+       cp ./lib/lwip/lwip-external/src/apps/http/http_client.c 
$(obj)/apps/http/http_client.c
+       cp ./lib/lwip/lwip-external/src/include/lwip/apps/http_client.h 
$(obj)/apps/http/http_client.h
+
+obj-$(CONFIG_CMD_LWIP_WGET) += apps/http/http_client.o
+obj-$(CONFIG_CMD_LWIP_WGET) += apps/http/lwip-wget.o
+
+$(obj)/apps/tftp/tftp.o: $(obj)/apps/tftp/tftp.c
+.PHONY: $(obj)/apps/tftp/tftp.c
+$(obj)/apps/tftp/tftp.c:
+       cp ./lib/lwip/lwip-external/src/apps/tftp/tftp.c $(obj)/apps/tftp/tftp.c
+       cp ./lib/lwip/lwip-external/src/include/lwip/apps/tftp_client.h 
$(obj)/apps/tftp/tftp_client.h
+       cp ./lib/lwip/lwip-external/src/include/lwip/apps/tftp_common.h 
$(obj)/apps/tftp/tftp_common.h
+       cp ./lib/lwip/lwip-external/contrib/examples/tftp/tftp_example.h 
$(obj)/apps/tftp/tftp_example.h
+
+obj-$(CONFIG_CMD_LWIP_TFTP) += apps/tftp/tftp.o
+obj-$(CONFIG_CMD_LWIP_TFTP) += apps/tftp/lwip-tftp.o
+
+obj-$(CONFIG_CMD_LWIP_DHCP) += apps/dhcp/lwip-dhcp.o
diff --git a/lib/lwip/apps/dhcp/lwip-dhcp.c b/lib/lwip/apps/dhcp/lwip-dhcp.c
new file mode 100644
index 0000000000..2e4812c7dd
--- /dev/null
+++ b/lib/lwip/apps/dhcp/lwip-dhcp.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include <lwip/dhcp.h>
+#include <lwip/prot/dhcp.h>
+
+#include "../../../lwip/ulwip.h"
+
+static struct dhcp dhcp;
+static bool dhcp_is_set;
+extern struct netif uboot_netif;
+
+static int ulwip_dhcp_tmo(void)
+{
+       switch (dhcp.state) {
+       case DHCP_STATE_BOUND:
+               env_set("bootfile", dhcp.boot_file_name);
+               env_set("ipaddr", ip4addr_ntoa(&dhcp.offered_ip_addr));
+               env_set("netmask", ip4addr_ntoa(&dhcp.offered_sn_mask));
+               env_set("serverip", ip4addr_ntoa(&dhcp.server_ip_addr));
+               printf("DHCP client bound to address %s\n", 
ip4addr_ntoa(&dhcp.offered_ip_addr));
+               break;
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+int ulwip_dhcp(void)
+{
+       int err;
+
+       ulwip_set_tmo(ulwip_dhcp_tmo);
+
+       if (!dhcp_is_set) {
+               dhcp_set_struct(&uboot_netif, &dhcp);
+               dhcp_is_set = true;
+       }
+       err = dhcp_start(&uboot_netif);
+       if (err)
+               printf("dhcp_start error %d\n", err);
+
+       return err;
+}
diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c
new file mode 100644
index 0000000000..07aabd15f3
--- /dev/null
+++ b/lib/lwip/apps/http/lwip-wget.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include "http_client.h"
+#include "../../../lwip/ulwip.h"
+
+static ulong daddr;
+static httpc_connection_t settings;
+
+static err_t httpc_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, 
err_t err)
+{
+       struct pbuf *q;
+       LWIP_UNUSED_ARG(err);
+
+       if (!p)
+               return ERR_BUF;
+
+       for (q = p; q != NULL; q = q->next) {
+               memcpy((void *)daddr, q->payload, q->len);
+               printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, 
daddr);
+               daddr += q->len;
+       }
+       altcp_recved(pcb, p->tot_len);
+       pbuf_free(p);
+       return ERR_OK;
+}
+
+static void httpc_result(void *arg, httpc_result_t httpc_result, u32_t 
rx_content_len,
+                        u32_t srv_res, err_t err)
+{
+       if (httpc_result == HTTPC_RESULT_OK) {
+               printf("\n%d bytes successfully downloaded.\n", rx_content_len);
+               ulwip_exit(0);
+       } else {
+               printf("\nhttp eroror: %d\n", httpc_result);
+               ulwip_exit(-1);
+       }
+}
+
+int lwip_wget(ulong addr, char *url)
+{
+       err_t err;
+       int port = 80;
+       char *server_name;
+       httpc_state_t *connection;
+
+       daddr = addr;
+       server_name = env_get("serverip");
+       if (!server_name) {
+               printf("error: serverip variable has to be set\n");
+               return CMD_RET_FAILURE;
+       }
+
+       printf("downloading %s to addr 0x%lx\n", url, addr);
+       memset(&settings, 0, sizeof(httpc_connection_t));
+       settings.result_fn = httpc_result;
+       err = httpc_get_file_dns(server_name, port, url, &settings,
+                                httpc_recv, NULL,  &connection);
+       if (err != ERR_OK) {
+               printf("httpc_init_connection failed\n");
+               return err;
+       }
+       return 0;
+}
diff --git a/lib/lwip/apps/ping/lwip_ping.c b/lib/lwip/apps/ping/lwip_ping.c
new file mode 100644
index 0000000000..a05dc76326
--- /dev/null
+++ b/lib/lwip/apps/ping/lwip_ping.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include "lwip/opt.h"
+#include "lwip/ip_addr.h"
+#include "ping.h"
+
+#include "../../../lwip/ulwip.h"
+
+static ip_addr_t ip_target;
+
+static int ulwip_ping_tmo(void)
+{
+
+       printf("ping failed; host %s is not alive\n", ipaddr_ntoa(&ip_target));
+       return 0;
+}
+
+int lwip_ping_init(char *ping_addr)
+{
+       int err;
+
+       err = ipaddr_aton(ping_addr, &ip_target);
+       if (err == 0) {
+               printf("wrong ping addr string \"%s\" \n", ping_addr);
+               return -1;
+       }
+
+       ulwip_set_tmo(ulwip_ping_tmo);
+
+       ping_init(&ip_target);
+
+       return 0;
+}
diff --git a/lib/lwip/apps/ping/lwip_ping.h b/lib/lwip/apps/ping/lwip_ping.h
new file mode 100644
index 0000000000..7f08095427
--- /dev/null
+++ b/lib/lwip/apps/ping/lwip_ping.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#ifndef LWIP_PING_H
+#define LWIP_PING_H
+
+#include <lwip/ip_addr.h>
+
+/**
+ * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used
+ */
+#ifndef PING_USE_SOCKETS
+#define PING_USE_SOCKETS   0
+#endif
+
+int lwip_ping_init(char *ping_addr);
+
+void ping_raw_init(void);
+void ping_send_now(void);
+
+#endif /* LWIP_PING_H */
diff --git a/lib/lwip/apps/ping/ping.h b/lib/lwip/apps/ping/ping.h
new file mode 100644
index 0000000000..0dd4bd78c7
--- /dev/null
+++ b/lib/lwip/apps/ping/ping.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "../../../lwip/ulwip.h"
+
+#include "lwip/prot/ip4.h"
+
+#define ip4_print_parts(a, b, c, d) \
+       printf("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d);
+
+#define ip4_print(ipaddr) \
+       ip4_print_parts(\
+                       (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \
+                       (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \
+                       (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \
+                       (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0))
+
+
+#define LWIP_DEBUG 1 /* ping_time is under ifdef*/
+#define PING_RESULT(cond) { \
+       if (cond == 1) { \
+               printf("host "); \
+               ip4_print(addr); \
+               printf(" is alive\n"); \
+               printf(" %"U32_F" ms\n", (sys_now() - ping_time)); \
+               ulwip_exit(0); \
+       } else { \
+               printf("ping failed; host "); \
+               ip4_print(addr); \
+               printf(" is not alive\n"); \
+               ulwip_exit(-1); \
+       } \
+     } while (0);
+
+#include "lwip/ip_addr.h"
+void ping_init(const ip_addr_t *ping_addr);
diff --git a/lib/lwip/apps/tftp/lwip-tftp.c b/lib/lwip/apps/tftp/lwip-tftp.c
new file mode 100644
index 0000000000..c38e83c8ee
--- /dev/null
+++ b/lib/lwip/apps/tftp/lwip-tftp.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include "lwip/apps/tftp_client.h"
+#include "lwip/apps/tftp_server.h"
+#include "tftp_example.h"
+
+#include <string.h>
+
+#include "../../../lwip/ulwip.h"
+
+#if LWIP_UDP
+
+static ulong daddr;
+static ulong size;
+
+static void *tftp_open(const char *fname, const char *mode, u8_t is_write)
+{
+       LWIP_UNUSED_ARG(mode);
+       return NULL;
+}
+
+static void tftp_close(void *handle)
+{
+       printf("\ndone\n");
+       printf("Bytes transferred = %ld (0x%lx hex)\n", size, size);
+       ulwip_exit(0);
+}
+
+static int tftp_read(void *handle, void *buf, int bytes)
+{
+       return 0;
+}
+
+static int tftp_write(void *handle, struct pbuf *p)
+{
+       struct pbuf *q;
+
+       for (q = p; q != NULL; q = q->next) {
+               memcpy((void *)daddr, q->payload, q->len);
+               /* printf("downloaded chunk size %d, to addr 0x%lx\n", q->len, 
daddr); */
+               daddr += q->len;
+               size += q->len;
+               printf("#");
+       }
+
+       return 0;
+}
+
+/* For TFTP client only */
+static void tftp_error(void *handle, int err, const char *msg, int size)
+{
+       char message[100];
+
+       LWIP_UNUSED_ARG(handle);
+
+       memset(message, 0, sizeof(message));
+       MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, (size_t)size));
+
+       printf("TFTP error: %d (%s)", err, message);
+}
+
+static const struct tftp_context tftp = {
+       tftp_open,
+       tftp_close,
+       tftp_read,
+       tftp_write,
+       tftp_error
+};
+
+int lwip_tftp(ulong addr, char *fname)
+{
+       void *f = (void *)0x1; /*fake handle*/
+       err_t err;
+       ip_addr_t srv;
+       int ret;
+       char *server_ip;
+
+       if (!fname || addr == 0)
+               return CMD_RET_FAILURE;
+
+       size = 0;
+       daddr = addr;
+       server_ip = env_get("serverip");
+       if (!server_ip) {
+               printf("error: serverip variable has to be set\n");
+               return CMD_RET_FAILURE;
+       }
+
+       ret = ipaddr_aton(server_ip, &srv);
+       LWIP_ASSERT("ipaddr_aton failed", ret == 1);
+
+       printf("TFTP from server %s; our IP address is %s\n",
+                       server_ip, env_get("ipaddr"));
+       printf("Filename '%s'.\n", fname);
+       printf("Load address: 0x%lx\n", daddr);
+       printf("Loading:");
+
+       err = tftp_init_client(&tftp);
+       if (!(err == ERR_OK || err == ERR_USE))
+               printf("tftp_init_client err: %d\n", err);
+
+       err = tftp_get(f, &srv, TFTP_PORT, fname, TFTP_MODE_OCTET);
+       /* might return different errors, like routing problems */
+       if (err != ERR_OK) {
+               printf("tftp_get err=%d\n", err);
+       }
+       LWIP_ASSERT("tftp_get failed", err == ERR_OK);
+
+       return err;
+}
+#else
+#error "UDP has to be supported"
+#endif /* LWIP_UDP */
diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c
new file mode 100644
index 0000000000..d7cdc4e411
--- /dev/null
+++ b/lib/lwip/cmd-lwip.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Maxim Uvarov, maxim.uvarov@linaro.org
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <display_options.h>
+#include <memalign.h>
+#include <net.h>
+#include <image.h>
+
+#include "apps/ping/lwip_ping.h"
+#include "ulwip.h"
+
+extern int uboot_lwip_init(void);
+extern int uboot_lwip_loop_is_done(void);
+
+static int do_lwip_info(struct cmd_tbl *cmdtp, int flag, int argc,
+                     char *const argv[])
+{
+       printf("TBD: %s\n", __func__);
+       return CMD_RET_SUCCESS;
+}
+
+static int do_lwip_init(struct cmd_tbl *cmdtp, int flag, int argc,
+                     char *const argv[])
+{
+       if (!uboot_lwip_init())
+               return CMD_RET_SUCCESS;
+       return CMD_RET_FAILURE;
+}
+
+static int lwip_empty_tmo(void) { return 0; };
+int (*ulwip_tmo)(void) = lwip_empty_tmo;
+void ulwip_set_tmo(int (*tmo)(void))
+{
+       ulwip_tmo = tmo;
+}
+
+static void ulwip_clear_tmo(void)
+{
+       ulwip_tmo = lwip_empty_tmo;
+}
+
+static void ulwip_timeout_handler(void)
+{
+       eth_halt();
+       ulwip_tmo();
+       net_set_state(NETLOOP_FAIL);    /* we did not get the reply */
+       ulwip_loop_set(0);
+}
+
+static int ulwip_loop(void)
+{
+       ulwip_loop_set(1);
+       if (net_loop(LWIP) < 0) {
+               ulwip_loop_set(0);
+               return CMD_RET_FAILURE;
+       }
+       ulwip_loop_set(0);
+       return CMD_RET_SUCCESS;
+}
+
+#if !defined(CONFIG_CMD_LWIP_REPLACE_PING)
+static
+#endif
+int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
+                char *const argv[])
+{
+       if (argc < 2) {
+               printf("argc = %d, error\n", argc);
+               return CMD_RET_USAGE;
+       }
+
+       uboot_lwip_init();
+
+       eth_init(); /* activate u-boot eth dev */
+
+       printf("Using %s device\n", eth_get_name());
+       printf("pinging addr: %s\n", argv[1]);
+
+       net_set_timeout_handler(1000UL, ulwip_timeout_handler);
+
+       if (lwip_ping_init(argv[1])) {
+               printf("ping init fail\n");
+               return CMD_RET_FAILURE;
+       }
+
+       ping_send_now();
+
+       return ulwip_loop();
+}
+
+extern int lwip_wget(ulong addr, char *url);
+
+#if !defined(CONFIG_CMD_LWIP_REPLACE_WGET)
+static
+#endif
+int do_lwip_wget(struct cmd_tbl *cmdtp, int flag, int argc,
+                char *const argv[])
+{
+       char *url;
+
+       if (argc < 2) {
+               printf("argc = %d, error\n", argc);
+               return CMD_RET_USAGE;
+       }
+       url = argv[1];
+
+       uboot_lwip_init();
+
+       eth_init(); /* activate u-boot eth dev */
+
+       lwip_wget(image_load_addr, url);
+
+       return ulwip_loop();
+}
+
+#if defined(CONFIG_CMD_LWIP_TFTP)
+extern int lwip_tftp(ulong addr, char *filename);
+#if !defined(CONFIG_CMD_LWIP_REPLACE_TFTP)
+static
+#endif
+int do_lwip_tftp(struct cmd_tbl *cmdtp, int flag, int argc,
+                char *const argv[])
+{
+       char *filename;
+       ulong addr;
+       char *end;
+       int ret;
+
+       switch (argc) {
+       case 1:
+               filename = env_get("bootfile");
+               break;
+       case 2:
+               /*
+                * Only one arg - accept two forms:
+                * Just load address, or just boot file name. The latter
+                * form must be written in a format which can not be
+                * mis-interpreted as a valid number.
+                */
+               addr = hextoul(argv[1], &end);
+               if (end == (argv[1] + strlen(argv[1]))) {
+                       image_load_addr = addr;
+                       filename = env_get("bootfile");
+               } else {
+                       filename = argv[1];
+               }
+               break;
+       case 3:
+               image_load_addr = hextoul(argv[1], NULL);
+               filename = argv[2];
+               break;
+       default:
+               return CMD_RET_USAGE;
+       }
+
+       uboot_lwip_init();
+
+       eth_init(); /* activate u-boot eth dev */
+
+       ret = lwip_tftp(image_load_addr, filename);
+       if (ret)
+               return ret;
+
+       return ulwip_loop();
+}
+#endif
+
+#if defined(CONFIG_CMD_LWIP_DHCP)
+extern int ulwip_dhcp(void);
+
+#if !defined(CONFIG_CMD_LWIP_REPLACE_DHCP)
+static
+#endif
+int do_lwip_dhcp(void)
+{
+       int ret;
+       char *filename;
+
+       uboot_lwip_init();
+
+       ret = ulwip_dhcp();
+
+       net_set_timeout_handler(2000UL, ulwip_timeout_handler);
+
+       ulwip_loop();
+       if (IS_ENABLED(CONFIG_CMD_LWIP_TFTP)) {
+               ulwip_clear_tmo();
+
+               filename = env_get("bootfile");
+               if (!filename) {
+                       printf("no bootfile\n");
+                       return CMD_RET_FAILURE;
+               }
+
+               eth_init(); /* activate u-boot eth dev */
+               net_set_timeout_handler(20000UL, ulwip_timeout_handler);
+               lwip_tftp(image_load_addr, filename);
+
+               ret =  ulwip_loop();
+       }
+
+       return ret;
+}
+
+static int _do_lwip_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
+               char *const argv[])
+{
+       return do_lwip_dhcp();
+}
+#endif
+
+static struct cmd_tbl cmds[] = {
+       U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "Info and stats", ""),
+       U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init,
+                        "initialize lwip stack", ""),
+#if defined(CONFIG_CMD_LWIP_PING)
+       U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping,
+                        "send ICMP ECHO_REQUEST to network host",
+                        "pingAddress"),
+#endif
+#if defined(CONFIG_CMD_LWIP_WGET)
+       U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""),
+#endif
+#if defined(CONFIG_CMD_LWIP_TFTP)
+       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_LWIP_DHCP)
+       U_BOOT_CMD_MKENT(dhcp, 1, 0, _do_lwip_dhcp,
+                       "boot image via network using DHCP/TFTP protocol",
+                       ""),
+#endif
+};
+
+static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
+                    char *const argv[])
+{
+       struct cmd_tbl *cp;
+
+       cp = find_cmd_tbl(argv[1], cmds, ARRAY_SIZE(cmds));
+
+       argc--;
+       argv++;
+
+       if (cp == NULL || argc > cp->maxargs)
+               return CMD_RET_USAGE;
+       if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+               return CMD_RET_SUCCESS;
+
+       return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+       lwip, 4, 1, do_ops,
+       "LWIP sub system",
+       "info - display info\n"
+       "init - init LWIP\n"
+       "ping addr - pingAddress\n"
+       "wget http://IPadress/url/\n";
+       "tftp [loadAddress] [[hostIPaddr:]bootfilename]\n"
+       "dhcp - boot image via network using DHCP/TFTP protocol\n"
+       );
+
+/* Old command kept for compatibility. Same as 'mmc info' */
+U_BOOT_CMD(
+       lwipinfo, 1, 0, do_lwip_info,
+       "display LWIP info",
+       "- display LWIP stack info"
+);
diff --git a/lib/lwip/lwipopts.h b/lib/lwip/lwipopts.h
new file mode 100644
index 0000000000..b943d7b9be
--- /dev/null
+++ b/lib/lwip/lwipopts.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#ifndef LWIP_LWIPOPTS_H
+#define LWIP_LWIPOPTS_H
+
+#include "lwipopts.h"
+
+#if defined(CONFIG_LWIP_LIB_DEBUG)
+#define LWIP_DEBUG 1
+#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
+#define ETHARP_DEBUG                    LWIP_DBG_OFF
+#define NETIF_DEBUG                     LWIP_DBG_OFF
+#define PBUF_DEBUG                      LWIP_DBG_OFF
+#define API_LIB_DEBUG                   LWIP_DBG_OFF
+#define API_MSG_DEBUG                   LWIP_DBG_OFF
+#define SOCKETS_DEBUG                   LWIP_DBG_OFF
+#define ICMP_DEBUG                      LWIP_DBG_OFF
+#define IGMP_DEBUG                      LWIP_DBG_OFF
+#define INET_DEBUG                      LWIP_DBG_OFF
+#define IP_DEBUG                        LWIP_DBG_OFF
+#define IP_REASS_DEBUG                  LWIP_DBG_OFF
+#define RAW_DEBUG                       LWIP_DBG_OFF
+#define MEM_DEBUG                       LWIP_DBG_OFF
+#define MEMP_DEBUG                      LWIP_DBG_OFF
+#define SYS_DEBUG                       LWIP_DBG_OFF
+#define TIMERS_DEBUG                    LWIP_DBG_OFF
+#define TCP_DEBUG                       LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
+#define TCP_FR_DEBUG                    LWIP_DBG_OFF
+#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
+#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
+#define TCP_WND_DEBUG                   LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
+#define TCP_RST_DEBUG                   LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
+#define UDP_DEBUG                       LWIP_DBG_OFF
+#define TCPIP_DEBUG                     LWIP_DBG_OFF
+#define SLIP_DEBUG                      LWIP_DBG_OFF
+#define DHCP_DEBUG                      LWIP_DBG_ON
+#define AUTOIP_DEBUG                    LWIP_DBG_ON
+#define DNS_DEBUG                       LWIP_DBG_OFF
+#define IP6_DEBUG                       LWIP_DBG_OFF
+#define DHCP6_DEBUG                     LWIP_DBG_OFF
+#else
+#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_ALL
+#define LWIP_DBG_TYPES_ON               LWIP_DBG_OFF
+#define ETHARP_DEBUG                    LWIP_DBG_OFF
+#define NETIF_DEBUG                     LWIP_DBG_OFF
+#define PBUF_DEBUG                      LWIP_DBG_OFF
+#define API_LIB_DEBUG                   LWIP_DBG_OFF
+#define API_MSG_DEBUG                   LWIP_DBG_OFF
+#define SOCKETS_DEBUG                   LWIP_DBG_OFF
+#define ICMP_DEBUG                      LWIP_DBG_OFF
+#define IGMP_DEBUG                      LWIP_DBG_OFF
+#define INET_DEBUG                      LWIP_DBG_OFF
+#define IP_DEBUG                        LWIP_DBG_OFF
+#define IP_REASS_DEBUG                  LWIP_DBG_OFF
+#define RAW_DEBUG                       LWIP_DBG_OFF
+#define MEM_DEBUG                       LWIP_DBG_OFF
+#define MEMP_DEBUG                      LWIP_DBG_OFF
+#define SYS_DEBUG                       LWIP_DBG_OFF
+#define TIMERS_DEBUG                    LWIP_DBG_OFF
+#define TCP_DEBUG                       LWIP_DBG_OFF
+#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
+#define TCP_FR_DEBUG                    LWIP_DBG_OFF
+#define TCP_RTO_DEBUG                   LWIP_DBG_OFF
+#define TCP_CWND_DEBUG                  LWIP_DBG_OFF
+#define TCP_WND_DEBUG                   LWIP_DBG_OFF
+#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
+#define TCP_RST_DEBUG                   LWIP_DBG_OFF
+#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF
+#define UDP_DEBUG                       LWIP_DBG_OFF
+#define TCPIP_DEBUG                     LWIP_DBG_OFF
+#define SLIP_DEBUG                      LWIP_DBG_OFF
+#define DHCP_DEBUG                      LWIP_DBG_OFF
+#define AUTOIP_DEBUG                    LWIP_DBG_OFF
+#define DNS_DEBUG                       LWIP_DBG_OFF
+#define IP6_DEBUG                       LWIP_DBG_OFF
+#define DHCP6_DEBUG                     LWIP_DBG_OFF
+#endif
+#define LWIP_TESTMODE                   0
+
+#if defined(CONFIG_LWIP_LIB_NOASSERT)
+#define LWIP_NOASSERT 1
+#define LWIP_ASSERT(message, assertion)
+#endif
+
+#include "lwip/debug.h"
+
+#define SYS_LIGHTWEIGHT_PROT            0
+#define NO_SYS                          0
+
+#define MEM_ALIGNMENT                   1
+#define MEM_SIZE                        CONFIG_LWIP_LIB_MEM_SIZE
+
+#define MEMP_NUM_PBUF                   4
+#define MEMP_NUM_RAW_PCB                2
+#define MEMP_NUM_UDP_PCB                4
+#define MEMP_NUM_TCP_PCB                2
+#define MEMP_NUM_TCP_PCB_LISTEN         2
+#define MEMP_NUM_TCP_SEG                16
+#define MEMP_NUM_REASSDATA              1
+#define MEMP_NUM_ARP_QUEUE              2
+#define MEMP_NUM_SYS_TIMEOUT            4
+#define MEMP_NUM_NETBUF                 2
+#define MEMP_NUM_NETCONN               32
+#define MEMP_NUM_TCPIP_MSG_API          8
+#define MEMP_NUM_TCPIP_MSG_INPKT        8
+#define PBUF_POOL_SIZE                  8
+
+#define LWIP_ARP                        1
+
+#define IP_FORWARD                      0
+#define IP_OPTIONS_ALLOWED              1
+#define IP_REASSEMBLY                   1
+#define IP_FRAG                         1
+#define IP_REASS_MAXAGE                 3
+#define IP_REASS_MAX_PBUFS              4
+#define IP_FRAG_USES_STATIC_BUF         0
+
+#define IP_DEFAULT_TTL                  255
+
+#define LWIP_ICMP                       1
+
+#define LWIP_RAW                        1
+
+#if defined(CONFIG_LWIP_LIB_DHCP)
+#define LWIP_DHCP                       1
+#define LWIP_DHCP_BOOTP_FILE           1
+#else
+#define LWIP_DHCP                       0
+#endif
+#define LWIP_DHCP_DOES_ACD_CHECK       0
+
+#define LWIP_AUTOIP                     0
+
+#define LWIP_SNMP                       0
+
+#define LWIP_IGMP                       0
+
+#if defined(CONFIG_LWIP_LIB_DNS)
+#define LWIP_DNS                        1
+#else
+#define LWIP_DNS                        0
+#endif
+
+#if defined(CONFIG_LWIP_LIB_TCP)
+#define LWIP_UDP                        1
+#else
+#define LWIP_UDP                        0
+#endif
+
+#if defined(CONFIG_LWIP_LIB_TCP)
+#define LWIP_TCP                        1
+#else
+#define LWIP_TCP                        0
+#endif
+
+#define LWIP_LISTEN_BACKLOG             0
+
+#define PBUF_LINK_HLEN                  CONFIG_LWIP_LIB_PBUF_LINK_HLEN
+#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + 
PBUF_LINK_HLEN)
+
+#define LWIP_HAVE_LOOPIF                0
+
+#if defined(CONFIG_LWIP_LIB_NETCONN)
+#define LWIP_NETCONN                    1
+#else
+#define LWIP_NETCONN                    0
+#define LWIP_DISABLE_MEMP_SANITY_CHECKS 1
+#endif
+
+#if defined(CONFIG_LWIP_LIB_SOCKET)
+#define LWIP_SOCKET                     1
+
+#define SO_REUSE                        1
+#else
+#define LWIP_SOCKET                     0
+#define SO_REUSE                        0
+#endif
+
+#define LWIP_STATS                      0
+
+#define PPP_SUPPORT                     0
+
+#define LWIP_TCPIP_CORE_LOCKING                0
+
+#if defined(CONFIG_LWIP_LIB_LOOPBACK)
+#define LWIP_NETIF_LOOPBACK            1
+#else
+#define LWIP_NETIF_LOOPBACK            0
+#endif
+/* use malloc instead of pool */
+#define MEMP_MEM_MALLOC                 1
+#define MEMP_MEM_INIT                  1
+#define MEM_LIBC_MALLOC                        1
+
+#endif /* LWIP_LWIPOPTS_H */
diff --git a/lib/lwip/port/if.c b/lib/lwip/port/if.c
new file mode 100644
index 0000000000..15d44054be
--- /dev/null
+++ b/lib/lwip/port/if.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <command.h>
+extern int eth_init(void); /* net.h */
+extern void string_to_enetaddr(const char *addr, uint8_t *enetaddr); /* net.h 
*/
+extern struct in_addr net_ip;
+extern u8 net_ethaddr[6];
+
+#include "lwip/debug.h"
+#include "lwip/arch.h"
+#include "netif/etharp.h"
+#include "lwip/stats.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include "lwip/netif.h"
+
+#include "lwip/ip.h"
+
+#define IFNAME0 'e'
+#define IFNAME1 '0'
+
+static struct pbuf *low_level_input(struct netif *netif);
+static int uboot_net_use_lwip;
+
+int ulwip_enabled(void)
+{
+       return uboot_net_use_lwip;
+}
+
+/* 1 - in loop
+ * 0 - no loop
+ */
+static int loop_lwip;
+
+/* ret 1 - in loop
+ *     0 - no loop
+ */
+int ulwip_in_loop(void)
+{
+       return loop_lwip;
+}
+
+void ulwip_loop_set(int loop)
+{
+       loop_lwip = loop;
+}
+
+static int ulwip_app_err;
+
+void ulwip_exit(int err)
+{
+       ulwip_app_err = err;
+       ulwip_loop_set(0);
+}
+
+int ulwip_app_get_err(void)
+{
+       return ulwip_app_err;
+}
+
+struct uboot_lwip_if {
+};
+
+#if defined(CONFIG_CMD_LWIP_DHCP)
+struct netif uboot_netif;
+#else
+static struct netif uboot_netif;
+#endif
+
+#define LWIP_PORT_INIT_NETMASK(addr)  IP4_ADDR((addr), 255, 255, 255, 0)
+
+extern uchar *net_rx_packet;
+extern int    net_rx_packet_len;
+
+int uboot_lwip_poll(void)
+{
+       struct pbuf *p;
+       int err;
+
+       p = low_level_input(&uboot_netif);
+       if (!p) {
+               printf("error p = low_level_input = NULL\n");
+               return 0;
+       }
+
+       err = ethernet_input(p, &uboot_netif);
+       if (err)
+               printf("ip4_input err %d\n", err);
+
+       return 0;
+}
+
+static struct pbuf *low_level_input(struct netif *netif)
+{
+       struct pbuf *p, *q;
+       u16_t len = net_rx_packet_len;
+       uchar *data = net_rx_packet;
+
+#if ETH_PAD_SIZE
+       len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+       /* We allocate a pbuf chain of pbufs from the pool. */
+       p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+       if (p) {
+#if ETH_PAD_SIZE
+               pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
+#endif
+               /* We iterate over the pbuf chain until we have read the entire
+                * packet into the pbuf.
+                */
+               for (q = p; q != NULL; q = q->next) {
+                       /* Read enough bytes to fill this pbuf in the chain. The
+                        * available data in the pbuf is given by the q->len
+                        * variable.
+                        * This does not necessarily have to be a memcpy, you 
can also preallocate
+                        * pbufs for a DMA-enabled MAC and after receiving 
truncate it to the
+                        * actually received size. In this case, ensure the 
tot_len member of the
+                        * pbuf is the sum of the chained pbuf len members.
+                        */
+                       MEMCPY(q->payload, data, q->len);
+                       data += q->len;
+               }
+               //acknowledge that packet has been read();
+
+#if ETH_PAD_SIZE
+               pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+               LINK_STATS_INC(link.recv);
+       } else {
+               //drop packet();
+               LINK_STATS_INC(link.memerr);
+               LINK_STATS_INC(link.drop);
+       }
+
+       return p;
+}
+
+static int ethernetif_input(struct pbuf *p, struct netif *netif)
+{
+       struct ethernetif *ethernetif;
+
+       ethernetif = netif->state;
+
+       /* move received packet into a new pbuf */
+       p = low_level_input(netif);
+
+       /* if no packet could be read, silently ignore this */
+       if (p) {
+               /* pass all packets to ethernet_input, which decides what 
packets it supports */
+               if (netif->input(p, netif) != ERR_OK) {
+                       LWIP_DEBUGF(NETIF_DEBUG, ("%s: IP input error\n", 
__func__));
+                       pbuf_free(p);
+                       p = NULL;
+               }
+       }
+       return 0;
+}
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+       int err;
+
+       err = eth_send(p->payload, p->len);
+       if (err != 0) {
+               printf("eth_send error %d\n", err);
+               return ERR_ABRT;
+       }
+       return ERR_OK;
+}
+
+err_t uboot_lwip_if_init(struct netif *netif)
+{
+       struct uboot_lwip_if *uif = (struct uboot_lwip_if 
*)malloc(sizeof(struct uboot_lwip_if));
+
+       if (!uif) {
+               printf("uboot_lwip_if: out of memory\n");
+               return ERR_MEM;
+       }
+       netif->state = uif;
+
+       netif->name[0] = IFNAME0;
+       netif->name[1] = IFNAME1;
+
+       netif->hwaddr_len = ETHARP_HWADDR_LEN;
+       string_to_enetaddr(env_get("ethaddr"), netif->hwaddr);
+#if defined(CONFIG_LWIP_LIB_DEBUG)
+       printf("              MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
+              netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
+              netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);
+#endif
+
+#if LWIP_IPV4
+       netif->output = etharp_output;
+#endif /* LWIP_IPV4 */
+#if LWIP_IPV6
+       netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
+       netif->linkoutput = low_level_output;
+       netif->mtu = 1500;
+       netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | 
NETIF_FLAG_LINK_UP;
+
+       eth_init(); /* activate u-boot eth dev */
+
+       if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
+               printf("Initialized LWIP stack\n");
+       }
+
+       return ERR_OK;
+}
+
+int uboot_lwip_init(void)
+{
+       ip4_addr_t ipaddr, netmask, gw;
+
+       if (uboot_net_use_lwip)
+               return CMD_RET_SUCCESS;
+
+       ip4_addr_set_zero(&gw);
+       ip4_addr_set_zero(&ipaddr);
+       ip4_addr_set_zero(&netmask);
+
+       ipaddr_aton(env_get("ipaddr"), &ipaddr);
+       ipaddr_aton(env_get("ipaddr"), &netmask);
+
+       LWIP_PORT_INIT_NETMASK(&netmask);
+       if (IS_ENABLED(CONFIG_LWIP_LIB_DEBUG)) {
+               printf("Starting lwIP, IP: %s\n", ip4addr_ntoa(&ipaddr));
+               printf("               GW: %s\n", ip4addr_ntoa(&gw));
+               printf("             mask: %s\n", ip4addr_ntoa(&netmask));
+       }
+
+       if (!netif_add(&uboot_netif, &ipaddr, &netmask, &gw,
+                      &uboot_netif, uboot_lwip_if_init, ethernetif_input))
+               printf("err: netif_add failed!\n");
+
+       netif_set_up(&uboot_netif);
+       netif_set_link_up(&uboot_netif);
+#if LWIP_IPV6
+       netif_create_ip6_linklocal_address(&uboot_netif, 1);
+       printf("             IPv6: %s\n", 
ip6addr_ntoa(netif_ip6_addr(uboot_netif, 0)));
+#endif /* LWIP_IPV6 */
+
+       uboot_net_use_lwip = 1;
+
+       return CMD_RET_SUCCESS;
+}
+
+/* placeholder, not used now */
+void uboot_lwip_destroy(void)
+{
+       uboot_net_use_lwip = 0;
+}
diff --git a/lib/lwip/port/include/arch/cc.h b/lib/lwip/port/include/arch/cc.h
new file mode 100644
index 0000000000..db30d7614e
--- /dev/null
+++ b/lib/lwip/port/include/arch/cc.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#define LWIP_ERRNO_INCLUDE <errno.h>
+
+#define LWIP_ERRNO_STDINCLUDE  1
+#define LWIP_NO_UNISTD_H 1
+#define LWIP_TIMEVAL_PRIVATE 1
+
+extern unsigned int lwip_port_rand(void);
+#define LWIP_RAND() (lwip_port_rand())
+
+/* different handling for unit test, normally not needed */
+#ifdef LWIP_NOASSERT_ON_ERROR
+#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
+                                                   handler; }} while (0)
+#endif
+
+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d 
in %s\n", \
+                                   x, __LINE__, __FILE__); } while (0)
+
+static inline int atoi(const char *str)
+{
+       int r = 0;
+       int i;
+
+       for (i = 0; str[i] != '\0'; ++i)
+               r = r * 10 + str[i] - '0';
+
+       return r;
+}
+
+#define LWIP_ERR_T int
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/lib/lwip/port/include/arch/sys_arch.h 
b/lib/lwip/port/include/arch/sys_arch.h
new file mode 100644
index 0000000000..8d95146275
--- /dev/null
+++ b/lib/lwip/port/include/arch/sys_arch.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#ifndef LWIP_ARCH_SYS_ARCH_H
+#define LWIP_ARCH_SYS_ARCH_H
+
+#include "lwip/opt.h"
+#include "lwip/arch.h"
+#include "lwip/err.h"
+
+#define ERR_NEED_SCHED 123
+
+void sys_arch_msleep(u32_t delay_ms);
+#define sys_msleep(ms) sys_arch_msleep(ms)
+
+#if SYS_LIGHTWEIGHT_PROT
+typedef u32_t sys_prot_t;
+#endif /* SYS_LIGHTWEIGHT_PROT */
+
+#include <errno.h>
+
+#define SYS_MBOX_NULL NULL
+#define SYS_SEM_NULL  NULL
+
+typedef u32_t sys_prot_t;
+
+struct sys_sem;
+typedef struct sys_sem *sys_sem_t;
+#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL))
+#define sys_sem_set_invalid(sem) do { if ((sem) != NULL) { *(sem) = NULL; }} 
while (0)
+
+/* let sys.h use binary semaphores for mutexes */
+#define LWIP_COMPAT_MUTEX 1
+#define LWIP_COMPAT_MUTEX_ALLOWED 1
+
+struct sys_mbox;
+typedef struct sys_mbox *sys_mbox_t;
+#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL))
+#define sys_mbox_set_invalid(mbox) do { if ((mbox) != NULL) { *(mbox) = NULL; 
}} while (0)
+
+struct sys_thread;
+typedef struct sys_thread *sys_thread_t;
+
+static inline u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
+{
+       return 0;
+};
+
+static inline err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
+{
+       return 0;
+};
+
+#define sys_sem_signal(s)
+
+#endif /* LWIP_ARCH_SYS_ARCH_H */
diff --git a/lib/lwip/port/include/limits.h b/lib/lwip/port/include/limits.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/lib/lwip/port/sys-arch.c b/lib/lwip/port/sys-arch.c
new file mode 100644
index 0000000000..609eeccf8c
--- /dev/null
+++ b/lib/lwip/port/sys-arch.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * (C) Copyright 2023 Linaro Ltd. <maxim.uvarov@linaro.org>
+ */
+
+#include <common.h>
+#include <rand.h>
+#include "lwip/opt.h"
+
+u32_t sys_now(void)
+{
+       return get_timer(0);
+}
+
+u32_t lwip_port_rand(void)
+{
+       return (u32_t)rand();
+}
+
diff --git a/lib/lwip/ulwip.h b/lib/lwip/ulwip.h
new file mode 100644
index 0000000000..11ca52aa1f
--- /dev/null
+++ b/lib/lwip/ulwip.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+int ulwip_enabled(void);
+int ulwip_in_loop(void);
+int ulwip_loop_set(int loop);
+int ulwip_exit(int err);
+int uboot_lwip_poll(void);
+int ulwip_app_get_err(void);
+void ulwip_set_tmo(int (*tmo)(void));
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index f41da4b37b..6031ad805d 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -367,8 +367,10 @@ int eth_send(void *packet, int length)
        if (!current)
                return -ENODEV;
 
-       if (!eth_is_active(current))
+       if (!eth_is_active(current)) {
+               printf("%s() !eth_is_active\n", __func__);
                return -EINVAL;
+       }
 
        ret = eth_get_ops(current)->send(current, packet, length);
        if (ret < 0) {
diff --git a/net/net.c b/net/net.c
index 57da9bda85..aa9dd85a99 100644
--- a/net/net.c
+++ b/net/net.c
@@ -121,6 +121,7 @@
 #endif
 #include <net/tcp.h>
 #include <net/wget.h>
+#include "../lib/lwip/ulwip.h"
 
 /** BOOTP EXTENTIONS **/
 
@@ -438,7 +439,11 @@ int net_loop(enum proto_t protocol)
 #endif
 
        bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
+#if defined(CONFIG_LWIP_LIB)
+       if (!ulwip_enabled() || !ulwip_in_loop())
+#endif
        net_init();
+
        if (eth_is_on_demand_init()) {
                eth_halt();
                eth_set_current();
@@ -619,10 +624,23 @@ restart:
                 */
                eth_rx();
 
+#if defined(CONFIG_LWIP_LIB)
+               if (ulwip_enabled()) {
+                       net_set_state(NETLOOP_CONTINUE);
+                       if (!ulwip_in_loop()) {
+                               if (ulwip_app_get_err())
+                                       net_set_state(NETLOOP_FAIL);
+                               else
+                                       net_set_state(NETLOOP_SUCCESS);
+                               goto done;
+                       }
+               }
+#endif
                /*
                 *      Abort if ctrl-c was pressed.
                 */
                if (ctrlc()) {
+                       printf("-->enter ctrlc\n");
                        /* cancel any ARP that may not have completed */
                        net_arp_wait_packet_ip.s_addr = 0;
 
@@ -1177,6 +1195,13 @@ void net_process_received_packet(uchar *in_packet, int 
len)
        if (len < ETHER_HDR_SIZE)
                return;
 
+#if defined(CONFIG_LWIP_LIB)
+       if (ulwip_enabled()) {
+               uboot_lwip_poll();
+               return;
+       }
+#endif
+
 #if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
        if (push_packet) {
                (*push_packet)(in_packet, len);
-- 
2.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]