Merge tag 'efi-next-2024-11-18' of https://source.denx.de/u-boot/custodians/u-boot-efi into next

CI: https://source.denx.de/u-boot/custodians/u-boot-efi/-/pipelines/23430

- Prepare for implementing the EFI_HTTP_PROTOCOL:
  - Make wget functionality callable even if the wget command is not
    built (add CONFIG_WGET symbol).
  - Ensure that wget_with_dns() works the same with the old network
    stack and with lwIP.
  - Put server_name and port into wget_ctx.
  - Integrate struct wget_info into wget code.
  - Move ip_to_string to lib/net_utils.c
This commit is contained in:
Tom Rini
2024-11-18 10:46:06 -06:00
12 changed files with 217 additions and 55 deletions
+1 -4
View File
@@ -2115,11 +2115,8 @@ config CMD_TFTPBOOT
config CMD_WGET
bool "wget"
depends on CMD_NET
default y if SANDBOX
select PROT_TCP if NET
select PROT_TCP_LWIP if NET_LWIP
select PROT_DNS_LWIP if NET_LWIP
select WGET
help
wget is a simple command to download kernel, or other files,
from a http server over TCP.
+2
View File
@@ -196,6 +196,8 @@ U_BOOT_CMD(
#if defined(CONFIG_CMD_WGET)
static int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
wget_info = &default_wget_info;
return netboot_common(WGET, cmdtp, argc, argv);
}
+63 -1
View File
@@ -8,6 +8,7 @@
#include <env.h>
#include <hexdump.h>
#include <linux/if_ether.h>
#include <linux/sizes.h>
#include <linux/types.h>
#include <rand.h>
#include <time.h>
@@ -425,6 +426,16 @@ void string_to_enetaddr(const char *addr, uint8_t *enetaddr);
*/
struct in_addr string_to_ip(const char *s);
/**
* ip_to_string() - Convert a string to ip address
*
* Implemented in lib/net_utils.c (built unconditionally)
*
* @x: Input ip to parse
* @s: string containing the parsed ip address
*/
void ip_to_string(struct in_addr x, char *s);
/* copy a filename (allow for "..." notation, limit length) */
void copy_filename(char *dst, const char *src, int size);
@@ -494,7 +505,7 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
*
* @dst_addr: destination address to download the file
* @uri: uri string of target file of wget
* Return: downloaded file size, negative if failed
* Return: zero on success, negative if failed
*/
int wget_with_dns(ulong dst_addr, char *uri);
/**
@@ -506,4 +517,55 @@ int wget_with_dns(ulong dst_addr, char *uri);
bool wget_validate_uri(char *uri);
//int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
/**
* enum wget_http_method - http method
*/
enum wget_http_method {
WGET_HTTP_METHOD_GET,
WGET_HTTP_METHOD_POST,
WGET_HTTP_METHOD_PATCH,
WGET_HTTP_METHOD_OPTIONS,
WGET_HTTP_METHOD_CONNECT,
WGET_HTTP_METHOD_HEAD,
WGET_HTTP_METHOD_PUT,
WGET_HTTP_METHOD_DELETE,
WGET_HTTP_METHOD_TRACE,
WGET_HTTP_METHOD_MAX
};
/**
* define MAX_HTTP_HEADERS_SIZE - maximum headers buffer size
*
* When receiving http headers, wget fills a buffer with up
* to MAX_HTTP_HEADERS_SIZE bytes of header information.
*/
#define MAX_HTTP_HEADERS_SIZE SZ_64K
/**
* struct wget_http_info - wget parameters
* @method: HTTP Method. Filled by client.
* @status_code: HTTP status code. Filled by wget.
* @file_size: download size. Filled by wget.
* @buffer_size: size of client-provided buffer. Filled by client.
* @set_bootdev: set boot device with download. Filled by client.
* @check_buffer_size: check download does not exceed buffer size.
* Filled by client.
* @hdr_cont_len: content length according to headers. Filled by wget
* @headers: buffer for headers. Filled by wget.
*/
struct wget_http_info {
enum wget_http_method method;
u32 status_code;
ulong file_size;
ulong buffer_size;
bool set_bootdev;
bool check_buffer_size;
u32 hdr_cont_len;
char *headers;
};
extern struct wget_http_info default_wget_info;
extern struct wget_http_info *wget_info;
int wget_request(ulong dst_addr, char *uri, struct wget_http_info *info);
#endif /* __NET_COMMON_H__ */
-9
View File
@@ -16,15 +16,6 @@ void net_lwip_remove_netif(struct netif *netif);
struct netif *net_lwip_get_netif(void);
int net_lwip_rx(struct udevice *udev, struct netif *netif);
/**
* wget_with_dns() - runs dns host IP address resulution before wget
*
* @dst_addr: destination address to download the file
* @uri: uri string of target file of wget
* Return: downloaded file size, negative if failed
*/
int wget_with_dns(ulong dst_addr, char *uri);
/**
* wget_validate_uri() - varidate the uri
*
+11
View File
@@ -152,6 +152,17 @@ out_err:
}
#endif
void ip_to_string(struct in_addr x, char *s)
{
x.s_addr = ntohl(x.s_addr);
sprintf(s, "%d.%d.%d.%d",
(int) ((x.s_addr >> 24) & 0xff),
(int) ((x.s_addr >> 16) & 0xff),
(int) ((x.s_addr >> 8) & 0xff),
(int) ((x.s_addr >> 0) & 0xff)
);
}
void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
{
char *end;
+9
View File
@@ -244,6 +244,15 @@ config NET_RANDOM_ETHADDR
generated. It will be saved to the appropriate environment variable,
too.
config WGET
bool "Enable wget"
select PROT_TCP if NET
select PROT_TCP_LWIP if NET_LWIP
select PROT_DNS_LWIP if NET_LWIP
help
Selecting this will enable wget, an interface to send HTTP requests
via the network stack.
config TFTP_BLOCKSIZE
int "TFTP block size"
default 1468
+1 -1
View File
@@ -29,7 +29,7 @@ obj-$(CONFIG_$(PHASE_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
obj-$(CONFIG_CMD_WOL) += wol.o
obj-$(CONFIG_PROT_UDP) += udp.o
obj-$(CONFIG_PROT_TCP) += tcp.o
obj-$(CONFIG_CMD_WGET) += wget.o
obj-$(CONFIG_WGET) += wget.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
+1 -1
View File
@@ -5,4 +5,4 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
obj-$(CONFIG_CMD_DNS) += dns.o
obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
obj-$(CONFIG_CMD_WGET) += wget.o
obj-$(CONFIG_WGET) += wget.o
+44 -6
View File
@@ -23,6 +23,8 @@ enum done_state {
};
struct wget_ctx {
char server_name[SERVER_NAME_SIZE];
u16 port;
char *path;
ulong daddr;
ulong saved_daddr;
@@ -32,6 +34,18 @@ struct wget_ctx {
enum done_state done;
};
static void wget_lwip_fill_info(struct pbuf *hdr, u16_t hdr_len, u32_t hdr_cont_len)
{
if (wget_info->headers && hdr_len < MAX_HTTP_HEADERS_SIZE)
pbuf_copy_partial(hdr, (void *)wget_info->headers, hdr_len, 0);
wget_info->hdr_cont_len = (u32)hdr_cont_len;
}
static void wget_lwip_set_file_size(u32_t rx_content_len)
{
wget_info->file_size = (ulong)rx_content_len;
}
static int parse_url(char *url, char *host, u16 *port, char **path)
{
char *p, *pp;
@@ -176,6 +190,13 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
struct wget_ctx *ctx = arg;
ulong elapsed;
wget_info->status_code = (u32)srv_res;
if (err == ERR_BUF) {
ctx->done = FAILURE;
return;
}
if (httpc_result != HTTPC_RESULT_OK) {
log_err("\nHTTP client error %d\n", httpc_result);
ctx->done = FAILURE;
@@ -195,8 +216,11 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
printf("%u bytes transferred in %lu ms (", rx_content_len, elapsed);
print_size(rx_content_len / elapsed * 1000, "/s)\n");
printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, ctx->size);
efi_set_bootdev("Net", "", ctx->path, map_sysmem(ctx->saved_daddr, 0),
rx_content_len);
if (wget_info->set_bootdev) {
efi_set_bootdev("Net", "", ctx->path, map_sysmem(ctx->saved_daddr, 0),
rx_content_len);
}
wget_lwip_set_file_size(rx_content_len);
if (env_set_hex("filesize", rx_content_len) ||
env_set_hex("fileaddr", ctx->saved_daddr)) {
log_err("Could not set filesize or fileaddr\n");
@@ -207,15 +231,24 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
ctx->done = SUCCESS;
}
static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct pbuf *hdr,
u16_t hdr_len, u32_t content_len)
{
wget_lwip_fill_info(hdr, hdr_len, content_len);
if (wget_info->check_buffer_size && (ulong)content_len > wget_info->buffer_size)
return ERR_BUF;
return ERR_OK;
}
static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
{
char server_name[SERVER_NAME_SIZE];
httpc_connection_t conn;
httpc_state_t *state;
struct netif *netif;
struct wget_ctx ctx;
char *path;
u16 port;
ctx.daddr = dst_addr;
ctx.saved_daddr = dst_addr;
@@ -224,7 +257,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
ctx.prevsize = 0;
ctx.start_time = 0;
if (parse_url(uri, server_name, &port, &path))
if (parse_url(uri, ctx.server_name, &ctx.port, &path))
return CMD_RET_USAGE;
netif = net_lwip_new_netif(udev);
@@ -233,8 +266,9 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
memset(&conn, 0, sizeof(conn));
conn.result_fn = httpc_result_cb;
conn.headers_done_fn = httpc_headers_done_cb;
ctx.path = path;
if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
if (httpc_get_file_dns(ctx.server_name, ctx.port, path, &conn, httpc_recv_cb,
&ctx, &state)) {
net_lwip_remove_netif(netif);
return CMD_RET_FAILURE;
@@ -259,6 +293,9 @@ int wget_with_dns(ulong dst_addr, char *uri)
{
eth_set_current();
if (!wget_info)
wget_info = &default_wget_info;
return wget_loop(eth_get_dev(), dst_addr, uri);
}
@@ -285,6 +322,7 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
if (parse_legacy_arg(url, nurl, sizeof(nurl)))
return CMD_RET_FAILURE;
wget_info = &default_wget_info;
if (wget_with_dns(dst_addr, nurl))
return CMD_RET_FAILURE;
+14
View File
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <net-common.h>
void copy_filename(char *dst, const char *src, int size)
{
@@ -11,3 +12,16 @@ void copy_filename(char *dst, const char *src, int size)
*dst++ = *src++;
*dst = '\0';
}
struct wget_http_info default_wget_info = {
.method = WGET_HTTP_METHOD_GET,
.set_bootdev = true,
};
struct wget_http_info *wget_info;
int wget_request(ulong dst_addr, char *uri, struct wget_http_info *info)
{
wget_info = info ? info : &default_wget_info;
return wget_with_dns(dst_addr, uri);
}
-11
View File
@@ -1723,17 +1723,6 @@ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len)
return 1;
}
void ip_to_string(struct in_addr x, char *s)
{
x.s_addr = ntohl(x.s_addr);
sprintf(s, "%d.%d.%d.%d",
(int) ((x.s_addr >> 24) & 0xff),
(int) ((x.s_addr >> 16) & 0xff),
(int) ((x.s_addr >> 8) & 0xff),
(int) ((x.s_addr >> 0) & 0xff)
);
}
void vlan_to_string(ushort x, char *s)
{
x = ntohs(x);
+71 -22
View File
@@ -22,10 +22,10 @@ DECLARE_GLOBAL_DATA_PTR;
/* The default, change with environment variable 'httpdstp' */
#define SERVER_PORT 80
static const char bootfile1[] = "GET ";
static const char bootfileGET[] = "GET ";
static const char bootfileHEAD[] = "HEAD ";
static const char bootfile3[] = " HTTP/1.0\r\n\r\n";
static const char http_eom[] = "\r\n\r\n";
static const char http_ok[] = "200";
static const char content_len[] = "Content-Length";
static const char linefeed[] = "\r\n";
static struct in_addr web_server_ip;
@@ -77,7 +77,7 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len)
ulong newsize = offset + len;
uchar *ptr;
if (CONFIG_IS_ENABLED(LMB)) {
if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) {
if (store_addr < image_load_addr ||
lmb_read_check(store_addr, len)) {
printf("\nwget error: ");
@@ -132,8 +132,17 @@ static void wget_send_stored(void)
IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
offset = ptr;
memcpy(offset, &bootfile1, strlen(bootfile1));
offset += strlen(bootfile1);
switch (wget_info->method) {
case WGET_HTTP_METHOD_HEAD:
memcpy(offset, &bootfileHEAD, strlen(bootfileHEAD));
offset += strlen(bootfileHEAD);
break;
case WGET_HTTP_METHOD_GET:
default:
memcpy(offset, &bootfileGET, strlen(bootfileGET));
offset += strlen(bootfileGET);
break;
}
memcpy(offset, image_url, strlen(image_url));
offset += strlen(image_url);
@@ -193,6 +202,47 @@ static void wget_timeout_handler(void)
#define PKT_QUEUE_OFFSET 0x20000
#define PKT_QUEUE_PACKET_SIZE 0x800
static void wget_fill_info(const uchar *pkt, int hlen)
{
const char *first_space;
const char *second_space;
char *pos, *end;
if (wget_info->headers && hlen < MAX_HTTP_HEADERS_SIZE)
strncpy(wget_info->headers, pkt, hlen);
//Get status code
first_space = strchr(pkt, ' ');
if (!first_space) {
wget_info->status_code = -1;
return;
}
second_space = strchr(first_space + 1, ' ');
if (!second_space) {
wget_info->status_code = -1;
return;
}
wget_info->status_code = (u32)simple_strtoul(first_space + 1, &end, 10);
if (second_space != end)
wget_info->status_code = -1;
pos = strstr((char *)pkt, content_len);
if (pos) {
pos += sizeof(content_len) + 1;
while (*pos == ' ')
pos++;
content_length = simple_strtoul(pos, &end, 10);
debug_cond(DEBUG_WGET,
"wget: Connected Len %lu\n",
content_length);
wget_info->hdr_cont_len = content_length;
}
}
static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
u8 action, unsigned int tcp_ack_num, unsigned int len)
{
@@ -241,7 +291,11 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
initial_data_seq_num = tcp_seq_num + hlen;
next_data_seq_num = tcp_seq_num + len;
if (strstr((char *)pkt, http_ok) == 0) {
wget_fill_info(pkt, hlen);
debug_cond(DEBUG_WGET,
"wget: HTTP Status Code %d\n", wget_info->status_code);
if (wget_info->status_code != 200) {
debug_cond(DEBUG_WGET,
"wget: Connected Bad Xfer\n");
wget_loop_state = NETLOOP_FAIL;
@@ -251,17 +305,6 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
"wget: Connected Pkt %p hlen %x\n",
pkt, hlen);
pos = strstr((char *)pkt, content_len);
if (!pos) {
content_length = -1;
} else {
pos += sizeof(content_len) + 2;
strict_strtoul(pos, 10, &content_length);
debug_cond(DEBUG_WGET,
"wget: Connected Len %lu\n",
content_length);
}
net_boot_file_size = 0;
if (len > hlen) {
@@ -397,10 +440,13 @@ static void wget_handler(uchar *pkt, u16 dport,
case WGET_TRANSFERRED:
printf("Packets received %d, Transfer Successful\n", packets);
net_set_state(wget_loop_state);
efi_set_bootdev("Net", "", image_url,
map_sysmem(image_load_addr, 0),
net_boot_file_size);
env_set_hex("filesize", net_boot_file_size);
wget_info->file_size = net_boot_file_size;
if (wget_info->method == WGET_HTTP_METHOD_GET && wget_info->set_bootdev) {
efi_set_bootdev("Net", "", image_url,
map_sysmem(image_load_addr, 0),
net_boot_file_size);
env_set_hex("filesize", net_boot_file_size);
}
break;
}
}
@@ -425,6 +471,9 @@ static unsigned int random_port(void)
void wget_start(void)
{
if (!wget_info)
wget_info = &default_wget_info;
image_url = strchr(net_boot_file_name, ':');
if (image_url > 0) {
web_server_ip = string_to_ip(net_boot_file_name);
@@ -530,7 +579,7 @@ int wget_with_dns(ulong dst_addr, char *uri)
out:
free(str_copy);
return ret;
return ret < 0 ? ret : 0;
}
#endif