diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S
index 2a913ba..451e832 100644
--- a/boot/i386/pc/lnxboot.S
+++ b/boot/i386/pc/lnxboot.S
@@ -38,6 +38,7 @@
 
 data_start:
 	xorl	%ebp, %ebp
+	xorl	%edi, %edi
 	jmp	linux_next
 
 	. = data_start + 0x1F1
@@ -115,7 +116,7 @@ gdt_dst2:
 	.long	0, 0, 0, 0		/* More space for the BIOS.  */
 
 reg_edx:
-	.byte	0x80, 0xFF, 0xFF, 0xFF
+	.byte	0x80, 0, 0xFF, 0xFF
 
 data_leng:
 	.long	0
@@ -123,6 +124,7 @@ data_leng:
 linux_init:
 
 	movw	%cs:(reg_edx - start), %dx
+	movl	%cs:(cmd_line_ptr - start), %edi
 	movl	%cs:(code32_start - start), %ebp
 
 linux_next:
@@ -140,25 +142,48 @@ normalize:
 	lret				/* Jump to real_code.  */
 
 real_code:
-	subw	$0x20, %ax
-	movw	%ax, %ds
-	movw	(setup_sects - data_start), %cx
-	shlw	$7, %cx
-
 	/* Setup stack.  */
 
-	xorw	%si, %si
-	movw	%si, %ss
+	xorw	%ax, %ax
+	movw	%ax, %ss
 	movw	$(CODE_ADDR), %sp
 
+	cld
+	movw	$(CODE_ADDR >> 4), %ax
+	movw	%ax, %es
+
+	/* Copy command line.  */
+	orl	%edi, %edi
+	jz	2f
+
+	movw	%di, %si
+	andw	$0xF, %si
+	shrl	$4, %edi
+	movw	%di, %ds
+	movw	$(CODE_LENG), %di
+
+1:
+	lodsb	%ds:(%si)
+	stosb	%es:(%di)
+	orb	%al, %al
+	jnz	1b
+
+	xorl	%edi, %edi
+	movw	%es, %di
+	addw	$(CODE_LENG >> 4), %di
+	shll	$4, %edi
+
+2:
+
+	pushl	%edi
+
 	/* Move itself to 0:CODE_ADDR.  */
 
-	cld
 	movw	%cs, %ax
 	movw	%ax, %ds
-	movw	$(CODE_ADDR >> 4), %ax
-	movw	%ax, %es
-	movw	%si, %di
+	movw	$(CODE_LENG >> 2), %cx
+	xorw	%si, %si
+	xorw	%di, %di
 
 	rep
 	movsl
@@ -201,12 +226,16 @@ real_code_2:
 2:
 	call	move_memory
 
+	popl	%ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_BOOT_CMDLINE)
+
 	movsbl	%dh, %eax
 	movl	%eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
 
 	movsbl	(reg_edx + 2 - start), %eax
 	movl	%eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
 
+	movb	$0xFF, %dh
+
 	ljmp	$(DATA_ADDR >> 4), $0
 
 /*
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index 848dad1..f7bf7ff 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -37,14 +37,17 @@
 /* The offset of GRUB_MEMDISK_IMAGE_SIZE.  */
 #define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE	0x1c
 
+/* The offset of GRUB_BOOT_CMDLINE.  */
+#define GRUB_KERNEL_MACHINE_BOOT_CMDLINE	0x20
+
 /* The offset of GRUB_PREFIX.  */
-#define GRUB_KERNEL_MACHINE_PREFIX		0x20
+#define GRUB_KERNEL_MACHINE_PREFIX		0x24
 
 /* End of the data section. */
 #define GRUB_KERNEL_MACHINE_DATA_END		0x50
 
 /* The size of the first region which won't be compressed.  */
-#define GRUB_KERNEL_MACHINE_RAW_SIZE		0x4A0
+#define GRUB_KERNEL_MACHINE_RAW_SIZE		0x4C0
 
 #ifndef ASM_FILE
 
@@ -66,6 +69,9 @@ extern grub_int32_t grub_install_bsd_part;
 /* The size of memory disk image, if present.  */
 extern grub_int32_t grub_memdisk_image_size;
 
+/* The boot command line options.  */
+extern char *grub_boot_cmdline;
+
 /* The prefix which points to the directory where GRUB modules and its
    configuration file are located.  */
 extern char grub_prefix[];
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 7237492..91c2c4e 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -31,6 +31,7 @@
 #include <grub/env.h>
 #include <grub/cache.h>
 #include <grub/time.h>
