From: Colin Watson <cjwatson@ubuntu.com>
To: grub-devel@gnu.org
Subject: Re: Which partitioning schemes should be supported by GRUB?
Date: Tue, 15 Jun 2010 12:21:11 +0100 [thread overview]
Message-ID: <20100615112111.GW21862@riva.ucam.org> (raw)
In-Reply-To: <4C166306.2030405@gmail.com>
On Mon, Jun 14, 2010 at 07:12:38PM +0200, Grégoire Sutre wrote:
> On 06/14/2010 18:43, Colin Watson wrote:
>> Do you have any suggestions on how to deal with that? I'm not familiar
>> with multiboot and need guidance.
>
> A possible solution would be to use the multiboot-command line. AFAIK,
> the boot_device field of the multiboot information structure is supposed
> to pass this kind of partition information, but you cannot specify the
> partmaps in this field, hence its interpretation is ambiguous.
That would potentially allow a user to override things, but doesn't help
with users who don't change their configuration. Unless the user
explicitly configures things, boot_device is all we've got.
Thus, I guess we end up with a two-part fix:
1) Honour key=value pairs in the multiboot command line when booting
GRUB itself as a multiboot image. These would simply become
environment variables. Presumably this goes in grub_machine_init,
by analogy with kern/ieee1275/init.c. This allows users to
override the prefix on the command line as if they had changed the
image itself.
2) If multiboot_trampoline needs to change install_dos_part or
install_bsd_part based on the value of boot_device in the MBI, then
we know that the drive/partition part of prefix (which was
calculated in the same way as install_dos_part and install_bsd_part
when grub-setup was run) is now invalid and should be ignored.
This fact needs to be passed on to make_install_device.
Something like this? I'm afraid I have no idea how to test this (GRUB's
multiboot command doesn't seem to accept command-line arguments?), not
to mention that this is the first time I've been anywhere near most of
this code. I would greatly appreciate advice and review.
2010-06-15 Colin Watson <cjwatson@ubuntu.com>
Fix i386-pc prefix handling with nested partitions (Debian bug
#585068).
* include/grub/i386/pc/kernel.h (grub_multiboot_change_prefix): New
declaration.
* kern/i386/pc/startup.S (multiboot_entry): Save a pointer to the
MBI in startup_multiboot_info.
(multiboot_trampoline): If the new partition numbers differ from the
previous ones, then set grub_multiboot_change_prefix.
(grub_multiboot_change_prefix): New definition.
* kern/i386/pc/init.c (make_install_device): Invalidate any
drive/partition part of the prefix if grub_multiboot_change_prefix
is set. After that, 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.
(grub_parse_multiboot_cmdline): New function.
(grub_machine_init): If we have an MBI, copy it, then call
grub_parse_multiboot_cmdline.
* 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.
=== modified file 'include/grub/i386/pc/kernel.h'
--- include/grub/i386/pc/kernel.h 2010-04-26 19:11:16 +0000
+++ include/grub/i386/pc/kernel.h 2010-06-15 11:02:34 +0000
@@ -44,6 +44,10 @@ extern grub_int32_t grub_install_bsd_par
/* The boot BIOS drive number. */
extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
+/* Set if multiboot changed the partition numbers, so grub_prefix is now
+ invalid. */
+extern grub_uint8_t grub_multiboot_change_prefix;
+
#endif /* ! ASM_FILE */
#endif /* ! KERNEL_MACHINE_HEADER */
=== modified file 'kern/i386/pc/init.c'
--- kern/i386/pc/init.c 2010-05-21 18:08:48 +0000
+++ kern/i386/pc/init.c 2010-06-15 11:06:20 +0000
@@ -32,6 +32,7 @@
#include <grub/cache.h>
#include <grub/time.h>
#include <grub/cpu/tsc.h>
+#include <grub/multiboot.h>
struct mem_region
{
@@ -47,12 +48,29 @@ static int num_regions;
grub_addr_t grub_os_area_addr;
grub_size_t grub_os_area_size;
+/* A pointer to the MBI in its initial location. */
+struct multiboot_info *startup_multiboot_info = NULL;
+
+/* The MBI has to be copied to our BSS so that it won't be
+ overwritten. This is its final location. */
+static struct multiboot_info kern_multiboot_info;
+
static char *
make_install_device (void)
{
/* XXX: This should be enough. */
char dev[100], *ptr = dev;
+ if (grub_prefix[0] == '(' && grub_multiboot_change_prefix)
+ {
+ /* The multiboot information invalidated our hardcoded prefix because
+ partition numbers differed. Eliminate the drive/partition part of
+ the prefix, if possible. */
+ char *ket = grub_strchr (grub_prefix, ')');
+ if (ket)
+ grub_memmove (grub_prefix, ket + 1, grub_strlen (ket));
+ }
+
if (grub_prefix[0] != '(')
{
/* No hardcoded root partition - make it from the boot drive and the
@@ -83,6 +101,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;
}
@@ -134,6 +160,45 @@ compact_mem_regions (void)
}
}
+static void
+grub_parse_multiboot_cmdline (void)
+{
+ char *cmdline;
+ char *p;
+
+ if (! (kern_multiboot_info.flags & MULTIBOOT_INFO_CMDLINE))
+ return;
+
+ p = cmdline = grub_strdup ((char *) kern_multiboot_info.cmdline);
+
+ while (*p)
+ {
+ char *command = p;
+ char *end;
+ char *val;
+
+ end = grub_strchr (command, ' ');
+ if (end)
+ {
+ *end = '\0';
+ p = end + 1;
+ while (*p == ' ')
+ ++p;
+ }
+
+ /* Process command. */
+ val = grub_strchr (command, '=');
+ if (val)
+ {
+ *val = '\0';
+ grub_env_set (command, val + 1);
+
+ if (grub_strcmp (command, "prefix") == 0)
+ grub_multiboot_change_prefix = 0;
+ }
+ }
+}
+
void
grub_machine_init (void)
{
@@ -214,6 +279,15 @@ grub_machine_init (void)
if (! grub_os_area_addr)
grub_fatal ("no upper memory");
+ if (startup_multiboot_info)
+ {
+ /* Move MBI to a safe place. */
+ grub_memmove (&kern_multiboot_info, startup_multiboot_info,
+ sizeof (struct multiboot_info));
+
+ grub_parse_multiboot_cmdline ();
+ }
+
grub_tsc_init ();
}
=== modified file 'kern/i386/pc/startup.S'
--- kern/i386/pc/startup.S 2010-04-05 13:59:32 +0000
+++ kern/i386/pc/startup.S 2010-06-15 11:02:19 +0000
@@ -142,6 +142,8 @@ multiboot_header:
multiboot_entry:
.code32
+ movl %ebx, EXT_C(startup_multiboot_info)
+
/* obtain the boot device */
movl 12(%ebx), %edx
@@ -161,20 +163,38 @@ multiboot_entry:
jmp *%eax
multiboot_trampoline:
+ /* remember the original boot information */
+ movl EXT_C(grub_install_dos_part), %eax
+ orl %eax, %eax
+ jns 1f
+ movb $0xFF, %al
+1:
+ movl EXT_C(grub_install_bsd_part), %ebx
+ orl %ebx, %ebx
+ jns 2f
+ movb $0xFF, %bl
+2:
+ movb %al, %bh
+
/* fill the boot information */
movl %edx, %eax
shrl $8, %eax
+ cmpw %ax, %bx
+ je 3f
+ /* doesn't match the original */
+ movb $1, EXT_C(grub_multiboot_change_prefix)
+3:
xorl %ebx, %ebx
cmpb $0xFF, %ah
- je 1f
+ je 4f
movb %ah, %bl
movl %ebx, EXT_C(grub_install_dos_part)
-1:
+4:
cmpb $0xFF, %al
- je 2f
+ je 5f
movb %al, %bl
movl %ebx, EXT_C(grub_install_bsd_part)
-2:
+5:
shrl $24, %edx
movb $0xFF, %dh
/* enter the usual booting */
@@ -285,6 +305,8 @@ LOCAL (codestart):
VARIABLE(grub_boot_drive)
.byte 0
+VARIABLE(grub_multiboot_change_prefix)
+ .byte 0
.p2align 2 /* force 4-byte alignment */
=== modified file 'util/i386/pc/grub-setup.c'
--- util/i386/pc/grub-setup.c 2010-06-11 20:31:16 +0000
+++ util/i386/pc/grub-setup.c 2010-06-14 16:29:54 +0000
@@ -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;
Thanks,
--
Colin Watson [cjwatson@ubuntu.com]
next prev parent reply other threads:[~2010-06-15 11:21 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-06 18:02 Which partitioning schemes should be supported by GRUB? Grégoire Sutre
2010-06-07 20:46 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-06-09 22:45 ` Grégoire Sutre
2010-06-09 23:03 ` C. P. Ghost
2010-06-12 16:32 ` Grégoire Sutre
2010-06-12 17:26 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-06-13 16:16 ` Grégoire Sutre
2010-06-14 11:37 ` Colin Watson
2010-06-14 13:07 ` richardvoigt
2010-06-14 13:25 ` Colin Watson
2010-06-14 15:02 ` Colin Watson
2010-06-14 15:58 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-06-14 16:43 ` Colin Watson
2010-06-14 16:55 ` Seth Goldberg
2010-06-14 17:33 ` Colin Watson
2010-06-14 17:12 ` Grégoire Sutre
2010-06-15 11:21 ` Colin Watson [this message]
2010-06-15 21:07 ` Grégoire Sutre
2010-06-16 13:01 ` Colin Watson
2010-06-16 23:31 ` Grégoire Sutre
2010-06-17 0:47 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-06-17 11:29 ` Colin Watson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100615112111.GW21862@riva.ucam.org \
--to=cjwatson@ubuntu.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.