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.uva...@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

Reply via email to