All of lore.kernel.org
 help / color / mirror / Atom feed
* Which partitioning schemes should be supported by GRUB?
@ 2010-06-06 18:02 Grégoire Sutre
  2010-06-07 20:46 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-06 18:02 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi,

Tests of GRUB on NetBSD (and FreeBSD) have raised several issues (most
of them reported on the list) regarding partition detection.  However,
I have the feeling that some of these issues are not considered as real
issues since the test configuration is not supported by GRUB.  This
surprises me since I naively thought that most user configurations
should be supported.

So I ask the question: Which partitioning schemes are (or shall be)
supported by GRUB on i386-pc (with standard BIOS)?

To start the discussion, I'll focus on a few examples (the list is
surely not exhaustive).  Maybe some configurations simply cannot exist,
in which case please let me know.

1. A single top-level partition map
    (a) MS-DOS
    (b) GPT
    (c) BSD disklabel
    (d) Apple partition map
    (e) Sun label

2. Hybrid: top-level MS-DOS + another *top-level* partition map
    (a) MS-DOS + GPT
        (i.e. GPT + at-least one non 0xEE MS-DOS partition)
    (b) MS-DOS + BSD
    (c) ...

If I read the code correctly, grub-setup (on i386-pc) only supports
1(a) and 1(b).  However, on NetBSD, 1(c) is very common, and 2(b) is
not rare.  Also, some OSes are fine with 2(a), e.g. FreeBSD.

Personally, I would rather support all possible configurations, unless
some technical reason prevents it.  So grub-setup would not test for
some specific configurations, but would instead use a generic
(and simple) approach.  If it fails, it should be for a good reason,
and not because "No DOS-style partitions [were] found".

What's your opinion?

Grégoire



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  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-12 16:32   ` Grégoire Sutre
  0 siblings, 2 replies; 22+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-06-07 20:46 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 2648 bytes --]

On 06/06/2010 08:02 PM, Grégoire Sutre wrote:
> Hi,
>
> Tests of GRUB on NetBSD (and FreeBSD) have raised several issues (most
> of them reported on the list) regarding partition detection.  However,
> I have the feeling that some of these issues are not considered as real
> issues since the test configuration is not supported by GRUB.  This
> surprises me since I naively thought that most user configurations
> should be supported.
>
> So I ask the question: Which partitioning schemes are (or shall be)
> supported by GRUB on i386-pc (with standard BIOS)?
There are two parts of this question:
1) Which partition schemes should GRUB be able to read modules and
payloads from ? It's platform-indepedent and 2 conditions apply:
- Usage. There are OS which are able to boot from such OS and such
configuration isn't considered obscure by them.
- Non-confusability. The risk of false positive of this partition config
which would prevent normal function is small.
If at least one condition is met it's worth considering. If both
conditions are met it should be supported.
2) Support for embedding.
Embedding is a potentially dangerous operation so we have to be
cautious. Using a dedicated embedding partition if it can be
unambiguously identified as such is a sane solution.
>
> To start the discussion, I'll focus on a few examples (the list is
> surely not exhaustive).  Maybe some configurations simply cannot exist,
> in which case please let me know.
>
> 1. A single top-level partition map
>    (a) MS-DOS
>    (b) GPT
>    (c) BSD disklabel
>    (d) Apple partition map
>    (e) Sun label
>
> 2. Hybrid: top-level MS-DOS + another *top-level* partition map
>    (a) MS-DOS + GPT
>        (i.e. GPT + at-least one non 0xEE MS-DOS partition)
>    (b) MS-DOS + BSD
>    (c) ...
>
> If I read the code correctly, grub-setup (on i386-pc) only supports
> 1(a) and 1(b).  However, on NetBSD, 1(c) is very common, and 2(b) is
> not rare.  Also, some OSes are fine with 2(a), e.g. FreeBSD.
>
> Personally, I would rather support all possible configurations, unless
> some technical reason prevents it.  So grub-setup would not test for
> some specific configurations, but would instead use a generic
> (and simple) approach.  If it fails, it should be for a good reason,
> and not because "No DOS-style partitions [were] found".
>
> What's your opinion?
>
> Grégoire
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  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
  1 sibling, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-09 22:45 UTC (permalink / raw)
  To: The development of GNU GRUB

On 06/07/2010 10:46 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:

> There are two parts of this question:
> 1) Which partition schemes should GRUB be able to read modules and
> payloads from ? It's platform-indepedent

Agreed.

> and 2 conditions apply:
> - Usage. There are OS which are able to boot from such OS and such
> configuration isn't considered obscure by them.
> - Non-confusability. The risk of false positive of this partition config
> which would prevent normal function is small.
> If at least one condition is met it's worth considering. If both
> conditions are met it should be supported.

Ok.  Regarding confusability, I can see potential problems in the
interpretation of offsets (absolute or relative?), such as for nested
BSD labels (discussed in another thread).  Do you see other potential
causes for confusion?


> 2) Support for embedding.
> Embedding is a potentially dangerous operation so we have to be
> cautious. Using a dedicated embedding partition if it can be
> unambiguously identified as such is a sane solution.

Sure.  As discussed on irc, this would require in-depth changes to
grub-setup, and it's worth another thread...

Grégoire


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-09 22:45   ` Grégoire Sutre
@ 2010-06-09 23:03     ` C. P. Ghost
  0 siblings, 0 replies; 22+ messages in thread
From: C. P. Ghost @ 2010-06-09 23:03 UTC (permalink / raw)
  To: The development of GNU GRUB

2010/6/10 Grégoire Sutre <gregoire.sutre@gmail.com>:
> On 06/07/2010 10:46 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
>
>> There are two parts of this question:
>> 1) Which partition schemes should GRUB be able to read modules and
>> payloads from ? It's platform-indepedent
>
> Agreed.
>
>> and 2 conditions apply:
>> - Usage. There are OS which are able to boot from such OS and such
>> configuration isn't considered obscure by them.
>> - Non-confusability. The risk of false positive of this partition config
>> which would prevent normal function is small.
>> If at least one condition is met it's worth considering. If both
>> conditions are met it should be supported.
>
> Ok.  Regarding confusability, I can see potential problems in the
> interpretation of offsets (absolute or relative?), such as for nested
> BSD labels (discussed in another thread).  Do you see other potential
> causes for confusion?
>
>> 2) Support for embedding.
>> Embedding is a potentially dangerous operation so we have to be
>> cautious. Using a dedicated embedding partition if it can be
>> unambiguously identified as such is a sane solution.
>
> Sure.  As discussed on irc, this would require in-depth changes to
> grub-setup, and it's worth another thread...

Whatever you guys implement, as long as it just works, it's
fine with me.

I'm interested in GRUB2 because of its multiboot capability: I need
to boot L4Ka::Pistachio on top of a FreeBSD/UFS2 filesystem.
If it works inside DOS/bsdlabel and GPT partitions, that's ideal.
Of course, if NetBSD partitions are supported too, that would be
even better.

Thanks for the great support so far. ;-)

> Grégoire

-cpghost.

-- 
Cordula's Web. http://www.cordula.ws/


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-07 20:46 ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-06-09 22:45   ` Grégoire Sutre
@ 2010-06-12 16:32   ` Grégoire Sutre
  2010-06-12 17:26     ` Vladimir 'φ-coder/phcoder' Serbinenko
  1 sibling, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-12 16:32 UTC (permalink / raw)
  To: The development of GNU GRUB

