From 2164da6b25efcc410b9624c8b95aaabd7340b82e Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 17 Jun 2010 12:15:37 +0100 Subject: [PATCH] Fix i386-pc prefix handling with nested partitions (Debian bug #585068). Note that the case where the core image is booted using multiboot and relocated from its original location still requires more work. * kern/i386/pc/init.c (make_install_device): If the prefix starts with "(,", fill the boot drive in between those two characters, but expect that a full partition specification including partition map names will follow. * util/i386/pc/grub-setup.c (setup): Unless an explicit prefix was specified, write a prefix without the drive name but including a full partition specification. --- ChangeLog | 15 +++++++++++++++ kern/i386/pc/init.c | 8 ++++++++ util/i386/pc/grub-setup.c | 15 +++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/ChangeLog b/ChangeLog index 88e1e43d6..e2f240f40 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2010-06-17 Colin Watson + + Fix i386-pc prefix handling with nested partitions (Debian bug + #585068). Note that the case where the core image is booted using + multiboot and relocated from its original location still requires + more work. + + * kern/i386/pc/init.c (make_install_device): If the prefix starts + with "(,", fill the boot drive in between those two characters, but + expect that a full partition specification including partition map + names will follow. + * util/i386/pc/grub-setup.c (setup): Unless an explicit prefix was + specified, write a prefix without the drive name but including a + full partition specification. + 2010-06-16 Colin Watson * util/grub-mkconfig.in: Ignore non-option arguments, for diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index d81b1e117..8cbc757b2 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -83,6 +83,14 @@ make_install_device (void) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); grub_strcpy (grub_prefix, dev); } + else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') + { + /* We have a prefix, but still need to fill in the boot drive. */ + grub_snprintf (dev, sizeof (dev), + "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', + grub_boot_drive & 0x7f, grub_prefix + 1); + grub_strcpy (grub_prefix, dev); + } return grub_prefix; } diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index f0baf1c89..454fba9fa 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -99,6 +99,7 @@ setup (const char *dir, struct grub_boot_blocklist *first_block, *block; grub_int32_t *install_dos_part, *install_bsd_part; grub_int32_t dos_part, bsd_part; + char *prefix; char *tmp_img; int i; grub_disk_addr_t first_sector; @@ -230,6 +231,8 @@ setup (const char *dir, + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + prefix = (char *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_PREFIX); /* Open the root device and the destination device. */ root_dev = grub_device_open (root); @@ -305,6 +308,18 @@ setup (const char *dir, dos_part = root_dev->disk->partition->number; bsd_part = -1; } + + if (prefix[0] != '(') + { + char *root_part_name, *new_prefix; + + root_part_name = + grub_partition_get_name (root_dev->disk->partition); + new_prefix = xasprintf ("(,%s)%s", root_part_name, prefix); + strcpy (prefix, new_prefix); + free (new_prefix); + free (root_part_name); + } } else dos_part = bsd_part = -1;