Hi,

For normal boot, the root device is passed to core.img in preloader.
However, if we load grub2 using linux header, there is no way to know
the root device. This patch add a new module findroot that can be used
to scan the root directory at startup.

One important usage is to create a grub2 boot file for vista boot loader:

mkimage -o g2ntfs.img pc ntfs biosdisk findroot
cat lnxboot.img g2ntfs.img > g2ntfs.mbr

The result g2ntfs.mbr is within 32K, which can be loaded by vista in
one pass, no need to use the g2ldr.mbr anymore. The findroot modules
ensure that prefix is set properly before switching to normal mode.

If findroot is not used to create core.img, the original booting method remains.

-- 
Bean
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 37a9f5b..89ad861 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -155,7 +155,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod 
linux.mod normal.mod \
        vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
        videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod  \
        ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \
-       aout.mod _bsd.mod bsd.mod
+       aout.mod _bsd.mod bsd.mod findroot.mod
 
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -322,4 +322,9 @@ bsd_mod_SOURCES = loader/i386/bsd_normal.c
 bsd_mod_CFLAGS = $(COMMON_CFLAGS)
 bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For findroot.mod.
+findroot_mod_SOURCES = kern/findroot.c
+findroot_mod_CFLAGS = $(COMMON_CFLAGS)
+findroot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index 43a8d5b..c35b8d4 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -68,7 +68,7 @@ extern grub_int32_t grub_memdisk_image_size;
 
 /* The prefix which points to the directory where GRUB modules and its
    configuration file are located.  */
-extern char grub_prefix[];
+extern char EXPORT_VAR(grub_prefix) [];
 
 /* The boot BIOS drive number.  */
 extern grub_int32_t EXPORT_VAR(grub_boot_drive);
diff --git a/kern/findroot.c b/kern/findroot.c
new file mode 100755
index 0000000..6a6cc69
--- /dev/null
+++ b/kern/findroot.c
@@ -0,0 +1,77 @@
+/* findroot.c - search for root device */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/file.h>
+#include <grub/env.h>
+#include <grub/machine/kernel.h>
+
+#define KERNEL_FILE    "/normal.mod"
+
+static void
+find_root (void)
+{
+  char *buf = 0;
+  auto int iterate_device (const char *name);
+
+  int iterate_device (const char *name)
+    {
+      grub_size_t len;
+      char *p;
+      grub_file_t file;
+
+      len = grub_strlen (name) + 2 + grub_strlen (grub_prefix) +
+            sizeof (KERNEL_FILE);
+
+      p = grub_realloc (buf, len);
+      if (! p)
+       return 1;
+
+      buf = p;
+      grub_sprintf (buf, "(%s)%s" KERNEL_FILE, name, grub_prefix);
+
+      file = grub_file_open (buf);
+      if (file)
+       {
+          buf[grub_strlen (name) + 2 + grub_strlen (grub_prefix)] = 0;
+          grub_env_set ("prefix", buf);
+
+          grub_file_close (file);
+
+          return 1;
+       }
+
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+
+  grub_device_iterate (iterate_device);
+
+  grub_free (buf);
+}
+
+GRUB_MOD_INIT(findroot)
+{
+  find_root ();
+}
diff --git a/kern/main.c b/kern/main.c
index 09de03a..a7e1e4f 100644
--- a/kern/main.c
+++ b/kern/main.c
@@ -124,7 +124,9 @@ grub_main (void)
 
   /* It is better to set the root device as soon as possible,
      for convenience.  */
-  grub_machine_set_prefix ();
+  if (! grub_env_get ("prefix"))
+    grub_machine_set_prefix ();
+
   grub_set_root_dev ();
 
   /* Load the normal mode module.  */
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to