[U-Boot,v1,08/15] efi_loader: use proper device-paths for partitions

Message ID 20170810182948.27653-9-robdclark@gmail.com
State New
Delegated to: Alexander Graf
Headers show

Commit Message

Rob Clark Aug. 10, 2017, 6:29 p.m.
Also, create disk objects for the disk itself, in addition to the
partitions.  (UEFI terminology is a bit confusing, a "disk" object is
really a partition.)  This helps grub properly identify the boot device
since it is trying to match up partition "disk" object with it's parent
device.

Now instead of seeing devices like:

  /File(sdhci@07864000.blk)/EndEntire
  /File(usb_mass_storage.lun0)/EndEntire

You see:

  /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,dd904a8c00000000,1,1)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,dd904a8c00000000,1,1)/EndEntire
  /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,dd904a8c00000000,1,1)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,38ca680200000000,1,1)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,38ca680200000000,1,1)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,38ca680200000000,1,1)/EndEntire
  /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,38ca680200000000,1,1)/EndEntire

This is on a board with single USB disk and single sd-card.  The
UnknownMessaging(1d) node in the device-path is the MMC device,
but grub_efi_print_device_path() hasn't been updated yet for some
of the newer device-path sub-types.

This patch is inspired by a patch originally from Peter Jones, but
re-worked to use efi_device_path, so it doesn't much resemble the
original.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 lib/efi_loader/efi_disk.c | 54 +++++++++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 23 deletions(-)

Comments

