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