@@ -104,3 +104,6 @@ __pycache__
# pylint files
/pylint.cur
/pylint.out/
+
+/lib/lwip/lwip-external
+lib/lwip/apps/ping/ping.c
@@ -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 */
@@ -1031,3 +1031,5 @@ menu "FWU Multi Bank Updates"
source lib/fwu_updates/Kconfig
endmenu
+
+source lib/lwip/Kconfig
@@ -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
new file mode 100644
@@ -0,0 +1,12 @@
+config LWIP_LIB
+ bool "Support LWIP library"
+ help
+ Selecting this option will enable the shared LWIP library code.
+
+config CMD_LWIP
+ bool "lwip"
+ default y
+ depends on LWIP_LIB
+ help
+ lwip networking command.
+
new file mode 100644
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2023 Linaro
+
+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-y += $(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-y += $(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-y += $(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-y += $(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-y += $(LWIPDIR)/netif/ethernet.o
+
+obj-y += port/if.o
+obj-y += port/sys-arch.o
+
+obj-$(CONFIG_CMD_LWIP) += cmd-lwip.o
+
+$(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
+ patch -p1 < $(obj)/apps/ping/rmstatic.patch
+
+obj-$(CONFIG_CMD_LWIP) += apps/ping/ping.o
+obj-$(CONFIG_CMD_LWIP) += apps/ping/lwip_ping.o
+
+
new file mode 100644
@@ -0,0 +1,33 @@
+#include "lwip/opt.h"
+
+#include "lwip_ping.h"
+
+#include "lwip/mem.h"
+#include "lwip/raw.h"
+#include "lwip/icmp.h"
+#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/timeouts.h"
+#include "lwip/inet_chksum.h"
+#include "lwip/prot/ip4.h"
+
+#include "lwip/ip_addr.h"
+
+extern const ip_addr_t* ping_target;
+
+static ip_addr_t ip_target;
+
+int lwip_ping_init(char *ping_addr)
+{
+ //ipaddr_aton(ping_addr, ping_target);
+ IP4_ADDR(&ip_target, 192,168,1,2);
+ ping_target = &ip_target;
+ if (ping_target == 0) {
+ printf("%s() wrong ping addr\n", __func__);
+ return -1;
+ }
+
+ ping_raw_init();
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,19 @@
+#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
+
+//void lwip_ping_init(const ip_addr_t* ping_addr);
+int lwip_ping_init(char *ping_addr);
+
+void ping_raw_init(void);
+void lwip_ping_send_now(void);
+
+#endif /* LWIP_PING_H */
new file mode 100644
new file mode 100644
@@ -0,0 +1,32 @@
+--- ./lib/lwip/lwip-external/contrib/apps/ping/ping.c 2023-05-03 13:20:14.510795833 +0000
++++ ./lib/lwip/apps/ping/ping.c 2023-05-03 14:37:05.497873883 +0000
+@@ -93,7 +93,7 @@
+ #endif
+
+ /* ping variables */
+-static const ip_addr_t* ping_target;
++const ip_addr_t* ping_target;
+ static u16_t ping_seq_num;
+ #ifdef LWIP_DEBUG
+ static u32_t ping_time;
+@@ -304,9 +304,9 @@ ping_recv(void *arg, struct raw_pcb *pcb
+ iecho = (struct icmp_echo_hdr *)p->payload;
+
+ if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
+- LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
++ printf("ping: recv ");
+ ip_addr_debug_print(PING_DEBUG, addr);
+- LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now()-ping_time)));
++ printf(" %"U32_F" ms\n", (sys_now()-ping_time));
+
+ /* do some ping result processing */
+ PING_RESULT(1);
+@@ -361,7 +361,7 @@ ping_timeout(void *arg)
+ sys_timeout(PING_DELAY, ping_timeout, pcb);
+ }
+
+-static void
++void
+ ping_raw_init(void)
+ {
+ ping_pcb = raw_new(IP_PROTO_ICMP);
new file mode 100644
@@ -0,0 +1,98 @@
+// 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 "apps/ping/lwip_ping.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 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;
+ }
+
+ eth_init(); /* activate u-boot eth dev */
+
+ printf("pinging addr: %s\n", argv[1]);
+ if (lwip_ping_init(argv[2])) {
+ printf("ping init fail\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ping_send_now();
+
+ lwip_loop_set();
+ if (net_loop(LWIP) < 0) {
+ printf("ping failed; host %s is not alive\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmds[] = {
+ U_BOOT_CMD_MKENT(info, 1, 0, do_lwip_info, "", ""),
+ U_BOOT_CMD_MKENT(init, 1, 0, do_lwip_init, "", ""),
+ U_BOOT_CMD_MKENT(ping, 2, 0, do_lwip_ping, "", ""),
+};
+
+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));
+
+ /* Drop the mmc command */
+ 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 - ping addr\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"
+);
new file mode 100644
@@ -0,0 +1,484 @@
+/**
+ * @file
+ *
+ * lwIP Options Configuration
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef LWIP_LWIPOPTS_H
+#define LWIP_LWIPOPTS_H
+
+
+
+/*
+ * Include user defined options first. Anything not defined in these files
+ * will be set to standard values. Override anything you don't like!
+ */
+#include "lwipopts.h"
+
+#define LWIP_DEBUG 1
+#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
+#define LWIP_TESTMODE 0
+#include "lwip/debug.h"
+
+/*
+ -----------------------------------------------
+ ---------- Platform specific locking ----------
+ -----------------------------------------------
+*/
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 0
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS 0
+
+/*
+ ------------------------------------
+ ---------- Memory options ----------
+ ------------------------------------
+*/
+
+/**
+ * MEM_ALIGNMENT: should be set to the alignment of the CPU
+ * 4 byte alignment -> #define MEM_ALIGNMENT 4
+ * 2 byte alignment -> #define MEM_ALIGNMENT 2
+ */
+#define MEM_ALIGNMENT 1
+
+/**
+ * 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.
+ */
+#define MEM_SIZE 1600
+
+/*
+ ------------------------------------------------
+ ---------- Internal Memory Pool Sizes ----------
+ ------------------------------------------------
+*/
+/**
+ * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF).
+ * If the application sends a lot of data out of ROM (or other static memory),
+ * this should be set high.
+ */
+#define MEMP_NUM_PBUF 4
+
+/**
+ * MEMP_NUM_RAW_PCB: Number of raw connection PCBs
+ * (requires the LWIP_RAW option)
+ */
+#define MEMP_NUM_RAW_PCB 2
+
+/**
+ * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+ * per active UDP "connection".
+ * (requires the LWIP_UDP option)
+ */
+#define MEMP_NUM_UDP_PCB 4
+
+/**
+ * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_PCB 2
+
+/**
+ * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_PCB_LISTEN 2
+
+/**
+ * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
+ * (requires the LWIP_TCP option)
+ */
+#define MEMP_NUM_TCP_SEG 16
+
+/**
+ * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
+ * reassembly (whole packets, not fragments!)
+ */
+#define MEMP_NUM_REASSDATA 1
+
+/**
+ * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
+ * packets (pbufs) that are waiting for an ARP request (to resolve
+ * their destination address) to finish.
+ * (requires the ARP_QUEUEING option)
+ */
+#define MEMP_NUM_ARP_QUEUE 2
+
+/**
+ * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
+ * (requires NO_SYS==0)
+ */
+#define MEMP_NUM_SYS_TIMEOUT 4
+
+/**
+ * MEMP_NUM_NETBUF: the number of struct netbufs.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#define MEMP_NUM_NETBUF 2
+
+/**
+ * MEMP_NUM_NETCONN: the number of struct netconns.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#define MEMP_NUM_NETCONN 32
+
+/**
+ * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
+ * for callback/timeout API communication.
+ * (only needed if you use tcpip.c)
+ */
+#define MEMP_NUM_TCPIP_MSG_API 8
+
+/**
+ * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
+ * for incoming packets.
+ * (only needed if you use tcpip.c)
+ */
+#define MEMP_NUM_TCPIP_MSG_INPKT 8
+
+/**
+ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
+ */
+#define PBUF_POOL_SIZE 8
+
+/*
+ ---------------------------------
+ ---------- ARP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_ARP==1: Enable ARP functionality.
+ */
+#define LWIP_ARP 1
+
+/*
+ --------------------------------
+ ---------- IP options ----------
+ --------------------------------
+*/
+/**
+ * IP_FORWARD==1: Enables the ability to forward IP packets across network
+ * interfaces. If you are going to run lwIP on a device with only one network
+ * interface, define this to 0.
+ */
+#define IP_FORWARD 0
+
+/**
+ * IP_OPTIONS: Defines the behavior for IP options.
+ * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
+ * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed).
+ */
+#define IP_OPTIONS_ALLOWED 1
+
+/**
+ * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
+ * this option does not affect outgoing packet sizes, which can be controlled
+ * via IP_FRAG.
+ */
+#define IP_REASSEMBLY 1
+
+/**
+ * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
+ * that this option does not affect incoming packet sizes, which can be
+ * controlled via IP_REASSEMBLY.
+ */
+#define IP_FRAG 1
+
+/**
+ * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
+ * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
+ * in this time, the whole packet is discarded.
+ */
+#define IP_REASS_MAXAGE 3
+
+/**
+ * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.
+ * Since the received pbufs are enqueued, be sure to configure
+ * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
+ * packets even if the maximum amount of fragments is enqueued for reassembly!
+ */
+#define IP_REASS_MAX_PBUFS 4
+
+/**
+ * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
+ * fragmentation. Otherwise pbufs are allocated and reference the original
+ * packet data to be fragmented.
+*/
+#define IP_FRAG_USES_STATIC_BUF 0
+
+/**
+ * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers.
+ */
+#define IP_DEFAULT_TTL 255
+
+/*
+ ----------------------------------
+ ---------- ICMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_ICMP==1: Enable ICMP module inside the IP stack.
+ * Be careful, disable that make your product non-compliant to RFC1122
+ */
+#define LWIP_ICMP 1
+
+/*
+ ---------------------------------
+ ---------- RAW options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
+ */
+#define LWIP_RAW 1
+
+/*
+ ----------------------------------
+ ---------- DHCP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_DHCP==1: Enable DHCP module.
+ */
+#define LWIP_DHCP 0
+
+
+/*
+ ------------------------------------
+ ---------- AUTOIP options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_AUTOIP==1: Enable AUTOIP module.
+ */
+#define LWIP_AUTOIP 0
+
+/*
+ ----------------------------------
+ ---------- SNMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP
+ * transport.
+ */
+#define LWIP_SNMP 0
+
+/*
+ ----------------------------------
+ ---------- IGMP options ----------
+ ----------------------------------
+*/
+/**
+ * LWIP_IGMP==1: Turn on IGMP module.
+ */
+#define LWIP_IGMP 0
+
+/*
+ ----------------------------------
+ ---------- DNS options -----------
+ ----------------------------------
+*/
+/**
+ * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
+ * transport.
+ */
+#define LWIP_DNS 0
+
+/*
+ ---------------------------------
+ ---------- UDP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_UDP==1: Turn on UDP.
+ */
+#define LWIP_UDP 1
+
+/*
+ ---------------------------------
+ ---------- TCP options ----------
+ ---------------------------------
+*/
+/**
+ * LWIP_TCP==1: Turn on TCP.
+ */
+#define LWIP_TCP 1
+
+#define LWIP_LISTEN_BACKLOG 0
+
+/*
+ ----------------------------------
+ ---------- Pbuf options ----------
+ ----------------------------------
+*/
+/**
+ * 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.
+ */
+#define PBUF_LINK_HLEN 16
+
+/**
+ * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
+ * designed to accommodate single full size TCP frame in one pbuf, including
+ * TCP_MSS, IP header, and link header.
+*
+ */
+#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN)
+
+/*
+ ------------------------------------
+ ---------- LOOPIF options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c
+ */
+#define LWIP_HAVE_LOOPIF 0
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 1
+
+/*
+ ------------------------------------
+ ---------- Socket options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 1
+
+/**
+ * SO_REUSE==1: Enable SO_REUSEADDR
+ */
+#define SO_REUSE 1
+
+/*
+ ----------------------------------------
+ ---------- Statistics options ----------
+ ----------------------------------------
+*/
+/**
+ * LWIP_STATS==1: Enable statistics collection in lwip_stats.
+ */
+#define LWIP_STATS 0
+/*
+ ---------------------------------
+ ---------- PPP options ----------
+ ---------------------------------
+*/
+/**
+ * PPP_SUPPORT==1: Enable PPP.
+ */
+#define PPP_SUPPORT 0
+
+
+
+/*
+ ---------------------------------------
+ ---------- Threading options ----------
+ ---------------------------------------
+*/
+
+#define LWIP_TCPIP_CORE_LOCKING 0
+
+// #if !NO_SYS
+// void sys_check_core_locking(void);
+// #define LWIP_ASSERT_CORE_LOCKED() sys_check_core_locking()
+// #endif
+
+#define LWIP_NETIF_LOOPBACK 1
+/* use malloc instead of pool */
+#define MEMP_MEM_MALLOC 1
+#define MEMP_MEM_INIT 1
+#define MEM_LIBC_MALLOC 1
+
+
+
+#endif /* LWIP_LWIPOPTS_H */
new file mode 100644
@@ -0,0 +1,256 @@
+#include <common.h>
+#include <command.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/ip.h"
+
+#define IFNAME0 'e'
+#define IFNAME1 '0'
+
+static struct pbuf * low_level_input(struct netif *netif);
+static int uboot_net_use_lwip = 0;
+
+int lwip_enabled(void)
+{
+ return uboot_net_use_lwip;
+}
+
+static int loop_lwip;
+
+/* ret 0 - loop not done
+ * 1 - loop is done.
+ */
+int lwip_loop_is_done(void)
+{
+ return loop_lwip;
+}
+
+void lwip_loop_set(void)
+{
+ loop_lwip = 1;
+}
+
+struct uboot_lwip_if {
+};
+
+static struct netif uboot_netif;
+
+#define LWIP_PORT_INIT_IPADDR(addr) IP4_ADDR((addr), 192,168,1,200)
+#define LWIP_PORT_INIT_GW(addr) IP4_ADDR((addr), 192,168,1,1)
+#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;
+
+ //printf("call for netif_poll!!!!\n");
+ //netif_poll(&uboot_netif);
+ p = low_level_input(&uboot_netif);
+ if (NULL == 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;
+
+ //printf("%s()\n", __func__);
+#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 != NULL) {
+#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;
+}
+
+/* Maxim: accoding to lwip idea this has to be separate thread in the background
+ * to poll RX packets from the network. The first we need to try to inject
+ * it directly to net/net.c eth_rx() calls. Assuming we do not implement threading
+ * and we roll in the main polling loop. Then socket operation should also be possible
+ * to call for non blocking socket calls.
+ * If lwip will not work without threading, then we to implement some scheduler with semaphores.
+ * We can base ./examples/standalone/sched.c example code for that.
+ *
+ */
+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 != NULL) {
+ /* pass all packets to ethernet_input, which decides what packets it supports */
+ if (netif->input(p, netif) != ERR_OK) {
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+ pbuf_free(p);
+ p = NULL;
+ }
+ }
+ return 0;
+}
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+ int err;
+
+ //printf("TX data len %d, tot_len %d\n", p->len, p->tot_len);
+ 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 == NULL) {
+ 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;
+ /* set MAC hardware address */
+ netif->hwaddr[0] = 0xf6;
+ netif->hwaddr[1] = 0x11;
+ netif->hwaddr[2] = 0x1;
+ netif->hwaddr[3] = 0x2;
+ netif->hwaddr[4] = 0x3;
+ netif->hwaddr[5] = 0x4;
+
+#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 */
+
+ printf("Initialized LWIP stack\n");
+ return ERR_OK;
+}
+
+int uboot_lwip_init()
+{
+ ip4_addr_t ipaddr, netmask, gw;
+ //int err;
+
+ if (uboot_net_use_lwip)
+ return CMD_RET_SUCCESS;
+
+ ip4_addr_set_zero(&gw);
+ ip4_addr_set_zero(&ipaddr);
+ ip4_addr_set_zero(&netmask);
+
+#if USE_DHCP
+ printf("Starting lwIP, local interface IP is dhcp-enabled\n");
+#elif USE_AUTOIP
+ printf("Starting lwIP, local interface IP is autoip-enabled\n");
+#else /* USE_DHCP */
+ LWIP_PORT_INIT_GW(&gw);
+ LWIP_PORT_INIT_IPADDR(&ipaddr);
+ LWIP_PORT_INIT_NETMASK(&netmask);
+ printf("Starting lwIP, local interface IP is %s\n", ip4addr_ntoa(&ipaddr));
+#endif /* USE_DHCP */
+
+ if (netif_add(&uboot_netif, &ipaddr, &netmask, &gw, &uboot_netif, uboot_lwip_if_init, ethernetif_input) == NULL)
+ 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(netif_default, 1);
+ printf("ip6 linklocal address: %s\n", ip6addr_ntoa(netif_ip6_addr(netif_default, 0)));
+#endif /* LWIP_IPV6 */
+
+#if LWIP_NETIF_STATUS_CALLBACK
+ netif_set_status_callback(netif_default, status_callback);
+#endif /* LWIP_NETIF_STATUS_CALLBACK */
+#if LWIP_NETIF_LINK_CALLBACK
+ netif_set_link_callback(netif_default, link_callback);
+#endif /* LWIP_NETIF_LINK_CALLBACK */
+
+#if LWIP_AUTOIP
+ autoip_set_struct(netif_default, &netif_autoip);
+#endif /* LWIP_AUTOIP */
+#if LWIP_DHCP
+ dhcp_set_struct(netif_default, &netif_dhcp);
+#endif /* LWIP_DHCP */
+ //netif_set_up(netif_default);
+#if USE_DHCP
+ err = dhcp_start(netif_default);
+ LWIP_ASSERT("dhcp_start failed", err == ERR_OK);
+#elif USE_AUTOIP
+ err = autoip_start(netif_default);
+ LWIP_ASSERT("autoip_start failed", err == ERR_OK);
+#endif /* USE_DHCP */
+ uboot_net_use_lwip = 1;
+
+ return CMD_RET_SUCCESS;
+}
new file mode 100644
@@ -0,0 +1,41 @@
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include "u-sockets.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 */
new file mode 100644
@@ -0,0 +1,78 @@
+#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;
+};
+
+#if 0
+#define sys_sem_new(s, c) ERR_OK
+
+#define sys_sem_wait(s)
+#define sys_sem_free(s)
+#define sys_sem_valid(s) 0
+#define sys_sem_set_invalid(s)
+#define sys_mutex_new(mu) ERR_OK
+#define sys_mutex_lock(mu)
+#define sys_mutex_unlock(mu)
+#define sys_mutex_free(mu)
+#define sys_mutex_valid(mu) 0
+#define sys_mutex_set_invalid(mu)
+#define sys_mbox_new(m, s) ERR_OK
+#define sys_mbox_fetch(m,d)
+#define sys_mbox_tryfetch(m,d)
+#define sys_mbox_post(m,d)
+
+#define sys_mbox_free(m)
+#define sys_mbox_valid(m)
+#define sys_mbox_set_invalid(m)
+#endif
+
+#define sys_sem_signal(s)
+
+//int uboot_lwip_init(void);
+
+#endif /* LWIP_ARCH_SYS_ARCH_H */
new file mode 100644
@@ -0,0 +1,26 @@
+#define MEMP_NUM_NETCONN 32
+#define LWIP_SOCKET_OFFSET 0
+#undef FD_SETSIZE
+/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */
+#define FD_SETSIZE MEMP_NUM_NETCONN
+#define FDSETSAFESET(n, code) do { \
+ if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \
+ code; }} while(0)
+#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\
+ (code) : 0)
+//#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] = (u8_t)((p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] | (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))))
+#define FD_SET(n, p) FDSETSAFESET(n, (p)->fds_bits[((n)-LWIP_SOCKET_OFFSET)/8] = (u8_t)((p)->fds_bits[((n)-LWIP_SOCKET_OFFSET)/8] | (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))))
+#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fds_bits[((n)-LWIP_SOCKET_OFFSET)/8] = (u8_t)((p)->fds_bits[((n)-LWIP_SOCKET_OFFSET)/8] & ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))))
+#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fds_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7)))
+#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p)))
+
+#if 0
+typedef struct fd_set
+{
+ unsigned char fd_bits [(FD_SETSIZE+7)/8];
+} fd_set;
+#endif
+
+#if FD_SETSIZE < (LWIP_SOCKET_OFFSET + MEMP_NUM_NETCONN)
+#error "external FD_SETSIZE too small for number of sockets"
+#endif
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
+#include <common.h>
+#include "lwip/opt.h"
+
+u32_t sys_now(void)
+{
+ return get_timer(0);
+}
@@ -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) {
@@ -201,6 +201,10 @@ static ulong time_delta;
/* THE transmit packet */
uchar *net_tx_packet;
+extern int lwip_enabled(void);
+extern int lwip_loop_is_done(void);
+extern int uboot_lwip_poll(void);
+
static int net_check_prereq(enum proto_t protocol);
static int net_try_count;
@@ -1177,6 +1181,16 @@ void net_process_received_packet(uchar *in_packet, int len)
if (len < ETHER_HDR_SIZE)
return;
+
+#if defined(CONFIG_LWIP_LIB)
+ if (lwip_enabled()) {
+ if (lwip_loop_is_done())
+ net_set_state(NETLOOP_SUCCESS);
+ uboot_lwip_poll();
+ return;
+ }
+#endif
+
#if defined(CONFIG_API) || defined(CONFIG_EFI_LOADER)
if (push_packet) {
(*push_packet)(in_packet, len);
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> --- .gitignore | 3 + include/net.h | 2 +- lib/Kconfig | 2 + lib/Makefile | 2 + lib/lwip/Kconfig | 12 + lib/lwip/Makefile | 78 ++++ lib/lwip/apps/ping/lwip_ping.c | 33 ++ lib/lwip/apps/ping/lwip_ping.h | 19 + lib/lwip/apps/ping/ping.h | 0 lib/lwip/apps/ping/rmstatic.patch | 32 ++ lib/lwip/cmd-lwip.c | 98 +++++ lib/lwip/lwipopts.h | 484 +++++++++++++++++++++++++ lib/lwip/port/if.c | 256 +++++++++++++ lib/lwip/port/include/arch/cc.h | 41 +++ lib/lwip/port/include/arch/sys_arch.h | 78 ++++ lib/lwip/port/include/arch/u-sockets.h | 26 ++ lib/lwip/port/include/limits.h | 0 lib/lwip/port/sys-arch.c | 7 + net/eth-uclass.c | 4 +- net/net.c | 14 + 20 files changed, 1189 insertions(+), 2 deletions(-) create mode 100644 lib/lwip/Kconfig create mode 100644 lib/lwip/Makefile 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/ping/rmstatic.patch 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/arch/u-sockets.h create mode 100644 lib/lwip/port/include/limits.h create mode 100644 lib/lwip/port/sys-arch.c