[U-Boot] [PATCH] efi_loader: Fix partition offsets
Heinrich Schuchardt
xypron.glpk at gmx.de
Fri Dec 8 07:02:01 UTC 2017
On 12/08/2017 06:55 AM, Alexander Graf wrote:
>
>
> On 07.12.17 12:45, Jonathan Gray wrote:
>> On Thu, Dec 07, 2017 at 11:57:43AM +0100, Heinrich Schuchardt wrote:
>>> On 12/07/2017 08:00 AM, Jonathan Gray wrote:
>>>> On Fri, Dec 01, 2017 at 04:10:33PM +0100, Alexander Graf wrote:
>>>>> Commit 884bcf6f65 (efi_loader: use proper device-paths for partitions) tried
>>>>> to introduce the el torito scheme to all partition table types: Spawn
>>>>> individual disk objects for each partition on a disk.
>>>>>
>>>>> Unfortunately, that code ended up creating partitions with offset=0 which meant
>>>>> that anyone accessing these objects gets data from the raw block device instead
>>>>> of the partition.
>>>>>
>>>>> Furthermore, all the el torito logic to spawn devices for partitions was
>>>>> duplicated. So let's merge the two code paths and give partition disk objects
>>>>> good offsets to work from, so that payloads can actually make use of them.
>>>>>
>>>>> Fixes: 884bcf6f65 (efi_loader: use proper device-paths for partitions)
>>>>> Reported-by: Yousaf Kaukab <yousaf.kaukab at suse.com>
>>>>> Signed-off-by: Alexander Graf <agraf at suse.de>
>>>>
>>>> This once again broke being able to find a DEVICE_PATH_TYPE_MEDIA_DEVICE
>>>> node with the loaded image protocol on rpi_3 with mmc/usb.
>>>
>>> Could you, please, specify which software you are trying to call:
>>> Linux EFI stub, Grub, or anything else?
>>
>> https://fastly.cdn.openbsd.org/pub/OpenBSD/snapshots/arm64/BOOTAA64.EFI
>> https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/arm64/stand/efiboot/
>> Disk image with fat/ffs filesystems
>> https://fastly.cdn.openbsd.org/pub/OpenBSD/snapshots/arm64/miniroot62.fs
>>
>> though it would likely show up on other archs as well
>>
>> armv7 equivalents of the above
>> https://fastly.cdn.openbsd.org/pub/OpenBSD/snapshots/armv7/BOOTARM.EFI
>> https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/armv7/stand/efiboot/
>> https://fastly.cdn.openbsd.org/pub/OpenBSD/snapshots/armv7/miniroot-am335x-62.fs
>>
>>>
>>> Which patches did you consider?
>>> Did you apply these patch series that are not yet in efi-next?
>>> efi_loader: correct media device paths
>>> efi_loader: avoid use after free
>>
>> just master
>> c8e1ca3ebfd21915f6f2e399c9ca1cd3d7a4b076 tools: omapimage: fix corner-case in byteswap path
>>
>> with a small patch to force calling gnu sed for some non-portable
>> sed use in check-config.sh
>>
>> 'efi_loader: avoid use after free' doesn't help
>> 'efi_loader: correct media device paths' doesn't either
>
> As a quick heads-up: The device path matching is broken. The patch below
> should fix it, but I want to create a travis-ci case around that first
> and also wrap it up more nicely.
>
> Alex
>
>
> diff --git a/lib/efi_loader/efi_device_path.c
> b/lib/efi_loader/efi_device_path.c
> index b4e2f933cb..d12a38c450 100644
> --- a/lib/efi_loader/efi_device_path.c
> +++ b/lib/efi_loader/efi_device_path.c
Hello Alex,
thank you for your further investigations
We really need comments above the functions stating what they are
expected to do.
> @@ -126,6 +126,7 @@ static struct efi_object *find_obj(struct
> efi_device_path *dp, bool short_path,
> struct efi_device_path **rem)
> {
> struct efi_object *efiobj;
> + unsigned int dp_size = efi_dp_size(dp);
>
> list_for_each_entry(efiobj, &efi_obj_list, link) {
> struct efi_handler *handler;
> @@ -141,10 +142,18 @@ static struct efi_object *find_obj(struct
> efi_device_path *dp, bool short_path,
> do {
> if (efi_dp_match(dp, obj_dp) == 0) {
> if (rem) {
> + /*
> + * Allow partial matches, but inform
> + * the caller.
> + */
> *rem = ((void *)dp) +
> efi_dp_size(obj_dp);
> + return efiobj;
> + } else {
> + /* Only return on exact matches */
> + if (efi_dp_size(obj_dp) == dp_size)
> + return efiobj;
> }
> - return efiobj;
> }
>
> obj_dp = shorten_path(efi_dp_next(obj_dp));
> @@ -164,8 +173,14 @@ struct efi_object *efi_dp_find_obj(struct
> efi_device_path *dp,
> {
> struct efi_object *efiobj;
>
> - efiobj = find_obj(dp, false, rem);
> + /* Search for an exact match first */
> + efiobj = find_obj(dp, false, NULL);
>
> + /* Then for a fuzzy match */
> + if (!efiobj)
> + efiobj = find_obj(dp, false, rem);
> +
> + /* And now for a fuzzy short match */
> if (!efiobj)
> efiobj = find_obj(dp, true, rem);
>
Unfortunately after your patch some problems with device paths still remain:
I applied your patch after my patch series. I ran qemu-x86_defconfig
with an IDE disk. To display the device paths I used 'bootefi selftest'.
With and without your patch I saw a device path
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/HD(1,MBR,0x986b6db1,0x800,0x3f800)
Between VenHW and HD the device path node for the IDE disk is missing.
We should have something like
/VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Ata(0,Master,0)/HD(1,MBR,0x986b6db1,0x800,0x3f800)
iPXE reports an error because the parent of the partition is not a block
device.
We should add to efi_selftest a test requiring:
The parent of a partition HD(* and the partition itself must expose the
EFI_BLOCK_IO_PROTOCOL.
Cf. UEFI Spec 10.4.5 Media Device Path Rules
The root node should not expose the EFI_BLOCK_IO_PROTOCOL.
We should further add a test requiring:
A partition HD(* with non-zero partition number must have a positive
offset and size.
Best regards
Heinrich
More information about the U-Boot
mailing list