NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-i386/42599: Multiboot(8) command-line format/parsing
>Number: 42599
>Category: port-i386
>Synopsis: Multiboot(8) command-line format/parsing problem with GRUB 2
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: port-i386-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jan 09 18:55:01 +0000 2010
>Originator: Grégoire Sutre
>Release: NetBSD 5.0_STABLE (20091024)
>Organization:
>Environment:
System: NetBSD niagara 5.0_STABLE NetBSD 5.0_STABLE (NIAGARA) #0: Sat Oct 24
11:54:39 CEST 2009
instsoft@niagara:/usr/build/usr/src/sys/arch/i386/compile/NIAGARA i386
Architecture: i386
Machine: i386
>Description:
I've been experimenting with multibooting NetBSD/i386 (5.0_STABLE) from
GRUB 2, and I had some problems passing the right arguments on the
multiboot command line. I thought this list might be a good place to
report them, especially since the problems are not so specific to GRUB 2.
This started with the fact that, in GRUB 2, the command-line passed to
the kernel does not contain the kernel itself, i.e. with the command
multiboot (hd0,1,a)/netbsd -z root=wd0a
the command-line passed to the kernel is "-z root=wd0a". The option
root=wd0a is detected ok by the kernel, but -z is ignored. Looking at
sys/arch/i386/i386/multiboot.c (the code is very clear by the way :-))
revealed the reason: when parsing boothowto(9) options, the first
argument of the multiboot command-line is assumed to be the kernel file
name, and is thus ignored. The other parsing functions do not make this
assumption, for instance, the command line "root=wd0a -z" works fine.
If the multiboot kernel code expects the command-line to be in a
specific format, then I would find it helpful to have the detailed
format in the multiboot(8) man page. As far as I understand the code,
the command-line passed to the kernel (by the boot-loader) is expected
to be of the form:
absolutefilename [-1234abcdmqsvxz] [extraopt=value ...]
An alternative solution would be to accept a more general format for the
multiboot command-line, with no pre-supposed ordering of the arguments.
For instance `-zs root=wd0a /netbsd console=pc' would be accepted. I
believe that all functions in multiboot.c already authorize this, except
setup_howto. A small patch that allows this for setup_howto is
attached. The patch actually also accepts boothowto options that are
not grouped together, e.g. `-z root=wd0a -s' but this can be removed.
The patch also removes an if test in the function setup_bootpath that
checks whether Multiboot_Loader_Name is lexicographically greater than
"GNU GRUB ". I fail to see why this is required, and, moreover, this is
specific to GRUB Legacy, since GRUB 2 identifies itself as "GRUB ".
Maybe the intention here is to avoid setting an empty bootpath, but this
could be checked by actually testing the guessed the bootpath before
setting it.
Thanks for your time,
Grégoire Sutre
p.s. Regarding NetBSD's boot-loader (boot(8)), with `multiboot netbsd',
the command-line passed to the kernel starts with `netbsd' instead of
`/netbsd', which leads to btinfo_bootpath not being set in function
setup_bootpath. But I did not see the actual effect of that (except
that the sysctl parameter `machdep.booted_kernel' is empty).
>How-To-Repeat:
Boot from GRUB 2 with a command of the form:
multiboot (hd0,1,a)/netbsd -z root=wd0a
and observe that `-z' is not taken into account.
>Fix:
Possible patch:
Index: multiboot.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/multiboot.c,v
retrieving revision 1.17
diff -C10 -a -u -p -r1.17 multiboot.c
--- multiboot.c 11 Oct 2008 11:06:19 -0000 1.17
+++ multiboot.c 9 Jan 2010 17:01:00 -0000
@@ -483,41 +483,38 @@ setup_bootdisk(struct multiboot_info *mi
* structure does not provide this detail directly, so we try to derive
* it from the command line setting.
*/
static void
setup_bootpath(struct multiboot_info *mi)
{
struct btinfo_bootpath bi;
char *cl, *cl2, old;
int len;
- if (strncmp(Multiboot_Loader_Name, "GNU GRUB ",
- sizeof(Multiboot_Loader_Name)) > 0) {
cl = mi->mi_cmdline;
while (*cl != '\0' && *cl != '/')
cl++;
cl2 = cl;
len = 0;
while (*cl2 != '\0' && *cl2 != ' ') {
len++;
cl2++;
}
old = *cl2;
*cl2 = '\0';
memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len));
*cl2 = old;
bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0';
bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH,
sizeof(struct btinfo_bootpath));
- }
}
/* --------------------------------------------------------------------- */
/*
* Sets up the console bootinfo structure if the user gave a 'console'
* argument on the boot command line. The Multiboot information
* structure gives no hint about this, so the only way to know where the
* console is is to let the user specify it.
*
@@ -583,39 +580,36 @@ setup_console(struct multiboot_info *mi)
static void
setup_howto(struct multiboot_info *mi)
{
char *cl;
if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE))
return;
cl = mi->mi_cmdline;
- /* Skip kernel file name. */
- while (*cl != '\0' && *cl != ' ')
- cl++;
- while (*cl != '\0' && *cl == ' ')
- cl++;
-
/* Check if there are flags and set 'howto' accordingly. */
- if (*cl == '-') {
- int howto = 0;
-
- cl++;
- while (*cl != '\0' && *cl != ' ') {
- BOOT_FLAG(*cl, howto);
+ while (*cl != '\0') {
+ /* Invariant: (cl == mi->mi_cmdline) or (*cl == ' '). */
+ while (*cl == ' ')
cl++;
- }
- if (*cl == ' ')
+ if (*cl == '-') {
cl++;
-
- boothowto = howto;
+ while (*cl != '\0' && *cl != ' ') {
+ BOOT_FLAG(*cl, boothowto);
+ cl++;
+ }
+ }
+ else {
+ while (*cl != '\0' && *cl != ' ')
+ cl++;
+ }
}
}
/* --------------------------------------------------------------------- */
/*
* Sets up the memmap bootinfo structure to describe available memory as
* given by the BIOS.
*/
static void
Home |
Main Index |
Thread Index |
Old Index