On 06/07/2010 10:46 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:

> There are two parts of this question:
> 1) Which partition schemes should GRUB be able to read modules and
> payloads from ? It's platform-indepedent and 2 conditions apply:
> - Usage. There are OS which are able to boot from such OS and such
> configuration isn't considered obscure by them.
> - Non-confusability. The risk of false positive of this partition config
> which would prevent normal function is small.
> If at least one condition is met it's worth considering. If both
> conditions are met it should be supported.

According to these rules, hybrid msdos+gpt partitioning schemes should
be supported.  Grub should be able to read files from a GPT partition
even if the protective GPT entry in the MBR is not in the first slot.
It's also the conclusion of the thread [1], but I admit that this thread
is two years old.

Grégoire

[1] http://lists.gnu.org/archive/html/grub-devel/2008-09/msg00101.html


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  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
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-06-12 17:26 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 2279 bytes --]

On 06/12/2010 06:32 PM, Grégoire Sutre wrote:
> On 06/07/2010 10:46 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
>
>> There are two parts of this question:
>> 1) Which partition schemes should GRUB be able to read modules and
>> payloads from ? It's platform-indepedent and 2 conditions apply:
>> - Usage. There are OS which are able to boot from such OS and such
>> configuration isn't considered obscure by them.
>> - Non-confusability. The risk of false positive of this partition config
>> which would prevent normal function is small.
>> If at least one condition is met it's worth considering. If both
>> conditions are met it should be supported.
>
> According to these rules, hybrid msdos+gpt partitioning schemes should
> be supported.  Grub should be able to read files from a GPT partition
> even if the protective GPT entry in the MBR is not in the first slot.
> It's also the conclusion of the thread [1], but I admit that this thread
> is two years old.
>
Any "hybrid" cofiguration fails the criteria of non confusability. Let's
consider a following situation:
- I format disk with scheme A and partitions A1, A2, A3
- I get bored and reformat with scheme B and partitios B1, B2, B3, B4.
When I did this filesystem on A2 may stay intact
- I use grub which supposes that it'shybrid system A+B and save_env's to
A2 since it's a valid partition on valid filesystem. But by a bad luck
save_env overlaps with superblock of B3 which becomes corrupted.
When installed grub sees both partitions A and B it makes sense to allow
user to see both of them for recovery purposes but in any case it should
be a recommended config. Desync is way too easy. And currently grub
isn't changed to new partition notation completely. E.g. during startup
prefix is calculated with old syntax and confusing A+B with either A or
B is likely to make user drop into rescue shell
Also save_env should ensure that no dangerous situation exist.
> Grégoire
>
> [1] http://lists.gnu.org/archive/html/grub-devel/2008-09/msg00101.html
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-12 17:26     ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-06-13 16:16       ` Grégoire Sutre
  2010-06-14 11:37         ` Colin Watson
  0 siblings, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-13 16:16 UTC (permalink / raw)
  To: The development of GNU GRUB

On 06/12/2010 07:26 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:

> Any "hybrid" cofiguration fails the criteria of non confusability.

I was assuming the new partition notation.  The old notation is clearly
ambiguous when there are multiple partmaps, and AFAIR the new notation
was introduced precisely to solve that problem:

http://lists.gnu.org/archive/html/grub-devel/2010-01/msg00320.html

By the way, the old notation is worse than ambiguous when there are
multiple partmaps: the meaning of partition identifiers depends on the
partmap modules that are loaded, and on the order in which they are
loaded.

> Let's consider a following situation: - I format disk with scheme A
> and partitions A1, A2, A3 - I get bored and reformat with scheme B
> and partitios B1, B2, B3, B4. When I did this filesystem on A2 may
> stay intact - I use grub which supposes that it'shybrid system A+B
> and save_env's to A2 since it's a valid partition on valid
> filesystem. But by a bad luck save_env overlaps with superblock of B3
> which becomes corrupted.

