
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@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' */