[RFC PATCH 5/5] lwip: implement wget command from http_client.c example

Maxim Uvarov maxim.uvarov at linaro.org
Fri May 5 12:25:29 CEST 2023


Intend of RFC is to show how we can reuse existance lwip apps
and examples inside u-boot. This commit shows how to do that with
minimal changes.

Signed-off-by: Maxim Uvarov <maxim.uvarov at linaro.org>
---
 .gitignore                        |  2 +
 doc/README.lwip                   | 34 ++++++++++++++++
 lib/lwip/Makefile                 |  8 ++++
 lib/lwip/apps/http/lwip-wget.c    | 67 +++++++++++++++++++++++++++++++
 lib/lwip/apps/http/rmstatic.patch | 47 ++++++++++++++++++++++
 lib/lwip/cmd-lwip.c               | 31 ++++++++++++++
 6 files changed, 189 insertions(+)
 create mode 100644 lib/lwip/apps/http/lwip-wget.c
 create mode 100644 lib/lwip/apps/http/rmstatic.patch

diff --git a/.gitignore b/.gitignore
index aeaf847543..339692f5a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,3 +107,5 @@ __pycache__
 
 /lib/lwip/lwip-external
 lib/lwip/apps/ping/ping.c
+lib/lwip/apps/http/http_client.c
+lib/lwip/apps/http/http_client.h
diff --git a/doc/README.lwip b/doc/README.lwip
index df3462ca1b..b59a1568b4 100644
--- a/doc/README.lwip
+++ b/doc/README.lwip
@@ -54,3 +54,37 @@ Unmodified ping example can be used. I did ping from qemu/u-boot tap device on t
 ping: recv 3 ms
 tcpdump on the host:
 5:09:10.925951 ARP, Request who-has 192.168.1.200 tell 192.168.1.200, length 28 15:09:12.114643 IP6 fe80::38e2:41ff:fec3:8bda > ip6-allrouters: ICMP6, router solicitation, length 16 15:09:20.370725 ARP, Request who-has 192.168.1.2 tell 192.168.1.200, length 28 15:09:20.370740 ARP, Reply 192.168.1.2 is-at 3a:e2:41:c3:8b:da (oui Unknown), length 28 15:09:20.372789 IP 192.168.1.200 > 192.168.1.2: ICMP echo request, id 44975, seq 1, length 40 15:09:20.372810 IP 192.168.1.2 > 192.168.1.200: ICMP echo reply, id 44975, seq 1, length 40 15:09:25.426636 ARP, Request who-has 192.168.1.200 tell 192.168.1.2, length 28 15:09:25.426870 ARP, Reply 192.168.1.200 is-at f6:11:01:02:03:04 (oui Unknown), length 28
