[PATCH v6 08/14] efi_loader: net: set EFI bootdevice device path to HTTP when loaded from wget

Heinrich Schuchardt xypron.glpk at gmx.de
Tue Dec 3 12:46:54 CET 2024


On 28.11.24 15:44, Adriano Cordova wrote:
> Set the device path of the efi boot device to an HTTP device path
> (as formed by efi_dp_from_http) when the next boot stage is loaded
> using wget (i.e., when wget is used with wget_info.set_bootdev=1).
>
> When loaded from HTTP, the device path should account for it so that
> the next boot stage is aware (e.g. grub only loads its http stack if
> it itself was loaded from http, and it checks this from its device path).
>
> Signed-off-by: Adriano Cordova <adrianox at gmail.com>

Reviewed-by: Heinrich Schuchardt <xypron.glpk at gmx.de>

> ---
> Changes in v6:
> - Add error handling to efi_net_set_dp and put it inside efi_set_bootdev,
>    reducing the number of calls to efi functions outside efi code.
> - Free net_dp before an update
> - Complete documentation for efi_net_get_dp. Error handling: returns NULL on error
> Changes in v5:
> - Add description of net_dp
> - Change a void** for an efi_device_path**
> (no changes since v2)
>
>   include/efi_loader.h             |  5 +++
>   lib/efi_loader/efi_bootbin.c     | 40 +++++++++++++----------
>   lib/efi_loader/efi_device_path.c |  5 +--
>   lib/efi_loader/efi_net.c         | 55 +++++++++++++++++++++++++++++++-
>   net/lwip/wget.c                  |  5 ++-
>   net/wget.c                       |  2 +-
>   6 files changed, 89 insertions(+), 23 deletions(-)
>
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index 96b204dfc3..0da0248db4 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -126,6 +126,10 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr,
>   #endif
>
>   #if CONFIG_IS_ENABLED(NETDEVICES) && CONFIG_IS_ENABLED(EFI_LOADER)
> +/* Call this to update the current device path of the efi net device */
> +efi_status_t efi_net_set_dp(const char *dev, const char *server);
> +/* Call this to get the current device path of the efi net device */
> +void efi_net_get_dp(struct efi_device_path **dp);
>   void efi_net_get_addr(struct efi_ipv4_address *ip,
>   		      struct efi_ipv4_address *mask,
>   		      struct efi_ipv4_address *gw);
> @@ -133,6 +137,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip,
>   		      struct efi_ipv4_address *mask,
>   		      struct efi_ipv4_address *gw);
>   #else
> +static inline void efi_net_get_dp(struct efi_device_path **dp) { }
>   static inline void efi_net_get_addr(struct efi_ipv4_address *ip,
>   				     struct efi_ipv4_address *mask,
>   				     struct efi_ipv4_address *gw) { }
> diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c
> index a87006b3c0..f8d3ee0bcf 100644
> --- a/lib/efi_loader/efi_bootbin.c
> +++ b/lib/efi_loader/efi_bootbin.c
> @@ -93,24 +93,32 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
>   	image_addr = buffer;
>   	image_size = buffer_size;
>
> +#if IS_ENABLED(CONFIG_NETDEVICES)
> +	ret = efi_net_set_dp(dev, devnr);
> +	if (ret != EFI_SUCCESS)
> +		goto error;
> +#endif
> +
>   	ret = efi_dp_from_name(dev, devnr, path, &device, &image);
> -	if (ret == EFI_SUCCESS) {
> -		bootefi_device_path = device;
> -		if (image) {
> -			/* FIXME: image should not contain device */
> -			struct efi_device_path *image_tmp = image;
> -
> -			efi_dp_split_file_path(image, &device, &image);
> -			efi_free_pool(image_tmp);
> -		}
> -		bootefi_image_path = image;
> -		log_debug("- boot device %pD\n", device);
> -		if (image)
> -			log_debug("- image %pD\n", image);
> -	} else {
> -		log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
> -		efi_clear_bootdev();
> +	if (ret != EFI_SUCCESS)
> +		goto error;
> +
> +	bootefi_device_path = device;
> +	if (image) {
> +		/* FIXME: image should not contain device */
> +		struct efi_device_path *image_tmp = image;
> +
> +		efi_dp_split_file_path(image, &device, &image);
> +		efi_free_pool(image_tmp);
>   	}
> +	bootefi_image_path = image;
> +	log_debug("- boot device %pD\n", device);
> +	if (image)
> +		log_debug("- image %pD\n", image);
> +	return;
> +error:
> +	log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
> +	efi_clear_bootdev();
>   }
>
>   /**
> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
> index a6d4300686..5eae6fd39c 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
> @@ -1185,8 +1185,9 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
>
>   		dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
>   				     (uintptr_t)image_addr, image_size);
> -	} else if (IS_ENABLED(CONFIG_NETDEVICES) && !strcmp(dev, "Net")) {
> -		dp = efi_dp_from_eth();
> +	} else if (IS_ENABLED(CONFIG_NETDEVICES) &&
> +		   (!strcmp(dev, "Net") || !strcmp(dev, "Http"))) {
> +		efi_net_get_dp(&dp);
>   	} else if (!strcmp(dev, "Uart")) {
>   		dp = efi_dp_from_uart();
>   	} else {
> diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
> index 3491d4c481..e8af2e3d95 100644
> --- a/lib/efi_loader/efi_net.c
> +++ b/lib/efi_loader/efi_net.c
> @@ -16,6 +16,7 @@
>    */
>
>   #include <efi_loader.h>
> +#include <dm.h>
>   #include <malloc.h>
>   #include <vsprintf.h>
>   #include <net.h>
> @@ -32,6 +33,13 @@ static int rx_packet_idx;
>   static int rx_packet_num;
>   static struct efi_net_obj *netobj;
>
> +/*
> + * The current network device path. This device path is updated when a new
> + * bootfile is downloaded from the network. If then the bootfile is loaded
> + * as an efi image, net_dp is passed as the device path of the loaded image.
> + */
> +static struct efi_device_path *net_dp;
> +
>   /*
>    * The notification function of this event is called in every timer cycle
>    * to check if a new network packet has been received.
> @@ -902,8 +910,10 @@ efi_status_t efi_net_register(void)
>   			     &netobj->net);
>   	if (r != EFI_SUCCESS)
>   		goto failure_to_add_protocol;
> +	if (!net_dp)
> +		efi_net_set_dp("Net", NULL);
>   	r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
> -			     efi_dp_from_eth());
> +			     net_dp);
>   	if (r != EFI_SUCCESS)
>   		goto failure_to_add_protocol;
>   	r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
> @@ -999,6 +1009,49 @@ out_of_resources:
>   	return EFI_OUT_OF_RESOURCES;
>   }
>
> +/**
> + * efi_net_set_dp() - set device path of efi net device
> + *
> + * This gets called to update the device path when a new boot
> + * file is downloaded
> + *
> + * @dev:	dev to set the device path from
> + * @server:	remote server address
> + * Return:	status code
> + */
> +efi_status_t efi_net_set_dp(const char *dev, const char *server)
> +{
> +	efi_free_pool(net_dp);
> +
> +	net_dp = NULL;
> +	if (!strcmp(dev, "Net"))
> +		net_dp = efi_dp_from_eth();
> +	else if (!strcmp(dev, "Http"))
> +		net_dp = efi_dp_from_http(server);
> +
> +	if (!net_dp)
> +		return EFI_OUT_OF_RESOURCES;
> +
> +	return EFI_SUCCESS;
> +}
> +
> +/**
> + * efi_net_get_dp() - get device path of efi net device
> + *
> + * Produce a copy of the current device path
> + *
> + * @dp:		copy of the current device path, or NULL on error
> + */
> +void efi_net_get_dp(struct efi_device_path **dp)
> +{
> +	if (!dp)
> +		return;
> +	if (!net_dp)
> +		efi_net_set_dp("Net", NULL);
> +	if (net_dp)
> +		*dp = efi_dp_dup(net_dp);
> +}
> +
>   /**
>    * efi_net_get_addr() - get IP address information
>    *
> diff --git a/net/lwip/wget.c b/net/lwip/wget.c
> index 2becb02f7b..fcc0e62512 100644
> --- a/net/lwip/wget.c
> +++ b/net/lwip/wget.c
> @@ -260,10 +260,9 @@ 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);
> -	if (wget_info->set_bootdev) {
> -		efi_set_bootdev("Net", "", ctx->path, map_sysmem(ctx->saved_daddr, 0),
> +	if (wget_info->set_bootdev)
> +		efi_set_bootdev("Http", ctx->server_name, 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)) {
> diff --git a/net/wget.c b/net/wget.c
> index f3b43b06b8..d338eaf4ef 100644
> --- a/net/wget.c
> +++ b/net/wget.c
> @@ -447,7 +447,7 @@ static void wget_handler(uchar *pkt, u16 dport,
>   		net_set_state(wget_loop_state);
>   		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,
> +			efi_set_bootdev("Http", NULL, image_url,
>   					map_sysmem(image_load_addr, 0),
>   					net_boot_file_size);
>   			env_set_hex("filesize", net_boot_file_size);



More information about the U-Boot mailing list