If you save_env with -f then, with new notation, you know that you are
using the old scheme A.  If you didn't use -f, then it means that grub
modules were installed into A2 and survived the reformat, but then,
how could GRUB know that A is obsolete?  IMHO corrupting the superblock
of B3 is acceptable in that case.  An alternative would be to check
that partitions do not overlap (with the exception of identical
partitions).  But even this would work only if the partmap module for
B was loaded, which is likely not the case (as grub was installed at
the time A was used).

> And currently grub isn't changed to new partition notation
> completely. E.g. during startup prefix is calculated with old syntax
> and confusing A+B with either A or B is likely to make user drop into
> rescue shell

Is someone working on making the startup prefix use the new notation?

Grégoire



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-13 16:16       ` Grégoire Sutre
@ 2010-06-14 11:37         ` Colin Watson
  2010-06-14 13:07           ` richardvoigt
  0 siblings, 1 reply; 22+ messages in thread
From: Colin Watson @ 2010-06-14 11:37 UTC (permalink / raw)
  To: The development of GNU GRUB

On Sun, Jun 13, 2010 at 06:16:13PM +0200, Grégoire Sutre wrote:
> On 06/12/2010 07:26 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
>> And currently grub isn't changed to new partition notation
>> completely. E.g. during startup prefix is calculated with old syntax
>> and confusing A+B with either A or B is likely to make user drop into
>> rescue shell
>
> Is someone working on making the startup prefix use the new notation?

I've only looked at the i386-pc startup sequence here, but the thing
that jumps out at me is that grub_install_dos_part and
grub_install_bsd_part are both longs.  I doubt we really need to support
2 billion partitions.  How about we split off, say, a byte of that to
hold the partition map type, and then it would be easy enough for the
startup code to turn that into appropriate prefixes?

There are two downsides that I can see:

  * We would need to maintain an enum of partition map identifiers; but
    there's precedent for this approach already, such as
    grub_disk_dev_id.

  * The names of all the partition maps would have to live in the kernel
    somewhere; packed as sequential strings, this comes to 42 bytes plus
    the code to use it, which isn't a lot by most measures but I know we
    never have much slack in the kernel.


I can think of an alternative.  We do still need grub_install_dos_part
and grub_install_bsd_part for the multiboot trampoline, which is in
assembly, so it's difficult to abandon them altogether.  However,
there's no reason we need to use them in make_install_device.  How about
we invent a way to encode most of the information in string form in
grub_prefix, while leaving a placeholder for make_install_device to fill
in the disk?  There are 64 bytes available for grub_prefix, which should
be plenty.  For example, how about the following (with \0 standing for
ASCII NUL):

  (\0,msdos1,bsd1)/boot/grub

It's then just a matter of spotting the "(\0," sequence and replacing
the \0 with the drive name.  I think this can probably be done using
less code than the first option above, and all told it feels a bit less
hacky to me.


What do people prefer?

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 11:37         ` Colin Watson
@ 2010-06-14 13:07           ` richardvoigt
  2010-06-14 13:25             ` Colin Watson
  0 siblings, 1 reply; 22+ messages in thread
From: richardvoigt @ 2010-06-14 13:07 UTC (permalink / raw)
  To: The development of GNU GRUB

> I can think of an alternative.  We do still need grub_install_dos_part
> and grub_install_bsd_part for the multiboot trampoline, which is in
> assembly, so it's difficult to abandon them altogether.  However,
> there's no reason we need to use them in make_install_device.  How about
> we invent a way to encode most of the information in string form in
> grub_prefix, while leaving a placeholder for make_install_device to fill
> in the disk?  There are 64 bytes available for grub_prefix, which should
> be plenty.  For example, how about the following (with \0 standing for
> ASCII NUL):
>
>  (\0,msdos1,bsd1)/boot/grub
>
> It's then just a matter of spotting the "(\0," sequence and replacing
> the \0 with the drive name.  I think this can probably be done using
> less code than the first option above, and all told it feels a bit less
> hacky to me.

Instead of doing string replacement, why not just define a
disk-relative partition format?

Also, the '\0' seems unnecessary.  Is having "(," meaningful in some
way already?


