Hi Heinrich, 

On Fri, Jul 21, 2023 at 12:03:46AM +0200, Heinrich Schuchardt wrote:
> The UEFI specification does not provide node types matching UCLASS_BLKMAP,
> UCLASS_HOST, UCLASS_VIRTIO block devices.
> 
> The current implementation uses VenHw() nodes with uclass specific GUIDs
> and a single byte for the device number appended. This leads to unaligned
> integers is succeeding device path nodes.

in succeeding 

> 
> The current implementation fails to create unique device paths for block
> devices based on other uclasses like UCLASS_PVBLOCK.

Is this fixed as well with this patch because we have a sane default switch
now?

> 
> Let's use a VenHw() node with the U-Boot GUID with a length dividable by
> four and encoding blkdesc->uclass_id as well as  blkdesc->devnum.
> 
> Signed-off-by: Heinrich Schuchardt <[email protected]>
> ---
>  lib/efi_loader/efi_device_path.c | 114 ++++++-------------------------
>  1 file changed, 21 insertions(+), 93 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_device_path.c 
> b/lib/efi_loader/efi_device_path.c
> index 19e8861ef4..5b050fa17c 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
> @@ -22,16 +22,6 @@
>  #include <asm-generic/unaligned.h>
>  #include <linux/compat.h> /* U16_MAX */
>  
> -#ifdef CONFIG_BLKMAP
> -const efi_guid_t efi_guid_blkmap_dev = U_BOOT_BLKMAP_DEV_GUID;
> -#endif
> -#ifdef CONFIG_SANDBOX
> -const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
> -#endif
> -#ifdef CONFIG_VIRTIO_BLK
> -const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID;
> -#endif
> -
>  /* template END node: */
>  const struct efi_device_path END = {
>       .type     = DEVICE_PATH_TYPE_END,
> @@ -524,43 +514,15 @@ __maybe_unused static unsigned int dp_size(struct 
> udevice *dev)
>                       return dp_size(dev->parent) +
>                               sizeof(struct efi_device_path_nvme);
>  #endif
> -#ifdef CONFIG_SANDBOX
> -             case UCLASS_HOST:
> -                      /*
> -                       * Sandbox's host device will be represented
> -                       * as vendor device with extra one byte for
> -                       * device number
> -                       */
> -                     return dp_size(dev->parent)
> -                             + sizeof(struct efi_device_path_vendor) + 1;
> -#endif
>  #ifdef CONFIG_USB
>               case UCLASS_MASS_STORAGE:
>                       return dp_size(dev->parent)
>                               + sizeof(struct efi_device_path_controller);
> -#endif
> -#ifdef CONFIG_VIRTIO_BLK
> -             case UCLASS_VIRTIO:
> -                      /*
> -                       * Virtio devices will be represented as a vendor
> -                       * device node with an extra byte for the device
> -                       * number.
> -                       */
> -                     return dp_size(dev->parent)
> -                             + sizeof(struct efi_device_path_vendor) + 1;
> -#endif
> -#ifdef CONFIG_BLKMAP
> -             case UCLASS_BLKMAP:
> -                      /*
> -                       * blkmap devices will be represented as a vendor
> -                       * device node with an extra byte for the device
> -                       * number.
> -                       */
> -                     return dp_size(dev->parent)
> -                             + sizeof(struct efi_device_path_vendor) + 1;
>  #endif
>               default:
> -                     return dp_size(dev->parent);
> +                     /* UCLASS_BLKMAP, UCLASS_HOST, UCLASS_VIRTIO */
> +                     return dp_size(dev->parent) +
> +                             sizeof(struct efi_device_path_udevice);


We are handling these for now , but this ends up being a catch all for all
UCLASS devices that arent explicitly handled but I guess this is ok?

>               }
>  #if defined(CONFIG_MMC)
>       case UCLASS_MMC:
> @@ -608,53 +570,7 @@ __maybe_unused static void *dp_fill(void *buf, struct 
> udevice *dev)
>       }
>  #endif
>       case UCLASS_BLK:
> -             switch (dev->parent->uclass->uc_drv->id) {
> -#ifdef CONFIG_BLKMAP
> -             case UCLASS_BLKMAP: {
> -                     struct efi_device_path_vendor *dp;
> -                     struct blk_desc *desc = dev_get_uclass_plat(dev);
> -
> -                     dp = dp_fill(buf, dev->parent);
> -                     dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
> -                     dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
> -                     dp->dp.length = sizeof(*dp) + 1;
> -                     memcpy(&dp->guid, &efi_guid_blkmap_dev,
> -                            sizeof(efi_guid_t));
> -                     dp->vendor_data[0] = desc->devnum;
> -                     return &dp->vendor_data[1];
> -                     }
> -#endif
> -#ifdef CONFIG_SANDBOX
> -             case UCLASS_HOST: {
> -                     /* stop traversing parents at this point: */
> -                     struct efi_device_path_vendor *dp;
> -                     struct blk_desc *desc = dev_get_uclass_plat(dev);
> -
> -                     dp = dp_fill(buf, dev->parent);
> -                     dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
> -                     dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
> -                     dp->dp.length = sizeof(*dp) + 1;
> -                     memcpy(&dp->guid, &efi_guid_host_dev,
> -                            sizeof(efi_guid_t));
> -                     dp->vendor_data[0] = desc->devnum;
> -                     return &dp->vendor_data[1];
> -                     }
> -#endif
> -#ifdef CONFIG_VIRTIO_BLK
> -             case UCLASS_VIRTIO: {
> -                     struct efi_device_path_vendor *dp;
> -                     struct blk_desc *desc = dev_get_uclass_plat(dev);
> -
> -                     dp = dp_fill(buf, dev->parent);
> -                     dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
> -                     dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
> -                     dp->dp.length = sizeof(*dp) + 1;
> -                     memcpy(&dp->guid, &efi_guid_virtio_dev,
> -                            sizeof(efi_guid_t));
> -                     dp->vendor_data[0] = desc->devnum;
> -                     return &dp->vendor_data[1];
> -                     }
> -#endif
> +             switch (device_get_uclass_id(dev->parent)) {
>  #ifdef CONFIG_IDE
>               case UCLASS_IDE: {
>                       struct efi_device_path_atapi *dp =
> @@ -744,12 +660,24 @@ __maybe_unused static void *dp_fill(void *buf, struct 
> udevice *dev)
>                       return &dp[1];
>               }
>  #endif
> -             default:
> -                     debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
> -                           __FILE__, __LINE__, __func__,
> -                           dev->name, dev->parent->uclass->uc_drv->id);
> -                     return dp_fill(buf, dev->parent);
> +             default: {
> +                     /* UCLASS_BLKMAP, UCLASS_HOST, UCLASS_VIRTIO */
> +                     struct efi_device_path_udevice *dp;
> +                     struct blk_desc *desc = dev_get_uclass_plat(dev);
> +
> +                     dp = dp_fill(buf, dev->parent);
> +                     dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
> +                     dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
> +                     dp->dp.length = sizeof(*dp);
> +                     memcpy(&dp->guid, &efi_u_boot_guid,
> +                            sizeof(efi_guid_t));
> +                     dp->uclass_id = (UCLASS_BLK & 0xffff) |
> +                                     (desc->uclass_id << 16);
> +                     dp->dev_number = desc->devnum;
> +
> +                     return &dp[1];
>               }
> +     }
>  #if defined(CONFIG_MMC)
>       case UCLASS_MMC: {
>               struct efi_device_path_sd_mmc_path *sddp =
> -- 
> 2.40.1
> 
In any case the patch LGTM
Reviewed-by: Ilias Apalodimas <[email protected]>

Reply via email to