+
+
+5. Wget example
+
+Http server has 192.168.1.2 IP address. (I did not port DNS resolving yet,
+but it's also exist in lwip.) So example just downloads some file with http
+protocol:
+
+Net:   eth0: virtio-net#30
+Hit any key to stop autoboot:  0 
+=> lwip init
+Starting lwIP, local interface IP is 192.168.1.200
+Initialized LWIP stack
+=> lwip wget http://192.168.1.2/
+downloading http://192.168.1.2/ to addr 0x40200000
+downloaded chunk size 294, to addr 0x40200000
+downloaded chunk size 318, to addr 0x40200126
+=> md 0x40200000 0x40
+40200000: 4f44213c 50595443 74682045 0a3e6c6d  <!DOCTYPE html>.
+40200010: 6d74683c 3c0a3e6c 64616568 743c0a3e  <html>.<head>.<t
+40200020: 656c7469 6c65573e 656d6f63 206f7420  itle>Welcome to 
+40200030: 6e69676e 2f3c2178 6c746974 3c0a3e65  nginx!</title>.<
+40200040: 6c797473 200a3e65 62202020 2079646f  style>.    body 
+40200050: 20200a7b 20202020 69772020 3a687464  {.        width:
+40200060: 65353320 200a3b6d 20202020 6d202020   35em;.        m
+40200070: 69677261 30203a6e 74756120 200a3b6f  argin: 0 auto;. 
+40200080: 20202020 66202020 2d746e6f 696d6166         font-fami
+40200090: 203a796c 6f686154 202c616d 64726556  ly: Tahoma, Verd
+402000a0: 2c616e61 69724120 202c6c61 736e6173  ana, Arial, sans
+402000b0: 7265732d 0a3b6669 20202020 2f3c0a7d  -serif;.    }.</
+402000c0: 6c797473 3c0a3e65 6165682f 3c0a3e64  style>.</head>.<
+402000d0: 79646f62 683c0a3e 65573e31 6d6f636c  body>.<h1>Welcom
+402000e0: 6f742065 69676e20 3c21786e 3e31682f  e to nginx!</h1>
+402000f0: 3e703c0a 79206649 7320756f 74206565  .<p>If you see t
diff --git a/lib/lwip/Makefile b/lib/lwip/Makefile
index 2c665dcb88..e28cfd726e 100644
--- a/lib/lwip/Makefile
+++ b/lib/lwip/Makefile
@@ -75,4 +75,12 @@ $(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
+$(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
+	patch -p0 < $(obj)/apps/http/rmstatic.patch
+
+obj-y += apps/http/http_client.o
+obj-y += apps/http/lwip-wget.o
 
diff --git a/lib/lwip/apps/http/lwip-wget.c b/lib/lwip/apps/http/lwip-wget.c
new file mode 100644
index 0000000000..f3295d67f1
--- /dev/null
+++ b/lib/lwip/apps/http/lwip-wget.c
@@ -0,0 +1,67 @@
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include "http_client.h"
+
+extern err_t
+httpc_init_connection(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name,
+                      u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg);
+extern err_t
+httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr);
+extern err_t
+httpc_free_state(httpc_state_t* req);
+
+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 == NULL) {
+		printf("httpc_tcp_recv bug!\n");
+		return ERR_BUF;
+	}
+
+	for (q = p; q != NULL; q = q->next) {
+		memcpy(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;
+}
+
+int lwip_wget(ulong addr, char *url)
+{
+  	httpc_state_t* req;
+	err_t err;
+	int port = 80;
+	ip4_addr_t  server_addr;
+	char *server_name;
+
+	daddr = addr;
+	IP4_ADDR(&server_addr, 192,168,1,2);
+	server_name = ipaddr_ntoa(&server_addr);
+
+	memset(&settings, 0, sizeof(httpc_connection_t));
+	err = httpc_init_connection(&req, &settings, server_name, port,
+			url, httpc_recv, NULL /*&addr*/);
+	if (err != ERR_OK) {
+		printf("httpc_init_connection failed\n");
+		return err;
+	}
+
+    	err = httpc_get_internal_addr(req, &server_addr);
+	if (err != ERR_OK) {
+		httpc_free_state(req);
+		printf("error httpc_get_internal_addr\n");
+		return err;
+	}
+
+	return 0;
+}
diff --git a/lib/lwip/apps/http/rmstatic.patch b/lib/lwip/apps/http/rmstatic.patch
new file mode 100644
index 0000000000..547236de52
--- /dev/null
+++ b/lib/lwip/apps/http/rmstatic.patch
@@ -0,0 +1,47 @@
+--- ./lib/lwip/lwip-external/src/apps/http/http_client.c	2023-05-03 15:26:42.038088829 +0000
++++ lib/lwip/apps/http/http_client.c	2023-05-03 15:27:25.298151160 +0000
+@@ -45,7 +48,7 @@
+  * - IPv6 support
+  */
+ 
+-#include "lwip/apps/http_client.h"
++#include "http_client.h"
+ 
+ #include "lwip/altcp_tcp.h"
+ #include "lwip/dns.h"
+@@ -153,7 +156,7 @@ typedef struct _httpc_state
+ } httpc_state_t;
+ 
+ /** Free http client state and deallocate all resources within */
+-static err_t
++/*static*/ err_t
+ httpc_free_state(httpc_state_t* req)
+ {
+   struct altcp_pcb* tpcb;
+@@ -415,7 +418,7 @@ httpc_tcp_connected(void *arg, struct al
+ }
+ 
+ /** Start the http request when the server IP addr is known */
+-static err_t
++/*static*/ err_t
+ httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr)
+ {
+   err_t err;
+@@ -592,7 +595,7 @@ httpc_init_connection_common(httpc_state
+ /**
+  * Initialize the connection struct
+  */
+-static err_t
++/* static */ err_t
+ httpc_init_connection(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name,
+                       u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg)
+ {
+@@ -786,7 +789,7 @@ httpc_fs_result(void *arg, httpc_result_
+ }
+ 
+ /** tcp recv callback */
+-static err_t
++/*static*/ err_t
+ httpc_fs_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
+ {
+   httpc_filestate_t *filestate = (httpc_filestate_t*)arg;
diff --git a/lib/lwip/cmd-lwip.c b/lib/lwip/cmd-lwip.c
index f2e25a8c29..797f0f2fe2 100644
--- a/lib/lwip/cmd-lwip.c
+++ b/lib/lwip/cmd-lwip.c
@@ -10,6 +10,7 @@
 #include <display_options.h>
 #include <memalign.h>
 #include <net.h>
+#include <image.h>
 
 #include "apps/ping/lwip_ping.h"
 
@@ -57,10 +58,39 @@ static int do_lwip_ping(struct cmd_tbl *cmdtp, int flag, int argc,
 	return CMD_RET_SUCCESS;
 }
 
+extern int lwip_wget(ulong addr, char *url);
+
+static 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];
+	printf("downloading %s to addr 0x%lx\n", url, image_load_addr);
+
+	eth_init(); /* activate u-boot eth dev */
+
+	lwip_wget(image_load_addr, url);
+
+	lwip_loop_set();
+	if (net_loop(LWIP) < 0) {
+		printf("wget failed\n");
+		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, "", ""),
+	U_BOOT_CMD_MKENT(wget, 2, 0, do_lwip_wget, "", ""),
 };
 
 static int do_ops(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -88,6 +118,7 @@ U_BOOT_CMD(
 	"info - display info\n"
 	"init - init LWIP\n"
 	"ping addr - ping addr\n"
+	"wget http://192.168.1.2/ \n"
 	);
 
 /* Old command kept for compatibility. Same as 'mmc info' */
-- 
2.30.2



More information about the U-Boot mailing list