[PATCH 1/1] efi_loader: support all uclasses in device path

AKASHI Takahiro takahiro.akashi at linaro.org
Wed Jul 19 07:00:06 CEST 2023


On Wed, Jul 19, 2023 at 06:43:08AM +0200, Heinrich Schuchardt wrote:
> On devices with multiple USB mass storage devices errors like
> 
>     Path /../USB(0x0,0x0)/USB(0x1,0x0)/Ctrl(0x0)
>     already installed.
> 
> are seen. This is due to creating non-unique device paths. To uniquely
> identify devices we must provide path nodes for all devices on the path
> from the root device.
> 
> Add support for generating device path nodes for all uclasses.

I think that this is the last resort for devices that cannot be classified/
identified by any other means. If possible, should we provide a more concrete
device path?
I have submitted a patch specifically for USB devices in the past:
https://lists.denx.de/pipermail/u-boot/2021-November/468216.html

# I'm no longer working on this patch, though.

-Takahiro Akashi


> Reported-by: Suniel Mahesh <sunil at amarulasolutions.com>
> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
> ---
>  include/efi_api.h                |  7 ++++
>  lib/efi_loader/efi_device_path.c | 56 ++++++++++++++------------------
>  2 files changed, 32 insertions(+), 31 deletions(-)
> 
> diff --git a/include/efi_api.h b/include/efi_api.h
> index 55a4c989fc..8f5ef5f680 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -579,6 +579,13 @@ struct efi_device_path_vendor {
>  	u8 vendor_data[];
>  } __packed;
>  
> +struct efi_device_path_udevice {
> +	struct efi_device_path dp;
> +	efi_guid_t guid;
> +	int uclass_id;
> +	int dev_number;
> +} __packed;
> +
>  struct efi_device_path_controller {
>  	struct efi_device_path dp;
>  	u32 controller_number;
> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
> index 04ebb449ca..d0be869d94 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
> @@ -10,6 +10,7 @@
>  #include <common.h>
>  #include <blk.h>
>  #include <dm.h>
> +#include <dm/root.h>
>  #include <log.h>
>  #include <net.h>
>  #include <usb.h>
> @@ -38,16 +39,6 @@ const struct efi_device_path END = {
>  	.length   = sizeof(END),
>  };
>  
> -/* template ROOT node: */
> -static const struct efi_device_path_vendor ROOT = {
> -	.dp = {
> -		.type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
> -		.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
> -		.length   = sizeof(ROOT),
> -	},
> -	.guid = U_BOOT_GUID,
> -};
> -
>  #if defined(CONFIG_MMC)
>  /*
>   * Determine if an MMC device is an SD card.
> @@ -497,13 +488,12 @@ bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
>  __maybe_unused static unsigned int dp_size(struct udevice *dev)
>  {
>  	if (!dev || !dev->driver)
> -		return sizeof(ROOT);
> +		return sizeof(struct efi_device_path_udevice);
>  
>  	switch (device_get_uclass_id(dev)) {
>  	case UCLASS_ROOT:
> -	case UCLASS_SIMPLE_BUS:
>  		/* stop traversing parents at this point: */
> -		return sizeof(ROOT);
> +		return sizeof(struct efi_device_path_udevice);
>  	case UCLASS_ETH:
>  		return dp_size(dev->parent) +
>  			sizeof(struct efi_device_path_mac_addr);
> @@ -582,8 +572,8 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
>  		return dp_size(dev->parent) +
>  			sizeof(struct efi_device_path_usb);
>  	default:
> -		/* just skip over unknown classes: */
> -		return dp_size(dev->parent);
> +		return dp_size(dev->parent) +
> +			sizeof(struct efi_device_path_udevice);
>  	}
>  }
>  
> @@ -600,13 +590,6 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
>  		return buf;
>  
>  	switch (device_get_uclass_id(dev)) {
> -	case UCLASS_ROOT:
> -	case UCLASS_SIMPLE_BUS: {
> -		/* stop traversing parents at this point: */
> -		struct efi_device_path_vendor *vdp = buf;
> -		*vdp = ROOT;
> -		return &vdp[1];
> -	}
>  #ifdef CONFIG_NETDEVICES
>  	case UCLASS_ETH: {
>  		struct efi_device_path_mac_addr *dp =
> @@ -811,11 +794,24 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
>  
>  		return &udp[1];
>  	}
> -	default:
> -		/* If the uclass driver is missing, this will show NULL */
> -		log_debug("unhandled device class: %s (%s)\n", dev->name,
> -			  dev_get_uclass_name(dev));
> -		return dp_fill(buf, dev->parent);
> +	default: {
> +		struct efi_device_path_udevice *vdp;
> +		enum uclass_id uclass_id = device_get_uclass_id(dev);
> +
> +		if (uclass_id == UCLASS_ROOT)
> +			vdp = buf;
> +		else
> +			vdp = dp_fill(buf, dev->parent);
> +
> +		vdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
> +		vdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
> +		vdp->dp.length = sizeof(*vdp);
> +		memcpy(&vdp->guid, &efi_u_boot_guid, sizeof(efi_guid_t));
> +		vdp->uclass_id = uclass_id;
> +		vdp->dev_number = dev->seq_;
> +
> +		return &vdp[1];
> +	    }
>  	}
>  }
>  
> @@ -1052,14 +1048,12 @@ struct efi_device_path *efi_dp_from_uart(void)
>  {
>  	void *buf, *pos;
>  	struct efi_device_path_uart *uart;
> -	size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
> +	size_t dpsize = dp_size(dm_root()) + sizeof(*uart) + sizeof(END);
>  
>  	buf = efi_alloc(dpsize);
>  	if (!buf)
>  		return NULL;
> -	pos = buf;
> -	memcpy(pos, &ROOT, sizeof(ROOT));
> -	pos += sizeof(ROOT);
> +	pos = dp_fill(buf, dm_root());
>  	uart = pos;
>  	uart->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
>  	uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART;
> -- 
> 2.40.1
> 


More information about the U-Boot mailing list