Alexander Graf Aug. 12, 2017, 12:36 p.m. | #1
On 10.08.17 20:29, Rob Clark wrote:
> Also, create disk objects for the disk itself, in addition to the
> partitions.  (UEFI terminology is a bit confusing, a "disk" object is
> really a partition.)  This helps grub properly identify the boot device
> since it is trying to match up partition "disk" object with it's parent
> device.
> 
> Now instead of seeing devices like:
> 
>    /File(sdhci@07864000.blk)/EndEntire
>    /File(usb_mass_storage.lun0)/EndEntire
> 
> You see:
> 
>    /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
>    /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,dd904a8c00000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,dd904a8c00000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,dd904a8c00000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,38ca680200000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,38ca680200000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,38ca680200000000,1,1)/EndEntire
>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,38ca680200000000,1,1)/EndEntire
> 
> This is on a board with single USB disk and single sd-card.  The
> UnknownMessaging(1d) node in the device-path is the MMC device,
> but grub_efi_print_device_path() hasn't been updated yet for some
> of the newer device-path sub-types.
> 
> This patch is inspired by a patch originally from Peter Jones, but
> re-worked to use efi_device_path, so it doesn't much resemble the
> original.
> 
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>   lib/efi_loader/efi_disk.c | 54 +++++++++++++++++++++++++++--------------------
>   1 file changed, 31 insertions(+), 23 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
> index ed06485e33..eea65a402a 100644
> --- a/lib/efi_loader/efi_disk.c
> +++ b/lib/efi_loader/efi_disk.c
> @@ -28,11 +28,13 @@ struct efi_disk_obj {
>   	/* EFI Interface Media descriptor struct, referenced by ops */
>   	struct efi_block_io_media media;
>   	/* EFI device path to this block device */
> -	struct efi_device_path_file_path *dp;
> +	struct efi_device_path *dp;
> +	/* partition # */
> +	unsigned part;
>   	/* Offset into disk for simple partitions */
>   	lbaint_t offset;
>   	/* Internal block device */
> -	const struct blk_desc *desc;
> +	struct blk_desc *desc;
>   };
>   
>   static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
> @@ -172,26 +174,26 @@ static const struct efi_block_io block_io_disk_template = {
>   
>   static void efi_disk_add_dev(const char *name,
>   			     const char *if_typename,
> -			     const struct blk_desc *desc,
> +			     struct blk_desc *desc,
>   			     int dev_index,
> -			     lbaint_t offset)
> +			     lbaint_t offset,
> +			     unsigned part)
>   {
>   	struct efi_disk_obj *diskobj;
> -	struct efi_device_path_file_path *dp;
> -	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
>   
>   	/* Don't add empty devices */
>   	if (!desc->lba)
>   		return;
>   
> -	diskobj = calloc(1, objlen);
> +	diskobj = calloc(1, sizeof(*diskobj));
>   
>   	/* Fill in object data */
> -	dp = (void *)&diskobj[1];
> +	diskobj->dp = efi_dp_from_part(desc, part);
> +	diskobj->part = part;
>   	diskobj->parent.protocols[0].guid = &efi_block_io_guid;
>   	diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
>   	diskobj->parent.protocols[1].guid = &efi_guid_device_path;
> -	diskobj->parent.protocols[1].protocol_interface = dp;
> +	diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
>   	diskobj->parent.handle = diskobj;
>   	diskobj->ops = block_io_disk_template;
>   	diskobj->ifname = if_typename;
> @@ -207,17 +209,6 @@ static void efi_disk_add_dev(const char *name,
>   	diskobj->media.last_block = desc->lba - offset;
>   	diskobj->ops.media = &diskobj->media;
>   
> -	/* Fill in device path */
> -	diskobj->dp = dp;
> -	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
> -	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
> -	dp[0].dp.length = sizeof(*dp);
> -	ascii2unicode(dp[0].str, name);
> -
> -	dp[1].dp.type = DEVICE_PATH_TYPE_END;
> -	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
> -	dp[1].dp.length = sizeof(*dp);
> -
>   	/* Hook up to the device list */
>   	list_add_tail(&diskobj->parent.link, &efi_obj_list);
>   }
> @@ -236,14 +227,18 @@ static int efi_disk_create_eltorito(struct blk_desc *desc,
>   	if (desc->part_type != PART_TYPE_ISO)
>   		return 0;
>   
> +	/* and devices for each partition: */
>   	while (!part_get_info(desc, part, &info)) {
>   		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
>   			 part);
>   		efi_disk_add_dev(devname, if_typename, desc, diskid,
> -				 info.start);
> +				 info.start, part);

In the el torito case we're doing basically what you're suggesting. Why 
can't we just rename the function and remove the PART_TYPE_ISO check?

>   		part++;
>   		disks++;
>   	}
> +
> +	/* ... and add block device: */
> +	efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
>   #endif
>   
>   	return disks;
> @@ -271,9 +266,22 @@ int efi_disk_register(void)
>   	     uclass_next_device_check(&dev)) {
>   		struct blk_desc *desc = dev_get_uclass_platdata(dev);
>   		const char *if_typename = dev->driver->name;
> +		disk_partition_t info;
> +		int part = 1;
>   
>   		printf("Scanning disk %s...\n", dev->name);
> -		efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
> +
> +		/* add devices for each partition: */

Doesn't this only kick in for the DM case, but misses out on the legacy one?


Alex

> +		while (!part_get_info(desc, part, &info)) {
> +			efi_disk_add_dev(dev->name, if_typename, desc,
> +					desc->devnum, 0, part);
> +			part++;
> +		}
> +
> +		/* ... and add block device: */
> +		efi_disk_add_dev(dev->name, if_typename, desc,
> +				desc->devnum, 0, 0);
> +
>   		disks++;
>   
>   		/*
> @@ -309,7 +317,7 @@ int efi_disk_register(void)
>   
>   			snprintf(devname, sizeof(devname), "%s%d",
>   				 if_typename, i);
> -			efi_disk_add_dev(devname, if_typename, desc, i, 0);
> +			efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
>   			disks++;
>   
>   			/*
>
Rob Clark Aug. 12, 2017, 2:31 p.m. | #2
On Sat, Aug 12, 2017 at 8:36 AM, Alexander Graf <agraf@suse.de> wrote:
>
>
> On 10.08.17 20:29, Rob Clark wrote:
>>
>> Also, create disk objects for the disk itself, in addition to the
>> partitions.  (UEFI terminology is a bit confusing, a "disk" object is
>> really a partition.)  This helps grub properly identify the boot device
>> since it is trying to match up partition "disk" object with it's parent
>> device.
>>
>> Now instead of seeing devices like:
>>
>>    /File(sdhci@07864000.blk)/EndEntire
>>    /File(usb_mass_storage.lun0)/EndEntire
>>
>> You see:
>>
>>    /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
>>
>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,dd904a8c00000000,1,1)/EndEntire
>>
>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,dd904a8c00000000,1,1)/EndEntire
>>
>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,dd904a8c00000000,1,1)/EndEntire
>>    /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
>>
>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,38ca680200000000,1,1)/EndEntire
>>
>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,38ca680200000000,1,1)/EndEntire
>>
>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,38ca680200000000,1,1)/EndEntire
>>
>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,38ca680200000000,1,1)/EndEntire
>>
>> This is on a board with single USB disk and single sd-card.  The
>> UnknownMessaging(1d) node in the device-path is the MMC device,
>> but grub_efi_print_device_path() hasn't been updated yet for some
>> of the newer device-path sub-types.
>>
>> This patch is inspired by a patch originally from Peter Jones, but
>> re-worked to use efi_device_path, so it doesn't much resemble the
>> original.
>>
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>> ---
>>   lib/efi_loader/efi_disk.c | 54
>> +++++++++++++++++++++++++++--------------------
>>   1 file changed, 31 insertions(+), 23 deletions(-)
>>
>> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
>> index ed06485e33..eea65a402a 100644
>> --- a/lib/efi_loader/efi_disk.c
>> +++ b/lib/efi_loader/efi_disk.c
>> @@ -28,11 +28,13 @@ struct efi_disk_obj {
>>         /* EFI Interface Media descriptor struct, referenced by ops */
>>         struct efi_block_io_media media;
>>         /* EFI device path to this block device */
>> -       struct efi_device_path_file_path *dp;
>> +       struct efi_device_path *dp;
>> +       /* partition # */
>> +       unsigned part;
>>         /* Offset into disk for simple partitions */
>>         lbaint_t offset;
>>         /* Internal block device */
>> -       const struct blk_desc *desc;
>> +       struct blk_desc *desc;
>>   };
>>     static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
>> @@ -172,26 +174,26 @@ static const struct efi_block_io
>> block_io_disk_template = {
>>     static void efi_disk_add_dev(const char *name,
>>                              const char *if_typename,
>> -                            const struct blk_desc *desc,
>> +                            struct blk_desc *desc,
>>                              int dev_index,
>> -                            lbaint_t offset)
>> +                            lbaint_t offset,
>> +                            unsigned part)
>>   {
>>         struct efi_disk_obj *diskobj;
>> -       struct efi_device_path_file_path *dp;
>> -       int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
>>         /* Don't add empty devices */
>>         if (!desc->lba)
>>                 return;
>>   -     diskobj = calloc(1, objlen);
>> +       diskobj = calloc(1, sizeof(*diskobj));
>>         /* Fill in object data */
>> -       dp = (void *)&diskobj[1];
>> +       diskobj->dp = efi_dp_from_part(desc, part);
>> +       diskobj->part = part;
>>         diskobj->parent.protocols[0].guid = &efi_block_io_guid;
>>         diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
>>         diskobj->parent.protocols[1].guid = &efi_guid_device_path;
>> -       diskobj->parent.protocols[1].protocol_interface = dp;
>> +       diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
>>         diskobj->parent.handle = diskobj;
>>         diskobj->ops = block_io_disk_template;
>>         diskobj->ifname = if_typename;
>> @@ -207,17 +209,6 @@ static void efi_disk_add_dev(const char *name,
>>         diskobj->media.last_block = desc->lba - offset;
>>         diskobj->ops.media = &diskobj->media;
>>   -     /* Fill in device path */
>> -       diskobj->dp = dp;
>> -       dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
>> -       dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
>> -       dp[0].dp.length = sizeof(*dp);
>> -       ascii2unicode(dp[0].str, name);
>> -
>> -       dp[1].dp.type = DEVICE_PATH_TYPE_END;
>> -       dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
>> -       dp[1].dp.length = sizeof(*dp);
>> -
>>         /* Hook up to the device list */
>>         list_add_tail(&diskobj->parent.link, &efi_obj_list);
>>   }
>> @@ -236,14 +227,18 @@ static int efi_disk_create_eltorito(struct blk_desc
>> *desc,
>>         if (desc->part_type != PART_TYPE_ISO)
>>                 return 0;
>>   +     /* and devices for each partition: */
>>         while (!part_get_info(desc, part, &info)) {
>>                 snprintf(devname, sizeof(devname), "%s:%d", pdevname,
>>                          part);
>>                 efi_disk_add_dev(devname, if_typename, desc, diskid,
>> -                                info.start);
>> +                                info.start, part);
>
>
> In the el torito case we're doing basically what you're suggesting. Why
> can't we just rename the function and remove the PART_TYPE_ISO check?

very nearly, except for the devname..  hmm, but actually devname is no
longer used so maybe we can just delete the eltorito case altogether.
tbh this was a case that I don't really have a good way to test, so I
mostly just wanted to leave it as-is.  If someone did have a way to
test this, it seems likely that we could delete some code.

>>                 part++;
>>                 disks++;
>>         }
>> +
>> +       /* ... and add block device: */
>> +       efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
>>   #endif
>>         return disks;
>> @@ -271,9 +266,22 @@ int efi_disk_register(void)
>>              uclass_next_device_check(&dev)) {
>>                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
>>                 const char *if_typename = dev->driver->name;
>> +               disk_partition_t info;
>> +               int part = 1;
>>                 printf("Scanning disk %s...\n", dev->name);
>> -               efi_disk_add_dev(dev->name, if_typename, desc,
>> desc->devnum, 0);
>> +
>> +               /* add devices for each partition: */
>
>
> Doesn't this only kick in for the DM case, but misses out on the legacy one?

Yeah.  But I also don't have a good way to test legacy case, so I
mostly just wanted to not break what was working before.

BR,
-R

>
> Alex
>
>
>> +               while (!part_get_info(desc, part, &info)) {
>> +                       efi_disk_add_dev(dev->name, if_typename, desc,
>> +                                       desc->devnum, 0, part);
>> +                       part++;
>> +               }
>> +
>> +               /* ... and add block device: */
>> +               efi_disk_add_dev(dev->name, if_typename, desc,
>> +                               desc->devnum, 0, 0);
>> +
>>                 disks++;
>>                 /*
>> @@ -309,7 +317,7 @@ int efi_disk_register(void)
>>                         snprintf(devname, sizeof(devname), "%s%d",
>>                                  if_typename, i);
>> -                       efi_disk_add_dev(devname, if_typename, desc, i,
>> 0);
>> +                       efi_disk_add_dev(devname, if_typename, desc, i, 0,
>> 0);
>>                         disks++;
>>                         /*
>>
>
Alexander Graf Aug. 12, 2017, 5:25 p.m. | #3
> Am 12.08.2017 um 16:31 schrieb Rob Clark <robdclark@gmail.com>:
> 
>> On Sat, Aug 12, 2017 at 8:36 AM, Alexander Graf <agraf@suse.de> wrote:
>> 
>> 
>>> On 10.08.17 20:29, Rob Clark wrote:
>>> 
>>> Also, create disk objects for the disk itself, in addition to the
>>> partitions.  (UEFI terminology is a bit confusing, a "disk" object is
>>> really a partition.)  This helps grub properly identify the boot device
>>> since it is trying to match up partition "disk" object with it's parent
>>> device.
>>> 
>>> Now instead of seeing devices like:
>>> 
>>>   /File(sdhci@07864000.blk)/EndEntire
>>>   /File(usb_mass_storage.lun0)/EndEntire
>>> 
>>> You see:
>>> 
>>>   /ACPI(133741d0,0)/UnknownMessaging(1d)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(0,800,64000,dd904a8c00000000,1,1)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(1,64800,200000,dd904a8c00000000,1,1)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/UnknownMessaging(1d)/HD(2,264800,19a000,dd904a8c00000000,1,1)/EndEntire
>>>   /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(0,800,60000,38ca680200000000,1,1)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(1,61000,155000,38ca680200000000,1,1)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(2,20fa800,1bbf8800,38ca680200000000,1,1)/EndEntire
>>> 
>>> /ACPI(133741d0,0)/USB(0,0)/USB(0,0)/USB(0,0)/HD(3,1b6800,1f44000,38ca680200000000,1,1)/EndEntire
>>> 
>>> This is on a board with single USB disk and single sd-card.  The
>>> UnknownMessaging(1d) node in the device-path is the MMC device,
>>> but grub_efi_print_device_path() hasn't been updated yet for some
>>> of the newer device-path sub-types.
>>> 
>>> This patch is inspired by a patch originally from Peter Jones, but
>>> re-worked to use efi_device_path, so it doesn't much resemble the
>>> original.
>>> 
>>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>>> ---
>>>  lib/efi_loader/efi_disk.c | 54
>>> +++++++++++++++++++++++++++--------------------
>>>  1 file changed, 31 insertions(+), 23 deletions(-)
>>> 
>>> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
>>> index ed06485e33..eea65a402a 100644
>>> --- a/lib/efi_loader/efi_disk.c
>>> +++ b/lib/efi_loader/efi_disk.c
>>> @@ -28,11 +28,13 @@ struct efi_disk_obj {
>>>        /* EFI Interface Media descriptor struct, referenced by ops */
>>>        struct efi_block_io_media media;
>>>        /* EFI device path to this block device */
>>> -       struct efi_device_path_file_path *dp;
>>> +       struct efi_device_path *dp;
>>> +       /* partition # */
>>> +       unsigned part;
>>>        /* Offset into disk for simple partitions */
>>>        lbaint_t offset;
>>>        /* Internal block device */
>>> -       const struct blk_desc *desc;
>>> +       struct blk_desc *desc;
>>>  };
>>>    static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
>>> @@ -172,26 +174,26 @@ static const struct efi_block_io
>>> block_io_disk_template = {
>>>    static void efi_disk_add_dev(const char *name,
>>>                             const char *if_typename,
>>> -                            const struct blk_desc *desc,
>>> +                            struct blk_desc *desc,
>>>                             int dev_index,
>>> -                            lbaint_t offset)
>>> +                            lbaint_t offset,
>>> +                            unsigned part)
>>>  {
>>>        struct efi_disk_obj *diskobj;
>>> -       struct efi_device_path_file_path *dp;
>>> -       int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
>>>        /* Don't add empty devices */
>>>        if (!desc->lba)
>>>                return;
>>>  -     diskobj = calloc(1, objlen);
>>> +       diskobj = calloc(1, sizeof(*diskobj));
>>>        /* Fill in object data */
>>> -       dp = (void *)&diskobj[1];
>>> +       diskobj->dp = efi_dp_from_part(desc, part);
>>> +       diskobj->part = part;
>>>        diskobj->parent.protocols[0].guid = &efi_block_io_guid;
>>>        diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
>>>        diskobj->parent.protocols[1].guid = &efi_guid_device_path;
>>> -       diskobj->parent.protocols[1].protocol_interface = dp;
>>> +       diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
>>>        diskobj->parent.handle = diskobj;
>>>        diskobj->ops = block_io_disk_template;
>>>        diskobj->ifname = if_typename;
>>> @@ -207,17 +209,6 @@ static void efi_disk_add_dev(const char *name,
>>>        diskobj->media.last_block = desc->lba - offset;
>>>        diskobj->ops.media = &diskobj->media;
>>>  -     /* Fill in device path */
>>> -       diskobj->dp = dp;
>>> -       dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
>>> -       dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
>>> -       dp[0].dp.length = sizeof(*dp);
>>> -       ascii2unicode(dp[0].str, name);
>>> -
>>> -       dp[1].dp.type = DEVICE_PATH_TYPE_END;
>>> -       dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
>>> -       dp[1].dp.length = sizeof(*dp);
>>> -
>>>        /* Hook up to the device list */
>>>        list_add_tail(&diskobj->parent.link, &efi_obj_list);
>>>  }
>>> @@ -236,14 +227,18 @@ static int efi_disk_create_eltorito(struct blk_desc
>>> *desc,
>>>        if (desc->part_type != PART_TYPE_ISO)
>>>                return 0;
>>>  +     /* and devices for each partition: */
>>>        while (!part_get_info(desc, part, &info)) {
>>>                snprintf(devname, sizeof(devname), "%s:%d", pdevname,
>>>                         part);
>>>                efi_disk_add_dev(devname, if_typename, desc, diskid,
>>> -                                info.start);
>>> +                                info.start, part);
>> 
>> 
>> In the el torito case we're doing basically what you're suggesting. Why
>> can't we just rename the function and remove the PART_TYPE_ISO check?
> 
> very nearly, except for the devname..  hmm, but actually devname is no
> longer used so maybe we can just delete the eltorito case altogether.
> tbh this was a case that I don't really have a good way to test, so I
> mostly just wanted to leave it as-is.  If someone did have a way to
> test this, it seems likely that we could delete some code.

Just grab an openSUSE aarch64 iso :).

> 
>>>                part++;
>>>                disks++;
>>>        }
>>> +
>>> +       /* ... and add block device: */
>>> +       efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
>>>  #endif
>>>        return disks;
>>> @@ -271,9 +266,22 @@ int efi_disk_register(void)
>>>             uclass_next_device_check(&dev)) {
>>>                struct blk_desc *desc = dev_get_uclass_platdata(dev);
>>>                const char *if_typename = dev->driver->name;
>>> +               disk_partition_t info;
>>> +               int part = 1;
>>>                printf("Scanning disk %s...\n", dev->name);
>>> -               efi_disk_add_dev(dev->name, if_typename, desc,
>>> desc->devnum, 0);
>>> +
>>> +               /* add devices for each partition: */
>> 
>> 
>> Doesn't this only kick in for the DM case, but misses out on the legacy one?
> 
> Yeah.  But I also don't have a good way to test legacy case, so I
> mostly just wanted to not break what was working before.

Mmmh, does the rpi use legacy? In that case I could give you a simple qemu test environment.


Alex

Patch

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index ed06485e33..eea65a402a 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -28,11 +28,13 @@  struct efi_disk_obj {
 	/* EFI Interface Media descriptor struct, referenced by ops */
 	struct efi_block_io_media media;
 	/* EFI device path to this block device */
-	struct efi_device_path_file_path *dp;
+	struct efi_device_path *dp;
+	/* partition # */
+	unsigned part;
 	/* Offset into disk for simple partitions */
 	lbaint_t offset;
 	/* Internal block device */
-	const struct blk_desc *desc;
+	struct blk_desc *desc;
 };
 
 static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
@@ -172,26 +174,26 @@  static const struct efi_block_io block_io_disk_template = {
 
 static void efi_disk_add_dev(const char *name,
 			     const char *if_typename,
-			     const struct blk_desc *desc,
+			     struct blk_desc *desc,
 			     int dev_index,
-			     lbaint_t offset)
+			     lbaint_t offset,
+			     unsigned part)
 {
 	struct efi_disk_obj *diskobj;
-	struct efi_device_path_file_path *dp;
-	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
 
 	/* Don't add empty devices */
 	if (!desc->lba)
 		return;
 
-	diskobj = calloc(1, objlen);
+	diskobj = calloc(1, sizeof(*diskobj));
 
 	/* Fill in object data */
-	dp = (void *)&diskobj[1];
+	diskobj->dp = efi_dp_from_part(desc, part);
+	diskobj->part = part;
 	diskobj->parent.protocols[0].guid = &efi_block_io_guid;
 	diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
 	diskobj->parent.protocols[1].guid = &efi_guid_device_path;
-	diskobj->parent.protocols[1].protocol_interface = dp;
+	diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
 	diskobj->parent.handle = diskobj;
 	diskobj->ops = block_io_disk_template;
 	diskobj->ifname = if_typename;
@@ -207,17 +209,6 @@  static void efi_disk_add_dev(const char *name,
 	diskobj->media.last_block = desc->lba - offset;
 	diskobj->ops.media = &diskobj->media;
 
-	/* Fill in device path */
-	diskobj->dp = dp;
-	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
-	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
-	dp[0].dp.length = sizeof(*dp);
-	ascii2unicode(dp[0].str, name);
-
-	dp[1].dp.type = DEVICE_PATH_TYPE_END;
-	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
-	dp[1].dp.length = sizeof(*dp);
-
 	/* Hook up to the device list */
 	list_add_tail(&diskobj->parent.link, &efi_obj_list);
 }
@@ -236,14 +227,18 @@  static int efi_disk_create_eltorito(struct blk_desc *desc,
 	if (desc->part_type != PART_TYPE_ISO)
 		return 0;
 
+	/* and devices for each partition: */
 	while (!part_get_info(desc, part, &info)) {
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
 		efi_disk_add_dev(devname, if_typename, desc, diskid,
-				 info.start);
+				 info.start, part);
 		part++;
 		disks++;
 	}
+
+	/* ... and add block device: */
+	efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
 #endif
 
 	return disks;
@@ -271,9 +266,22 @@  int efi_disk_register(void)
 	     uclass_next_device_check(&dev)) {
 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
 		const char *if_typename = dev->driver->name;
+		disk_partition_t info;
+		int part = 1;
 
 		printf("Scanning disk %s...\n", dev->name);
-		efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
+
+		/* add devices for each partition: */
+		while (!part_get_info(desc, part, &info)) {
+			efi_disk_add_dev(dev->name, if_typename, desc,
+					desc->devnum, 0, part);
+			part++;
+		}
+
+		/* ... and add block device: */
+		efi_disk_add_dev(dev->name, if_typename, desc,
+				desc->devnum, 0, 0);
+
 		disks++;
 
 		/*
@@ -309,7 +317,7 @@  int efi_disk_register(void)
 
 			snprintf(devname, sizeof(devname), "%s%d",
 				 if_typename, i);
-			efi_disk_add_dev(devname, if_typename, desc, i, 0);
+			efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
 			disks++;
 
 			/*