>
>
> What do people prefer?
>
> --
> Colin Watson                                       [cjwatson@ubuntu.com]
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 13:07           ` richardvoigt
@ 2010-06-14 13:25             ` Colin Watson
  2010-06-14 15:02               ` Colin Watson
  0 siblings, 1 reply; 22+ messages in thread
From: Colin Watson @ 2010-06-14 13:25 UTC (permalink / raw)
  To: grub-devel

On Mon, Jun 14, 2010 at 08:07:35AM -0500, richardvoigt@gmail.com wrote:
> Colin Watson wrote:
> > I can think of an alternative.  We do still need grub_install_dos_part
> > and grub_install_bsd_part for the multiboot trampoline, which is in
> > assembly, so it's difficult to abandon them altogether.  However,
> > there's no reason we need to use them in make_install_device.  How about
> > we invent a way to encode most of the information in string form in
> > grub_prefix, while leaving a placeholder for make_install_device to fill
> > in the disk?  There are 64 bytes available for grub_prefix, which should
> > be plenty.  For example, how about the following (with \0 standing for
> > ASCII NUL):
> >
> >  (\0,msdos1,bsd1)/boot/grub
> >
> > It's then just a matter of spotting the "(\0," sequence and replacing
> > the \0 with the drive name.  I think this can probably be done using
> > less code than the first option above, and all told it feels a bit less
> > hacky to me.
> 
> Instead of doing string replacement, why not just define a
> disk-relative partition format?

Simple string replacement would be much easier to implement, and
probably smaller.  Plus, we don't need disk-relative device naming
elsewhere, and I think it would require putting platform-specific code
(otherwise how do you know which disk to be relative to?) in places that
are otherwise pretty platform-independent.

> Also, the '\0' seems unnecessary.  Is having "(," meaningful in some
> way already?

Good point.  This would be sufficient.

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 13:25             ` Colin Watson
@ 2010-06-14 15:02               ` Colin Watson
  2010-06-14 15:58                 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 22+ messages in thread
From: Colin Watson @ 2010-06-14 15:02 UTC (permalink / raw)
  To: grub-devel; +Cc: Axel Beckert, 585068

On Mon, Jun 14, 2010 at 02:25:39PM +0100, Colin Watson wrote:
> On Mon, Jun 14, 2010 at 08:07:35AM -0500, richardvoigt@gmail.com wrote:
> > Colin Watson wrote:
> > > I can think of an alternative.  We do still need grub_install_dos_part
> > > and grub_install_bsd_part for the multiboot trampoline, which is in
> > > assembly, so it's difficult to abandon them altogether.  However,
> > > there's no reason we need to use them in make_install_device.  How about
> > > we invent a way to encode most of the information in string form in
> > > grub_prefix, while leaving a placeholder for make_install_device to fill
> > > in the disk?  There are 64 bytes available for grub_prefix, which should
> > > be plenty.  For example, how about the following (with \0 standing for
> > > ASCII NUL):
> > >
> > >  (\0,msdos1,bsd1)/boot/grub
> > >
> > > It's then just a matter of spotting the "(\0," sequence and replacing
> > > the \0 with the drive name.  I think this can probably be done using
> > > less code than the first option above, and all told it feels a bit less
> > > hacky to me.
> > 
> > Instead of doing string replacement, why not just define a
> > disk-relative partition format?
> 
> Simple string replacement would be much easier to implement, and
> probably smaller.  Plus, we don't need disk-relative device naming
> elsewhere, and I think it would require putting platform-specific code
> (otherwise how do you know which disk to be relative to?) in places that
> are otherwise pretty platform-independent.
> 
> > Also, the '\0' seems unnecessary.  Is having "(," meaningful in some
> > way already?
> 
> Good point.  This would be sufficient.

How about the following patch, implementing this proposal?  I've tested this
with Debian GNU/kFreeBSD, and it's enough to make the boot loader work again
out of the box after grub-install.  The 'root' variable is still wrong, but
that isn't particularly urgent as UUIDs usually take care of that.

The kernel.img size increase is 84 bytes, yielding a core.img size
increase of 50 bytes in this configuration (22932 -> 22982 bytes).  Do I
need to work on making that smaller somehow?  It seems tolerable to me.

2010-06-14  Colin Watson  <cjwatson@ubuntu.com>

	Fix i386-pc prefix handling with nested partitions (Debian bug
	#585068).

	* 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.

=== 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-14 14:44:13 +0000
@@ -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] == ',')
+    {
+      /* 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;
 }

=== 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 14:45:24 +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);
@@ -289,21 +292,45 @@ setup (const char *dir,
      override the current setting.  */
   if (*install_dos_part != -2)
     {
+      grub_partition_t root_part = root_dev->disk->partition;
+
       /* Embed information about the installed location.  */
-      if (root_dev->disk->partition)
+      if (root_part)
 	{
-	  if (root_dev->disk->partition->parent)
+	  char *new_prefix;
+
+	  if (root_part->parent)
  	    {
-	      if (root_dev->disk->partition->parent->parent)
+	      if (root_part->parent->parent)
 		grub_util_error ("Installing on doubly nested partitions is "
 				 "not supported");
-	      dos_part = root_dev->disk->partition->parent->number;
-	      bsd_part = root_dev->disk->partition->number;
+	      dos_part = root_part->parent->number;
+	      bsd_part = root_part->number;
+
+	      if (prefix[0] != '(')
+		{
+		  new_prefix = xasprintf ("(,%s%d,%s%d)%s",
+					  root_part->parent->partmap->name,
+					  root_part->parent->number + 1,
+					  root_part->partmap->name,
+					  root_part->number + 1,
+					  prefix);
+		  strcpy (prefix, new_prefix);
+		}
  	    }
 	  else
  	    {
-	      dos_part = root_dev->disk->partition->number;
+	      dos_part = root_part->number;
  	      bsd_part = -1;
+
+	      if (prefix[0] != '(')
+		{
+		  new_prefix = xasprintf ("(,%s%d)%s",
+					  root_part->partmap->name,
+					  root_part->number + 1,
+					  prefix);
+		  strcpy (prefix, new_prefix);
+		}
  	    }
 	}
       else

Thanks,

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 15:02               ` Colin Watson
@ 2010-06-14 15:58                 ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-06-14 16:43                   ` Colin Watson
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-06-14 15:58 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 4228 bytes --]

On 06/14/2010 05:02 PM, Colin Watson wrote:
>
> 2010-06-14  Colin Watson  <cjwatson@ubuntu.com>
>
> 	Fix i386-pc prefix handling with nested partitions (Debian bug
> 	#585068).
>
> 	* 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.
>
>   
That makes a regression for multiboot loading of image if it was moved
from one partition to another.
> === 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-14 14:44:13 +0000
> @@ -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] == ',')
> +    {
> +      /* 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);
> +    }
>  
>   
Or grub_prefix[1] == ')' to allow ()/boot/grub syntax for unpartitioned
devices
>    return grub_prefix;
>  }
>
> === 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 14:45:24 +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);
> @@ -289,21 +292,45 @@ setup (const char *dir,
>       override the current setting.  */
>    if (*install_dos_part != -2)
>      {
> +      grub_partition_t root_part = root_dev->disk->partition;
> +
>        /* Embed information about the installed location.  */
> -      if (root_dev->disk->partition)
> +      if (root_part)
>  	{
> -	  if (root_dev->disk->partition->parent)
> +	  char *new_prefix;
> +
> +	  if (root_part->parent)
>   	    {
> -	      if (root_dev->disk->partition->parent->parent)
> +	      if (root_part->parent->parent)
>  		grub_util_error ("Installing on doubly nested partitions is "
>  				 "not supported");
>   
This error must go away with that new syntax.
> -	      dos_part = root_dev->disk->partition->parent->number;
> -	      bsd_part = root_dev->disk->partition->number;
> +	      dos_part = root_part->parent->number;
> +	      bsd_part = root_part->number;
> +
> +	      if (prefix[0] != '(')
> +		{
> +		  new_prefix = xasprintf ("(,%s%d,%s%d)%s",
> +					  root_part->parent->partmap->name,
> +					  root_part->parent->number + 1,
> +					  root_part->partmap->name,
> +					  root_part->number + 1,
> +					  prefix);
> +		  strcpy (prefix, new_prefix);
> +		}
>   
Please use grub_partition_get_name. It will greatly simplify this part.
>   	    }
>  	  else
>   	    {
> -	      dos_part = root_dev->disk->partition->number;
> +	      dos_part = root_part->number;
>   	      bsd_part = -1;
> +
> +	      if (prefix[0] != '(')
> +		{
> +		  new_prefix = xasprintf ("(,%s%d)%s",
> +					  root_part->partmap->name,
> +					  root_part->number + 1,
> +					  prefix);
> +		  strcpy (prefix, new_prefix);
> +		}
>   	    }
>  	}
>        else
>
> Thanks,
>
>   


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  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:12                     ` Grégoire Sutre
  0 siblings, 2 replies; 22+ messages in thread
