[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Which partitioning schemes should be supported by GRUB?
From: |
Vladimir 'φ-coder/phcoder' Serbinenko |
Subject: |
Re: Which partitioning schemes should be supported by GRUB? |
Date: |
Thu, 17 Jun 2010 02:47:11 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100515 Icedove/3.0.4 |
On 06/15/2010 01:21 PM, Colin Watson wrote:
> 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.
>
>
Apparently multiboot part has revealed to be a bit more tricky due to
heterogenity. Go ahead with non-multiboot part, I'll review multiboot
part separately (need to think about it a bit)
> 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 <address@hidden>
>
> 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,
>
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
signature.asc
Description: OpenPGP digital signature
- Re: Which partitioning schemes should be supported by GRUB?, (continued)
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Vladimir 'φ-coder/phcoder' Serbinenko, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Seth Goldberg, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Grégoire Sutre, 2010/06/14
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/15
- Re: Which partitioning schemes should be supported by GRUB?, Grégoire Sutre, 2010/06/15
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/16
- Re: Which partitioning schemes should be supported by GRUB?, Grégoire Sutre, 2010/06/16
- Re: Which partitioning schemes should be supported by GRUB?,
Vladimir 'φ-coder/phcoder' Serbinenko <=
- Re: Which partitioning schemes should be supported by GRUB?, Colin Watson, 2010/06/17