Fix prefix autodetection when booting from EFI CD-ROM
PATCH 1/1 Fix prefix autodetection when booting from EFI CD-ROM
Fix autodetection of $prefix when booted from EFI CD-ROM.
Based on patch from Matthew Garrett, modified to not overwrite memory returned by device path protocol handler and rebased to current trunk.
Additionally fixes potential memory leak - dup_dp was not deallocated if device path was not found.
--- grub-core/disk/efi/efidisk.c | 121 +++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 55 deletions(-)
grub-core/disk/efi/efidisk.c +66 -55
@@ -775,67 +775,78 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)if (! ldp)return 0 ; -if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE )) +if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ) { -struct grub_efidisk_get_device_name_ctx ctx; -char *dev_name; -grub_efi_device_path_t *dup_dp, *dup_ldp; -grub_disk_t parent =0 ; - -/* It is necessary to duplicate the device path so that GRUB -can overwrite it. */ - dup_dp =duplicate_device_path (dp); -if (! dup_dp) -return 0 ; - - dup_ldp =find_last_device_path (dup_dp); - dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; - dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; - dup_ldp->length[0 ] =sizeof (*dup_ldp); - dup_ldp->length[1 ] =0 ; +int is_cdrom =0 ; -if (!get_diskname_from_path (dup_dp, device_name)) -return 0 ; - parent =grub_disk_open (device_name); -grub_free (dup_dp); - -if (! parent) -return 0 ; - -/* Find a partition which matches the hard drive device path. */ - ctx.partition_name =NULL ; -grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); -if (ctx.hd.partition_start ==0 - && ctx.hd.partition_size ==grub_disk_get_size (parent)) - { - dev_name =grub_strdup (parent->name); - } -else +switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)) { -grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, - &ctx); - -if (! ctx.partition_name) +case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE : + is_cdrom =1 ; +/* Intentionally fall through */ +case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE : { +struct grub_efidisk_get_device_name_ctx ctx; +char *dev_name; +grub_efi_device_path_t *dup_dp, *dup_ldp; +grub_disk_t parent =0 ; + +/* It is necessary to duplicate the device path so that GRUB +can overwrite it. */ + dup_dp =duplicate_device_path (dp); +if (! dup_dp) +return 0 ; + + dup_ldp =find_last_device_path (dup_dp); + dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; + dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; + dup_ldp->length[0 ] =sizeof (*dup_ldp); + dup_ldp->length[1 ] =0 ; + +if (!get_diskname_from_path (dup_dp, device_name)) + { +grub_free (dup_dp); +return 0 ; + } +grub_free (dup_dp); +if (is_cdrom) +return grub_strdup (device_name); + + parent =grub_disk_open (device_name); +if (! parent) +return 0 ; + +/* Find a partition which matches the hard drive device path. */ + ctx.partition_name =NULL ; +grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); +if (ctx.hd.partition_start ==0 + && ctx.hd.partition_size ==grub_disk_get_size (parent)) + { + dev_name =grub_strdup (parent->name); + } +else + { +grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, + &ctx); + +if (! ctx.partition_name) + { +grub_disk_close (parent); +return 0 ; + } + + dev_name =grub_xasprintf ("%s,%s" , parent->name, + ctx.partition_name); +grub_free (ctx.partition_name); + }grub_disk_close (parent); -return 0 ; - } - dev_name =grub_xasprintf ("%s,%s" , parent->name, - ctx.partition_name); -grub_free (ctx.partition_name); +return dev_name; + } } -grub_disk_close (parent); - -return dev_name; - } -else - { -/* This should be an entire disk. */ -if (!get_diskname_from_path (dp, device_name)) -return 0 ; -return grub_strdup (device_name); } +/* This may be guessed device - floppy, cdrom or entire disk. */ +if (!get_diskname_from_path (dp, device_name)) +return 0 ; +return grub_strdup (device_name); }
Signature · 1 line
tg: (4b9ea2e..) u/efi-cdrom-prefix (depends on: master)
Quoted 5 lines · Andrey Borzenkov
Fix autodetection of $prefix when booted from EFI CD-ROM.
Based on patch from Matthew Garrett, modified to not overwrite memory returned by device path protocol handler and rebased to current trunk.
Due to legal issues we need Matthew Garrett, or someone from Red Hat, to send the patch. I wonder why this didn't happen before.
Quoted 148 lines
Additionally fixes potential memory leak -
dup_dpwas not deallocated if device path was not found.Signed-off-by Andrey Borzenkov <[email protected]>--- grub-core/disk/efi/efidisk.c | 121 +++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 55 deletions(-)grub-core/disk/efi/efidisk.c +66
-55@@ -775,67 +775,78 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)if (! ldp)return 0 ; -if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE )) +if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ) { -struct grub_efidisk_get_device_name_ctx ctx; -char *dev_name; -grub_efi_device_path_t *dup_dp, *dup_ldp; -grub_disk_t parent =0 ; - -/* It is necessary to duplicate the device path so that GRUB -can overwrite it. */ - dup_dp =duplicate_device_path (dp); -if (! dup_dp) -return 0 ; - - dup_ldp =find_last_device_path (dup_dp); - dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; - dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; - dup_ldp->length[0 ] =sizeof (*dup_ldp); - dup_ldp->length[1 ] =0 ; +int is_cdrom =0 ; -if (!get_diskname_from_path (dup_dp, device_name)) -return 0 ; - parent =grub_disk_open (device_name); -grub_free (dup_dp); - -if (! parent) -return 0 ; - -/* Find a partition which matches the hard drive device path. */ - ctx.partition_name =NULL ; -grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); -if (ctx.hd.partition_start ==0 - && ctx.hd.partition_size ==grub_disk_get_size (parent)) - { - dev_name =grub_strdup (parent->name); - } -else +switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)) { -grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, - &ctx); - -if (! ctx.partition_name) +case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE : + is_cdrom =1 ; +/* Intentionally fall through */ +case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE : { +struct grub_efidisk_get_device_name_ctx ctx; +char *dev_name; +grub_efi_device_path_t *dup_dp, *dup_ldp; +grub_disk_t parent =0 ; + +/* It is necessary to duplicate the device path so that GRUB +can overwrite it. */ + dup_dp =duplicate_device_path (dp); +if (! dup_dp) +return 0 ; + + dup_ldp =find_last_device_path (dup_dp); + dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; + dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; + dup_ldp->length[0 ] =sizeof (*dup_ldp); + dup_ldp->length[1 ] =0 ; + +if (!get_diskname_from_path (dup_dp, device_name)) + { +grub_free (dup_dp); +return 0 ; + } +grub_free (dup_dp); +if (is_cdrom) +return grub_strdup (device_name); + + parent =grub_disk_open (device_name); +if (! parent) +return 0 ; + +/* Find a partition which matches the hard drive device path. */ + ctx.partition_name =NULL ; +grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); +if (ctx.hd.partition_start ==0 + && ctx.hd.partition_size ==grub_disk_get_size (parent)) + { + dev_name =grub_strdup (parent->name); + } +else + { +grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, + &ctx); + +if (! ctx.partition_name) + { +grub_disk_close (parent); +return 0 ; + } + + dev_name =grub_xasprintf ("%s,%s" , parent->name, + ctx.partition_name); +grub_free (ctx.partition_name); + }grub_disk_close (parent); -return 0 ; - } - dev_name =grub_xasprintf ("%s,%s" , parent->name, - ctx.partition_name); -grub_free (ctx.partition_name); +return dev_name; + } } -grub_disk_close (parent); - -return dev_name; - } -else - { -/* This should be an entire disk. */ -if (!get_diskname_from_path (dp, device_name)) -return 0 ; -return grub_strdup (device_name); } +/* This may be guessed device - floppy, cdrom or entire disk. */ +if (!get_diskname_from_path (dp, device_name)) +return 0 ; +return grub_strdup (device_name); }
Signature · 2 lines
Regards Vladimir 'φ-coder/phcoder' Serbinenko
Quoted 8 lines · Andrey Borzenkov
Fix autodetection of $prefix when booted from EFI CD-ROM.
Based on patch from Matthew Garrett, modified to not overwrite memory returned by device path protocol handler and rebased to current trunk.
Additionally fixes potential memory leak -
dup_dpwas not deallocated if device path was not found.
Why any special treatement for CD-ROMs? They can have partitions and do so on CD-ROMs intended for macs. What about following patch:
[email protected]:15:02:18:~/grub2/bzr/mainline$ bzr diff === modified file 'grub-core/disk/efi/efidisk.c' --- grub-core/disk/efi/efidisk.c 2013-04-05 08:59:26 +0000 +++ grub-core/disk/efi/efidisk.c 2013-04-05 13:07:39 +0000 @@ -633,9 +633,6 @@ return d->handle;
case 'c':
- /* FIXME: probably this is not correct. */
- return d->handle;
-
case 'h':
/* If this is the whole disk, just return its own data. */
if (! disk->partition)@@ -657,7 +654,9 @@
if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path)
== GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path)
- == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) + == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) + == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE)
&& (grub_partition_get_start (disk->partition)
== (hd.partition_start << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)))
@@ -770,7 +769,9 @@
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
- == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
+ == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
+ == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE))
{
struct grub_efidisk_get_device_name_ctx ctx;
char *dev_name;В Fri, 05 Apr 2013 15:12:26 +0200
Vladimir 'φ-coder/phcoder' Serbinenko <[email protected]> пишет:
Quoted 8 lines · Andrey Borzenkov
Quoted 7 lines
Fix autodetection of $prefix when booted from EFI CD-ROM.
Based on patch from Matthew Garrett, modified to not overwrite memory returned by device path protocol handler and rebased to current trunk.
Quoted 6 lines
Quoted 2 lines
Additionally fixes potential memory leak -
dup_dpwas not deallocated if device path was not found.Why any special treatement for CD-ROMs? They can have partitions and do so on CD-ROMs intended for macs. What about following patch:
CD-ROM media device path in UEFI is defined for a single boot catalog entry - EFI system partition. EFI will *always* return this when booted from CD. But we do *not* want this "partition" - we want full CD access here. This ESP image normally exists just to load grub off it. Everything else is part of normal ISO on CD-ROM.
Also there is no partition label that can be detected and points to this boot catalog entry; so partition matching code will simply fail.
So we want a) skip partition search based on media device subpath and
b) strip media device subpath.
I'm not sure what partitions on MAC are but I suspect they are not boot catalog entries.
Quoted 39 lines
[email protected]:15:02:18:~/grub2/bzr/mainline$ bzr diff === modified file 'grub-core/disk/efi/efidisk.c'disk/efi/efidisk.c +6
-5@@ -633,9 +633,6 @@return d->handle;case 'c' : -/* FIXME: probably this is not correct. */ -return d->handle; -case 'h' :/* If this is the whole disk, just return its own data. */ if (! disk->partition)@@ -657,7 +654,9 @@if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) - ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE ) + ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE + ||GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) + ==GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE ) && (grub_partition_get_start (disk->partition) == (hd.partition_start << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))@@ -770,7 +769,9 @@if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE )) + ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE + ||GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) + ==GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE )) {struct grub_efidisk_get_device_name_ctx ctx;char *dev_name;
Committed with a change to handle Apple HFS+ boot (return full disk only if no matching partition is found).
Thanks.
Quoted 154 lines · Andrey Borzenkov
Fix autodetection of $prefix when booted from EFI CD-ROM.
Based on patch from Matthew Garrett, modified to not overwrite memory returned by device path protocol handler and rebased to current trunk.
Additionally fixes potential memory leak -
dup_dpwas not deallocated if device path was not found.Signed-off-by Andrey Borzenkov <[email protected]>--- grub-core/disk/efi/efidisk.c | 121 +++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 55 deletions(-)grub-core/disk/efi/efidisk.c +66
-55@@ -775,67 +775,78 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)if (! ldp)return 0 ; -if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - ==GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE )) +if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) ==GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ) { -struct grub_efidisk_get_device_name_ctx ctx; -char *dev_name; -grub_efi_device_path_t *dup_dp, *dup_ldp; -grub_disk_t parent =0 ; - -/* It is necessary to duplicate the device path so that GRUB -can overwrite it. */ - dup_dp =duplicate_device_path (dp); -if (! dup_dp) -return 0 ; - - dup_ldp =find_last_device_path (dup_dp); - dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; - dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; - dup_ldp->length[0 ] =sizeof (*dup_ldp); - dup_ldp->length[1 ] =0 ; +int is_cdrom =0 ; -if (!get_diskname_from_path (dup_dp, device_name)) -return 0 ; - parent =grub_disk_open (device_name); -grub_free (dup_dp); - -if (! parent) -return 0 ; - -/* Find a partition which matches the hard drive device path. */ - ctx.partition_name =NULL ; -grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); -if (ctx.hd.partition_start ==0 - && ctx.hd.partition_size ==grub_disk_get_size (parent)) - { - dev_name =grub_strdup (parent->name); - } -else +switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)) { -grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, - &ctx); - -if (! ctx.partition_name) +case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE : + is_cdrom =1 ; +/* Intentionally fall through */ +case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE : { +struct grub_efidisk_get_device_name_ctx ctx; +char *dev_name; +grub_efi_device_path_t *dup_dp, *dup_ldp; +grub_disk_t parent =0 ; + +/* It is necessary to duplicate the device path so that GRUB +can overwrite it. */ + dup_dp =duplicate_device_path (dp); +if (! dup_dp) +return 0 ; + + dup_ldp =find_last_device_path (dup_dp); + dup_ldp->type =GRUB_EFI_END_DEVICE_PATH_TYPE ; + dup_ldp->subtype =GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE ; + dup_ldp->length[0 ] =sizeof (*dup_ldp); + dup_ldp->length[1 ] =0 ; + +if (!get_diskname_from_path (dup_dp, device_name)) + { +grub_free (dup_dp); +return 0 ; + } +grub_free (dup_dp); +if (is_cdrom) +return grub_strdup (device_name); + + parent =grub_disk_open (device_name); +if (! parent) +return 0 ; + +/* Find a partition which matches the hard drive device path. */ + ctx.partition_name =NULL ; +grub_memcpy (&ctx.hd, ldp,sizeof (ctx.hd)); +if (ctx.hd.partition_start ==0 + && ctx.hd.partition_size ==grub_disk_get_size (parent)) + { + dev_name =grub_strdup (parent->name); + } +else + { +grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, + &ctx); + +if (! ctx.partition_name) + { +grub_disk_close (parent); +return 0 ; + } + + dev_name =grub_xasprintf ("%s,%s" , parent->name, + ctx.partition_name); +grub_free (ctx.partition_name); + }grub_disk_close (parent); -return 0 ; - } - dev_name =grub_xasprintf ("%s,%s" , parent->name, - ctx.partition_name); -grub_free (ctx.partition_name); +return dev_name; + } } -grub_disk_close (parent); - -return dev_name; - } -else - { -/* This should be an entire disk. */ -if (!get_diskname_from_path (dp, device_name)) -return 0 ; -return grub_strdup (device_name); } +/* This may be guessed device - floppy, cdrom or entire disk. */ +if (!get_diskname_from_path (dp, device_name)) +return 0 ; +return grub_strdup (device_name); }