From: Colin Watson @ 2010-06-14 16:43 UTC (permalink / raw)
  To: grub-devel

On Mon, Jun 14, 2010 at 05:58:55PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On 06/14/2010 05:02 PM, Colin Watson wrote:
> > 2010-06-14  Colin Watson  <cjwatson@ubuntu.com>
> >
> > 	Fix i386-pc prefix handling with nested partitions (Debian bug
> > 	#585068).
> >
> > 	* 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.
> 
> That makes a regression for multiboot loading of image if it was moved
> from one partition to another.

Do you have any suggestions on how to deal with that?  I'm not familiar
with multiboot and need guidance.

> > === 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-14 14:44:13 +0000
> > @@ -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] == ',')
> > +    {
> > +      /* 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);
> > +    }
> 
> Or grub_prefix[1] == ')' to allow ()/boot/grub syntax for unpartitioned
> devices

Makes sense.  I've updated my local tree.

> > +	  if (root_part->parent)
> >   	    {
> > -	      if (root_dev->disk->partition->parent->parent)
> > +	      if (root_part->parent->parent)
> >  		grub_util_error ("Installing on doubly nested partitions is "
> >  				 "not supported");
> >   
> 
> This error must go away with that new syntax.

I agree, but how should kern/i386/pc/startup.S:multiboot_trampoline
cope?  I left this there because I didn't know a straightforward way to
deal with that.

> > -	      dos_part = root_dev->disk->partition->parent->number;
> > -	      bsd_part = root_dev->disk->partition->number;
> > +	      dos_part = root_part->parent->number;
> > +	      bsd_part = root_part->number;
> > +
> > +	      if (prefix[0] != '(')
> > +		{
> > +		  new_prefix = xasprintf ("(,%s%d,%s%d)%s",
> > +					  root_part->parent->partmap->name,
> > +					  root_part->parent->number + 1,
> > +					  root_part->partmap->name,
> > +					  root_part->number + 1,
> > +					  prefix);
> > +		  strcpy (prefix, new_prefix);
> > +		}
> >   
> 
> Please use grub_partition_get_name. It will greatly simplify this part.

Done, thanks.  (I had a memory leak too.)

Updated patch follows; same ChangeLog.

=== 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-14 16:21:53 +0000
@@ -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;
 }

=== 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;

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  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
  1 sibling, 1 reply; 22+ messages in thread
From: Seth Goldberg @ 2010-06-14 16:55 UTC (permalink / raw)
  To: The development of GNU GRUB


>>> === 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-14 14:44:13 +0000
>>> @@ -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] == ',')
>>> +    {
>>> +      /* 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);
>>> +    }

   What about CD devices?  Seems like you're limiting to hd and fd here (though 
CD may just be an alias for hd198 or something like that).  Just checking :).

  --S


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 16:43                   ` Colin Watson
  2010-06-14 16:55                     ` Seth Goldberg
@ 2010-06-14 17:12                     ` Grégoire Sutre
  2010-06-15 11:21                       ` Colin Watson
  1 sibling, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-14 17:12 UTC (permalink / raw)
  To: The development of GNU GRUB

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.

Grégoire

p.s. This issue (with boot_device field) was discussed a bit in:

http://lists.gnu.org/archive/html/grub-devel/2010-01/msg00351.html
http://lists.gnu.org/archive/html/grub-devel/2010-02/msg00070.html


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 16:55                     ` Seth Goldberg
@ 2010-06-14 17:33                       ` Colin Watson
  0 siblings, 0 replies; 22+ messages in thread
From: Colin Watson @ 2010-06-14 17:33 UTC (permalink / raw)
  To: The development of GNU GRUB

On Mon, Jun 14, 2010 at 09:55:09AM -0700, Seth Goldberg wrote:
>>>> === 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-14 14:44:13 +0000
>>>> @@ -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] == ',')
>>>> +    {
>>>> +      /* 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);
>>>> +    }
>
>   What about CD devices?  Seems like you're limiting to hd and fd here 
> (though CD may just be an alias for hd198 or something like that).  Just 
> checking :).

That part of my patch was just copied from immediately above, so doesn't
really change the current state.

grub-mkrescue has special code for dealing with CDs and setting an
appropriate prefix at run-time from the output of a 'search' command.

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-14 17:12                     ` Grégoire Sutre
@ 2010-06-15 11:21                       ` Colin Watson
  2010-06-15 21:07                         ` Grégoire Sutre
  2010-06-17  0:47                         ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 2 replies; 22+ messages in thread
From: Colin Watson @ 2010-06-15 11:21 UTC (permalink / raw)
  To: grub-devel

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]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-15 11:21                       ` Colin Watson
@ 2010-06-15 21:07                         ` Grégoire Sutre
  2010-06-16 13:01                           ` Colin Watson
  2010-06-17  0:47                         ` Vladimir 'φ-coder/phcoder' Serbinenko
  1 sibling, 1 reply; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-15 21:07 UTC (permalink / raw)
  To: The development of GNU GRUB

On 06/15/2010 01:21 PM, Colin Watson wrote:

>> 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.

Ok.

> 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.

This would be nice.

>    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.

Since the command-line processing of the MBI is done after startup.S (in 
grub_machine_init()),

- the MBI (only the relevant portions for simplicity) needs to be copied
   to a safe place.  The patch does it at the end of grub_machine_init(),
   but I'm afraid this might be too late: the MBI may have been
   overwritten before we reach that point.  Or is the code (startup.S and
   grub_machine_init()) designed to guarantee that all memory writes are
   in safe locations, outside of the whole MBI?

- couldn't the complete processing of the MBI be performed in the same
   place, i.e. grub_machine_init()?  The assembly multiboot part would
   only check whether GRUB was booted by multiboot, and set (or copy)
   the MBI in that case.  Then the procedure to set grub_prefix would be
   coded in one place.  This would require though, for multiboot, to get
   grub_boot_drive from the boot_device field (the current assembly code
   takes care of this).

>   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));

Moving the MBI is more complex, since the structure contains pointers
to other structures (themselves containing pointers etc.).  But in our
case it's not too painful since we only need to copy the struct
multiboot_info and the string pointed to by its cmdline field (and set
the field to the new address).

Grégoire


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-15 21:07                         ` Grégoire Sutre
@ 2010-06-16 13:01                           ` Colin Watson
  2010-06-16 23:31                             ` Grégoire Sutre
  0 siblings, 1 reply; 22+ messages in thread
From: Colin Watson @ 2010-06-16 13:01 UTC (permalink / raw)
  To: grub-devel

On Tue, Jun 15, 2010 at 11:07:42PM +0200, Grégoire Sutre wrote:
> On 06/15/2010 01:21 PM, Colin Watson wrote:
>>    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.
>
> Since the command-line processing of the MBI is done after startup.S (in  
> grub_machine_init()),
>
> - the MBI (only the relevant portions for simplicity) needs to be copied
>   to a safe place.  The patch does it at the end of grub_machine_init(),
>   but I'm afraid this might be too late: the MBI may have been
>   overwritten before we reach that point.  Or is the code (startup.S and
>   grub_machine_init()) designed to guarantee that all memory writes are
>   in safe locations, outside of the whole MBI?

You're right.  I was copying this from coreboot, but it does much less
in its startup.S - in particular it doesn't relocate and decompress the
GRUB kernel!

> - couldn't the complete processing of the MBI be performed in the same
>   place, i.e. grub_machine_init()?  The assembly multiboot part would
>   only check whether GRUB was booted by multiboot, and set (or copy)
>   the MBI in that case.  Then the procedure to set grub_prefix would be
>   coded in one place.  This would require though, for multiboot, to get
>   grub_boot_drive from the boot_device field (the current assembly code
>   takes care of this).

My investigations suggest that this is very difficult.  Relocating the
GRUB kernel, which is almost the first thing multiboot_entry does, is
liable to overwrite the MBI, and you can't get at C code until you've
done that.  That's why multiboot_entry has to copy out the boot device
field even before it relocates the kernel.

>>   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));
>
> Moving the MBI is more complex, since the structure contains pointers
> to other structures (themselves containing pointers etc.).  But in our
> case it's not too painful since we only need to copy the struct
> multiboot_info and the string pointed to by its cmdline field (and set
> the field to the new address).

Yes, you're right that we do need to copy the cmdline string itself.

Here's an updated patch, which I've tested to the point of it actually
being able to make use of prefix environment variables passed on the
multiboot command line.  Please review this again?

2010-06-16  Colin Watson  <cjwatson@ubuntu.com>

	Fix i386-pc prefix handling with nested partitions (Debian bug
	#585068).  Take some care to avoid regressing multiboot, including
	adding command-line environment variable support on i386-pc.

	* include/grub/i386/pc/kernel.h (grub_multiboot_flags): New
	declaration.
	(grub_multiboot_change_prefix): Likewise.
	* include/grub/i386/pc/memory.h
	(GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS): Reserve space after the
	initial struct grub_machine_mmap_entry in the scratch area.
	(GRUB_MEMORY_MACHINE_MULTIBOOT_CMDLINE): Likewise.
	* include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Increase to
	GRUB_KERNEL_I386_PC_DATA_END + 0x620.
	* kern/i386/pc/startup.S (multiboot_entry): Copy the MBI flags and
	command line (if set) to the scratch area.
	(multiboot_trampoline): Copy the MBI flags to grub_multiboot_flags
	now that we're relocated.  If the new partition numbers differ from
	the previous ones, then set grub_multiboot_change_prefix.
	(grub_multiboot_change_prefix): New definition.
	(grub_multiboot_flags): Likewise.
	* kern/i386/pc/init.c (make_install_device): Invalidate any
	drive/partition part of the prefix if grub_multiboot_change_prefix
	is set and an explicit prefix was not set on the multiboot command
	line.  After that, if the prefix starts with "(," or "()", 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 the MULTIBOOT_INFO_CMDLINE flag is set, call
	grub_parse_multiboot_cmdline.
	(grub_machine_set_prefix): Don't overwrite an explicit prefix set on
	the multiboot command line.
	* 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-16 12:53:46 +0000
@@ -44,6 +44,13 @@ extern grub_int32_t grub_install_bsd_par
 /* The boot BIOS drive number.  */
 extern grub_uint8_t EXPORT_VAR(grub_boot_drive);
 
+/* The multiboot flags.  Zero if not booted using multiboot.  */
+extern grub_uint32_t grub_multiboot_flags;
+
+/* 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 'include/grub/i386/pc/memory.h'
--- include/grub/i386/pc/memory.h	2010-04-26 08:56:12 +0000
+++ include/grub/i386/pc/memory.h	2010-06-16 12:32:34 +0000
@@ -54,6 +54,15 @@
 #define GRUB_MEMORY_MACHINE_RESERVED_END	\
 	(GRUB_MEMORY_MACHINE_PROT_STACK + 0x10)
 
+/* The area where multiboot information is copied at early startup.  These
+   need to live in the scratch area rather than in normal variables because
+   they are copied away for safekeeping before GRUB relocates its own code.
+   We leave space for the heap memory allocator first.  */
+#define GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS	\
+	(GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x20)
+#define GRUB_MEMORY_MACHINE_MULTIBOOT_CMDLINE	\
+	(GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS + 0x4)
+
 /* The area where GRUB is decompressed at early startup.  */
 #define GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR	0x100000
 

=== modified file 'include/grub/offsets.h'
--- include/grub/offsets.h	2010-04-26 19:11:16 +0000
+++ include/grub/offsets.h	2010-06-16 12:53:07 +0000
@@ -41,7 +41,7 @@
 #define GRUB_KERNEL_I386_PC_DATA_END		0x5c
 
 /* The size of the first region which won't be compressed.  */
-#define GRUB_KERNEL_I386_PC_RAW_SIZE		(GRUB_KERNEL_I386_PC_DATA_END + 0x5F0)
+#define GRUB_KERNEL_I386_PC_RAW_SIZE		(GRUB_KERNEL_I386_PC_DATA_END + 0x620)
 
 /* The segment where the kernel is loaded.  */
 #define GRUB_BOOT_I386_PC_KERNEL_SEG	0x800

=== 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-16 12:55:50 +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,25 @@ static int num_regions;
 grub_addr_t grub_os_area_addr;
 grub_size_t grub_os_area_size;
 
+static int found_multiboot_prefix;
+
 static char *
 make_install_device (void)
 {
   /* XXX: This should be enough.  */
   char dev[100], *ptr = dev;
 
+  if (grub_prefix[0] == '(' && grub_multiboot_change_prefix &&
+      !found_multiboot_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 +97,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 +156,49 @@ compact_mem_regions (void)
       }
 }
 
+static void
+grub_parse_multiboot_cmdline (void)
+{
+  char *cmdline = (char *) GRUB_MEMORY_MACHINE_MULTIBOOT_CMDLINE;
+  char *p;
+
+  if (!*cmdline)
+    return;
+
+  p = cmdline = grub_strdup (cmdline);
+
+  while (*p)
+    {
+      char *command = p;
+      char *end;
+      char *val;
+
+      end = grub_strchr (command, ' ');
+      if (end)
+	{
+	  *end = '\0';
+	  p = end + 1;
+	  while (*p == ' ')
+	    ++p;
+	}
+      else
+	p = grub_strchr (command, '\0');
+
+      /* Process command.  */
+      val = grub_strchr (command, '=');
+      if (val)
+	{
+	  *val = '\0';
+	  grub_env_set (command, val + 1);
+
+	  /* If "prefix" is explicitly on the command line, then don't override
+	     it later.  */
+	  if (grub_strcmp (command, "prefix") == 0)
+	    found_multiboot_prefix = 1;
+	}
+    }
+}
+
 void
 grub_machine_init (void)
 {
@@ -214,6 +279,9 @@ grub_machine_init (void)
   if (! grub_os_area_addr)
     grub_fatal ("no upper memory");
 
+  if (grub_multiboot_flags & MULTIBOOT_INFO_CMDLINE)
+    grub_parse_multiboot_cmdline ();
+
   grub_tsc_init ();
 }
 
@@ -221,7 +289,8 @@ void
 grub_machine_set_prefix (void)
 {
   /* Initialize the prefix.  */
-  grub_env_set ("prefix", make_install_device ());
+  if (!found_multiboot_prefix)
+    grub_env_set ("prefix", make_install_device ());
 }
 
 void

=== 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-16 12:55:05 +0000
@@ -145,6 +145,32 @@ multiboot_entry:
 	/* obtain the boot device */
 	movl	12(%ebx), %edx
 
+	cld
+
+	/* do we have a multiboot command line? */
+	movl	(%ebx), %eax
+	movl	$GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS, %edi
+	movl	%eax, (%edi)
+	testl	$MULTIBOOT_INFO_CMDLINE, %eax
+	jz	1f
+
+	/* if so, copy it to a safe place; do this before relocating code to
+	   make sure that we don't lose it */
+	movl	16(%ebx), %edi
+	pushl	%edi
+	xorb	%al, %al
+	xorl	%ecx, %ecx
+	decl	%ecx
+	repne
+	scasb
+	incl	%ecx
+	negl	%ecx
+	popl	%esi
+	movl	$GRUB_MEMORY_MACHINE_MULTIBOOT_CMDLINE, %edi
+	rep
+	movsb
+
+1:
 	movl	$GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
 	movl	%ebp, %esp
 
@@ -153,7 +179,6 @@ multiboot_entry:
 	addl	EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
 	movl	$0x100000, %esi
 	movl	$GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
-	cld
 	rep
 	movsb
 	/* jump to the real address */
@@ -161,20 +186,44 @@ multiboot_entry:
 	jmp	*%eax
 
 multiboot_trampoline:
+	/* move the multiboot flags to a local variable now that we've
+	   relocated ourselves; this lets us guarantee that multiboot_flags
+	   will be zero when not booted using multiboot */
+	movl	$GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS, %eax
+	movl	(%eax), %eax
+	movl	%eax, EXT_C(grub_multiboot_flags)
+
+	movl	EXT_C(grub_install_dos_part), %eax
+	testl	%eax, %eax
+	jns	1f
+	movb	$0xFF, %al
+1:
+	movl	EXT_C(grub_install_bsd_part), %ebx
+	testl	%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 */
+	incb	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,9 +334,14 @@ LOCAL (codestart):
 
 VARIABLE(grub_boot_drive)
 	.byte	0
+VARIABLE(grub_multiboot_change_prefix)
+	.byte	0
 
 	.p2align	2	/* force 4-byte alignment */
 
+VARIABLE(grub_multiboot_flags)
+	.long	0
+
 #include "../realmode.S"
 
 /*

=== 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]


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-16 13:01                           ` Colin Watson
@ 2010-06-16 23:31                             ` Grégoire Sutre
  0 siblings, 0 replies; 22+ messages in thread
From: Grégoire Sutre @ 2010-06-16 23:31 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi,

I made several tests, and the patch works fine with standard boot.  When
multibooting core.img, the command-line is taken into account correctly.
However, if no multiboot command-line is given, the prefix is set as
before (old partition naming style).

This comes from the fact that the modifications to the prefix done in
grub-setup only apply to the embedded image, and not to the core.img
file.  The grub-mkimage command used by grub-install is:

grub-mkimage -O i386-pc --output=/path/to/core.img --prefix=/boot/grub

Would it make sense to put the full prefix here?


>> - couldn't the complete processing of the MBI be performed in the same
>>    place, i.e. grub_machine_init()?  The assembly multiboot part would
>>    only check whether GRUB was booted by multiboot, and set (or copy)
>>    the MBI in that case.  Then the procedure to set grub_prefix would be
>>    coded in one place.  This would require though, for multiboot, to get
>>    grub_boot_drive from the boot_device field (the current assembly code
>>    takes care of this).
>
> My investigations suggest that this is very difficult.  Relocating the
> GRUB kernel, which is almost the first thing multiboot_entry does, is
> liable to overwrite the MBI, and you can't get at C code until you've
> done that.  That's why multiboot_entry has to copy out the boot device
> field even before it relocates the kernel.

What I meant is: the assembly part could be restricted to the copy of
the relevant MBI information, i.e. flags, boot_device and cmdline.  And
leave the actual decisions regarding the contents of those fields to
grub_machine_init().  This would mean that the part dealing with
grub_install_dos/bsd_part (multiboot_trampoline) would be part of the C
code (probably in make_install_device()).


>   grub_machine_set_prefix (void)
>   {
>     /* Initialize the prefix.  */
> -  grub_env_set ("prefix", make_install_device ());
> +  if (!found_multiboot_prefix)
> +    grub_env_set ("prefix", make_install_device ());

You could avoid the variable found_multiboot_prefix and use
grub_env_find("prefix").  The intention would be that if someone
(multiboot or someone else) has already set the prefix in grub_env,
then we shouldn't override this choice here.  This would simplify
a bit grub_parse_multiboot_cmdline(), which would become purely
generic.  But this is essentially cosmetic...


  === 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-16 12:55:05 +0000
> @@ -145,6 +145,32 @@ multiboot_entry:
>   	/* obtain the boot device */
>   	movl	12(%ebx), %edx

The boot_device field should be used only if the MULTIBOOT_INFO_BOOTDEV
flag is set.  This problem is already present in trunk.

> +	/* if so, copy it to a safe place; do this before relocating code to
> +	   make sure that we don't lose it */
> +	movl	16(%ebx), %edi
> +	pushl	%edi

Is it safe to push?  Maybe we should start by setting %esp as is done a
few lines below.

I honestly do not understand all the details regarding the assembly code
or the memory management, so I can't provide useful feedback on that.
I just noticed that GRUB_MEMORY_MACHINE_MULTIBOOT_FLAGS is copied into a
``regular'' variable, but GRUB_MEMORY_MACHINE_MULTIBOOT_CMDLINE is not.

Grégoire


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-15 11:21                       ` Colin Watson
  2010-06-15 21:07                         ` Grégoire Sutre
@ 2010-06-17  0:47                         ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-06-17 11:29                           ` Colin Watson
  1 sibling, 1 reply; 22+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-06-17  0:47 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 10306 bytes --]

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  <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,
>
>   


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Which partitioning schemes should be supported by GRUB?
  2010-06-17  0:47                         ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-06-17 11:29                           ` Colin Watson
  0 siblings, 0 replies; 22+ messages in thread
From: Colin Watson @ 2010-06-17 11:29 UTC (permalink / raw)
  To: grub-devel

On Thu, Jun 17, 2010 at 02:47:11AM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> 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)

OK, thanks.  I've committed the non-multiboot part as per
http://lists.gnu.org/archive/html/grub-devel/2010-06/msg00093.html.

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2010-06-17 11:29 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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.