+#include <grub/parser.h>
 
 struct mem_region
 {
@@ -63,9 +64,15 @@ static char *
 make_install_device (void)
 {
   /* XXX: This should be enough.  */
-  char dev[100];
+  char dev[100], *p;
 
-  if (grub_memdisk_image_size)
+  p = grub_env_get ("root");
+  if (p)
+    {
+      grub_sprintf (dev, "%s%s", p, grub_prefix);
+      grub_strcpy (grub_prefix, dev);
+    }
+  else if (grub_memdisk_image_size)
     {
       grub_sprintf (dev, "(memdisk)%s", grub_prefix);
       grub_strcpy (grub_prefix, dev);
@@ -248,7 +255,32 @@ void
 grub_machine_set_prefix (void)
 {
   /* Initialize the prefix.  */
-  grub_env_set ("prefix", make_install_device ());
+  if ((grub_boot_cmdline) && (grub_boot_cmdline[0]))
+    {
+      int argc;
+      char **argv;
+
+      if (! grub_parser_split_cmdline (grub_boot_cmdline, 0, &argc, &argv))
+        {
+          int i;
+
+          for (i = 0; i <= argc; i++)
+            {
+              char *p;
+
+              p = grub_strchr (argv[i], '=');
+              if (p)
+                {
+                  *(p++) = 0;
+                  grub_env_set (argv[i], p);
+                }
+            }
+          grub_free (argv);
+        }
+    }
+
+  if (! grub_env_get ("prefix"))
+    grub_env_set ("prefix", make_install_device ());
 }
 
 void
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index bf3d4ee..e31dbe7 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -98,6 +98,8 @@ VARIABLE(grub_install_bsd_part)
 	.long	0xFFFFFFFF
 VARIABLE(grub_memdisk_image_size)
 	.long	0
+VARIABLE(grub_boot_cmdline)
+	.long	0
 VARIABLE(grub_prefix)
 	/* to be filled by grub-mkimage */
 
@@ -149,6 +151,18 @@ multiboot_entry:
 	
 multiboot_trampoline:
 	/* fill the boot information */
+	movl	16(%ebx), %esi
+	orl	%esi, %esi
+	jz	2f
+	movl	$(GRUB_MEMORY_MACHINE_REAL_STACK + 0x10), %edi
+	movl	%edi, EXT_C(grub_boot_cmdline)
+	cld
+1:
+	lodsb	%ds:(%esi)
+	stosb	%es:(%edi)
+	orb	%al, %al
+	jnz	1b
+2:
 	movl	%edx, %eax
 	shrl	$8, %eax
 	xorl	%ebx, %ebx
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
index 67959cf..2a67ef1 100644
--- a/loader/i386/pc/multiboot.c
+++ b/loader/i386/pc/multiboot.c
@@ -44,6 +44,7 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/gzio.h>
+#include <grub/env.h>
 
 extern grub_dl_t my_mod;
 static struct grub_multiboot_info *mbi;
@@ -261,6 +262,52 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer)
   return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
 }
 
+static int
+grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
+{
+  char *p;
+
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      grub_uint32_t bd;
+
+      bd = (p[0] == 'h') ? 0x80 : 0;
+      bd += grub_strtoul (p + 2, &p, 0);
+      bd <<= 24;
+
+      if ((p) && (p[0] == ','))
+	{
+	  if ((p[1] >= '0') && (p[1] <= '9'))
+	    {
+
+	      bd += ((grub_strtoul (p + 1, &p, 0) - 1) & 0xFF) << 16;
+
+	      if ((p) && (p[0] == ','))
+		p++;
+	    }
+          else
+            bd += 0xFF0000;
+
+	  if ((p[0] >= 'a') && (p[0] <= 'z'))
+            bd += (p[0] - 'a') << 8;
+          else
+            bd += 0xFF00;
+	}
+      else
+        bd += 0xFFFF00;
+
+      bd += 0xFF;
+
+      *bootdev = bd;
+      return 1;
+    }
+
+  return 0;
+}
+
+
 void
 grub_multiboot (int argc, char *argv[])
 {
@@ -368,6 +415,9 @@ grub_multiboot (int argc, char *argv[])
   mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
   mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);
 
+  if (grub_multiboot_get_bootdev (&mbi->boot_device))
+    mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
+
   grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
 
  fail:
