]> git.proxmox.com Git - grub2.git/commitdiff
reorganized grub-emu sources to suite upcoming automake build system
authorBVK Chaitanya <bvk.groups@gmail.com>
Tue, 27 Apr 2010 05:20:28 +0000 (10:50 +0530)
committerBVK Chaitanya <bvk.groups@gmail.com>
Tue, 27 Apr 2010 05:20:28 +0000 (10:50 +0530)
32 files changed:
bus/emu/pci.c [new file with mode: 0644]
bus/usb/emu/usb.c [new file with mode: 0644]
conf/any-emu.rmk
conf/common.rmk
include/grub/emu/console.h [new file with mode: 0644]
include/grub/emu/getroot.h [new file with mode: 0644]
include/grub/emu/hostdisk.h [new file with mode: 0644]
include/grub/emu/misc.h [new file with mode: 0644]
include/grub/util/console.h [deleted file]
include/grub/util/getroot.h [deleted file]
include/grub/util/hostdisk.h [deleted file]
kern/emu/cache.S [new file with mode: 0644]
kern/emu/console.c [new file with mode: 0644]
kern/emu/dummy/dl.c [new file with mode: 0644]
kern/emu/getroot.c [new file with mode: 0644]
kern/emu/hostdisk.c [new file with mode: 0644]
kern/emu/hostfs.c [new file with mode: 0644]
kern/emu/lite.c [new file with mode: 0644]
kern/emu/main.c [new file with mode: 0644]
kern/emu/misc.c [new file with mode: 0644]
kern/emu/time.c [new file with mode: 0644]
util/console.c [deleted file]
util/getroot.c [deleted file]
util/grub-emu.c [deleted file]
util/grub-probe.c
util/hostdisk.c [deleted file]
util/hostfs.c [deleted file]
util/pci.c [deleted file]
util/sdl.c [deleted file]
util/time.c [deleted file]
util/usb.c [deleted file]
video/emu/sdl.c [new file with mode: 0644]

diff --git a/bus/emu/pci.c b/bus/emu/pci.c
new file mode 100644 (file)
index 0000000..420ae32
--- /dev/null
@@ -0,0 +1,76 @@
+/* pci.c - Generic PCI interfaces.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2009  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/pci.h>
+#include <grub/dl.h>
+#include <grub/util/misc.h>
+
+grub_pci_address_t
+grub_pci_make_address (grub_pci_device_t dev, int reg)
+{
+  grub_pci_address_t ret;
+  ret.dev = dev;
+  ret.pos = reg;
+  return ret;
+}
+
+void
+grub_pci_iterate (grub_pci_iteratefunc_t hook)
+{
+  struct pci_device_iterator *iter;
+  struct pci_slot_match slot;
+  struct pci_device *dev;
+  slot.domain = PCI_MATCH_ANY;
+  slot.bus = PCI_MATCH_ANY;
+  slot.dev = PCI_MATCH_ANY;
+  slot.func = PCI_MATCH_ANY;
+  iter = pci_slot_match_iterator_create (&slot);
+  while ((dev = pci_device_next (iter)))
+    hook (dev, dev->vendor_id | (dev->device_id << 16));
+  pci_iterator_destroy (iter);
+}
+
+void *
+grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
+                          grub_size_t size)
+{
+  void *addr;
+  int err;
+  err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
+  if (err)
+    grub_util_error ("mapping 0x%x failed (error %d)\n", base, err);
+  return addr;
+}
+
+void
+grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
+                            grub_size_t size)
+{
+  pci_device_unmap_range (dev, mem, size);
+}
+
+GRUB_MOD_INIT (pci)
+{
+  pci_system_init ();
+}
+
+GRUB_MOD_FINI (pci)
+{
+  pci_system_cleanup ();
+}
diff --git a/bus/usb/emu/usb.c b/bus/usb/emu/usb.c
new file mode 100644 (file)
index 0000000..a687eea
--- /dev/null
@@ -0,0 +1,195 @@
+/*  usb.c -- libusb USB support for GRUB.  */
+/*
+ *  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 <config.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <usb.h>
+#include <grub/usb.h>
+#include <grub/dl.h>
+
+\f
+static struct grub_usb_controller_dev usb_controller =
+{
+  .name = "libusb"
+};
+
+static struct grub_usb_device *grub_usb_devs[128];
+
+struct usb_bus *busses;
+
+static grub_err_t
+grub_libusb_devices (void)
+
+{
+  struct usb_bus *bus;
+  int last = 0;
+
+  busses = usb_get_busses();
+
+  for (bus = busses; bus; bus = bus->next)
+    {
+      struct usb_device *usbdev;
+      struct grub_usb_device *dev;
+
+      for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
+       {
+         struct usb_device_descriptor *desc = &usbdev->descriptor;
+         grub_err_t err;
+
+         if (! desc->bcdUSB)
+           continue;
+
+         dev = grub_malloc (sizeof (*dev));
+         if (! dev)
+           return grub_errno;
+
+         dev->data = usbdev;
+
+         /* Fill in all descriptors.  */
+         err = grub_usb_device_initialize (dev);
+         if (err)
+           {
+             grub_errno = GRUB_ERR_NONE;
+             continue;
+           }
+
+         /* Register the device.  */
+         grub_usb_devs[last++] = dev;
+       }
+    }
+
+  return GRUB_USB_ERR_NONE;
+}
+
+\f
+int
+grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
+{
+  int i;
+
+  for (i = 0; i < 128; i++)
+    {
+      if (grub_usb_devs[i])
+       {
+         if (hook (grub_usb_devs[i]))
+             return 1;
+       }
+    }
+
+  return 0;
+}
+
+grub_usb_err_t
+grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
+{
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
+                     grub_uint8_t request, grub_uint16_t value,
+                     grub_uint16_t index, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_control_msg (devh, reqtype, request,
+                      value, index, data, size, 20) < 0)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_bulk_read (grub_usb_device_t dev,
+                   int endpoint, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_claim_interface (devh, 0) < 1)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  usb_release_interface (devh, 0);
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_bulk_write (grub_usb_device_t dev,
+                    int endpoint, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_claim_interface (devh, 0) < 0)
+    goto fail;
+
+  if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
+    goto fail;
+
+  if (usb_release_interface (devh, 0) < 0)
+    goto fail;
+
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+
+ fail:
+  usb_close (devh);
+  return GRUB_USB_ERR_STALL;
+}
+
+GRUB_MOD_INIT (libusb)
+{
+  usb_init();
+  usb_find_busses();
+  usb_find_devices();
+
+  if (grub_libusb_devices ())
+    return;
+
+  grub_usb_controller_dev_register (&usb_controller);
+
+  return;
+}
+
+GRUB_MOD_FINI (libusb)
+{
+  return;
+}
index d1e5754dc0fe9219ad200727e292fc921f3c3548..5f6798d791a1ce30c4d87a6c240318981b8c22b5 100644 (file)
@@ -10,11 +10,11 @@ kernel_img_SOURCES = kern/device.c kern/disk.c kern/dl.c kern/env.c \
        kern/parser.c kern/partition.c kern/term.c                      \
        kern/rescue_reader.c kern/rescue_parser.c                       \
        \
-       util/console.c  util/grub-emu.c util/misc.c                     \
-       util/hostdisk.c util/getroot.c util/mm.c util/time.c            \
+       kern/emu/misc.c kern/emu/getroot.c kern/emu/time.c              \
+       kern/emu/hostdisk.c kern/emu/hostfs.c kern/emu/console.c        \
        \
-       gnulib/progname.c util/hostfs.c disk/host.c
-kernel_img_HEADERS += datetime.h util/misc.h
+       gnulib/progname.c disk/host.c
+kernel_img_HEADERS += datetime.h emu/misc.h
 kernel_img_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Wno-undef -I$(srcdir)/gnulib
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS)
 TARGET_NO_STRIP = yes
@@ -49,7 +49,7 @@ ifeq ($(enable_grub_emu_usb), yes)
 kernel_img_HEADERS += libusb.h
 
 pkglib_MODULES += libusb.mod
-libusb_mod_SOURCES = util/usb.c
+libusb_mod_SOURCES = bus/usb/emu/usb.c
 libusb_mod_CFLAGS = 
 libusb_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
@@ -76,7 +76,7 @@ endif
 
 ifeq ($(enable_grub_emu_sdl), yes)
 pkglib_MODULES += sdl.mod
-sdl_mod_SOURCES = util/sdl.c
+sdl_mod_SOURCES = video/emu/sdl.c
 sdl_mod_CFLAGS = 
 sdl_mod_LDFLAGS = $(COMMON_LDFLAGS)
 grub_emu_LDFLAGS += $(LIBSDL)
@@ -106,8 +106,13 @@ ifneq ($(TARGET_NO_MODULES), yes)
 grub-emu: $(pkglib_PROGRAMS)
        $(CC) -o $@ $(pkglib_PROGRAMS) $(grub_emu_LDFLAGS) $(LDFLAGS)
 else
+
+pkglib_MODULES += emu.mod
+emu_mod_SOURCES = kern/emu/main.c
+emu_mod_CFLAGS = -I$(srcdir)/gnulib
+
 grub-emu: $(pkglib_MODULES) $(pkglib_PROGRAMS)
-       $(CC) -o $@ $(pkglib_MODULES) $(pkglib_PROGRAMS) $(grub_emu_LDFLAGS) $(LDFLAGS)
+       $(CC) -o $@ $^ $(grub_emu_LDFLAGS) $(LDFLAGS)
 endif
 GRUB_EMU=grub-emu
 
index 8df232a0b915fe74b64944d67616f32c9b041c6c..6267d781826af7270d954fb8d3ce488910095b7a 100644 (file)
@@ -25,7 +25,7 @@ util/elf/grub-mkimage.c_DEPENDENCIES = Makefile
 sbin_UTILITIES += grub-probe
 util/grub-probe.c_DEPENDENCIES = grub_probe_init.h
 grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c       \
-       util/hostdisk.c util/misc.c util/getroot.c util/mm.c    \
+       kern/emu/hostdisk.c util/misc.c kern/emu/getroot.c util/mm.c    \
        kern/device.c kern/disk.c kern/err.c kern/misc.c        \
        kern/parser.c kern/partition.c kern/file.c kern/list.c  \
        \
@@ -60,7 +60,7 @@ grub_mkisofs_CFLAGS = -D_FILE_OFFSET_BITS=64                          \
 
 # For grub-fstest.
 util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
-grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c util/hostfs.c \
+grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c kern/emu/hostfs.c \
        util/misc.c util/mm.c   \
        kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c    \
        disk/host.c disk/loopback.c kern/list.c kern/command.c          \
diff --git a/include/grub/emu/console.h b/include/grub/emu/console.h
new file mode 100644 (file)
index 0000000..1e55682
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  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/>.
+ */
+
+#ifndef GRUB_CONSOLE_UTIL_HEADER
+#define GRUB_CONSOLE_UTIL_HEADER       1
+
+/* Initialize the console system.  */
+void grub_console_init (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_UTIL_HEADER */
diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h
new file mode 100644 (file)
index 0000000..f9f7f9b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003, 2007, 2008, 2009  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/>.
+ */
+
+#ifndef GRUB_UTIL_GETROOT_HEADER
+#define GRUB_UTIL_GETROOT_HEADER       1
+
+enum grub_dev_abstraction_types {
+  GRUB_DEV_ABSTRACTION_NONE,
+  GRUB_DEV_ABSTRACTION_LVM,
+  GRUB_DEV_ABSTRACTION_RAID,
+};
+
+char *grub_guess_root_device (const char *dir);
+char *grub_get_prefix (const char *dir);
+int grub_util_get_dev_abstraction (const char *os_dev);
+char *grub_util_get_grub_dev (const char *os_dev);
+const char *grub_util_check_block_device (const char *blk_dev);
+const char *grub_util_check_char_device (const char *blk_dev);
+
+#endif /* ! GRUB_UTIL_GETROOT_HEADER */
diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h
new file mode 100644 (file)
index 0000000..246046e
--- /dev/null
@@ -0,0 +1,30 @@
+/* biosdisk.h - emulate biosdisk */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2007  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/>.
+ */
+
+#ifndef GRUB_BIOSDISK_MACHINE_UTIL_HEADER
+#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER      1
+
+#include <grub/disk.h>
+
+void grub_util_biosdisk_init (const char *dev_map);
+void grub_util_biosdisk_fini (void);
+char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
+const char *grub_util_biosdisk_get_osdev (grub_disk_t disk);
+
+#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
new file mode 100644 (file)
index 0000000..e62aeba
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef GRUB_EMU_MISC_H
+#define GRUB_EMU_MISC_H 1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+#ifdef __NetBSD__
+/* NetBSD uses /boot for its boot block.  */
+# define DEFAULT_DIRECTORY     "/grub"
+#else
+# define DEFAULT_DIRECTORY     "/boot/grub"
+#endif
+
+#define DEFAULT_DEVICE_MAP     DEFAULT_DIRECTORY "/device.map"
+
+extern int verbosity;
+extern const char *program_name;
+
+void grub_init_all (void);
+void grub_fini_all (void);
+
+void * EXPORT_FUNC(xmalloc) (grub_size_t size);
+void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size);
+char * EXPORT_FUNC(xstrdup) (const char *str);
+char * EXPORT_FUNC(xasprintf) (const char *fmt, ...);
+
+void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...);
+void EXPORT_FUNC(grub_util_info) (const char *fmt, ...);
+void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((noreturn));
+
+#endif /* GRUB_EMU_MISC_H */
diff --git a/include/grub/util/console.h b/include/grub/util/console.h
deleted file mode 100644 (file)
index 1e55682..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2009  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/>.
- */
-
-#ifndef GRUB_CONSOLE_UTIL_HEADER
-#define GRUB_CONSOLE_UTIL_HEADER       1
-
-/* Initialize the console system.  */
-void grub_console_init (void);
-
-/* Finish the console system.  */
-void grub_console_fini (void);
-
-#endif /* ! GRUB_CONSOLE_UTIL_HEADER */
diff --git a/include/grub/util/getroot.h b/include/grub/util/getroot.h
deleted file mode 100644 (file)
index f9f7f9b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003, 2007, 2008, 2009  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/>.
- */
-
-#ifndef GRUB_UTIL_GETROOT_HEADER
-#define GRUB_UTIL_GETROOT_HEADER       1
-
-enum grub_dev_abstraction_types {
-  GRUB_DEV_ABSTRACTION_NONE,
-  GRUB_DEV_ABSTRACTION_LVM,
-  GRUB_DEV_ABSTRACTION_RAID,
-};
-
-char *grub_guess_root_device (const char *dir);
-char *grub_get_prefix (const char *dir);
-int grub_util_get_dev_abstraction (const char *os_dev);
-char *grub_util_get_grub_dev (const char *os_dev);
-const char *grub_util_check_block_device (const char *blk_dev);
-const char *grub_util_check_char_device (const char *blk_dev);
-
-#endif /* ! GRUB_UTIL_GETROOT_HEADER */
diff --git a/include/grub/util/hostdisk.h b/include/grub/util/hostdisk.h
deleted file mode 100644 (file)
index 246046e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* biosdisk.h - emulate biosdisk */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2007  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/>.
- */
-
-#ifndef GRUB_BIOSDISK_MACHINE_UTIL_HEADER
-#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER      1
-
-#include <grub/disk.h>
-
-void grub_util_biosdisk_init (const char *dev_map);
-void grub_util_biosdisk_fini (void);
-char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
-const char *grub_util_biosdisk_get_osdev (grub_disk_t disk);
-
-#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
diff --git a/kern/emu/cache.S b/kern/emu/cache.S
new file mode 100644 (file)
index 0000000..087b2b4
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef GRUB_MACHINE_EMU
+#error "This source is only meant for grub-emu platform"
+#endif
+
+#if GRUB_CPU_I386
+#elif GRUB_CPU_X86_64
+#elif GRUB_CPU_SPARC64
+#include "../sparc64/cache.S"
+#elif GRUB_CPU_MIPS
+#include "../mips/cache.S"
+#elif GRUB_CPU_MIPSEL
+#include "../mips/cache.S"
+#elif GRUB_CPU_POWERPC
+#include "../powerpc/cache.S"
+#else
+#error "No target cpu type is defined"
+#endif
diff --git a/kern/emu/console.c b/kern/emu/console.c
new file mode 100644 (file)
index 0000000..f7fbc89
--- /dev/null
@@ -0,0 +1,384 @@
+/*  console.c -- Ncurses console for GRUB.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,2007,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 <config.h>
+
+/* For compatibility.  */
+#ifndef A_NORMAL
+# define A_NORMAL      0
+#endif /* ! A_NORMAL */
+#ifndef A_STANDOUT
+# define A_STANDOUT    0
+#endif /* ! A_STANDOUT */
+
+#include <grub/emu/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+
+#if defined(HAVE_NCURSES_CURSES_H)
+# include <ncurses/curses.h>
+#elif defined(HAVE_NCURSES_H)
+# include <ncurses.h>
+#elif defined(HAVE_CURSES_H)
+# include <curses.h>
+#endif
+
+static int grub_console_attr = A_NORMAL;
+
+grub_uint8_t grub_console_cur_color = 7;
+
+static grub_uint8_t grub_console_standard_color = 0x7;
+static grub_uint8_t grub_console_normal_color = 0x7;
+static grub_uint8_t grub_console_highlight_color = 0x70;
+
+#define NUM_COLORS     8
+
+static grub_uint8_t color_map[NUM_COLORS] =
+{
+  COLOR_BLACK,
+  COLOR_BLUE,
+  COLOR_GREEN,
+  COLOR_CYAN,
+  COLOR_RED,
+  COLOR_MAGENTA,
+  COLOR_YELLOW,
+  COLOR_WHITE
+};
+
+static int use_color;
+
+static void
+grub_ncurses_putchar (grub_uint32_t c)
+{
+  /* Better than nothing.  */
+  switch (c)
+    {
+    case GRUB_TERM_DISP_LEFT:
+      c = '<';
+      break;
+
+    case GRUB_TERM_DISP_UP:
+      c = '^';
+      break;
+
+    case GRUB_TERM_DISP_RIGHT:
+      c = '>';
+      break;
+
+    case GRUB_TERM_DISP_DOWN:
+      c = 'v';
+      break;
+
+    case GRUB_TERM_DISP_HLINE:
+      c = '-';
+      break;
+
+    case GRUB_TERM_DISP_VLINE:
+      c = '|';
+      break;
+
+    case GRUB_TERM_DISP_UL:
+    case GRUB_TERM_DISP_UR:
+    case GRUB_TERM_DISP_LL:
+    case GRUB_TERM_DISP_LR:
+      c = '+';
+      break;
+
+    default:
+      /* ncurses does not support Unicode.  */
+      if (c > 0x7f)
+       c = '?';
+      break;
+    }
+
+  addch (c | grub_console_attr);
+}
+
+static grub_ssize_t
+grub_ncurses_getcharwidth (grub_uint32_t code __attribute__ ((unused)))
+{
+  return 1;
+}
+
+static void
+grub_ncurses_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+      grub_console_cur_color = grub_console_standard_color;
+      grub_console_attr = A_NORMAL;
+      break;
+    case GRUB_TERM_COLOR_NORMAL:
+      grub_console_cur_color = grub_console_normal_color;
+      grub_console_attr = A_NORMAL;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      grub_console_cur_color = grub_console_highlight_color;
+      grub_console_attr = A_STANDOUT;
+      break;
+    default:
+      break;
+    }
+
+  if (use_color)
+    {
+      grub_uint8_t fg, bg;
+
+      fg = (grub_console_cur_color & 7);
+      bg = (grub_console_cur_color >> 4) & 7;
+
+      grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
+      color_set ((bg << 3) + fg, 0);
+    }
+}
+
+/* XXX: This function is never called.  */
+static void
+grub_ncurses_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
+{
+  grub_console_normal_color = normal_color;
+  grub_console_highlight_color = highlight_color;
+}
+
+static void
+grub_ncurses_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  *normal_color = grub_console_normal_color;
+  *highlight_color = grub_console_highlight_color;
+}
+
+static int saved_char = ERR;
+
+static int
+grub_ncurses_checkkey (void)
+{
+  int c;
+
+  /* Check for SAVED_CHAR. This should not be true, because this
+     means checkkey is called twice continuously.  */
+  if (saved_char != ERR)
+    return saved_char;
+
+  wtimeout (stdscr, 100);
+  c = getch ();
+  /* If C is not ERR, then put it back in the input queue.  */
+  if (c != ERR)
+    {
+      saved_char = c;
+      return c;
+    }
+
+  return -1;
+}
+
+static int
+grub_ncurses_getkey (void)
+{
+  int c;
+
+  /* If checkkey has already got a character, then return it.  */
+  if (saved_char != ERR)
+    {
+      c = saved_char;
+      saved_char = ERR;
+    }
+  else
+    {
+      wtimeout (stdscr, -1);
+      c = getch ();
+    }
+
+  switch (c)
+    {
+    case KEY_LEFT:
+      c = 2;
+      break;
+
+    case KEY_RIGHT:
+      c = 6;
+      break;
+
+    case KEY_UP:
+      c = 16;
+      break;
+
+    case KEY_DOWN:
+      c = 14;
+      break;
+
+    case KEY_IC:
+      c = 24;
+      break;
+
+    case KEY_DC:
+      c = 4;
+      break;
+
+    case KEY_BACKSPACE:
+      /* XXX: For some reason ncurses on xterm does not return
+        KEY_BACKSPACE.  */
+    case 127:
+      c = 8;
+      break;
+
+    case KEY_HOME:
+      c = 1;
+      break;
+
+    case KEY_END:
+      c = 5;
+      break;
+
+    case KEY_NPAGE:
+      c = 3;
+      break;
+
+    case KEY_PPAGE:
+      c = 7;
+      break;
+    }
+
+  return c;
+}
+
+static grub_uint16_t
+grub_ncurses_getxy (void)
+{
+  int x;
+  int y;
+
+  getyx (stdscr, y, x);
+
+  return (x << 8) | y;
+}
+
+static grub_uint16_t
+grub_ncurses_getwh (void)
+{
+  int x;
+  int y;
+
+  getmaxyx (stdscr, y, x);
+
+  return (x << 8) | y;
+}
+
+static void
+grub_ncurses_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  move (y, x);
+}
+
+static void
+grub_ncurses_cls (void)
+{
+  clear ();
+  refresh ();
+}
+
+static void
+grub_ncurses_setcursor (int on)
+{
+  curs_set (on ? 1 : 0);
+}
+
+static void
+grub_ncurses_refresh (void)
+{
+  refresh ();
+}
+
+static grub_err_t
+grub_ncurses_init (void)
+{
+  initscr ();
+  raw ();
+  noecho ();
+  scrollok (stdscr, TRUE);
+
+  nonl ();
+  intrflush (stdscr, FALSE);
+  keypad (stdscr, TRUE);
+
+  if (has_colors ())
+    {
+      start_color ();
+
+      if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
+        {
+          int i, j, n;
+
+          n = 0;
+          for (i = 0; i < NUM_COLORS; i++)
+            for (j = 0; j < NUM_COLORS; j++)
+              init_pair(n++, color_map[j], color_map[i]);
+
+          use_color = 1;
+        }
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_ncurses_fini (void)
+{
+  endwin ();
+  return 0;
+}
+
+\f
+static struct grub_term_input grub_ncurses_term_input =
+  {
+    .name = "console",
+    .checkkey = grub_ncurses_checkkey,
+    .getkey = grub_ncurses_getkey,
+  };
+
+static struct grub_term_output grub_ncurses_term_output =
+  {
+    .name = "console",
+    .init = grub_ncurses_init,
+    .fini = grub_ncurses_fini,
+    .putchar = grub_ncurses_putchar,
+    .getcharwidth = grub_ncurses_getcharwidth,
+    .getxy = grub_ncurses_getxy,
+    .getwh = grub_ncurses_getwh,
+    .gotoxy = grub_ncurses_gotoxy,
+    .cls = grub_ncurses_cls,
+    .setcolorstate = grub_ncurses_setcolorstate,
+    .setcolor = grub_ncurses_setcolor,
+    .getcolor = grub_ncurses_getcolor,
+    .setcursor = grub_ncurses_setcursor,
+    .refresh = grub_ncurses_refresh
+  };
+
+void
+grub_console_init (void)
+{
+  grub_term_register_output ("console", &grub_ncurses_term_output);
+  grub_term_register_input ("console", &grub_ncurses_term_input);
+}
+
+void
+grub_console_fini (void)
+{
+  grub_ncurses_fini ();
+}
diff --git a/kern/emu/dummy/dl.c b/kern/emu/dummy/dl.c
new file mode 100644 (file)
index 0000000..8e9fabf
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  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 <config.h>
+#include <grub/dl.h>
+
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  (void) mod;
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+
+/* int */
+/* grub_dl_ref (grub_dl_t mod) */
+/* {  */
+/*   (void) mod; */
+/*   return 0; */
+/* } */
+
+/* int */
+/* grub_dl_unref (grub_dl_t mod) */
+/* {  */
+/*   (void) mod; */
+/*   return 0; */
+/* } */
diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c
new file mode 100644 (file)
index 0000000..91799aa
--- /dev/null
@@ -0,0 +1,644 @@
+/* getroot.c - Get root device */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009  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 <config.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __CYGWIN__
+# include <sys/fcntl.h>
+# include <sys/cygwin.h>
+# include <limits.h>
+# define DEV_CYGDRIVE_MAJOR 98
+#endif
+
+#ifdef __GNU__
+#include <hurd.h>
+#include <hurd/lookup.h>
+#include <hurd/fs.h>
+#endif
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+
+static void
+strip_extra_slashes (char *dir)
+{
+  char *p = dir;
+
+  while ((p = strchr (p, '/')) != 0)
+    {
+      if (p[1] == '/')
+       {
+         memmove (p, p + 1, strlen (p));
+         continue;
+       }
+      else if (p[1] == '\0')
+       {
+         if (p > dir)
+           p[0] = '\0';
+         break;
+       }
+
+      p++;
+    }
+}
+
+static char *
+xgetcwd (void)
+{
+  size_t size = 10;
+  char *path;
+
+  path = xmalloc (size);
+  while (! getcwd (path, size))
+    {
+      size <<= 1;
+      path = xrealloc (path, size);
+    }
+
+  return path;
+}
+
+#ifdef __CYGWIN__
+/* Convert POSIX path to Win32 path,
+   remove drive letter, replace backslashes.  */
+static char *
+get_win32_path (const char *path)
+{
+  char winpath[PATH_MAX];
+  cygwin_conv_to_full_win32_path (path, winpath);
+
+  int len = strlen (winpath);
+  if (len > 2 && winpath[1] == ':')
+    {
+      len -= 2;
+      memmove (winpath, winpath + 2, len + 1);
+    }
+
+  int i;
+  for (i = 0; i < len; i++)
+    if (winpath[i] == '\\')
+      winpath[i] = '/';
+  return xstrdup (winpath);
+}
+#endif
+
+char *
+grub_get_prefix (const char *dir)
+{
+  char *saved_cwd;
+  char *abs_dir, *prev_dir;
+  char *prefix;
+  struct stat st, prev_st;
+
+  /* Save the current directory.  */
+  saved_cwd = xgetcwd ();
+
+  if (chdir (dir) < 0)
+    grub_util_error ("cannot change directory to `%s'", dir);
+
+  abs_dir = xgetcwd ();
+  strip_extra_slashes (abs_dir);
+  prev_dir = xstrdup (abs_dir);
+
+  if (stat (".", &prev_st) < 0)
+    grub_util_error ("cannot stat `%s'", dir);
+
+  if (! S_ISDIR (prev_st.st_mode))
+    grub_util_error ("`%s' is not a directory", dir);
+
+  while (1)
+    {
+      if (chdir ("..") < 0)
+       grub_util_error ("cannot change directory to the parent");
+
+      if (stat (".", &st) < 0)
+       grub_util_error ("cannot stat current directory");
+
+      if (! S_ISDIR (st.st_mode))
+       grub_util_error ("current directory is not a directory???");
+
+      if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
+       break;
+
+      free (prev_dir);
+      prev_dir = xgetcwd ();
+      prev_st = st;
+    }
+
+  strip_extra_slashes (prev_dir);
+  prefix = xmalloc (strlen (abs_dir) - strlen (prev_dir) + 2);
+  prefix[0] = '/';
+  strcpy (prefix + 1, abs_dir + strlen (prev_dir));
+  strip_extra_slashes (prefix);
+
+  if (chdir (saved_cwd) < 0)
+    grub_util_error ("cannot change directory to `%s'", dir);
+
+#ifdef __CYGWIN__
+  if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
+    {
+      /* Reached some mount point not below /cygdrive.
+        GRUB does not know Cygwin's emulated mounts,
+        convert to Win32 path.  */
+      grub_util_info ("Cygwin prefix = %s", prefix);
+      char * wprefix = get_win32_path (prefix);
+      free (prefix);
+      prefix = wprefix;
+    }
+#endif
+
+  free (saved_cwd);
+  free (abs_dir);
+  free (prev_dir);
+
+  grub_util_info ("prefix = %s", prefix);
+  return prefix;
+}
+
+#ifdef __MINGW32__
+
+static char *
+find_root_device (const char *dir __attribute__ ((unused)),
+                  dev_t dev __attribute__ ((unused)))
+{
+  return 0;
+}
+
+#elif ! defined(__CYGWIN__)
+
+static char *
+find_root_device (const char *dir, dev_t dev)
+{
+  DIR *dp;
+  char *saved_cwd;
+  struct dirent *ent;
+
+  dp = opendir (dir);
+  if (! dp)
+    return 0;
+
+  saved_cwd = xgetcwd ();
+
+  grub_util_info ("changing current directory to %s", dir);
+  if (chdir (dir) < 0)
+    {
+      free (saved_cwd);
+      closedir (dp);
+      return 0;
+    }
+
+  while ((ent = readdir (dp)) != 0)
+    {
+      struct stat st;
+
+      /* Avoid:
+        - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
+        - dotdirs (like "/dev/.static") since they could contain duplicates.  */
+      if (ent->d_name[0] == '.')
+       continue;
+
+      if (lstat (ent->d_name, &st) < 0)
+       /* Ignore any error.  */
+       continue;
+
+      if (S_ISLNK (st.st_mode))
+       /* Don't follow symbolic links.  */
+       continue;
+
+      if (S_ISDIR (st.st_mode))
+       {
+         /* Find it recursively.  */
+         char *res;
+
+         res = find_root_device (ent->d_name, dev);
+
+         if (res)
+           {
+             if (chdir (saved_cwd) < 0)
+               grub_util_error ("cannot restore the original directory");
+
+             free (saved_cwd);
+             closedir (dp);
+             return res;
+           }
+       }
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
+#else
+      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
+#endif
+       {
+#ifdef __linux__
+         /* Skip device names like /dev/dm-0, which are short-hand aliases
+            to more descriptive device names, e.g. those under /dev/mapper */
+         if (ent->d_name[0] == 'd' &&
+             ent->d_name[1] == 'm' &&
+             ent->d_name[2] == '-' &&
+             ent->d_name[3] >= '0' &&
+             ent->d_name[3] <= '9')
+           continue;
+#endif
+
+         /* Found!  */
+         char *res;
+         char *cwd;
+#if defined(__NetBSD__)
+         /* Convert this block device to its character (raw) device.  */
+         const char *template = "%s/r%s";
+#else
+         /* Keep the device name as it is.  */
+         const char *template = "%s/%s";
+#endif
+
+         cwd = xgetcwd ();
+         res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
+         sprintf (res, template, cwd, ent->d_name);
+         strip_extra_slashes (res);
+         free (cwd);
+
+         /* /dev/root is not a real block device keep looking, takes care
+            of situation where root filesystem is on the same partition as
+            grub files */
+
+         if (strcmp(res, "/dev/root") == 0)
+               continue;
+
+         if (chdir (saved_cwd) < 0)
+           grub_util_error ("cannot restore the original directory");
+
+         free (saved_cwd);
+         closedir (dp);
+         return res;
+       }
+    }
+
+  if (chdir (saved_cwd) < 0)
+    grub_util_error ("cannot restore the original directory");
+
+  free (saved_cwd);
+  closedir (dp);
+  return 0;
+}
+
+#else /* __CYGWIN__ */
+
+/* Read drive/partition serial number from mbr/boot sector,
+   return 0 on read error, ~0 on unknown serial.  */
+static unsigned
+get_bootsec_serial (const char *os_dev, int mbr)
+{
+  /* Read boot sector.  */
+  int fd = open (os_dev, O_RDONLY);
+  if (fd < 0)
+    return 0;
+  unsigned char buf[0x200];
+  int n = read (fd, buf, sizeof (buf));
+  close (fd);
+  if (n != sizeof(buf))
+    return 0;
+
+  /* Check signature.  */
+  if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
+    return ~0;
+
+  /* Serial number offset depends on boot sector type.  */
+  if (mbr)
+    n = 0x1b8;
+  else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
+    n = 0x048;
+  else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
+    n = 0x043;
+  else if (memcmp (buf + 0x36, "FAT", 3) == 0)
+    n = 0x027;
+  else
+    return ~0;
+
+  unsigned serial = *(unsigned *)(buf + n);
+  if (serial == 0)
+    return ~0;
+  return serial;
+}
+
+static char *
+find_cygwin_root_device (const char *path, dev_t dev)
+{
+  /* No root device for /cygdrive.  */
+  if (dev == (DEV_CYGDRIVE_MAJOR << 16))
+    return 0;
+
+  /* Convert to full POSIX and Win32 path.  */
+  char fullpath[PATH_MAX], winpath[PATH_MAX];
+  cygwin_conv_to_full_posix_path (path, fullpath);
+  cygwin_conv_to_full_win32_path (fullpath, winpath);
+
+  /* If identical, this is no real filesystem path.  */
+  if (strcmp (fullpath, winpath) == 0)
+    return 0;
+
+  /* Check for floppy drive letter.  */
+  if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
+    return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
+
+  /* Cygwin returns the partition serial number in stat.st_dev.
+     This is never identical to the device number of the emulated
+     /dev/sdXN device, so above find_root_device () does not work.
+     Search the partition with the same serial in boot sector instead.  */
+  char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia.  */
+  int d;
+  for (d = 'a'; d <= 'z'; d++)
+    {
+      sprintf (devpath, "/dev/sd%c", d);
+      if (get_bootsec_serial (devpath, 1) == 0)
+       continue;
+      int p;
+      for (p = 1; p <= 15; p++)
+       {
+         sprintf (devpath, "/dev/sd%c%d", d, p);
+         unsigned ser = get_bootsec_serial (devpath, 0);
+         if (ser == 0)
+           break;
+         if (ser != (unsigned)~0 && dev == (dev_t)ser)
+           return xstrdup (devpath);
+       }
+    }
+  return 0;
+}
+
+#endif /* __CYGWIN__ */
+
+char *
+grub_guess_root_device (const char *dir)
+{
+  char *os_dev;
+#ifdef __GNU__
+  file_t file;
+  mach_port_t *ports;
+  int *ints;
+  loff_t *offsets;
+  char *data;
+  error_t err;
+  mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
+  size_t name_len;
+
+  file = file_name_lookup (dir, 0, 0);
+  if (file == MACH_PORT_NULL)
+    return 0;
+
+  err = file_get_storage_info (file,
+                              &ports, &num_ports,
+                              &ints, &num_ints,
+                              &offsets, &num_offsets,
+                              &data, &data_len);
+
+  if (num_ints < 1)
+    grub_util_error ("Storage info for `%s' does not include type", dir);
+  if (ints[0] != STORAGE_DEVICE)
+    grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
+
+  if (num_ints < 5)
+    grub_util_error ("Storage info for `%s' does not include name", dir);
+  name_len = ints[4];
+  if (name_len < data_len)
+    grub_util_error ("Bogus name length for storage info for `%s'", dir);
+  if (data[name_len - 1] != '\0')
+    grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
+
+  os_dev = xmalloc (strlen ("/dev/") + data_len);
+  memcpy (os_dev, "/dev/", strlen ("/dev/"));
+  memcpy (os_dev + strlen ("/dev/"), data, data_len);
+
+  if (ports && num_ports > 0)
+    {
+      mach_msg_type_number_t i;
+      for (i = 0; i < num_ports; i++)
+        {
+         mach_port_t port = ports[i];
+         if (port != MACH_PORT_NULL)
+           mach_port_deallocate (mach_task_self(), port);
+        }
+      munmap ((caddr_t) ports, num_ports * sizeof (*ports));
+    }
+
+  if (ints && num_ints > 0)
+    munmap ((caddr_t) ints, num_ints * sizeof (*ints));
+  if (offsets && num_offsets > 0)
+    munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
+  if (data && data_len > 0)
+    munmap (data, data_len);
+  mach_port_deallocate (mach_task_self (), file);
+#else /* !__GNU__ */
+  struct stat st;
+
+  if (stat (dir, &st) < 0)
+    grub_util_error ("cannot stat `%s'", dir);
+
+#ifdef __CYGWIN__
+  /* Cygwin specific function.  */
+  os_dev = find_cygwin_root_device (dir, st.st_dev);
+
+#else
+
+  /* This might be truly slow, but is there any better way?  */
+  os_dev = find_root_device ("/dev", st.st_dev);
+#endif
+#endif /* !__GNU__ */
+
+  return os_dev;
+}
+
+static int
+grub_util_is_dmraid (const char *os_dev)
+{
+  if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
+    return 1;
+  else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
+    return 1;
+
+  return 0;
+}
+
+int
+grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
+{
+#ifdef __linux__
+  /* Check for LVM.  */
+  if (!strncmp (os_dev, "/dev/mapper/", 12)
+      && ! grub_util_is_dmraid (os_dev)
+      && strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
+    return GRUB_DEV_ABSTRACTION_LVM;
+
+  /* Check for RAID.  */
+  if (!strncmp (os_dev, "/dev/md", 7))
+    return GRUB_DEV_ABSTRACTION_RAID;
+#endif
+
+  /* No abstraction found.  */
+  return GRUB_DEV_ABSTRACTION_NONE;
+}
+
+char *
+grub_util_get_grub_dev (const char *os_dev)
+{
+  char *grub_dev;
+
+  switch (grub_util_get_dev_abstraction (os_dev))
+    {
+    case GRUB_DEV_ABSTRACTION_LVM:
+
+      {
+       unsigned short i, len;
+       grub_size_t offset = sizeof ("/dev/mapper/") - 1;
+
+       len = strlen (os_dev) - offset + 1;
+       grub_dev = xmalloc (len);
+
+       for (i = 0; i < len; i++, offset++)
+         {
+           grub_dev[i] = os_dev[offset];
+           if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
+             offset++;
+         }
+      }
+
+      break;
+
+    case GRUB_DEV_ABSTRACTION_RAID:
+
+      if (os_dev[7] == '_' && os_dev[8] == 'd')
+       {
+         /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
+
+         char *p, *q;
+
+         p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
+
+         q = strchr (p, 'p');
+         if (q)
+           *q = ',';
+
+         grub_dev = xasprintf ("md%s", p);
+         free (p);
+       }
+      else if (os_dev[7] == '/' && os_dev[8] == 'd')
+       {
+         /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
+
+         char *p, *q;
+
+         p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
+
+         q = strchr (p, 'p');
+         if (q)
+           *q = ',';
+
+         grub_dev = xasprintf ("md%s", p);
+         free (p);
+       }
+      else if (os_dev[7] >= '0' && os_dev[7] <= '9')
+       {
+         char *p , *q;
+
+         p = strdup (os_dev + sizeof ("/dev/md") - 1);
+
+         q = strchr (p, 'p');
+         if (q)
+           *q = ',';
+
+         grub_dev = xasprintf ("md%s", p);
+         free (p);
+       }
+      else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
+       {
+         char *p , *q;
+
+         p = strdup (os_dev + sizeof ("/dev/md/") - 1);
+
+         q = strchr (p, 'p');
+         if (q)
+           *q = ',';
+
+         grub_dev = xasprintf ("md%s", p);
+         free (p);
+       }
+      else
+       grub_util_error ("unknown kind of RAID device `%s'", os_dev);
+
+      break;
+
+    default:  /* GRUB_DEV_ABSTRACTION_NONE */
+      grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
+    }
+
+  return grub_dev;
+}
+
+const char *
+grub_util_check_block_device (const char *blk_dev)
+{
+  struct stat st;
+
+  if (stat (blk_dev, &st) < 0)
+    grub_util_error ("cannot stat `%s'", blk_dev);
+
+  if (S_ISBLK (st.st_mode))
+    return (blk_dev);
+  else
+    return 0;
+}
+
+const char *
+grub_util_check_char_device (const char *blk_dev)
+{
+  struct stat st;
+
+  if (stat (blk_dev, &st) < 0)
+    grub_util_error ("cannot stat `%s'", blk_dev);
+
+  if (S_ISCHR (st.st_mode))
+    return (blk_dev);
+  else
+    return 0;
+}
+
diff --git a/kern/emu/hostdisk.c b/kern/emu/hostdisk.c
new file mode 100644 (file)
index 0000000..983f101
--- /dev/null
@@ -0,0 +1,1360 @@
+/* hostdisk.c - emulate biosdisk */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009  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/disk.h>
+#include <grub/partition.h>
+#include <grub/msdos_partition.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/emu/misc.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/list.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifdef __linux__
+# include <sys/ioctl.h>         /* ioctl */
+# if !defined(__GLIBC__) || \
+        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
+/* Maybe libc doesn't have large file support.  */
+#  include <linux/unistd.h>     /* _llseek */
+# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
+# ifndef BLKFLSBUF
+#  define BLKFLSBUF     _IO (0x12,97)   /* flush buffer cache */
+# endif /* ! BLKFLSBUF */
+# include <sys/ioctl.h>                /* ioctl */
+# ifndef HDIO_GETGEO
+#  define HDIO_GETGEO  0x0301  /* get device geometry */
+/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
+   defined.  */
+struct hd_geometry
+{
+  unsigned char heads;
+  unsigned char sectors;
+  unsigned short cylinders;
+  unsigned long start;
+};
+# endif /* ! HDIO_GETGEO */
+# ifndef BLKGETSIZE64
+#  define BLKGETSIZE64  _IOR(0x12,114,size_t)    /* return device size */
+# endif /* ! BLKGETSIZE64 */
+# ifndef MAJOR
+#  ifndef MINORBITS
+#   define MINORBITS   8
+#  endif /* ! MINORBITS */
+#  define MAJOR(dev)   ((unsigned) ((dev) >> MINORBITS))
+# endif /* ! MAJOR */
+# ifndef FLOPPY_MAJOR
+#  define FLOPPY_MAJOR 2
+# endif /* ! FLOPPY_MAJOR */
+# ifndef LOOP_MAJOR
+#  define LOOP_MAJOR   7
+# endif /* ! LOOP_MAJOR */
+#endif /* __linux__ */
+
+#ifdef __CYGWIN__
+# include <sys/ioctl.h>
+# include <cygwin/fs.h> /* BLKGETSIZE64 */
+# include <cygwin/hdreg.h> /* HDIO_GETGEO */
+# define MAJOR(dev)    ((unsigned) ((dev) >> 16))
+# define FLOPPY_MAJOR  2
+#endif
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# include <sys/disk.h> /* DIOCGMEDIASIZE */
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#endif
+
+#if defined(__APPLE__)
+# include <sys/disk.h>
+#endif
+
+#if defined(__NetBSD__)
+# include <sys/ioctl.h>
+# include <sys/disklabel.h>    /* struct disklabel */
+# ifdef HAVE_GETRAWPARTITION
+#  include <util.h>    /* getrawpartition */
+# endif /* HAVE_GETRAWPARTITION */
+# include <sys/fdio.h>
+# ifndef RAW_FLOPPY_MAJOR
+#  define RAW_FLOPPY_MAJOR     9
+# endif /* ! RAW_FLOPPY_MAJOR */
+#endif /* defined(__NetBSD__) */
+
+struct
+{
+  char *drive;
+  char *device;
+} map[256];
+
+struct grub_util_biosdisk_data
+{
+  char *dev;
+  int access_mode;
+  int fd;
+};
+
+#ifdef __linux__
+/* Check if we have devfs support.  */
+static int
+have_devfs (void)
+{
+  static int dev_devfsd_exists = -1;
+
+  if (dev_devfsd_exists < 0)
+    {
+      struct stat st;
+
+      dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
+    }
+
+  return dev_devfsd_exists;
+}
+#endif /* __linux__ */
+
+#if defined(__NetBSD__)
+/* Adjust device driver parameters.  This function should be called just
+   after successfully opening the device.  For now, it simply prevents the
+   floppy driver from retrying operations on failure, as otherwise the
+   driver takes a while to abort when there is no floppy in the drive.  */
+static void
+configure_device_driver (int fd)
+{
+  struct stat st;
+
+  if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
+    return;
+  if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)
+    {
+      int floppy_opts;
+
+      if (ioctl (fd, FDIOCGETOPTS, &floppy_opts) == -1)
+       return;
+      floppy_opts |= FDOPT_NORETRY;
+      if (ioctl (fd, FDIOCSETOPTS, &floppy_opts) == -1)
+       return;
+    }
+}
+#endif /* defined(__NetBSD__) */
+
+static int
+find_grub_drive (const char *name)
+{
+  unsigned int i;
+
+  if (name)
+    {
+      for (i = 0; i < ARRAY_SIZE (map); i++)
+       if (map[i].drive && ! strcmp (map[i].drive, name))
+         return i;
+    }
+
+  return -1;
+}
+
+static int
+find_free_slot (void)
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    if (! map[i].drive)
+      return i;
+
+  return -1;
+}
+
+static int
+grub_util_biosdisk_iterate (int (*hook) (const char *name))
+{
+  unsigned i;
+
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    if (map[i].drive && hook (map[i].drive))
+      return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_util_biosdisk_open (const char *name, grub_disk_t disk)
+{
+  int drive;
+  struct stat st;
+  struct grub_util_biosdisk_data *data;
+
+  drive = find_grub_drive (name);
+  if (drive < 0)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "no mapping exists for `%s'", name);
+
+  disk->has_partitions = 1;
+  disk->id = drive;
+  disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
+  data->dev = NULL;
+  data->access_mode = 0;
+  data->fd = -1;
+
+  /* Get the size.  */
+#if defined(__MINGW32__)
+  {
+    grub_uint64_t size;
+
+    size = grub_util_get_disk_size (map[drive].device);
+
+    if (size % 512)
+      grub_util_error ("unaligned device size");
+
+    disk->total_sectors = size >> 9;
+
+    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
+
+    return GRUB_ERR_NONE;
+  }
+#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
+      defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+  {
+# if defined(__NetBSD__)
+    struct disklabel label;
+# else
+    unsigned long long nr;
+# endif
+    int fd;
+
+    fd = open (map[drive].device, O_RDONLY);
+    if (fd == -1)
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+    if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
+# else
+    if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
+# endif
+      {
+       close (fd);
+       goto fail;
+      }
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+    if (ioctl (fd, DIOCGMEDIASIZE, &nr))
+# elif defined(__APPLE__)
+    if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
+# elif defined(__NetBSD__)
+    configure_device_driver (fd);
+    if (ioctl (fd, DIOCGDINFO, &label) == -1)
+# else
+    if (ioctl (fd, BLKGETSIZE64, &nr))
+# endif
+      {
+       close (fd);
+       goto fail;
+      }
+
+    close (fd);
+
+# if defined (__APPLE__)
+    disk->total_sectors = nr;
+# elif defined(__NetBSD__)
+    disk->total_sectors = label.d_secperunit;
+# else
+    disk->total_sectors = nr / 512;
+
+    if (nr % 512)
+      grub_util_error ("unaligned device size");
+# endif
+
+    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
+
+    return GRUB_ERR_NONE;
+  }
+
+ fail:
+  /* In GNU/Hurd, stat() will return the right size.  */
+#elif !defined (__GNU__)
+# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
+#endif
+  if (stat (map[drive].device, &st) < 0)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
+
+  disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
+
+  grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
+
+  return GRUB_ERR_NONE;
+}
+
+#ifdef __linux__
+/* Cache of partition start sectors for each disk.  */
+struct linux_partition_cache
+{
+  struct linux_partition_cache *next;
+  char *dev;
+  unsigned long start;
+  int partno;
+};
+
+struct linux_partition_cache *linux_partition_cache_list;
+
+static int
+linux_find_partition (char *dev, unsigned long sector)
+{
+  size_t len = strlen (dev);
+  const char *format;
+  char *p;
+  int i;
+  char real_dev[PATH_MAX];
+  struct linux_partition_cache *cache;
+
+  strcpy(real_dev, dev);
+
+  if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0)
+    {
+      p = real_dev + len - 4;
+      format = "part%d";
+    }
+  else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
+    {
+      p = real_dev + len;
+      format = "p%d";
+    }
+  else
+    {
+      p = real_dev + len;
+      format = "%d";
+    }
+
+  for (cache = linux_partition_cache_list; cache; cache = cache->next)
+    {
+      if (strcmp (cache->dev, dev) == 0 && cache->start == sector)
+       {
+         sprintf (p, format, cache->partno);
+         strcpy (dev, real_dev);
+         return 1;
+       }
+    }
+
+  for (i = 1; i < 10000; i++)
+    {
+      int fd;
+      struct hd_geometry hdg;
+
+      sprintf (p, format, i);
+      fd = open (real_dev, O_RDONLY);
+      if (fd == -1)
+       return 0;
+
+      if (ioctl (fd, HDIO_GETGEO, &hdg))
+       {
+         close (fd);
+         return 0;
+       }
+
+      close (fd);
+
+      if (hdg.start == sector)
+       {
+         struct linux_partition_cache *new_cache_item;
+
+         new_cache_item = xmalloc (sizeof *new_cache_item);
+         new_cache_item->dev = xstrdup (dev);
+         new_cache_item->start = hdg.start;
+         new_cache_item->partno = i;
+         grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list),
+                         GRUB_AS_LIST (new_cache_item));
+
+         strcpy (dev, real_dev);
+         return 1;
+       }
+    }
+
+  return 0;
+}
+#endif /* __linux__ */
+
+static int
+open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
+{
+  int fd;
+  struct grub_util_biosdisk_data *data = disk->data;
+
+#ifdef O_LARGEFILE
+  flags |= O_LARGEFILE;
+#endif
+#ifdef O_SYNC
+  flags |= O_SYNC;
+#endif
+#ifdef O_FSYNC
+  flags |= O_FSYNC;
+#endif
+#ifdef O_BINARY
+  flags |= O_BINARY;
+#endif
+
+#ifdef __linux__
+  /* Linux has a bug that the disk cache for a whole disk is not consistent
+     with the one for a partition of the disk.  */
+  {
+    int is_partition = 0;
+    char dev[PATH_MAX];
+    grub_disk_addr_t part_start = 0;
+
+    part_start = grub_partition_get_start (disk->partition);
+
+    strcpy (dev, map[disk->id].device);
+    if (disk->partition && sector >= part_start
+       && strncmp (map[disk->id].device, "/dev/", 5) == 0)
+      is_partition = linux_find_partition (dev, part_start);
+
+    if (data->dev && strcmp (data->dev, dev) == 0 &&
+       data->access_mode == (flags & O_ACCMODE))
+      {
+       grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev);
+       fd = data->fd;
+      }
+    else
+      {
+       free (data->dev);
+       if (data->fd != -1)
+         close (data->fd);
+
+       /* Open the partition.  */
+       grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
+       fd = open (dev, flags);
+       if (fd < 0)
+         {
+           grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
+           return -1;
+         }
+
+       /* Flush the buffer cache to the physical disk.
+          XXX: This also empties the buffer cache.  */
+       ioctl (fd, BLKFLSBUF, 0);
+
+       data->dev = xstrdup (dev);
+       data->access_mode = (flags & O_ACCMODE);
+       data->fd = fd;
+      }
+
+    if (is_partition)
+      sector -= part_start;
+  }
+#else /* ! __linux__ */
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+  int sysctl_flags, sysctl_oldflags;
+  size_t sysctl_size = sizeof (sysctl_flags);
+
+  if (sysctlbyname ("kern.geom.debugflags", &sysctl_oldflags, &sysctl_size, NULL, 0))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current flags of sysctl kern.geom.debugflags");
+      return -1;
+    }
+  sysctl_flags = sysctl_oldflags | 0x10;
+  if (! (sysctl_oldflags & 0x10)
+      && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags");
+      return -1;
+    }
+#endif
+
+  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
+      data->access_mode == (flags & O_ACCMODE))
+    {
+      grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
+      fd = data->fd;
+    }
+  else
+    {
+      free (data->dev);
+      if (data->fd != -1)
+       close (data->fd);
+
+      fd = open (map[disk->id].device, flags);
+      if (fd >= 0)
+       {
+         data->dev = xstrdup (map[disk->id].device);
+         data->access_mode = (flags & O_ACCMODE);
+         data->fd = fd;
+       }
+    }
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+  if (! (sysctl_oldflags & 0x10)
+      && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags back to the old value for sysctl kern.geom.debugflags");
+      return -1;
+    }
+#endif
+
+#if defined(__APPLE__)
+  /* If we can't have exclusive access, try shared access */
+  if (fd < 0)
+    fd = open(map[disk->id].device, flags | O_SHLOCK);
+#endif
+
+  if (fd < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device);
+      return -1;
+    }
+#endif /* ! __linux__ */
+
+#if defined(__NetBSD__)
+  configure_device_driver (fd);
+#endif /* defined(__NetBSD__) */
+
+#if defined(__linux__) && (!defined(__GLIBC__) || \
+        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
+  /* Maybe libc doesn't have large file support.  */
+  {
+    loff_t offset, result;
+    static int _llseek (uint filedes, ulong hi, ulong lo,
+                        loff_t *res, uint wh);
+    _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
+               loff_t *, res, uint, wh);
+
+    offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
+    if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
+       close (fd);
+       return -1;
+      }
+  }
+#else
+  {
+    off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
+
+    if (lseek (fd, offset, SEEK_SET) != offset)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
+       close (fd);
+       return -1;
+      }
+  }
+#endif
+
+  return fd;
+}
+
+/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
+   error occurs, otherwise return LEN.  */
+static ssize_t
+nread (int fd, char *buf, size_t len)
+{
+  ssize_t size = len;
+
+  while (len)
+    {
+      ssize_t ret = read (fd, buf, len);
+
+      if (ret <= 0)
+        {
+          if (errno == EINTR)
+            continue;
+          else
+            return ret;
+        }
+
+      len -= ret;
+      buf += ret;
+    }
+
+  return size;
+}
+
+/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
+   error occurs, otherwise return LEN.  */
+static ssize_t
+nwrite (int fd, const char *buf, size_t len)
+{
+  ssize_t size = len;
+
+  while (len)
+    {
+      ssize_t ret = write (fd, buf, len);
+
+      if (ret <= 0)
+        {
+          if (errno == EINTR)
+            continue;
+          else
+            return ret;
+        }
+
+      len -= ret;
+      buf += ret;
+    }
+
+  return size;
+}
+
+static grub_err_t
+grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+                        grub_size_t size, char *buf)
+{
+  int fd;
+
+  /* Split pre-partition and partition reads.  */
+  if (disk->partition && sector < disk->partition->start
+      && sector + size > disk->partition->start)
+    {
+      grub_err_t err;
+      err = grub_util_biosdisk_read (disk, sector,
+                                    disk->partition->start - sector,
+                                    buf);
+      if (err)
+       return err;
+
+      return grub_util_biosdisk_read (disk, disk->partition->start,
+                                     size - (disk->partition->start - sector),
+                                     buf + ((disk->partition->start - sector)
+                                            << GRUB_DISK_SECTOR_BITS));
+    }
+
+  fd = open_device (disk, sector, O_RDONLY);
+  if (fd < 0)
+    return grub_errno;
+
+#ifdef __linux__
+  if (sector == 0 && size > 1)
+    {
+      /* Work around a bug in Linux ez remapping.  Linux remaps all
+        sectors that are read together with the MBR in one read.  It
+        should only remap the MBR, so we split the read in two
+        parts. -jochen  */
+      if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+       {
+         grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
+         close (fd);
+         return grub_errno;
+       }
+
+      buf += GRUB_DISK_SECTOR_SIZE;
+      size--;
+    }
+#endif /* __linux__ */
+
+  if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+    grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
+                         grub_size_t size, const char *buf)
+{
+  int fd;
+
+  /* Split pre-partition and partition writes.  */
+  if (disk->partition && sector < disk->partition->start
+      && sector + size > disk->partition->start)
+    {
+      grub_err_t err;
+      err = grub_util_biosdisk_write (disk, sector,
+                                     disk->partition->start - sector,
+                                     buf);
+      if (err)
+       return err;
+
+      return grub_util_biosdisk_write (disk, disk->partition->start,
+                                      size - (disk->partition->start - sector),
+                                      buf + ((disk->partition->start - sector)
+                                             << GRUB_DISK_SECTOR_BITS));
+    }
+
+  fd = open_device (disk, sector, O_WRONLY);
+  if (fd < 0)
+    return grub_errno;
+
+  if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+    grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
+
+  return grub_errno;
+}
+
+static void
+grub_util_biosdisk_close (struct grub_disk *disk)
+{
+  struct grub_util_biosdisk_data *data = disk->data;
+
+  free (data->dev);
+  if (data->fd != -1)
+    close (data->fd);
+  free (data);
+}
+
+static struct grub_disk_dev grub_util_biosdisk_dev =
+  {
+    .name = "biosdisk",
+    .id = GRUB_DISK_DEVICE_BIOSDISK_ID,
+    .iterate = grub_util_biosdisk_iterate,
+    .open = grub_util_biosdisk_open,
+    .close = grub_util_biosdisk_close,
+    .read = grub_util_biosdisk_read,
+    .write = grub_util_biosdisk_write,
+    .next = 0
+  };
+
+static void
+read_device_map (const char *dev_map)
+{
+  FILE *fp;
+  char buf[1024];      /* XXX */
+  int lineno = 0;
+  struct stat st;
+
+  auto void show_error (const char *msg);
+  void show_error (const char *msg)
+    {
+      grub_util_error ("%s:%d: %s", dev_map, lineno, msg);
+    }
+
+  fp = fopen (dev_map, "r");
+  if (! fp)
+    {
+      grub_util_info (_("cannot open `%s'"), dev_map);
+      return;
+    }
+
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      char *p = buf;
+      char *e;
+      int drive;
+
+      lineno++;
+
+      /* Skip leading spaces.  */
+      while (*p && isspace (*p))
+       p++;
+
+      /* If the first character is `#' or NUL, skip this line.  */
+      if (*p == '\0' || *p == '#')
+       continue;
+
+      if (*p != '(')
+       show_error ("No open parenthesis found");
+
+      p++;
+      /* Find a free slot.  */
+      drive = find_free_slot ();
+      if (drive < 0)
+       show_error ("Map table size exceeded");
+
+      e = p;
+      p = strchr (p, ')');
+      if (! p)
+       show_error ("No close parenthesis found");
+
+      map[drive].drive = xmalloc (p - e + sizeof ('\0'));
+      strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
+      map[drive].drive[p - e] = '\0';
+
+      p++;
+      /* Skip leading spaces.  */
+      while (*p && isspace (*p))
+       p++;
+
+      if (*p == '\0')
+       show_error ("No filename found");
+
+      /* NUL-terminate the filename.  */
+      e = p;
+      while (*e && ! isspace (*e))
+       e++;
+      *e = '\0';
+
+#ifdef __MINGW32__
+      (void) st;
+      if (grub_util_get_disk_size (p) == -1LL)
+#else
+      if (stat (p, &st) == -1)
+#endif
+       {
+         free (map[drive].drive);
+         map[drive].drive = NULL;
+         grub_util_info ("Cannot stat `%s', skipping", p);
+         continue;
+       }
+
+#ifdef __linux__
+      /* On Linux, the devfs uses symbolic links horribly, and that
+        confuses the interface very much, so use realpath to expand
+        symbolic links.  */
+      map[drive].device = xmalloc (PATH_MAX);
+      if (! realpath (p, map[drive].device))
+       grub_util_error ("cannot get the real path of `%s'", p);
+#else
+      map[drive].device = xstrdup (p);
+#endif
+    }
+
+  fclose (fp);
+}
+
+void
+grub_util_biosdisk_init (const char *dev_map)
+{
+  read_device_map (dev_map);
+  grub_disk_dev_register (&grub_util_biosdisk_dev);
+}
+
+void
+grub_util_biosdisk_fini (void)
+{
+  unsigned i;
+
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    {
+      if (map[i].drive)
+       free (map[i].drive);
+      if (map[i].device)
+       free (map[i].device);
+      map[i].drive = map[i].device = NULL;
+    }
+
+  grub_disk_dev_unregister (&grub_util_biosdisk_dev);
+}
+
+static char *
+make_device_name (int drive, int dos_part, int bsd_part)
+{
+  char *ret;
+  char *dos_part_str = NULL;
+  char *bsd_part_str = NULL;
+
+  if (dos_part >= 0)
+    dos_part_str = xasprintf (",%d", dos_part + 1);
+
+  if (bsd_part >= 0)
+    bsd_part_str = xasprintf (",%d", bsd_part + 1);
+
+  ret = xasprintf ("%s%s%s", map[drive].drive,
+                   dos_part_str ? : "",
+                   bsd_part_str ? : "");
+
+  if (dos_part_str)
+    free (dos_part_str);
+
+  if (bsd_part_str)
+    free (bsd_part_str);
+
+  return ret;
+}
+
+static char *
+convert_system_partition_to_system_disk (const char *os_dev)
+{
+#if defined(__linux__)
+  char *path = xmalloc (PATH_MAX);
+  if (! realpath (os_dev, path))
+    return NULL;
+
+  if (strncmp ("/dev/", path, 5) == 0)
+    {
+      char *p = path + 5;
+
+      /* If this is an IDE disk.  */
+      if (strncmp ("ide/", p, 4) == 0)
+       {
+         p = strstr (p, "part");
+         if (p)
+           strcpy (p, "disc");
+
+         return path;
+       }
+
+      /* If this is a SCSI disk.  */
+      if (strncmp ("scsi/", p, 5) == 0)
+       {
+         p = strstr (p, "part");
+         if (p)
+           strcpy (p, "disc");
+
+         return path;
+       }
+
+      /* If this is a DAC960 disk.  */
+      if (strncmp ("rd/c", p, 4) == 0)
+       {
+         /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+
+      /* If this is a Mylex AcceleRAID Array.  */
+      if (strncmp ("rs/c", p, 4) == 0)
+       {
+         /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+      /* If this is a CCISS disk.  */
+      if (strncmp ("cciss/c", p, sizeof ("cciss/c") - 1) == 0)
+       {
+         /* /dev/cciss/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+
+      /* If this is a Compaq Intelligent Drive Array.  */
+      if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0)
+       {
+         /* /dev/ida/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+
+      /* If this is an I2O disk.  */
+      if (strncmp ("i2o/hd", p, sizeof ("i2o/hd") - 1) == 0)
+       {
+         /* /dev/i2o/hd[a-z]([0-9]+)? */
+         p[sizeof ("i2o/hda") - 1] = '\0';
+         return path;
+       }
+
+      /* If this is a MultiMediaCard (MMC).  */
+      if (strncmp ("mmcblk", p, sizeof ("mmcblk") - 1) == 0)
+       {
+         /* /dev/mmcblk[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+
+      /* If this is an IDE, SCSI or Virtio disk.  */
+      if (strncmp ("vdisk", p, 5) == 0
+         && p[5] >= 'a' && p[5] <= 'z')
+       {
+         /* /dev/vdisk[a-z][0-9]* */
+         p[6] = '\0';
+         return path;
+       }
+      if ((strncmp ("hd", p, 2) == 0
+          || strncmp ("vd", p, 2) == 0
+          || strncmp ("sd", p, 2) == 0)
+         && p[2] >= 'a' && p[2] <= 'z')
+       {
+         /* /dev/[hsv]d[a-z][0-9]* */
+         p[3] = '\0';
+         return path;
+       }
+
+      /* If this is a Xen virtual block device.  */
+      if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
+       {
+         /* /dev/xvd[a-z][0-9]* */
+         p[4] = '\0';
+         return path;
+       }
+    }
+
+  return path;
+
+#elif defined(__GNU__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
+    {
+      char *p = strchr (path + 7, 's');
+      if (p)
+       *p = '\0';
+    }
+  return path;
+
+#elif defined(__CYGWIN__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z')
+    path[8] = 0;
+  return path;
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/", path, 5) == 0)
+    {
+      char *p;
+      for (p = path + 5; *p; ++p)
+        if (grub_isdigit(*p))
+          {
+            p = strchr (p, 's');
+            if (p)
+              *p = '\0';
+            break;
+          }
+    }
+  return path;
+
+#elif defined(__NetBSD__)
+  /* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]".  */
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/rwd", path, 8) == 0 ||
+      strncmp ("/dev/rsd", path, 8) == 0 ||
+      strncmp ("/dev/rcd", path, 8) == 0)
+    {
+      char *q;
+      q = path + strlen(path) - 1;    /* last character */
+      if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
+        {
+          int rawpart = -1;
+# ifdef HAVE_GETRAWPARTITION
+          rawpart = getrawpartition();
+# endif /* HAVE_GETRAWPARTITION */
+          if (rawpart >= 0)
+            *q = 'a' + rawpart;
+        }
+    }
+  return path;
+
+#else
+# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
+  return xstrdup (os_dev);
+#endif
+}
+
+#if defined(__linux__) || defined(__CYGWIN__)
+static int
+device_is_wholedisk (const char *os_dev)
+{
+  int len = strlen (os_dev);
+
+  if (os_dev[len - 1] < '0' || os_dev[len - 1] > '9')
+    return 1;
+  return 0;
+}
+#endif
+
+#if defined(__NetBSD__)
+/* Try to determine whether a given device name corresponds to a whole disk.
+   This function should give in most cases a definite answer, but it may
+   actually give an approximate one in the following sense: if the return
+   value is 0 then the device name does not correspond to a whole disk.  */
+static int
+device_is_wholedisk (const char *os_dev)
+{
+  int len = strlen (os_dev);
+  int rawpart = -1;
+
+# ifdef HAVE_GETRAWPARTITION
+  rawpart = getrawpartition();
+# endif /* HAVE_GETRAWPARTITION */
+  if (rawpart < 0)
+    return 1;
+  return (os_dev[len - 1] == ('a' + rawpart));
+}
+#endif /* defined(__NetBSD__) */
+
+static int
+find_system_device (const char *os_dev)
+{
+  unsigned int i;
+  char *os_disk;
+
+  os_disk = convert_system_partition_to_system_disk (os_dev);
+  if (! os_disk)
+    return -1;
+
+  for (i = 0; i < ARRAY_SIZE (map); i++)
+    if (! map[i].device)
+      break;
+    else if (strcmp (map[i].device, os_disk) == 0)
+      {
+       free (os_disk);
+       return i;
+      }
+
+  if (i == ARRAY_SIZE (map))
+    grub_util_error (_("device count exceeds limit"));
+
+  map[i].device = os_disk;
+  map[i].drive = xstrdup (os_disk);
+
+  return i;
+}
+
+char *
+grub_util_biosdisk_get_grub_dev (const char *os_dev)
+{
+  struct stat st;
+  int drive;
+
+  if (stat (os_dev, &st) < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
+      return 0;
+    }
+
+  drive = find_system_device (os_dev);
+  if (drive < 0)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                 "no mapping exists for `%s'", os_dev);
+      return 0;
+    }
+
+  if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev))
+      == 0)
+    return make_device_name (drive, -1, -1);
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+  if (! S_ISCHR (st.st_mode))
+#else
+  if (! S_ISBLK (st.st_mode))
+#endif
+    return make_device_name (drive, -1, -1);
+
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
+  /* Linux counts partitions uniformly, whether a BSD partition or a DOS
+     partition, so mapping them to GRUB devices is not trivial.
+     Here, get the start sector of a partition by HDIO_GETGEO, and
+     compare it with each partition GRUB recognizes.
+
+     Cygwin /dev/sdXN emulation uses Windows partition mapping. It
+     does not count the extended partition and missing primary
+     partitions.  Use same method as on Linux here.
+
+     For NetBSD, proceed as for Linux, except that the start sector is
+     obtained from the disk label.  */
+  {
+    char *name;
+    grub_disk_t disk;
+    int fd;
+# if !defined(__NetBSD__)
+    struct hd_geometry hdg;
+    typeof (hdg.start) p_offset;
+# else /* defined(__NetBSD__) */
+    struct disklabel label;
+    int index;
+    u_int32_t p_offset;
+# endif /* !defined(__NetBSD__) */
+    int dos_part = -1;
+    int bsd_part = -1;
+    auto int find_partition (grub_disk_t dsk,
+                            const grub_partition_t partition);
+
+    int find_partition (grub_disk_t dsk __attribute__ ((unused)),
+                       const grub_partition_t partition)
+      {
+       grub_disk_addr_t part_start = 0;
+       grub_util_info ("Partition %d starts from %lu",
+                       partition->number, partition->start);
+
+       part_start = grub_partition_get_start (partition);
+
+       if (p_offset == part_start)
+         {
+           if (partition->parent)
+             {
+               dos_part = partition->parent->number;
+               bsd_part = partition->number;
+             }
+           else
+             {
+               dos_part = partition->number;
+               bsd_part = -1;
+             }
+
+           return 1;
+         }
+
+       return 0;
+      }
+
+    name = make_device_name (drive, -1, -1);
+
+# if !defined(__NetBSD__)
+    if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
+      return name;
+# else /* defined(__NetBSD__) */
+    /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
+     * different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
+     * and in particular it cannot be a floppy device.  */
+    index = os_dev[strlen(os_dev) - 1] - 'a';
+# endif /* !defined(__NetBSD__) */
+
+    fd = open (os_dev, O_RDONLY);
+    if (fd == -1)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev);
+       free (name);
+       return 0;
+      }
+
+# if !defined(__NetBSD__)
+    if (ioctl (fd, HDIO_GETGEO, &hdg))
+# else /* defined(__NetBSD__) */
+    configure_device_driver (fd);
+    if (ioctl (fd, DIOCGDINFO, &label) == -1)
+# endif /* !defined(__NetBSD__) */
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot get disk geometry of `%s'", os_dev);
+       close (fd);
+       free (name);
+       return 0;
+      }
+
+    close (fd);
+
+# if !defined(__NetBSD__)
+    p_offset = hdg.start;
+# else /* defined(__NetBSD__) */
+    if (index >= label.d_npartitions)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "no disk label entry for `%s'", os_dev);
+       free (name);
+       return 0;
+      }
+    p_offset = label.d_partitions[index].p_offset;
+# endif /* !defined(__NetBSD__) */
+
+    grub_util_info ("%s starts from %lu", os_dev, p_offset);
+
+    if (p_offset == 0 && device_is_wholedisk (os_dev))
+      return name;
+
+    grub_util_info ("opening the device %s", name);
+    disk = grub_disk_open (name);
+    free (name);
+
+    if (! disk)
+      return 0;
+
+    grub_partition_iterate (disk, find_partition);
+    if (grub_errno != GRUB_ERR_NONE)
+      {
+       grub_disk_close (disk);
+       return 0;
+      }
+
+    if (dos_part < 0)
+      {
+       grub_disk_close (disk);
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot find the partition of `%s'", os_dev);
+       return 0;
+      }
+
+    return make_device_name (drive, dos_part, bsd_part);
+  }
+
+#elif defined(__GNU__)
+  /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?".  */
+  {
+    char *p;
+    int dos_part = -1;
+    int bsd_part = -1;
+
+    p = strrchr (os_dev, 's');
+    if (p)
+      {
+       long int n;
+       char *q;
+
+       p++;
+       n = strtol (p, &q, 10);
+       if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
+         {
+           dos_part = (int) n - 1;
+
+           if (*q >= 'a' && *q <= 'g')
+             bsd_part = *q - 'a';
+         }
+      }
+
+    return make_device_name (drive, dos_part, bsd_part);
+  }
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+  /* FreeBSD uses "/dev/[a-z]+[0-9]+(s[0-9]+[a-z]?)?".  */
+  {
+    int dos_part = -1;
+    int bsd_part = -1;
+
+    if (strncmp ("/dev/", os_dev, 5) == 0)
+      {
+        const char *p;
+        char *q;
+        long int n;
+
+        for (p = os_dev + 5; *p; ++p)
+          if (grub_isdigit(*p))
+            {
+              p = strchr (p, 's');
+              if (p)
+                {
+                  p++;
+                  n = strtol (p, &q, 10);
+                  if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
+                    {
+                      dos_part = (int) n - 1;
+
+                      if (*q >= 'a' && *q <= 'g')
+                        bsd_part = *q - 'a';
+                    }
+                }
+              break;
+            }
+      }
+
+    return make_device_name (drive, dos_part, bsd_part);
+  }
+
+#else
+# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
+  return make_device_name (drive, -1, -1);
+#endif
+}
+
+const char *
+grub_util_biosdisk_get_osdev (grub_disk_t disk)
+{
+  return map[disk->id].device;
+}
diff --git a/kern/emu/hostfs.c b/kern/emu/hostfs.c
new file mode 100644 (file)
index 0000000..501ad46
--- /dev/null
@@ -0,0 +1,175 @@
+/* hostfs.c - Dummy filesystem to provide access to the hosts filesystem  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008,2009,2010  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/>.
+ */
+#define _BSD_SOURCE
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/util/misc.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/* dirent.d_type is a BSD extension, not part of POSIX */
+#include <sys/stat.h>
+#include <string.h>
+
+static int
+is_dir (const char *path, const char *name)
+{
+  int len1 = strlen(path);
+  int len2 = strlen(name);
+
+  char pathname[len1 + 1 + len2 + 1 + 13];
+  strcpy (pathname, path);
+
+  /* Avoid UNC-path "//name" on Cygwin.  */
+  if (len1 > 0 && pathname[len1 - 1] != '/')
+    strcat (pathname, "/");
+
+  strcat (pathname, name);
+
+  struct stat st;
+  if (stat (pathname, &st))
+    return 0;
+  return S_ISDIR (st.st_mode);
+}
+
+static grub_err_t
+grub_hostfs_dir (grub_device_t device, const char *path,
+                int (*hook) (const char *filename,
+                             const struct grub_dirhook_info *info))
+{
+  DIR *dir;
+
+  /* Check if the disk is our dummy disk.  */
+  if (grub_strcmp (device->disk->name, "host"))
+    return grub_error (GRUB_ERR_BAD_FS, "not a hostfs");
+
+  dir = opendir (path);
+  if (! dir)
+    return grub_error (GRUB_ERR_BAD_FILENAME,
+                      "can't open the hostfs directory `%s'", path);
+
+  while (1)
+    {
+      struct dirent *de;
+      struct grub_dirhook_info info;
+      grub_memset (&info, 0, sizeof (info));
+
+      de = readdir (dir);
+      if (! de)
+       break;
+
+      info.dir = !! is_dir (path, de->d_name);
+      hook (de->d_name, &info);
+
+    }
+
+  closedir (dir);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_hostfs_open (struct grub_file *file, const char *name)
+{
+  FILE *f;
+
+  f = fopen (name, "rb");
+  if (! f)
+    return grub_error (GRUB_ERR_BAD_FILENAME,
+                      "can't open `%s'", name);
+  file->data = f;
+
+#ifdef __MINGW32__
+  file->size = grub_util_get_disk_size (name);
+#else
+  fseeko (f, 0, SEEK_END);
+  file->size = ftello (f);
+  fseeko (f, 0, SEEK_SET);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  FILE *f;
+
+  f = (FILE *) file->data;
+  if (fseeko (f, file->offset, SEEK_SET) != 0)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "fseeko: %s", strerror (errno));
+      return -1;
+    }
+
+  unsigned int s = fread (buf, 1, len, f);
+  if (s != len)
+    grub_error (GRUB_ERR_FILE_READ_ERROR, "fread: %s", strerror (errno));
+
+  return (signed) s;
+}
+
+static grub_err_t
+grub_hostfs_close (grub_file_t file)
+{
+  FILE *f;
+
+  f = (FILE *) file->data;
+  fclose (f);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_hostfs_label (grub_device_t device __attribute ((unused)),
+                  char **label __attribute ((unused)))
+{
+  *label = 0;
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fs grub_hostfs_fs =
+  {
+    .name = "hostfs",
+    .dir = grub_hostfs_dir,
+    .open = grub_hostfs_open,
+    .read = grub_hostfs_read,
+    .close = grub_hostfs_close,
+    .label = grub_hostfs_label,
+    .next = 0
+  };
+
+\f
+
+GRUB_MOD_INIT(hostfs)
+{
+  grub_fs_register (&grub_hostfs_fs);
+}
+
+GRUB_MOD_FINI(hostfs)
+{
+  grub_fs_unregister (&grub_hostfs_fs);
+}
diff --git a/kern/emu/lite.c b/kern/emu/lite.c
new file mode 100644 (file)
index 0000000..1f06e39
--- /dev/null
@@ -0,0 +1,16 @@
+#include <config.h>
+#include <grub/emu/misc.h>
+
+/* grub-emu-lite supports dynamic module loading, so it won't have any
+   embedded modules.  */
+void
+grub_init_all(void)
+{
+  return;
+}
+
+void
+grub_fini_all(void)
+{
+  return;
+}
diff --git a/kern/emu/main.c b/kern/emu/main.c
new file mode 100644 (file)
index 0000000..978919f
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010  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 <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grub/mm.h>
+#include <grub/setjmp.h>
+#include <grub/fs.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/time.h>
+#include <grub/emu/console.h>
+#include <grub/emu/misc.h>
+#include <grub/kernel.h>
+#include <grub/normal.h>
+#include <grub/emu/getroot.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+#include <grub/i18n.h>
+
+#define ENABLE_RELOCATABLE 0
+#include "progname.h"
+
+/* Used for going back to the main function.  */
+static jmp_buf main_env;
+
+/* Store the prefix specified by an argument.  */
+static char *prefix = NULL;
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return 0;
+}
+
+#if GRUB_NO_MODULES
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  (void) mod;
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+#endif
+
+void
+grub_reboot (void)
+{
+  longjmp (main_env, 1);
+}
+
+void
+grub_halt (
+#ifdef GRUB_MACHINE_PCBIOS
+          int no_apm __attribute__ ((unused))
+#endif
+          )
+{
+  grub_reboot ();
+}
+
+void
+grub_machine_init (void)
+{
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  grub_env_set ("prefix", prefix);
+  free (prefix);
+  prefix = 0;
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_console_fini ();
+}
+
+\f
+
+static struct option options[] =
+  {
+    {"root-device", required_argument, 0, 'r'},
+    {"device-map", required_argument, 0, 'm'},
+    {"directory", required_argument, 0, 'd'},
+    {"hold", optional_argument, 0, 'H'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    { 0, 0, 0, 0 }
+  };
+
+static int
+usage (int status)
+{
+  if (status)
+    fprintf (stderr,
+            "Try `%s --help' for more information.\n", program_name);
+  else
+    printf (
+      "Usage: %s [OPTION]...\n"
+      "\n"
+      "GRUB emulator.\n"
+      "\n"
+      "  -r, --root-device=DEV     use DEV as the root device [default=guessed]\n"
+      "  -m, --device-map=FILE     use FILE as the device map [default=%s]\n"
+      "  -d, --directory=DIR       use GRUB files in the directory DIR [default=%s]\n"
+      "  -v, --verbose             print verbose messages\n"
+      "  -H, --hold[=SECONDS]      wait until a debugger will attach\n"
+      "  -h, --help                display this message and exit\n"
+      "  -V, --version             print version information and exit\n"
+      "\n"
+      "Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
+  return status;
+}
+\f
+
+void grub_hostfs_init (void);
+void grub_hostfs_fini (void);
+void grub_host_init (void);
+void grub_host_fini (void);
+#if GRUB_NO_MODULES
+void grub_init_all (void);
+void grub_fini_all (void);
+#endif
+
+int
+main (int argc, char *argv[])
+{
+  char *root_dev = 0;
+  char *dir = DEFAULT_DIRECTORY;
+  char *dev_map = DEFAULT_DEVICE_MAP;
+  volatile int hold = 0;
+  int opt;
+
+  set_program_name (argv[0]);
+
+  while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
+    switch (opt)
+      {
+      case 'r':
+        root_dev = optarg;
+        break;
+      case 'd':
+        dir = optarg;
+        break;
+      case 'm':
+        dev_map = optarg;
+        break;
+      case 'v':
+        verbosity++;
+        break;
+      case 'H':
+        hold = (optarg ? atoi (optarg) : -1);
+        break;
+      case 'h':
+        return usage (0);
+      case 'V':
+        printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+        return 0;
+      default:
+        return usage (1);
+      }
+
+  if (optind < argc)
+    {
+      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]);
+      return usage (1);
+    }
+
+  /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
+  if (hold && verbosity > 0)
+    printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
+            program_name, (int) getpid ());
+  while (hold)
+    {
+      if (hold > 0)
+        hold--;
+
+      sleep (1);
+    }
+
+  signal (SIGINT, SIG_IGN);
+  grub_console_init ();
+  grub_host_init ();
+  grub_hostfs_init ();
+
+  /* XXX: This is a bit unportable.  */
+  grub_util_biosdisk_init (dev_map);
+
+#if GRUB_NO_MODULES
+  grub_init_all ();
+#endif
+
+  /* Make sure that there is a root device.  */
+  if (! root_dev)
+    {
+      char *device_name = grub_guess_root_device (dir);
+      if (! device_name)
+        grub_util_error ("cannot find a device for %s", dir);
+
+      root_dev = grub_util_get_grub_dev (device_name);
+      if (! root_dev)
+       {
+         grub_util_info ("guessing the root device failed, because of `%s'",
+                         grub_errmsg);
+         grub_util_error ("cannot guess the root device. Specify the option `--root-device'");
+       }
+    }
+
+  if (strcmp (root_dev, "host") == 0)
+    dir = xstrdup (dir);
+  else
+    dir = grub_get_prefix (dir);
+  prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
+  sprintf (prefix, "(%s)%s", root_dev, dir);
+  free (dir);
+
+  /* Start GRUB!  */
+  if (setjmp (main_env) == 0)
+    grub_main ();
+
+#if GRUB_NO_MODULES
+  grub_fini_all ();
+#endif
+  grub_hostfs_fini ();
+  grub_host_fini ();
+
+  grub_machine_fini ();
+
+  return 0;
+}
+
+#ifdef __MINGW32__
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+  Sleep (ms);
+}
+
+#else
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+  struct timespec ts;
+
+  ts.tv_sec = ms / 1000;
+  ts.tv_nsec = (ms % 1000) * 1000000;
+  nanosleep (&ts, NULL);
+}
+
+#endif
+
+#if GRUB_NO_MODULES
+void
+grub_register_exported_symbols (void)
+{
+}
+#endif
diff --git a/kern/emu/misc.c b/kern/emu/misc.c
new file mode 100644 (file)
index 0000000..d8dfc93
--- /dev/null
@@ -0,0 +1,199 @@
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/env.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/time.h>
+#include <grub/emu/misc.h>
+
+int verbosity;
+
+void
+grub_util_warn (const char *fmt, ...)
+{
+  va_list ap;
+
+  fprintf (stderr, _("%s: warn:"), program_name);
+  fprintf (stderr, " ");
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fprintf (stderr, ".\n");
+  fflush (stderr);
+}
+
+void
+grub_util_info (const char *fmt, ...)
+{
+  if (verbosity > 0)
+    {
+      va_list ap;
+
+      fprintf (stderr, _("%s: info:"), program_name);
+      fprintf (stderr, " ");
+      va_start (ap, fmt);
+      vfprintf (stderr, fmt, ap);
+      va_end (ap);
+      fprintf (stderr, ".\n");
+      fflush (stderr);
+    }
+}
+
+void
+grub_util_error (const char *fmt, ...)
+{
+  va_list ap;
+
+  fprintf (stderr, _("%s: error:"), program_name);
+  fprintf (stderr, " ");
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fprintf (stderr, ".\n");
+  exit (1);
+}
+
+void *
+grub_malloc (grub_size_t size)
+{
+  return malloc (size);
+}
+
+void *
+grub_zalloc (grub_size_t size)
+{
+  void *ret;
+
+  ret = malloc (size);
+  memset (ret, 0, size);
+  return ret;
+}
+
+void
+grub_free (void *ptr)
+{
+  free (ptr);
+}
+
+void *
+grub_realloc (void *ptr, grub_size_t size)
+{
+  return realloc (ptr, size);
+}
+
+void *
+grub_memalign (grub_size_t align, grub_size_t size)
+{
+  void *p;
+
+#if defined(HAVE_POSIX_MEMALIGN)
+  if (align < sizeof (void *))
+    align = sizeof (void *);
+
+  else if (align % sizeof (void *))
+    grub_fatal ("bad alignment");
+
+  if (posix_memalign (&p, align, size) != 0)
+    p = 0;
+#elif defined(HAVE_MEMALIGN)
+  p = memalign (align, size);
+#else
+  (void) align;
+  (void) size;
+  grub_fatal ("grub_memalign is not supported");
+#endif
+
+  if (! p)
+    grub_fatal ("out of memory");
+
+  return p;
+}
+
+void *
+xmalloc (grub_size_t size)
+{
+  void *p;
+
+  p = grub_malloc (size);
+  if (! p)
+    grub_fatal ("out of memory");
+
+  return p;
+}
+
+void *
+xrealloc (void *ptr, grub_size_t size)
+{
+  ptr = grub_realloc (ptr, size);
+  if (! ptr)
+    grub_fatal ("out of memory");
+
+  return ptr;
+}
+
+char *
+xstrdup (const char *str)
+{
+  size_t len;
+  char *newstr;
+
+  len = grub_strlen (str);
+  newstr = (char *) xmalloc (len + 1);
+  grub_memcpy (newstr, str, len + 1);
+
+  return newstr;
+}
+
+char *
+xasprintf (const char *fmt, ...)
+{ 
+  va_list ap;
+  char *result;
+  
+  va_start (ap, fmt);
+  if (vasprintf (&result, fmt, ap) < 0)
+    { 
+      if (errno == ENOMEM)
+        grub_util_error ("out of memory");
+      return NULL;
+    }
+  
+  return result;
+}
+
+void
+grub_exit (void)
+{
+  exit (1);
+}
+
+grub_uint64_t
+grub_get_time_ms (void)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, 0);
+
+  return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, 0);
+
+  return (tv.tv_sec * GRUB_TICKS_PER_SECOND
+         + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec)
+            * GRUB_TICKS_PER_SECOND / 1000000));
+}
diff --git a/kern/emu/time.c b/kern/emu/time.c
new file mode 100644 (file)
index 0000000..5da8092
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  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/datetime.h>
+#include <time.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+  struct tm *mytm;
+  time_t mytime;
+
+  mytime = time (&mytime);
+  mytm = gmtime (&mytime);
+
+  datetime->year = mytm->tm_year + 1900;
+  datetime->month = mytm->tm_mon + 1;
+  datetime->day = mytm->tm_mday;
+  datetime->hour = mytm->tm_hour;
+  datetime->minute = mytm->tm_min;
+  datetime->second = mytm->tm_sec;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
+{
+  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                    "no clock setting routine available");
+}
diff --git a/util/console.c b/util/console.c
deleted file mode 100644 (file)
index 382fd7f..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-/*  console.c -- Ncurses console for GRUB.  */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2005,2007,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 <config.h>
-
-/* For compatibility.  */
-#ifndef A_NORMAL
-# define A_NORMAL      0
-#endif /* ! A_NORMAL */
-#ifndef A_STANDOUT
-# define A_STANDOUT    0
-#endif /* ! A_STANDOUT */
-
-#include <grub/util/console.h>
-#include <grub/term.h>
-#include <grub/types.h>
-
-#if defined(HAVE_NCURSES_CURSES_H)
-# include <ncurses/curses.h>
-#elif defined(HAVE_NCURSES_H)
-# include <ncurses.h>
-#elif defined(HAVE_CURSES_H)
-# include <curses.h>
-#endif
-
-static int grub_console_attr = A_NORMAL;
-
-grub_uint8_t grub_console_cur_color = 7;
-
-static grub_uint8_t grub_console_standard_color = 0x7;
-static grub_uint8_t grub_console_normal_color = 0x7;
-static grub_uint8_t grub_console_highlight_color = 0x70;
-
-#define NUM_COLORS     8
-
-static grub_uint8_t color_map[NUM_COLORS] =
-{
-  COLOR_BLACK,
-  COLOR_BLUE,
-  COLOR_GREEN,
-  COLOR_CYAN,
-  COLOR_RED,
-  COLOR_MAGENTA,
-  COLOR_YELLOW,
-  COLOR_WHITE
-};
-
-static int use_color;
-
-static void
-grub_ncurses_putchar (grub_uint32_t c)
-{
-  /* Better than nothing.  */
-  switch (c)
-    {
-    case GRUB_TERM_DISP_LEFT:
-      c = '<';
-      break;
-
-    case GRUB_TERM_DISP_UP:
-      c = '^';
-      break;
-
-    case GRUB_TERM_DISP_RIGHT:
-      c = '>';
-      break;
-
-    case GRUB_TERM_DISP_DOWN:
-      c = 'v';
-      break;
-
-    case GRUB_TERM_DISP_HLINE:
-      c = '-';
-      break;
-
-    case GRUB_TERM_DISP_VLINE:
-      c = '|';
-      break;
-
-    case GRUB_TERM_DISP_UL:
-    case GRUB_TERM_DISP_UR:
-    case GRUB_TERM_DISP_LL:
-    case GRUB_TERM_DISP_LR:
-      c = '+';
-      break;
-
-    default:
-      /* ncurses does not support Unicode.  */
-      if (c > 0x7f)
-       c = '?';
-      break;
-    }
-
-  addch (c | grub_console_attr);
-}
-
-static grub_ssize_t
-grub_ncurses_getcharwidth (grub_uint32_t code __attribute__ ((unused)))
-{
-  return 1;
-}
-
-static void
-grub_ncurses_setcolorstate (grub_term_color_state state)
-{
-  switch (state)
-    {
-    case GRUB_TERM_COLOR_STANDARD:
-      grub_console_cur_color = grub_console_standard_color;
-      grub_console_attr = A_NORMAL;
-      break;
-    case GRUB_TERM_COLOR_NORMAL:
-      grub_console_cur_color = grub_console_normal_color;
-      grub_console_attr = A_NORMAL;
-      break;
-    case GRUB_TERM_COLOR_HIGHLIGHT:
-      grub_console_cur_color = grub_console_highlight_color;
-      grub_console_attr = A_STANDOUT;
-      break;
-    default:
-      break;
-    }
-
-  if (use_color)
-    {
-      grub_uint8_t fg, bg;
-
-      fg = (grub_console_cur_color & 7);
-      bg = (grub_console_cur_color >> 4) & 7;
-
-      grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
-      color_set ((bg << 3) + fg, 0);
-    }
-}
-
-/* XXX: This function is never called.  */
-static void
-grub_ncurses_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
-{
-  grub_console_normal_color = normal_color;
-  grub_console_highlight_color = highlight_color;
-}
-
-static void
-grub_ncurses_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
-{
-  *normal_color = grub_console_normal_color;
-  *highlight_color = grub_console_highlight_color;
-}
-
-static int saved_char = ERR;
-
-static int
-grub_ncurses_checkkey (void)
-{
-  int c;
-
-  /* Check for SAVED_CHAR. This should not be true, because this
-     means checkkey is called twice continuously.  */
-  if (saved_char != ERR)
-    return saved_char;
-
-  wtimeout (stdscr, 100);
-  c = getch ();
-  /* If C is not ERR, then put it back in the input queue.  */
-  if (c != ERR)
-    {
-      saved_char = c;
-      return c;
-    }
-
-  return -1;
-}
-
-static int
-grub_ncurses_getkey (void)
-{
-  int c;
-
-  /* If checkkey has already got a character, then return it.  */
-  if (saved_char != ERR)
-    {
-      c = saved_char;
-      saved_char = ERR;
-    }
-  else
-    {
-      wtimeout (stdscr, -1);
-      c = getch ();
-    }
-
-  switch (c)
-    {
-    case KEY_LEFT:
-      c = 2;
-      break;
-
-    case KEY_RIGHT:
-      c = 6;
-      break;
-
-    case KEY_UP:
-      c = 16;
-      break;
-
-    case KEY_DOWN:
-      c = 14;
-      break;
-
-    case KEY_IC:
-      c = 24;
-      break;
-
-    case KEY_DC:
-      c = 4;
-      break;
-
-    case KEY_BACKSPACE:
-      /* XXX: For some reason ncurses on xterm does not return
-        KEY_BACKSPACE.  */
-    case 127:
-      c = 8;
-      break;
-
-    case KEY_HOME:
-      c = 1;
-      break;
-
-    case KEY_END:
-      c = 5;
-      break;
-
-    case KEY_NPAGE:
-      c = 3;
-      break;
-
-    case KEY_PPAGE:
-      c = 7;
-      break;
-    }
-
-  return c;
-}
-
-static grub_uint16_t
-grub_ncurses_getxy (void)
-{
-  int x;
-  int y;
-
-  getyx (stdscr, y, x);
-
-  return (x << 8) | y;
-}
-
-static grub_uint16_t
-grub_ncurses_getwh (void)
-{
-  int x;
-  int y;
-
-  getmaxyx (stdscr, y, x);
-
-  return (x << 8) | y;
-}
-
-static void
-grub_ncurses_gotoxy (grub_uint8_t x, grub_uint8_t y)
-{
-  move (y, x);
-}
-
-static void
-grub_ncurses_cls (void)
-{
-  clear ();
-  refresh ();
-}
-
-static void
-grub_ncurses_setcursor (int on)
-{
-  curs_set (on ? 1 : 0);
-}
-
-static void
-grub_ncurses_refresh (void)
-{
-  refresh ();
-}
-
-static grub_err_t
-grub_ncurses_init (void)
-{
-  initscr ();
-  raw ();
-  noecho ();
-  scrollok (stdscr, TRUE);
-
-  nonl ();
-  intrflush (stdscr, FALSE);
-  keypad (stdscr, TRUE);
-
-  if (has_colors ())
-    {
-      start_color ();
-
-      if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
-        {
-          int i, j, n;
-
-          n = 0;
-          for (i = 0; i < NUM_COLORS; i++)
-            for (j = 0; j < NUM_COLORS; j++)
-              init_pair(n++, color_map[j], color_map[i]);
-
-          use_color = 1;
-        }
-    }
-
-  return 0;
-}
-
-static grub_err_t
-grub_ncurses_fini (void)
-{
-  endwin ();
-  return 0;
-}
-
-\f
-static struct grub_term_input grub_ncurses_term_input =
-  {
-    .name = "console",
-    .checkkey = grub_ncurses_checkkey,
-    .getkey = grub_ncurses_getkey,
-  };
-
-static struct grub_term_output grub_ncurses_term_output =
-  {
-    .name = "console",
-    .init = grub_ncurses_init,
-    .fini = grub_ncurses_fini,
-    .putchar = grub_ncurses_putchar,
-    .getcharwidth = grub_ncurses_getcharwidth,
-    .getxy = grub_ncurses_getxy,
-    .getwh = grub_ncurses_getwh,
-    .gotoxy = grub_ncurses_gotoxy,
-    .cls = grub_ncurses_cls,
-    .setcolorstate = grub_ncurses_setcolorstate,
-    .setcolor = grub_ncurses_setcolor,
-    .getcolor = grub_ncurses_getcolor,
-    .setcursor = grub_ncurses_setcursor,
-    .refresh = grub_ncurses_refresh
-  };
-
-void
-grub_console_init (void)
-{
-  grub_term_register_output ("console", &grub_ncurses_term_output);
-  grub_term_register_input ("console", &grub_ncurses_term_input);
-}
-
-void
-grub_console_fini (void)
-{
-  grub_ncurses_fini ();
-}
diff --git a/util/getroot.c b/util/getroot.c
deleted file mode 100644 (file)
index 94eadc5..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-/* getroot.c - Get root device */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009  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 <config.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-
-#ifdef __CYGWIN__
-# include <sys/fcntl.h>
-# include <sys/cygwin.h>
-# include <limits.h>
-# define DEV_CYGDRIVE_MAJOR 98
-#endif
-
-#ifdef __GNU__
-#include <hurd.h>
-#include <hurd/lookup.h>
-#include <hurd/fs.h>
-#endif
-
-#include <grub/util/misc.h>
-#include <grub/util/hostdisk.h>
-#include <grub/util/getroot.h>
-
-static void
-strip_extra_slashes (char *dir)
-{
-  char *p = dir;
-
-  while ((p = strchr (p, '/')) != 0)
-    {
-      if (p[1] == '/')
-       {
-         memmove (p, p + 1, strlen (p));
-         continue;
-       }
-      else if (p[1] == '\0')
-       {
-         if (p > dir)
-           p[0] = '\0';
-         break;
-       }
-
-      p++;
-    }
-}
-
-static char *
-xgetcwd (void)
-{
-  size_t size = 10;
-  char *path;
-
-  path = xmalloc (size);
-  while (! getcwd (path, size))
-    {
-      size <<= 1;
-      path = xrealloc (path, size);
-    }
-
-  return path;
-}
-
-#ifdef __CYGWIN__
-/* Convert POSIX path to Win32 path,
-   remove drive letter, replace backslashes.  */
-static char *
-get_win32_path (const char *path)
-{
-  char winpath[PATH_MAX];
-  cygwin_conv_to_full_win32_path (path, winpath);
-
-  int len = strlen (winpath);
-  if (len > 2 && winpath[1] == ':')
-    {
-      len -= 2;
-      memmove (winpath, winpath + 2, len + 1);
-    }
-
-  int i;
-  for (i = 0; i < len; i++)
-    if (winpath[i] == '\\')
-      winpath[i] = '/';
-  return xstrdup (winpath);
-}
-#endif
-
-char *
-grub_get_prefix (const char *dir)
-{
-  char *saved_cwd;
-  char *abs_dir, *prev_dir;
-  char *prefix;
-  struct stat st, prev_st;
-
-  /* Save the current directory.  */
-  saved_cwd = xgetcwd ();
-
-  if (chdir (dir) < 0)
-    grub_util_error ("cannot change directory to `%s'", dir);
-
-  abs_dir = xgetcwd ();
-  strip_extra_slashes (abs_dir);
-  prev_dir = xstrdup (abs_dir);
-
-  if (stat (".", &prev_st) < 0)
-    grub_util_error ("cannot stat `%s'", dir);
-
-  if (! S_ISDIR (prev_st.st_mode))
-    grub_util_error ("`%s' is not a directory", dir);
-
-  while (1)
-    {
-      if (chdir ("..") < 0)
-       grub_util_error ("cannot change directory to the parent");
-
-      if (stat (".", &st) < 0)
-       grub_util_error ("cannot stat current directory");
-
-      if (! S_ISDIR (st.st_mode))
-       grub_util_error ("current directory is not a directory???");
-
-      if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
-       break;
-
-      free (prev_dir);
-      prev_dir = xgetcwd ();
-      prev_st = st;
-    }
-
-  strip_extra_slashes (prev_dir);
-  prefix = xmalloc (strlen (abs_dir) - strlen (prev_dir) + 2);
-  prefix[0] = '/';
-  strcpy (prefix + 1, abs_dir + strlen (prev_dir));
-  strip_extra_slashes (prefix);
-
-  if (chdir (saved_cwd) < 0)
-    grub_util_error ("cannot change directory to `%s'", dir);
-
-#ifdef __CYGWIN__
-  if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
-    {
-      /* Reached some mount point not below /cygdrive.
-        GRUB does not know Cygwin's emulated mounts,
-        convert to Win32 path.  */
-      grub_util_info ("Cygwin prefix = %s", prefix);
-      char * wprefix = get_win32_path (prefix);
-      free (prefix);
-      prefix = wprefix;
-    }
-#endif
-
-  free (saved_cwd);
-  free (abs_dir);
-  free (prev_dir);
-
-  grub_util_info ("prefix = %s", prefix);
-  return prefix;
-}
-
-#ifdef __MINGW32__
-
-static char *
-find_root_device (const char *dir __attribute__ ((unused)),
-                  dev_t dev __attribute__ ((unused)))
-{
-  return 0;
-}
-
-#elif ! defined(__CYGWIN__)
-
-static char *
-find_root_device (const char *dir, dev_t dev)
-{
-  DIR *dp;
-  char *saved_cwd;
-  struct dirent *ent;
-
-  dp = opendir (dir);
-  if (! dp)
-    return 0;
-
-  saved_cwd = xgetcwd ();
-
-  grub_util_info ("changing current directory to %s", dir);
-  if (chdir (dir) < 0)
-    {
-      free (saved_cwd);
-      closedir (dp);
-      return 0;
-    }
-
-  while ((ent = readdir (dp)) != 0)
-    {
-      struct stat st;
-
-      /* Avoid:
-        - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
-        - dotdirs (like "/dev/.static") since they could contain duplicates.  */
-      if (ent->d_name[0] == '.')
-       continue;
-
-      if (lstat (ent->d_name, &st) < 0)
-       /* Ignore any error.  */
-       continue;
-
-      if (S_ISLNK (st.st_mode))
-       /* Don't follow symbolic links.  */
-       continue;
-
-      if (S_ISDIR (st.st_mode))
-       {
-         /* Find it recursively.  */
-         char *res;
-
-         res = find_root_device (ent->d_name, dev);
-
-         if (res)
-           {
-             if (chdir (saved_cwd) < 0)
-               grub_util_error ("cannot restore the original directory");
-
-             free (saved_cwd);
-             closedir (dp);
-             return res;
-           }
-       }
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
-      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
-#else
-      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
-#endif
-       {
-#ifdef __linux__
-         /* Skip device names like /dev/dm-0, which are short-hand aliases
-            to more descriptive device names, e.g. those under /dev/mapper */
-         if (ent->d_name[0] == 'd' &&
-             ent->d_name[1] == 'm' &&
-             ent->d_name[2] == '-' &&
-             ent->d_name[3] >= '0' &&
-             ent->d_name[3] <= '9')
-           continue;
-#endif
-
-         /* Found!  */
-         char *res;
-         char *cwd;
-#if defined(__NetBSD__)
-         /* Convert this block device to its character (raw) device.  */
-         const char *template = "%s/r%s";
-#else
-         /* Keep the device name as it is.  */
-         const char *template = "%s/%s";
-#endif
-
-         cwd = xgetcwd ();
-         res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
-         sprintf (res, template, cwd, ent->d_name);
-         strip_extra_slashes (res);
-         free (cwd);
-
-         /* /dev/root is not a real block device keep looking, takes care
-            of situation where root filesystem is on the same partition as
-            grub files */
-
-         if (strcmp(res, "/dev/root") == 0)
-               continue;
-
-         if (chdir (saved_cwd) < 0)
-           grub_util_error ("cannot restore the original directory");
-
-         free (saved_cwd);
-         closedir (dp);
-         return res;
-       }
-    }
-
-  if (chdir (saved_cwd) < 0)
-    grub_util_error ("cannot restore the original directory");
-
-  free (saved_cwd);
-  closedir (dp);
-  return 0;
-}
-
-#else /* __CYGWIN__ */
-
-/* Read drive/partition serial number from mbr/boot sector,
-   return 0 on read error, ~0 on unknown serial.  */
-static unsigned
-get_bootsec_serial (const char *os_dev, int mbr)
-{
-  /* Read boot sector.  */
-  int fd = open (os_dev, O_RDONLY);
-  if (fd < 0)
-    return 0;
-  unsigned char buf[0x200];
-  int n = read (fd, buf, sizeof (buf));
-  close (fd);
-  if (n != sizeof(buf))
-    return 0;
-
-  /* Check signature.  */
-  if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
-    return ~0;
-
-  /* Serial number offset depends on boot sector type.  */
-  if (mbr)
-    n = 0x1b8;
-  else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
-    n = 0x048;
-  else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
-    n = 0x043;
-  else if (memcmp (buf + 0x36, "FAT", 3) == 0)
-    n = 0x027;
-  else
-    return ~0;
-
-  unsigned serial = *(unsigned *)(buf + n);
-  if (serial == 0)
-    return ~0;
-  return serial;
-}
-
-static char *
-find_cygwin_root_device (const char *path, dev_t dev)
-{
-  /* No root device for /cygdrive.  */
-  if (dev == (DEV_CYGDRIVE_MAJOR << 16))
-    return 0;
-
-  /* Convert to full POSIX and Win32 path.  */
-  char fullpath[PATH_MAX], winpath[PATH_MAX];
-  cygwin_conv_to_full_posix_path (path, fullpath);
-  cygwin_conv_to_full_win32_path (fullpath, winpath);
-
-  /* If identical, this is no real filesystem path.  */
-  if (strcmp (fullpath, winpath) == 0)
-    return 0;
-
-  /* Check for floppy drive letter.  */
-  if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
-    return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
-
-  /* Cygwin returns the partition serial number in stat.st_dev.
-     This is never identical to the device number of the emulated
-     /dev/sdXN device, so above find_root_device () does not work.
-     Search the partition with the same serial in boot sector instead.  */
-  char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia.  */
-  int d;
-  for (d = 'a'; d <= 'z'; d++)
-    {
-      sprintf (devpath, "/dev/sd%c", d);
-      if (get_bootsec_serial (devpath, 1) == 0)
-       continue;
-      int p;
-      for (p = 1; p <= 15; p++)
-       {
-         sprintf (devpath, "/dev/sd%c%d", d, p);
-         unsigned ser = get_bootsec_serial (devpath, 0);
-         if (ser == 0)
-           break;
-         if (ser != (unsigned)~0 && dev == (dev_t)ser)
-           return xstrdup (devpath);
-       }
-    }
-  return 0;
-}
-
-#endif /* __CYGWIN__ */
-
-char *
-grub_guess_root_device (const char *dir)
-{
-  char *os_dev;
-#ifdef __GNU__
-  file_t file;
-  mach_port_t *ports;
-  int *ints;
-  loff_t *offsets;
-  char *data;
-  error_t err;
-  mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
-  size_t name_len;
-
-  file = file_name_lookup (dir, 0, 0);
-  if (file == MACH_PORT_NULL)
-    return 0;
-
-  err = file_get_storage_info (file,
-                              &ports, &num_ports,
-                              &ints, &num_ints,
-                              &offsets, &num_offsets,
-                              &data, &data_len);
-
-  if (num_ints < 1)
-    grub_util_error ("Storage info for `%s' does not include type", dir);
-  if (ints[0] != STORAGE_DEVICE)
-    grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
-
-  if (num_ints < 5)
-    grub_util_error ("Storage info for `%s' does not include name", dir);
-  name_len = ints[4];
-  if (name_len < data_len)
-    grub_util_error ("Bogus name length for storage info for `%s'", dir);
-  if (data[name_len - 1] != '\0')
-    grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
-
-  os_dev = xmalloc (strlen ("/dev/") + data_len);
-  memcpy (os_dev, "/dev/", strlen ("/dev/"));
-  memcpy (os_dev + strlen ("/dev/"), data, data_len);
-
-  if (ports && num_ports > 0)
-    {
-      mach_msg_type_number_t i;
-      for (i = 0; i < num_ports; i++)
-        {
-         mach_port_t port = ports[i];
-         if (port != MACH_PORT_NULL)
-           mach_port_deallocate (mach_task_self(), port);
-        }
-      munmap ((caddr_t) ports, num_ports * sizeof (*ports));
-    }
-
-  if (ints && num_ints > 0)
-    munmap ((caddr_t) ints, num_ints * sizeof (*ints));
-  if (offsets && num_offsets > 0)
-    munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
-  if (data && data_len > 0)
-    munmap (data, data_len);
-  mach_port_deallocate (mach_task_self (), file);
-#else /* !__GNU__ */
-  struct stat st;
-
-  if (stat (dir, &st) < 0)
-    grub_util_error ("cannot stat `%s'", dir);
-
-#ifdef __CYGWIN__
-  /* Cygwin specific function.  */
-  os_dev = find_cygwin_root_device (dir, st.st_dev);
-
-#else
-
-  /* This might be truly slow, but is there any better way?  */
-  os_dev = find_root_device ("/dev", st.st_dev);
-#endif
-#endif /* !__GNU__ */
-
-  return os_dev;
-}
-
-static int
-grub_util_is_dmraid (const char *os_dev)
-{
-  if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
-    return 1;
-  else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
-    return 1;
-
-  return 0;
-}
-
-int
-grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
-{
-#ifdef __linux__
-  /* Check for LVM.  */
-  if (!strncmp (os_dev, "/dev/mapper/", 12)
-      && ! grub_util_is_dmraid (os_dev)
-      && strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
-    return GRUB_DEV_ABSTRACTION_LVM;
-
-  /* Check for RAID.  */
-  if (!strncmp (os_dev, "/dev/md", 7))
-    return GRUB_DEV_ABSTRACTION_RAID;
-#endif
-
-  /* No abstraction found.  */
-  return GRUB_DEV_ABSTRACTION_NONE;
-}
-
-char *
-grub_util_get_grub_dev (const char *os_dev)
-{
-  char *grub_dev;
-
-  switch (grub_util_get_dev_abstraction (os_dev))
-    {
-    case GRUB_DEV_ABSTRACTION_LVM:
-
-      {
-       unsigned short i, len;
-       grub_size_t offset = sizeof ("/dev/mapper/") - 1;
-
-       len = strlen (os_dev) - offset + 1;
-       grub_dev = xmalloc (len);
-
-       for (i = 0; i < len; i++, offset++)
-         {
-           grub_dev[i] = os_dev[offset];
-           if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
-             offset++;
-         }
-      }
-
-      break;
-
-    case GRUB_DEV_ABSTRACTION_RAID:
-
-      if (os_dev[7] == '_' && os_dev[8] == 'd')
-       {
-         /* This a partitionable RAID device of the form /dev/md_dNNpMM. */
-
-         char *p, *q;
-
-         p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
-
-         q = strchr (p, 'p');
-         if (q)
-           *q = ',';
-
-         grub_dev = xasprintf ("md%s", p);
-         free (p);
-       }
-      else if (os_dev[7] == '/' && os_dev[8] == 'd')
-       {
-         /* This a partitionable RAID device of the form /dev/md/dNNpMM. */
-
-         char *p, *q;
-
-         p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
-
-         q = strchr (p, 'p');
-         if (q)
-           *q = ',';
-
-         grub_dev = xasprintf ("md%s", p);
-         free (p);
-       }
-      else if (os_dev[7] >= '0' && os_dev[7] <= '9')
-       {
-         char *p , *q;
-
-         p = strdup (os_dev + sizeof ("/dev/md") - 1);
-
-         q = strchr (p, 'p');
-         if (q)
-           *q = ',';
-
-         grub_dev = xasprintf ("md%s", p);
-         free (p);
-       }
-      else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
-       {
-         char *p , *q;
-
-         p = strdup (os_dev + sizeof ("/dev/md/") - 1);
-
-         q = strchr (p, 'p');
-         if (q)
-           *q = ',';
-
-         grub_dev = xasprintf ("md%s", p);
-         free (p);
-       }
-      else
-       grub_util_error ("unknown kind of RAID device `%s'", os_dev);
-
-      break;
-
-    default:  /* GRUB_DEV_ABSTRACTION_NONE */
-      grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
-    }
-
-  return grub_dev;
-}
-
-const char *
-grub_util_check_block_device (const char *blk_dev)
-{
-  struct stat st;
-
-  if (stat (blk_dev, &st) < 0)
-    grub_util_error ("cannot stat `%s'", blk_dev);
-
-  if (S_ISBLK (st.st_mode))
-    return (blk_dev);
-  else
-    return 0;
-}
-
-const char *
-grub_util_check_char_device (const char *blk_dev)
-{
-  struct stat st;
-
-  if (stat (blk_dev, &st) < 0)
-    grub_util_error ("cannot stat `%s'", blk_dev);
-
-  if (S_ISCHR (st.st_mode))
-    return (blk_dev);
-  else
-    return 0;
-}
-
diff --git a/util/grub-emu.c b/util/grub-emu.c
deleted file mode 100644 (file)
index 8660f0a..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010  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 <stdlib.h>
-#include <sys/stat.h>
-#include <getopt.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <grub/mm.h>
-#include <grub/setjmp.h>
-#include <grub/fs.h>
-#include <grub/util/hostdisk.h>
-#include <grub/dl.h>
-#include <grub/util/console.h>
-#include <grub/util/misc.h>
-#include <grub/kernel.h>
-#include <grub/normal.h>
-#include <grub/util/getroot.h>
-#include <grub/env.h>
-#include <grub/partition.h>
-#include <grub/i18n.h>
-
-#define ENABLE_RELOCATABLE 0
-#include "progname.h"
-
-/* Used for going back to the main function.  */
-static jmp_buf main_env;
-
-/* Store the prefix specified by an argument.  */
-static char *prefix = NULL;
-
-grub_addr_t
-grub_arch_modules_addr (void)
-{
-  return 0;
-}
-
-#if GRUB_NO_MODULES
-grub_err_t
-grub_arch_dl_check_header (void *ehdr)
-{
-  (void) ehdr;
-
-  return GRUB_ERR_BAD_MODULE;
-}
-
-grub_err_t
-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
-{
-  (void) mod;
-  (void) ehdr;
-
-  return GRUB_ERR_BAD_MODULE;
-}
-#endif
-
-void
-grub_reboot (void)
-{
-  longjmp (main_env, 1);
-}
-
-void
-grub_halt (
-#ifdef GRUB_MACHINE_PCBIOS
-          int no_apm __attribute__ ((unused))
-#endif
-          )
-{
-  grub_reboot ();
-}
-
-void
-grub_machine_init (void)
-{
-}
-
-void
-grub_machine_set_prefix (void)
-{
-  grub_env_set ("prefix", prefix);
-  free (prefix);
-  prefix = 0;
-}
-
-void
-grub_machine_fini (void)
-{
-  grub_console_fini ();
-}
-
-\f
-
-static struct option options[] =
-  {
-    {"root-device", required_argument, 0, 'r'},
-    {"device-map", required_argument, 0, 'm'},
-    {"directory", required_argument, 0, 'd'},
-    {"hold", optional_argument, 0, 'H'},
-    {"help", no_argument, 0, 'h'},
-    {"version", no_argument, 0, 'V'},
-    {"verbose", no_argument, 0, 'v'},
-    { 0, 0, 0, 0 }
-  };
-
-static int
-usage (int status)
-{
-  if (status)
-    fprintf (stderr,
-            "Try `%s --help' for more information.\n", program_name);
-  else
-    printf (
-      "Usage: %s [OPTION]...\n"
-      "\n"
-      "GRUB emulator.\n"
-      "\n"
-      "  -r, --root-device=DEV     use DEV as the root device [default=guessed]\n"
-      "  -m, --device-map=FILE     use FILE as the device map [default=%s]\n"
-      "  -d, --directory=DIR       use GRUB files in the directory DIR [default=%s]\n"
-      "  -v, --verbose             print verbose messages\n"
-      "  -H, --hold[=SECONDS]      wait until a debugger will attach\n"
-      "  -h, --help                display this message and exit\n"
-      "  -V, --version             print version information and exit\n"
-      "\n"
-      "Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
-  return status;
-}
-\f
-
-void grub_hostfs_init (void);
-void grub_hostfs_fini (void);
-void grub_host_init (void);
-void grub_host_fini (void);
-#if GRUB_NO_MODULES
-void grub_init_all (void);
-void grub_fini_all (void);
-#endif
-
-int
-main (int argc, char *argv[])
-{
-  char *root_dev = 0;
-  char *dir = DEFAULT_DIRECTORY;
-  char *dev_map = DEFAULT_DEVICE_MAP;
-  volatile int hold = 0;
-  int opt;
-
-  set_program_name (argv[0]);
-
-  while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
-    switch (opt)
-      {
-      case 'r':
-        root_dev = optarg;
-        break;
-      case 'd':
-        dir = optarg;
-        break;
-      case 'm':
-        dev_map = optarg;
-        break;
-      case 'v':
-        verbosity++;
-        break;
-      case 'H':
-        hold = (optarg ? atoi (optarg) : -1);
-        break;
-      case 'h':
-        return usage (0);
-      case 'V':
-        printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
-        return 0;
-      default:
-        return usage (1);
-      }
-
-  if (optind < argc)
-    {
-      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]);
-      return usage (1);
-    }
-
-  /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
-  if (hold && verbosity > 0)
-    printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
-            program_name, (int) getpid ());
-  while (hold)
-    {
-      if (hold > 0)
-        hold--;
-
-      sleep (1);
-    }
-
-  signal (SIGINT, SIG_IGN);
-  grub_console_init ();
-  grub_host_init ();
-  grub_hostfs_init ();
-
-  /* XXX: This is a bit unportable.  */
-  grub_util_biosdisk_init (dev_map);
-
-#if GRUB_NO_MODULES
-  grub_init_all ();
-#endif
-
-  /* Make sure that there is a root device.  */
-  if (! root_dev)
-    {
-      char *device_name = grub_guess_root_device (dir);
-      if (! device_name)
-        grub_util_error ("cannot find a device for %s", dir);
-
-      root_dev = grub_util_get_grub_dev (device_name);
-      if (! root_dev)
-       {
-         grub_util_info ("guessing the root device failed, because of `%s'",
-                         grub_errmsg);
-         grub_util_error ("cannot guess the root device. Specify the option `--root-device'");
-       }
-    }
-
-  if (strcmp (root_dev, "host") == 0)
-    dir = xstrdup (dir);
-  else
-    dir = grub_get_prefix (dir);
-  prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
-  sprintf (prefix, "(%s)%s", root_dev, dir);
-  free (dir);
-
-  /* Start GRUB!  */
-  if (setjmp (main_env) == 0)
-    grub_main ();
-
-#if GRUB_NO_MODULES
-  grub_fini_all ();
-#endif
-  grub_hostfs_fini ();
-  grub_host_fini ();
-
-  grub_machine_fini ();
-
-  return 0;
-}
index bb41480e2cbfe2d68b7cefa82e850457dd75fa6e..1b2606dc7b88dd689f25049f2b52cb39e8b17ef9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <config.h>
 #include <grub/types.h>
+#include <grub/emu/misc.h>
 #include <grub/util/misc.h>
 #include <grub/device.h>
 #include <grub/disk.h>
@@ -26,8 +27,8 @@
 #include <grub/fs.h>
 #include <grub/partition.h>
 #include <grub/msdos_partition.h>
-#include <grub/util/hostdisk.h>
-#include <grub/util/getroot.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
 #include <grub/term.h>
 #include <grub/env.h>
 #include <grub/raid.h>
diff --git a/util/hostdisk.c b/util/hostdisk.c
deleted file mode 100644 (file)
index 8be4874..0000000
+++ /dev/null
@@ -1,1360 +0,0 @@
-/* hostdisk.c - emulate biosdisk */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009  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/disk.h>
-#include <grub/partition.h>
-#include <grub/msdos_partition.h>
-#include <grub/types.h>
-#include <grub/err.h>
-#include <grub/util/misc.h>
-#include <grub/util/hostdisk.h>
-#include <grub/misc.h>
-#include <grub/i18n.h>
-#include <grub/list.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-
-#ifdef __linux__
-# include <sys/ioctl.h>         /* ioctl */
-# if !defined(__GLIBC__) || \
-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
-/* Maybe libc doesn't have large file support.  */
-#  include <linux/unistd.h>     /* _llseek */
-# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
-# ifndef BLKFLSBUF
-#  define BLKFLSBUF     _IO (0x12,97)   /* flush buffer cache */
-# endif /* ! BLKFLSBUF */
-# include <sys/ioctl.h>                /* ioctl */
-# ifndef HDIO_GETGEO
-#  define HDIO_GETGEO  0x0301  /* get device geometry */
-/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
-   defined.  */
-struct hd_geometry
-{
-  unsigned char heads;
-  unsigned char sectors;
-  unsigned short cylinders;
-  unsigned long start;
-};
-# endif /* ! HDIO_GETGEO */
-# ifndef BLKGETSIZE64
-#  define BLKGETSIZE64  _IOR(0x12,114,size_t)    /* return device size */
-# endif /* ! BLKGETSIZE64 */
-# ifndef MAJOR
-#  ifndef MINORBITS
-#   define MINORBITS   8
-#  endif /* ! MINORBITS */
-#  define MAJOR(dev)   ((unsigned) ((dev) >> MINORBITS))
-# endif /* ! MAJOR */
-# ifndef FLOPPY_MAJOR
-#  define FLOPPY_MAJOR 2
-# endif /* ! FLOPPY_MAJOR */
-# ifndef LOOP_MAJOR
-#  define LOOP_MAJOR   7
-# endif /* ! LOOP_MAJOR */
-#endif /* __linux__ */
-
-#ifdef __CYGWIN__
-# include <sys/ioctl.h>
-# include <cygwin/fs.h> /* BLKGETSIZE64 */
-# include <cygwin/hdreg.h> /* HDIO_GETGEO */
-# define MAJOR(dev)    ((unsigned) ((dev) >> 16))
-# define FLOPPY_MAJOR  2
-#endif
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-# include <sys/disk.h> /* DIOCGMEDIASIZE */
-# include <sys/param.h>
-# include <sys/sysctl.h>
-#endif
-
-#if defined(__APPLE__)
-# include <sys/disk.h>
-#endif
-
-#if defined(__NetBSD__)
-# include <sys/ioctl.h>
-# include <sys/disklabel.h>    /* struct disklabel */
-# ifdef HAVE_GETRAWPARTITION
-#  include <util.h>    /* getrawpartition */
-# endif /* HAVE_GETRAWPARTITION */
-# include <sys/fdio.h>
-# ifndef RAW_FLOPPY_MAJOR
-#  define RAW_FLOPPY_MAJOR     9
-# endif /* ! RAW_FLOPPY_MAJOR */
-#endif /* defined(__NetBSD__) */
-
-struct
-{
-  char *drive;
-  char *device;
-} map[256];
-
-struct grub_util_biosdisk_data
-{
-  char *dev;
-  int access_mode;
-  int fd;
-};
-
-#ifdef __linux__
-/* Check if we have devfs support.  */
-static int
-have_devfs (void)
-{
-  static int dev_devfsd_exists = -1;
-
-  if (dev_devfsd_exists < 0)
-    {
-      struct stat st;
-
-      dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
-    }
-
-  return dev_devfsd_exists;
-}
-#endif /* __linux__ */
-
-#if defined(__NetBSD__)
-/* Adjust device driver parameters.  This function should be called just
-   after successfully opening the device.  For now, it simply prevents the
-   floppy driver from retrying operations on failure, as otherwise the
-   driver takes a while to abort when there is no floppy in the drive.  */
-static void
-configure_device_driver (int fd)
-{
-  struct stat st;
-
-  if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
-    return;
-  if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)
-    {
-      int floppy_opts;
-
-      if (ioctl (fd, FDIOCGETOPTS, &floppy_opts) == -1)
-       return;
-      floppy_opts |= FDOPT_NORETRY;
-      if (ioctl (fd, FDIOCSETOPTS, &floppy_opts) == -1)
-       return;
-    }
-}
-#endif /* defined(__NetBSD__) */
-
-static int
-find_grub_drive (const char *name)
-{
-  unsigned int i;
-
-  if (name)
-    {
-      for (i = 0; i < ARRAY_SIZE (map); i++)
-       if (map[i].drive && ! strcmp (map[i].drive, name))
-         return i;
-    }
-
-  return -1;
-}
-
-static int
-find_free_slot (void)
-{
-  unsigned int i;
-
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
-    if (! map[i].drive)
-      return i;
-
-  return -1;
-}
-
-static int
-grub_util_biosdisk_iterate (int (*hook) (const char *name))
-{
-  unsigned i;
-
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
-    if (map[i].drive && hook (map[i].drive))
-      return 1;
-
-  return 0;
-}
-
-static grub_err_t
-grub_util_biosdisk_open (const char *name, grub_disk_t disk)
-{
-  int drive;
-  struct stat st;
-  struct grub_util_biosdisk_data *data;
-
-  drive = find_grub_drive (name);
-  if (drive < 0)
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
-                      "no mapping exists for `%s'", name);
-
-  disk->has_partitions = 1;
-  disk->id = drive;
-  disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
-  data->dev = NULL;
-  data->access_mode = 0;
-  data->fd = -1;
-
-  /* Get the size.  */
-#if defined(__MINGW32__)
-  {
-    grub_uint64_t size;
-
-    size = grub_util_get_disk_size (map[drive].device);
-
-    if (size % 512)
-      grub_util_error ("unaligned device size");
-
-    disk->total_sectors = size >> 9;
-
-    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
-
-    return GRUB_ERR_NONE;
-  }
-#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
-      defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
-  {
-# if defined(__NetBSD__)
-    struct disklabel label;
-# else
-    unsigned long long nr;
-# endif
-    int fd;
-
-    fd = open (map[drive].device, O_RDONLY);
-    if (fd == -1)
-      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
-
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
-    if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
-# else
-    if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
-# endif
-      {
-       close (fd);
-       goto fail;
-      }
-
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-    if (ioctl (fd, DIOCGMEDIASIZE, &nr))
-# elif defined(__APPLE__)
-    if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
-# elif defined(__NetBSD__)
-    configure_device_driver (fd);
-    if (ioctl (fd, DIOCGDINFO, &label) == -1)
-# else
-    if (ioctl (fd, BLKGETSIZE64, &nr))
-# endif
-      {
-       close (fd);
-       goto fail;
-      }
-
-    close (fd);
-
-# if defined (__APPLE__)
-    disk->total_sectors = nr;
-# elif defined(__NetBSD__)
-    disk->total_sectors = label.d_secperunit;
-# else
-    disk->total_sectors = nr / 512;
-
-    if (nr % 512)
-      grub_util_error ("unaligned device size");
-# endif
-
-    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
-
-    return GRUB_ERR_NONE;
-  }
-
- fail:
-  /* In GNU/Hurd, stat() will return the right size.  */
-#elif !defined (__GNU__)
-# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
-#endif
-  if (stat (map[drive].device, &st) < 0)
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
-
-  disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
-
-  grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
-
-  return GRUB_ERR_NONE;
-}
-
-#ifdef __linux__
-/* Cache of partition start sectors for each disk.  */
-struct linux_partition_cache
-{
-  struct linux_partition_cache *next;
-  char *dev;
-  unsigned long start;
-  int partno;
-};
-
-struct linux_partition_cache *linux_partition_cache_list;
-
-static int
-linux_find_partition (char *dev, unsigned long sector)
-{
-  size_t len = strlen (dev);
-  const char *format;
-  char *p;
-  int i;
-  char real_dev[PATH_MAX];
-  struct linux_partition_cache *cache;
-
-  strcpy(real_dev, dev);
-
-  if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0)
-    {
-      p = real_dev + len - 4;
-      format = "part%d";
-    }
-  else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
-    {
-      p = real_dev + len;
-      format = "p%d";
-    }
-  else
-    {
-      p = real_dev + len;
-      format = "%d";
-    }
-
-  for (cache = linux_partition_cache_list; cache; cache = cache->next)
-    {
-      if (strcmp (cache->dev, dev) == 0 && cache->start == sector)
-       {
-         sprintf (p, format, cache->partno);
-         strcpy (dev, real_dev);
-         return 1;
-       }
-    }
-
-  for (i = 1; i < 10000; i++)
-    {
-      int fd;
-      struct hd_geometry hdg;
-
-      sprintf (p, format, i);
-      fd = open (real_dev, O_RDONLY);
-      if (fd == -1)
-       return 0;
-
-      if (ioctl (fd, HDIO_GETGEO, &hdg))
-       {
-         close (fd);
-         return 0;
-       }
-
-      close (fd);
-
-      if (hdg.start == sector)
-       {
-         struct linux_partition_cache *new_cache_item;
-
-         new_cache_item = xmalloc (sizeof *new_cache_item);
-         new_cache_item->dev = xstrdup (dev);
-         new_cache_item->start = hdg.start;
-         new_cache_item->partno = i;
-         grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list),
-                         GRUB_AS_LIST (new_cache_item));
-
-         strcpy (dev, real_dev);
-         return 1;
-       }
-    }
-
-  return 0;
-}
-#endif /* __linux__ */
-
-static int
-open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
-{
-  int fd;
-  struct grub_util_biosdisk_data *data = disk->data;
-
-#ifdef O_LARGEFILE
-  flags |= O_LARGEFILE;
-#endif
-#ifdef O_SYNC
-  flags |= O_SYNC;
-#endif
-#ifdef O_FSYNC
-  flags |= O_FSYNC;
-#endif
-#ifdef O_BINARY
-  flags |= O_BINARY;
-#endif
-
-#ifdef __linux__
-  /* Linux has a bug that the disk cache for a whole disk is not consistent
-     with the one for a partition of the disk.  */
-  {
-    int is_partition = 0;
-    char dev[PATH_MAX];
-    grub_disk_addr_t part_start = 0;
-
-    part_start = grub_partition_get_start (disk->partition);
-
-    strcpy (dev, map[disk->id].device);
-    if (disk->partition && sector >= part_start
-       && strncmp (map[disk->id].device, "/dev/", 5) == 0)
-      is_partition = linux_find_partition (dev, part_start);
-
-    if (data->dev && strcmp (data->dev, dev) == 0 &&
-       data->access_mode == (flags & O_ACCMODE))
-      {
-       grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev);
-       fd = data->fd;
-      }
-    else
-      {
-       free (data->dev);
-       if (data->fd != -1)
-         close (data->fd);
-
-       /* Open the partition.  */
-       grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
-       fd = open (dev, flags);
-       if (fd < 0)
-         {
-           grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
-           return -1;
-         }
-
-       /* Flush the buffer cache to the physical disk.
-          XXX: This also empties the buffer cache.  */
-       ioctl (fd, BLKFLSBUF, 0);
-
-       data->dev = xstrdup (dev);
-       data->access_mode = (flags & O_ACCMODE);
-       data->fd = fd;
-      }
-
-    if (is_partition)
-      sector -= part_start;
-  }
-#else /* ! __linux__ */
-#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-  int sysctl_flags, sysctl_oldflags;
-  size_t sysctl_size = sizeof (sysctl_flags);
-
-  if (sysctlbyname ("kern.geom.debugflags", &sysctl_oldflags, &sysctl_size, NULL, 0))
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current flags of sysctl kern.geom.debugflags");
-      return -1;
-    }
-  sysctl_flags = sysctl_oldflags | 0x10;
-  if (! (sysctl_oldflags & 0x10)
-      && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size))
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags");
-      return -1;
-    }
-#endif
-
-  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
-      data->access_mode == (flags & O_ACCMODE))
-    {
-      grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
-      fd = data->fd;
-    }
-  else
-    {
-      free (data->dev);
-      if (data->fd != -1)
-       close (data->fd);
-
-      fd = open (map[disk->id].device, flags);
-      if (fd >= 0)
-       {
-         data->dev = xstrdup (map[disk->id].device);
-         data->access_mode = (flags & O_ACCMODE);
-         data->fd = fd;
-       }
-    }
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-  if (! (sysctl_oldflags & 0x10)
-      && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size))
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags back to the old value for sysctl kern.geom.debugflags");
-      return -1;
-    }
-#endif
-
-#if defined(__APPLE__)
-  /* If we can't have exclusive access, try shared access */
-  if (fd < 0)
-    fd = open(map[disk->id].device, flags | O_SHLOCK);
-#endif
-
-  if (fd < 0)
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device);
-      return -1;
-    }
-#endif /* ! __linux__ */
-
-#if defined(__NetBSD__)
-  configure_device_driver (fd);
-#endif /* defined(__NetBSD__) */
-
-#if defined(__linux__) && (!defined(__GLIBC__) || \
-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
-  /* Maybe libc doesn't have large file support.  */
-  {
-    loff_t offset, result;
-    static int _llseek (uint filedes, ulong hi, ulong lo,
-                        loff_t *res, uint wh);
-    _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
-               loff_t *, res, uint, wh);
-
-    offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
-    if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
-      {
-       grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
-       close (fd);
-       return -1;
-      }
-  }
-#else
-  {
-    off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
-
-    if (lseek (fd, offset, SEEK_SET) != offset)
-      {
-       grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
-       close (fd);
-       return -1;
-      }
-  }
-#endif
-
-  return fd;
-}
-
-/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
-   error occurs, otherwise return LEN.  */
-static ssize_t
-nread (int fd, char *buf, size_t len)
-{
-  ssize_t size = len;
-
-  while (len)
-    {
-      ssize_t ret = read (fd, buf, len);
-
-      if (ret <= 0)
-        {
-          if (errno == EINTR)
-            continue;
-          else
-            return ret;
-        }
-
-      len -= ret;
-      buf += ret;
-    }
-
-  return size;
-}
-
-/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
-   error occurs, otherwise return LEN.  */
-static ssize_t
-nwrite (int fd, const char *buf, size_t len)
-{
-  ssize_t size = len;
-
-  while (len)
-    {
-      ssize_t ret = write (fd, buf, len);
-
-      if (ret <= 0)
-        {
-          if (errno == EINTR)
-            continue;
-          else
-            return ret;
-        }
-
-      len -= ret;
-      buf += ret;
-    }
-
-  return size;
-}
-
-static grub_err_t
-grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
-                        grub_size_t size, char *buf)
-{
-  int fd;
-
-  /* Split pre-partition and partition reads.  */
-  if (disk->partition && sector < disk->partition->start
-      && sector + size > disk->partition->start)
-    {
-      grub_err_t err;
-      err = grub_util_biosdisk_read (disk, sector,
-                                    disk->partition->start - sector,
-                                    buf);
-      if (err)
-       return err;
-
-      return grub_util_biosdisk_read (disk, disk->partition->start,
-                                     size - (disk->partition->start - sector),
-                                     buf + ((disk->partition->start - sector)
-                                            << GRUB_DISK_SECTOR_BITS));
-    }
-
-  fd = open_device (disk, sector, O_RDONLY);
-  if (fd < 0)
-    return grub_errno;
-
-#ifdef __linux__
-  if (sector == 0 && size > 1)
-    {
-      /* Work around a bug in Linux ez remapping.  Linux remaps all
-        sectors that are read together with the MBR in one read.  It
-        should only remap the MBR, so we split the read in two
-        parts. -jochen  */
-      if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
-       {
-         grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
-         close (fd);
-         return grub_errno;
-       }
-
-      buf += GRUB_DISK_SECTOR_SIZE;
-      size--;
-    }
-#endif /* __linux__ */
-
-  if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
-      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
-    grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
-
-  return grub_errno;
-}
-
-static grub_err_t
-grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
-                         grub_size_t size, const char *buf)
-{
-  int fd;
-
-  /* Split pre-partition and partition writes.  */
-  if (disk->partition && sector < disk->partition->start
-      && sector + size > disk->partition->start)
-    {
-      grub_err_t err;
-      err = grub_util_biosdisk_write (disk, sector,
-                                     disk->partition->start - sector,
-                                     buf);
-      if (err)
-       return err;
-
-      return grub_util_biosdisk_write (disk, disk->partition->start,
-                                      size - (disk->partition->start - sector),
-                                      buf + ((disk->partition->start - sector)
-                                             << GRUB_DISK_SECTOR_BITS));
-    }
-
-  fd = open_device (disk, sector, O_WRONLY);
-  if (fd < 0)
-    return grub_errno;
-
-  if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
-      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
-    grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
-
-  return grub_errno;
-}
-
-static void
-grub_util_biosdisk_close (struct grub_disk *disk)
-{
-  struct grub_util_biosdisk_data *data = disk->data;
-
-  free (data->dev);
-  if (data->fd != -1)
-    close (data->fd);
-  free (data);
-}
-
-static struct grub_disk_dev grub_util_biosdisk_dev =
-  {
-    .name = "biosdisk",
-    .id = GRUB_DISK_DEVICE_BIOSDISK_ID,
-    .iterate = grub_util_biosdisk_iterate,
-    .open = grub_util_biosdisk_open,
-    .close = grub_util_biosdisk_close,
-    .read = grub_util_biosdisk_read,
-    .write = grub_util_biosdisk_write,
-    .next = 0
-  };
-
-static void
-read_device_map (const char *dev_map)
-{
-  FILE *fp;
-  char buf[1024];      /* XXX */
-  int lineno = 0;
-  struct stat st;
-
-  auto void show_error (const char *msg);
-  void show_error (const char *msg)
-    {
-      grub_util_error ("%s:%d: %s", dev_map, lineno, msg);
-    }
-
-  fp = fopen (dev_map, "r");
-  if (! fp)
-    {
-      grub_util_info (_("cannot open `%s'"), dev_map);
-      return;
-    }
-
-  while (fgets (buf, sizeof (buf), fp))
-    {
-      char *p = buf;
-      char *e;
-      int drive;
-
-      lineno++;
-
-      /* Skip leading spaces.  */
-      while (*p && isspace (*p))
-       p++;
-
-      /* If the first character is `#' or NUL, skip this line.  */
-      if (*p == '\0' || *p == '#')
-       continue;
-
-      if (*p != '(')
-       show_error ("No open parenthesis found");
-
-      p++;
-      /* Find a free slot.  */
-      drive = find_free_slot ();
-      if (drive < 0)
-       show_error ("Map table size exceeded");
-
-      e = p;
-      p = strchr (p, ')');
-      if (! p)
-       show_error ("No close parenthesis found");
-
-      map[drive].drive = xmalloc (p - e + sizeof ('\0'));
-      strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
-      map[drive].drive[p - e] = '\0';
-
-      p++;
-      /* Skip leading spaces.  */
-      while (*p && isspace (*p))
-       p++;
-
-      if (*p == '\0')
-       show_error ("No filename found");
-
-      /* NUL-terminate the filename.  */
-      e = p;
-      while (*e && ! isspace (*e))
-       e++;
-      *e = '\0';
-
-#ifdef __MINGW32__
-      (void) st;
-      if (grub_util_get_disk_size (p) == -1LL)
-#else
-      if (stat (p, &st) == -1)
-#endif
-       {
-         free (map[drive].drive);
-         map[drive].drive = NULL;
-         grub_util_info ("Cannot stat `%s', skipping", p);
-         continue;
-       }
-
-#ifdef __linux__
-      /* On Linux, the devfs uses symbolic links horribly, and that
-        confuses the interface very much, so use realpath to expand
-        symbolic links.  */
-      map[drive].device = xmalloc (PATH_MAX);
-      if (! realpath (p, map[drive].device))
-       grub_util_error ("cannot get the real path of `%s'", p);
-#else
-      map[drive].device = xstrdup (p);
-#endif
-    }
-
-  fclose (fp);
-}
-
-void
-grub_util_biosdisk_init (const char *dev_map)
-{
-  read_device_map (dev_map);
-  grub_disk_dev_register (&grub_util_biosdisk_dev);
-}
-
-void
-grub_util_biosdisk_fini (void)
-{
-  unsigned i;
-
-  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
-    {
-      if (map[i].drive)
-       free (map[i].drive);
-      if (map[i].device)
-       free (map[i].device);
-      map[i].drive = map[i].device = NULL;
-    }
-
-  grub_disk_dev_unregister (&grub_util_biosdisk_dev);
-}
-
-static char *
-make_device_name (int drive, int dos_part, int bsd_part)
-{
-  char *ret;
-  char *dos_part_str = NULL;
-  char *bsd_part_str = NULL;
-
-  if (dos_part >= 0)
-    dos_part_str = xasprintf (",%d", dos_part + 1);
-
-  if (bsd_part >= 0)
-    bsd_part_str = xasprintf (",%d", bsd_part + 1);
-
-  ret = xasprintf ("%s%s%s", map[drive].drive,
-                   dos_part_str ? : "",
-                   bsd_part_str ? : "");
-
-  if (dos_part_str)
-    free (dos_part_str);
-
-  if (bsd_part_str)
-    free (bsd_part_str);
-
-  return ret;
-}
-
-static char *
-convert_system_partition_to_system_disk (const char *os_dev)
-{
-#if defined(__linux__)
-  char *path = xmalloc (PATH_MAX);
-  if (! realpath (os_dev, path))
-    return NULL;
-
-  if (strncmp ("/dev/", path, 5) == 0)
-    {
-      char *p = path + 5;
-
-      /* If this is an IDE disk.  */
-      if (strncmp ("ide/", p, 4) == 0)
-       {
-         p = strstr (p, "part");
-         if (p)
-           strcpy (p, "disc");
-
-         return path;
-       }
-
-      /* If this is a SCSI disk.  */
-      if (strncmp ("scsi/", p, 5) == 0)
-       {
-         p = strstr (p, "part");
-         if (p)
-           strcpy (p, "disc");
-
-         return path;
-       }
-
-      /* If this is a DAC960 disk.  */
-      if (strncmp ("rd/c", p, 4) == 0)
-       {
-         /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
-         p = strchr (p, 'p');
-         if (p)
-           *p = '\0';
-
-         return path;
-       }
-
-      /* If this is a Mylex AcceleRAID Array.  */
-      if (strncmp ("rs/c", p, 4) == 0)
-       {
-         /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
-         p = strchr (p, 'p');
-         if (p)
-           *p = '\0';
-
-         return path;
-       }
-      /* If this is a CCISS disk.  */
-      if (strncmp ("cciss/c", p, sizeof ("cciss/c") - 1) == 0)
-       {
-         /* /dev/cciss/c[0-9]+d[0-9]+(p[0-9]+)? */
-         p = strchr (p, 'p');
-         if (p)
-           *p = '\0';
-
-         return path;
-       }
-
-      /* If this is a Compaq Intelligent Drive Array.  */
-      if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0)
-       {
-         /* /dev/ida/c[0-9]+d[0-9]+(p[0-9]+)? */
-         p = strchr (p, 'p');
-         if (p)
-           *p = '\0';
-
-         return path;
-       }
-
-      /* If this is an I2O disk.  */
-      if (strncmp ("i2o/hd", p, sizeof ("i2o/hd") - 1) == 0)
-       {
-         /* /dev/i2o/hd[a-z]([0-9]+)? */
-         p[sizeof ("i2o/hda") - 1] = '\0';
-         return path;
-       }
-
-      /* If this is a MultiMediaCard (MMC).  */
-      if (strncmp ("mmcblk", p, sizeof ("mmcblk") - 1) == 0)
-       {
-         /* /dev/mmcblk[0-9]+(p[0-9]+)? */
-         p = strchr (p, 'p');
-         if (p)
-           *p = '\0';
-
-         return path;
-       }
-
-      /* If this is an IDE, SCSI or Virtio disk.  */
-      if (strncmp ("vdisk", p, 5) == 0
-         && p[5] >= 'a' && p[5] <= 'z')
-       {
-         /* /dev/vdisk[a-z][0-9]* */
-         p[6] = '\0';
-         return path;
-       }
-      if ((strncmp ("hd", p, 2) == 0
-          || strncmp ("vd", p, 2) == 0
-          || strncmp ("sd", p, 2) == 0)
-         && p[2] >= 'a' && p[2] <= 'z')
-       {
-         /* /dev/[hsv]d[a-z][0-9]* */
-         p[3] = '\0';
-         return path;
-       }
-
-      /* If this is a Xen virtual block device.  */
-      if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
-       {
-         /* /dev/xvd[a-z][0-9]* */
-         p[4] = '\0';
-         return path;
-       }
-    }
-
-  return path;
-
-#elif defined(__GNU__)
-  char *path = xstrdup (os_dev);
-  if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
-    {
-      char *p = strchr (path + 7, 's');
-      if (p)
-       *p = '\0';
-    }
-  return path;
-
-#elif defined(__CYGWIN__)
-  char *path = xstrdup (os_dev);
-  if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z')
-    path[8] = 0;
-  return path;
-
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
-  char *path = xstrdup (os_dev);
-  if (strncmp ("/dev/", path, 5) == 0)
-    {
-      char *p;
-      for (p = path + 5; *p; ++p)
-        if (grub_isdigit(*p))
-          {
-            p = strchr (p, 's');
-            if (p)
-              *p = '\0';
-            break;
-          }
-    }
-  return path;
-
-#elif defined(__NetBSD__)
-  /* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]".  */
-  char *path = xstrdup (os_dev);
-  if (strncmp ("/dev/rwd", path, 8) == 0 ||
-      strncmp ("/dev/rsd", path, 8) == 0 ||
-      strncmp ("/dev/rcd", path, 8) == 0)
-    {
-      char *q;
-      q = path + strlen(path) - 1;    /* last character */
-      if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
-        {
-          int rawpart = -1;
-# ifdef HAVE_GETRAWPARTITION
-          rawpart = getrawpartition();
-# endif /* HAVE_GETRAWPARTITION */
-          if (rawpart >= 0)
-            *q = 'a' + rawpart;
-        }
-    }
-  return path;
-
-#else
-# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
-  return xstrdup (os_dev);
-#endif
-}
-
-#if defined(__linux__) || defined(__CYGWIN__)
-static int
-device_is_wholedisk (const char *os_dev)
-{
-  int len = strlen (os_dev);
-
-  if (os_dev[len - 1] < '0' || os_dev[len - 1] > '9')
-    return 1;
-  return 0;
-}
-#endif
-
-#if defined(__NetBSD__)
-/* Try to determine whether a given device name corresponds to a whole disk.
-   This function should give in most cases a definite answer, but it may
-   actually give an approximate one in the following sense: if the return
-   value is 0 then the device name does not correspond to a whole disk.  */
-static int
-device_is_wholedisk (const char *os_dev)
-{
-  int len = strlen (os_dev);
-  int rawpart = -1;
-
-# ifdef HAVE_GETRAWPARTITION
-  rawpart = getrawpartition();
-# endif /* HAVE_GETRAWPARTITION */
-  if (rawpart < 0)
-    return 1;
-  return (os_dev[len - 1] == ('a' + rawpart));
-}
-#endif /* defined(__NetBSD__) */
-
-static int
-find_system_device (const char *os_dev)
-{
-  unsigned int i;
-  char *os_disk;
-
-  os_disk = convert_system_partition_to_system_disk (os_dev);
-  if (! os_disk)
-    return -1;
-
-  for (i = 0; i < ARRAY_SIZE (map); i++)
-    if (! map[i].device)
-      break;
-    else if (strcmp (map[i].device, os_disk) == 0)
-      {
-       free (os_disk);
-       return i;
-      }
-
-  if (i == ARRAY_SIZE (map))
-    grub_util_error (_("device count exceeds limit"));
-
-  map[i].device = os_disk;
-  map[i].drive = xstrdup (os_disk);
-
-  return i;
-}
-
-char *
-grub_util_biosdisk_get_grub_dev (const char *os_dev)
-{
-  struct stat st;
-  int drive;
-
-  if (stat (os_dev, &st) < 0)
-    {
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
-      return 0;
-    }
-
-  drive = find_system_device (os_dev);
-  if (drive < 0)
-    {
-      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
-                 "no mapping exists for `%s'", os_dev);
-      return 0;
-    }
-
-  if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev))
-      == 0)
-    return make_device_name (drive, -1, -1);
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
-  if (! S_ISCHR (st.st_mode))
-#else
-  if (! S_ISBLK (st.st_mode))
-#endif
-    return make_device_name (drive, -1, -1);
-
-#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
-  /* Linux counts partitions uniformly, whether a BSD partition or a DOS
-     partition, so mapping them to GRUB devices is not trivial.
-     Here, get the start sector of a partition by HDIO_GETGEO, and
-     compare it with each partition GRUB recognizes.
-
-     Cygwin /dev/sdXN emulation uses Windows partition mapping. It
-     does not count the extended partition and missing primary
-     partitions.  Use same method as on Linux here.
-
-     For NetBSD, proceed as for Linux, except that the start sector is
-     obtained from the disk label.  */
-  {
-    char *name;
-    grub_disk_t disk;
-    int fd;
-# if !defined(__NetBSD__)
-    struct hd_geometry hdg;
-    typeof (hdg.start) p_offset;
-# else /* defined(__NetBSD__) */
-    struct disklabel label;
-    int index;
-    u_int32_t p_offset;
-# endif /* !defined(__NetBSD__) */
-    int dos_part = -1;
-    int bsd_part = -1;
-    auto int find_partition (grub_disk_t dsk,
-                            const grub_partition_t partition);
-
-    int find_partition (grub_disk_t dsk __attribute__ ((unused)),
-                       const grub_partition_t partition)
-      {
-       grub_disk_addr_t part_start = 0;
-       grub_util_info ("Partition %d starts from %lu",
-                       partition->number, partition->start);
-
-       part_start = grub_partition_get_start (partition);
-
-       if (p_offset == part_start)
-         {
-           if (partition->parent)
-             {
-               dos_part = partition->parent->number;
-               bsd_part = partition->number;
-             }
-           else
-             {
-               dos_part = partition->number;
-               bsd_part = -1;
-             }
-
-           return 1;
-         }
-
-       return 0;
-      }
-
-    name = make_device_name (drive, -1, -1);
-
-# if !defined(__NetBSD__)
-    if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
-      return name;
-# else /* defined(__NetBSD__) */
-    /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
-     * different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
-     * and in particular it cannot be a floppy device.  */
-    index = os_dev[strlen(os_dev) - 1] - 'a';
-# endif /* !defined(__NetBSD__) */
-
-    fd = open (os_dev, O_RDONLY);
-    if (fd == -1)
-      {
-       grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev);
-       free (name);
-       return 0;
-      }
-
-# if !defined(__NetBSD__)
-    if (ioctl (fd, HDIO_GETGEO, &hdg))
-# else /* defined(__NetBSD__) */
-    configure_device_driver (fd);
-    if (ioctl (fd, DIOCGDINFO, &label) == -1)
-# endif /* !defined(__NetBSD__) */
-      {
-       grub_error (GRUB_ERR_BAD_DEVICE,
-                   "cannot get disk geometry of `%s'", os_dev);
-       close (fd);
-       free (name);
-       return 0;
-      }
-
-    close (fd);
-
-# if !defined(__NetBSD__)
-    p_offset = hdg.start;
-# else /* defined(__NetBSD__) */
-    if (index >= label.d_npartitions)
-      {
-       grub_error (GRUB_ERR_BAD_DEVICE,
-                   "no disk label entry for `%s'", os_dev);
-       free (name);
-       return 0;
-      }
-    p_offset = label.d_partitions[index].p_offset;
-# endif /* !defined(__NetBSD__) */
-
-    grub_util_info ("%s starts from %lu", os_dev, p_offset);
-
-    if (p_offset == 0 && device_is_wholedisk (os_dev))
-      return name;
-
-    grub_util_info ("opening the device %s", name);
-    disk = grub_disk_open (name);
-    free (name);
-
-    if (! disk)
-      return 0;
-
-    grub_partition_iterate (disk, find_partition);
-    if (grub_errno != GRUB_ERR_NONE)
-      {
-       grub_disk_close (disk);
-       return 0;
-      }
-
-    if (dos_part < 0)
-      {
-       grub_disk_close (disk);
-       grub_error (GRUB_ERR_BAD_DEVICE,
-                   "cannot find the partition of `%s'", os_dev);
-       return 0;
-      }
-
-    return make_device_name (drive, dos_part, bsd_part);
-  }
-
-#elif defined(__GNU__)
-  /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?".  */
-  {
-    char *p;
-    int dos_part = -1;
-    int bsd_part = -1;
-
-    p = strrchr (os_dev, 's');
-    if (p)
-      {
-       long int n;
-       char *q;
-
-       p++;
-       n = strtol (p, &q, 10);
-       if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
-         {
-           dos_part = (int) n - 1;
-
-           if (*q >= 'a' && *q <= 'g')
-             bsd_part = *q - 'a';
-         }
-      }
-
-    return make_device_name (drive, dos_part, bsd_part);
-  }
-
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
-  /* FreeBSD uses "/dev/[a-z]+[0-9]+(s[0-9]+[a-z]?)?".  */
-  {
-    int dos_part = -1;
-    int bsd_part = -1;
-
-    if (strncmp ("/dev/", os_dev, 5) == 0)
-      {
-        const char *p;
-        char *q;
-        long int n;
-
-        for (p = os_dev + 5; *p; ++p)
-          if (grub_isdigit(*p))
-            {
-              p = strchr (p, 's');
-              if (p)
-                {
-                  p++;
-                  n = strtol (p, &q, 10);
-                  if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
-                    {
-                      dos_part = (int) n - 1;
-
-                      if (*q >= 'a' && *q <= 'g')
-                        bsd_part = *q - 'a';
-                    }
-                }
-              break;
-            }
-      }
-
-    return make_device_name (drive, dos_part, bsd_part);
-  }
-
-#else
-# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
-  return make_device_name (drive, -1, -1);
-#endif
-}
-
-const char *
-grub_util_biosdisk_get_osdev (grub_disk_t disk)
-{
-  return map[disk->id].device;
-}
diff --git a/util/hostfs.c b/util/hostfs.c
deleted file mode 100644 (file)
index 501ad46..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/* hostfs.c - Dummy filesystem to provide access to the hosts filesystem  */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2007,2008,2009,2010  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/>.
- */
-#define _BSD_SOURCE
-#include <grub/fs.h>
-#include <grub/file.h>
-#include <grub/disk.h>
-#include <grub/misc.h>
-#include <grub/dl.h>
-#include <grub/util/misc.h>
-
-#include <dirent.h>
-#include <stdio.h>
-#include <errno.h>
-
-
-/* dirent.d_type is a BSD extension, not part of POSIX */
-#include <sys/stat.h>
-#include <string.h>
-
-static int
-is_dir (const char *path, const char *name)
-{
-  int len1 = strlen(path);
-  int len2 = strlen(name);
-
-  char pathname[len1 + 1 + len2 + 1 + 13];
-  strcpy (pathname, path);
-
-  /* Avoid UNC-path "//name" on Cygwin.  */
-  if (len1 > 0 && pathname[len1 - 1] != '/')
-    strcat (pathname, "/");
-
-  strcat (pathname, name);
-
-  struct stat st;
-  if (stat (pathname, &st))
-    return 0;
-  return S_ISDIR (st.st_mode);
-}
-
-static grub_err_t
-grub_hostfs_dir (grub_device_t device, const char *path,
-                int (*hook) (const char *filename,
-                             const struct grub_dirhook_info *info))
-{
-  DIR *dir;
-
-  /* Check if the disk is our dummy disk.  */
-  if (grub_strcmp (device->disk->name, "host"))
-    return grub_error (GRUB_ERR_BAD_FS, "not a hostfs");
-
-  dir = opendir (path);
-  if (! dir)
-    return grub_error (GRUB_ERR_BAD_FILENAME,
-                      "can't open the hostfs directory `%s'", path);
-
-  while (1)
-    {
-      struct dirent *de;
-      struct grub_dirhook_info info;
-      grub_memset (&info, 0, sizeof (info));
-
-      de = readdir (dir);
-      if (! de)
-       break;
-
-      info.dir = !! is_dir (path, de->d_name);
-      hook (de->d_name, &info);
-
-    }
-
-  closedir (dir);
-
-  return GRUB_ERR_NONE;
-}
-
-/* Open a file named NAME and initialize FILE.  */
-static grub_err_t
-grub_hostfs_open (struct grub_file *file, const char *name)
-{
-  FILE *f;
-
-  f = fopen (name, "rb");
-  if (! f)
-    return grub_error (GRUB_ERR_BAD_FILENAME,
-                      "can't open `%s'", name);
-  file->data = f;
-
-#ifdef __MINGW32__
-  file->size = grub_util_get_disk_size (name);
-#else
-  fseeko (f, 0, SEEK_END);
-  file->size = ftello (f);
-  fseeko (f, 0, SEEK_SET);
-#endif
-
-  return GRUB_ERR_NONE;
-}
-
-static grub_ssize_t
-grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len)
-{
-  FILE *f;
-
-  f = (FILE *) file->data;
-  if (fseeko (f, file->offset, SEEK_SET) != 0)
-    {
-      grub_error (GRUB_ERR_OUT_OF_RANGE, "fseeko: %s", strerror (errno));
-      return -1;
-    }
-
-  unsigned int s = fread (buf, 1, len, f);
-  if (s != len)
-    grub_error (GRUB_ERR_FILE_READ_ERROR, "fread: %s", strerror (errno));
-
-  return (signed) s;
-}
-
-static grub_err_t
-grub_hostfs_close (grub_file_t file)
-{
-  FILE *f;
-
-  f = (FILE *) file->data;
-  fclose (f);
-
-  return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_hostfs_label (grub_device_t device __attribute ((unused)),
-                  char **label __attribute ((unused)))
-{
-  *label = 0;
-  return GRUB_ERR_NONE;
-}
-
-static struct grub_fs grub_hostfs_fs =
-  {
-    .name = "hostfs",
-    .dir = grub_hostfs_dir,
-    .open = grub_hostfs_open,
-    .read = grub_hostfs_read,
-    .close = grub_hostfs_close,
-    .label = grub_hostfs_label,
-    .next = 0
-  };
-
-\f
-
-GRUB_MOD_INIT(hostfs)
-{
-  grub_fs_register (&grub_hostfs_fs);
-}
-
-GRUB_MOD_FINI(hostfs)
-{
-  grub_fs_unregister (&grub_hostfs_fs);
-}
diff --git a/util/pci.c b/util/pci.c
deleted file mode 100644 (file)
index 420ae32..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* pci.c - Generic PCI interfaces.  */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2007,2009  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/pci.h>
-#include <grub/dl.h>
-#include <grub/util/misc.h>
-
-grub_pci_address_t
-grub_pci_make_address (grub_pci_device_t dev, int reg)
-{
-  grub_pci_address_t ret;
-  ret.dev = dev;
-  ret.pos = reg;
-  return ret;
-}
-
-void
-grub_pci_iterate (grub_pci_iteratefunc_t hook)
-{
-  struct pci_device_iterator *iter;
-  struct pci_slot_match slot;
-  struct pci_device *dev;
-  slot.domain = PCI_MATCH_ANY;
-  slot.bus = PCI_MATCH_ANY;
-  slot.dev = PCI_MATCH_ANY;
-  slot.func = PCI_MATCH_ANY;
-  iter = pci_slot_match_iterator_create (&slot);
-  while ((dev = pci_device_next (iter)))
-    hook (dev, dev->vendor_id | (dev->device_id << 16));
-  pci_iterator_destroy (iter);
-}
-
-void *
-grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
-                          grub_size_t size)
-{
-  void *addr;
-  int err;
-  err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
-  if (err)
-    grub_util_error ("mapping 0x%x failed (error %d)\n", base, err);
-  return addr;
-}
-
-void
-grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
-                            grub_size_t size)
-{
-  pci_device_unmap_range (dev, mem, size);
-}
-
-GRUB_MOD_INIT (pci)
-{
-  pci_system_init ();
-}
-
-GRUB_MOD_FINI (pci)
-{
-  pci_system_cleanup ();
-}
diff --git a/util/sdl.c b/util/sdl.c
deleted file mode 100644 (file)
index d261db6..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005,2006,2007,2008,2009  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/>.
- */
-
-#define grub_video_render_target grub_video_fbrender_target
-
-#include <grub/err.h>
-#include <grub/types.h>
-#include <grub/dl.h>
-#include <grub/misc.h>
-#include <grub/mm.h>
-#include <grub/video.h>
-#include <grub/video_fb.h>
-#include <SDL/SDL.h>
-
-static SDL_Surface *window = 0;
-static struct grub_video_render_target *sdl_render_target;
-static struct grub_video_mode_info mode_info;
-
-static grub_err_t
-grub_video_sdl_set_palette (unsigned int start, unsigned int count,
-                            struct grub_video_palette_data *palette_data);
-
-static grub_err_t
-grub_video_sdl_init (void)
-{
-  window = 0;
-
-  if (SDL_Init (SDL_INIT_VIDEO) < 0)
-    return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't init SDL: %s",
-                      SDL_GetError ());
-
-  grub_memset (&mode_info, 0, sizeof (mode_info));
-
-  return grub_video_fb_init ();
-}
-
-static grub_err_t
-grub_video_sdl_fini (void)
-{
-  SDL_Quit ();
-  window = 0;
-
-  grub_memset (&mode_info, 0, sizeof (mode_info));
-
-  return grub_video_fb_fini ();
-}
-
-static inline unsigned int
-get_mask_size (grub_uint32_t mask)
-{
-  unsigned i;
-  for (i = 0; mask > 1U << i; i++);
-  return i;
-}
-
-static grub_err_t
-grub_video_sdl_setup (unsigned int width, unsigned int height,
-                      unsigned int mode_type, unsigned int mode_mask)
-{
-  int depth;
-  int flags = 0;
-  grub_err_t err;
-
-  /* Decode depth from mode_type.  If it is zero, then autodetect.  */
-  depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
-          >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
-
-  if (depth == 0)
-    depth = 32;
-
-  if (width == 0 && height == 0)
-    {
-      width = 800;
-      height = 600;
-    }
-
-  if ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
-      || !(mode_mask & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED))
-    flags |= SDL_DOUBLEBUF;
-
-  window = SDL_SetVideoMode (width, height, depth, flags | SDL_HWSURFACE);
-  if (! window)
-    window = SDL_SetVideoMode (width, height, depth, flags | SDL_SWSURFACE);
-  if (! window)
-    return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't open window: %s",
-                      SDL_GetError ());
-
-  grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target));
-
-  mode_info.width = window->w;
-  mode_info.height = window->h;
-  mode_info.mode_type = 0;
-  if (window->flags & SDL_DOUBLEBUF)
-    mode_info.mode_type
-      |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
-  if (window->format->palette)
-    mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
-  else
-    mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
-
-  mode_info.bpp = window->format->BitsPerPixel;
-  mode_info.bytes_per_pixel = window->format->BytesPerPixel;
-  mode_info.pitch = window->pitch;
-
-  /* In index color mode, number of colors.  In RGB mode this is 256.  */
-  if (window->format->palette)
-    mode_info.number_of_colors
-      = 1 << window->format->BitsPerPixel;
-  else
-    mode_info.number_of_colors = 256;
-
-  if (! window->format->palette)
-    {
-      mode_info.red_mask_size
-       = get_mask_size (window->format->Rmask >> window->format->Rshift);
-      mode_info.red_field_pos = window->format->Rshift;
-      mode_info.green_mask_size
-       = get_mask_size (window->format->Gmask >> window->format->Gshift);
-      mode_info.green_field_pos = window->format->Gshift;
-      mode_info.blue_mask_size
-       = get_mask_size (window->format->Bmask >> window->format->Bshift);
-      mode_info.blue_field_pos = window->format->Bshift;
-      mode_info.reserved_mask_size
-       = get_mask_size (window->format->Amask >> window->format->Ashift);
-      mode_info.reserved_field_pos = window->format->Ashift;
-      mode_info.blit_format
-       = grub_video_get_blit_format (&mode_info);
-    }
-
-  err = grub_video_fb_create_render_target_from_pointer (&sdl_render_target,
-                                                        &mode_info,
-                                                        window->pixels);
-  if (err)
-    return err;
-
-  /* Copy default palette to initialize emulated palette.  */
-  grub_video_sdl_set_palette (0, (sizeof (grub_video_fbstd_colors)
-                                 / sizeof (grub_video_fbstd_colors[0])),
-                             grub_video_fbstd_colors);
-
-  /* Reset render target to SDL one.  */
-  return grub_video_fb_set_active_render_target (sdl_render_target);
-}
-
-static grub_err_t
-grub_video_sdl_set_palette (unsigned int start, unsigned int count,
-                            struct grub_video_palette_data *palette_data)
-{
-  unsigned i;
-  if (window->format->palette)
-    {
-      SDL_Color *tmp = grub_malloc (count * sizeof (tmp[0]));
-      for (i = 0; i < count; i++)
-       {
-         tmp[i].r = palette_data[i].r;
-         tmp[i].g = palette_data[i].g;
-         tmp[i].b = palette_data[i].b;
-         tmp[i].unused = palette_data[i].a;
-       }
-      SDL_SetColors (window, tmp, start, count);
-      grub_free (tmp);
-    }
-
-  return grub_video_fb_set_palette (start, count, palette_data);
-}
-
-static grub_err_t
-grub_video_sdl_swap_buffers (void)
-{
-  if (SDL_Flip (window) < 0)
-    return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't swap buffers: %s",
-                      SDL_GetError ());
-  return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_video_sdl_set_active_render_target (struct grub_video_render_target *target)
-{
-  if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
-    return grub_video_fb_set_active_render_target (sdl_render_target);
-
-  return grub_video_fb_set_active_render_target (target);
-}
-
-static struct grub_video_adapter grub_video_sdl_adapter =
-  {
-    .name = "SDL Video Driver",
-
-    .init = grub_video_sdl_init,
-    .fini = grub_video_sdl_fini,
-    .setup = grub_video_sdl_setup,
-    .get_info = grub_video_fb_get_info,
-    .set_palette = grub_video_sdl_set_palette,
-    .get_palette = grub_video_fb_get_palette,
-    .set_viewport = grub_video_fb_set_viewport,
-    .get_viewport = grub_video_fb_get_viewport,
-    .map_color = grub_video_fb_map_color,
-    .map_rgb = grub_video_fb_map_rgb,
-    .map_rgba = grub_video_fb_map_rgba,
-    .unmap_color = grub_video_fb_unmap_color,
-    .fill_rect = grub_video_fb_fill_rect,
-    .blit_bitmap = grub_video_fb_blit_bitmap,
-    .blit_render_target = grub_video_fb_blit_render_target,
-    .scroll = grub_video_fb_scroll,
-    .swap_buffers = grub_video_sdl_swap_buffers,
-    .create_render_target = grub_video_fb_create_render_target,
-    .delete_render_target = grub_video_fb_delete_render_target,
-    .set_active_render_target = grub_video_sdl_set_active_render_target,
-    .get_active_render_target = grub_video_fb_get_active_render_target,
-
-    .next = 0
-  };
-
-GRUB_MOD_INIT(sdl)
-{
-  grub_video_register (&grub_video_sdl_adapter);
-}
-
-GRUB_MOD_FINI(sdl)
-{
-  grub_video_unregister (&grub_video_sdl_adapter);
-}
diff --git a/util/time.c b/util/time.c
deleted file mode 100644 (file)
index 5da8092..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2010  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/datetime.h>
-#include <time.h>
-
-grub_err_t
-grub_get_datetime (struct grub_datetime *datetime)
-{
-  struct tm *mytm;
-  time_t mytime;
-
-  mytime = time (&mytime);
-  mytm = gmtime (&mytime);
-
-  datetime->year = mytm->tm_year + 1900;
-  datetime->month = mytm->tm_mon + 1;
-  datetime->day = mytm->tm_mday;
-  datetime->hour = mytm->tm_hour;
-  datetime->minute = mytm->tm_min;
-  datetime->second = mytm->tm_sec;
-
-  return GRUB_ERR_NONE;
-}
-
-grub_err_t
-grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
-{
-  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-                    "no clock setting routine available");
-}
diff --git a/util/usb.c b/util/usb.c
deleted file mode 100644 (file)
index a687eea..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*  usb.c -- libusb USB support for GRUB.  */
-/*
- *  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 <config.h>
-#include <grub/misc.h>
-#include <grub/mm.h>
-#include <usb.h>
-#include <grub/usb.h>
-#include <grub/dl.h>
-
-\f
-static struct grub_usb_controller_dev usb_controller =
-{
-  .name = "libusb"
-};
-
-static struct grub_usb_device *grub_usb_devs[128];
-
-struct usb_bus *busses;
-
-static grub_err_t
-grub_libusb_devices (void)
-
-{
-  struct usb_bus *bus;
-  int last = 0;
-
-  busses = usb_get_busses();
-
-  for (bus = busses; bus; bus = bus->next)
-    {
-      struct usb_device *usbdev;
-      struct grub_usb_device *dev;
-
-      for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
-       {
-         struct usb_device_descriptor *desc = &usbdev->descriptor;
-         grub_err_t err;
-
-         if (! desc->bcdUSB)
-           continue;
-
-         dev = grub_malloc (sizeof (*dev));
-         if (! dev)
-           return grub_errno;
-
-         dev->data = usbdev;
-
-         /* Fill in all descriptors.  */
-         err = grub_usb_device_initialize (dev);
-         if (err)
-           {
-             grub_errno = GRUB_ERR_NONE;
-             continue;
-           }
-
-         /* Register the device.  */
-         grub_usb_devs[last++] = dev;
-       }
-    }
-
-  return GRUB_USB_ERR_NONE;
-}
-
-\f
-int
-grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
-{
-  int i;
-
-  for (i = 0; i < 128; i++)
-    {
-      if (grub_usb_devs[i])
-       {
-         if (hook (grub_usb_devs[i]))
-             return 1;
-       }
-    }
-
-  return 0;
-}
-
-grub_usb_err_t
-grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
-{
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
-                     grub_uint8_t request, grub_uint16_t value,
-                     grub_uint16_t index, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_control_msg (devh, reqtype, request,
-                      value, index, data, size, 20) < 0)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_bulk_read (grub_usb_device_t dev,
-                   int endpoint, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_claim_interface (devh, 0) < 1)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
-    {
-      usb_close (devh);
-      return GRUB_USB_ERR_STALL;
-    }
-
-  usb_release_interface (devh, 0);
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-}
-
-grub_usb_err_t
-grub_usb_bulk_write (grub_usb_device_t dev,
-                    int endpoint, grub_size_t size, char *data)
-{
-  usb_dev_handle *devh;
-  struct usb_device *d = dev->data;
-
-  devh = usb_open (d);
-  if (usb_claim_interface (devh, 0) < 0)
-    goto fail;
-
-  if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
-    goto fail;
-
-  if (usb_release_interface (devh, 0) < 0)
-    goto fail;
-
-  usb_close (devh);
-
-  return GRUB_USB_ERR_NONE;
-
- fail:
-  usb_close (devh);
-  return GRUB_USB_ERR_STALL;
-}
-
-GRUB_MOD_INIT (libusb)
-{
-  usb_init();
-  usb_find_busses();
-  usb_find_devices();
-
-  if (grub_libusb_devices ())
-    return;
-
-  grub_usb_controller_dev_register (&usb_controller);
-
-  return;
-}
-
-GRUB_MOD_FINI (libusb)
-{
-  return;
-}
diff --git a/video/emu/sdl.c b/video/emu/sdl.c
new file mode 100644 (file)
index 0000000..d261db6
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,2007,2008,2009  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/>.
+ */
+
+#define grub_video_render_target grub_video_fbrender_target
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/video.h>
+#include <grub/video_fb.h>
+#include <SDL/SDL.h>
+
+static SDL_Surface *window = 0;
+static struct grub_video_render_target *sdl_render_target;
+static struct grub_video_mode_info mode_info;
+
+static grub_err_t
+grub_video_sdl_set_palette (unsigned int start, unsigned int count,
+                            struct grub_video_palette_data *palette_data);
+
+static grub_err_t
+grub_video_sdl_init (void)
+{
+  window = 0;
+
+  if (SDL_Init (SDL_INIT_VIDEO) < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't init SDL: %s",
+                      SDL_GetError ());
+
+  grub_memset (&mode_info, 0, sizeof (mode_info));
+
+  return grub_video_fb_init ();
+}
+
+static grub_err_t
+grub_video_sdl_fini (void)
+{
+  SDL_Quit ();
+  window = 0;
+
+  grub_memset (&mode_info, 0, sizeof (mode_info));
+
+  return grub_video_fb_fini ();
+}
+
+static inline unsigned int
+get_mask_size (grub_uint32_t mask)
+{
+  unsigned i;
+  for (i = 0; mask > 1U << i; i++);
+  return i;
+}
+
+static grub_err_t
+grub_video_sdl_setup (unsigned int width, unsigned int height,
+                      unsigned int mode_type, unsigned int mode_mask)
+{
+  int depth;
+  int flags = 0;
+  grub_err_t err;
+
+  /* Decode depth from mode_type.  If it is zero, then autodetect.  */
+  depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
+          >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+
+  if (depth == 0)
+    depth = 32;
+
+  if (width == 0 && height == 0)
+    {
+      width = 800;
+      height = 600;
+    }
+
+  if ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
+      || !(mode_mask & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED))
+    flags |= SDL_DOUBLEBUF;
+
+  window = SDL_SetVideoMode (width, height, depth, flags | SDL_HWSURFACE);
+  if (! window)
+    window = SDL_SetVideoMode (width, height, depth, flags | SDL_SWSURFACE);
+  if (! window)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't open window: %s",
+                      SDL_GetError ());
+
+  grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target));
+
+  mode_info.width = window->w;
+  mode_info.height = window->h;
+  mode_info.mode_type = 0;
+  if (window->flags & SDL_DOUBLEBUF)
+    mode_info.mode_type
+      |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
+  if (window->format->palette)
+    mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+  else
+    mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
+
+  mode_info.bpp = window->format->BitsPerPixel;
+  mode_info.bytes_per_pixel = window->format->BytesPerPixel;
+  mode_info.pitch = window->pitch;
+
+  /* In index color mode, number of colors.  In RGB mode this is 256.  */
+  if (window->format->palette)
+    mode_info.number_of_colors
+      = 1 << window->format->BitsPerPixel;
+  else
+    mode_info.number_of_colors = 256;
+
+  if (! window->format->palette)
+    {
+      mode_info.red_mask_size
+       = get_mask_size (window->format->Rmask >> window->format->Rshift);
+      mode_info.red_field_pos = window->format->Rshift;
+      mode_info.green_mask_size
+       = get_mask_size (window->format->Gmask >> window->format->Gshift);
+      mode_info.green_field_pos = window->format->Gshift;
+      mode_info.blue_mask_size
+       = get_mask_size (window->format->Bmask >> window->format->Bshift);
+      mode_info.blue_field_pos = window->format->Bshift;
+      mode_info.reserved_mask_size
+       = get_mask_size (window->format->Amask >> window->format->Ashift);
+      mode_info.reserved_field_pos = window->format->Ashift;
+      mode_info.blit_format
+       = grub_video_get_blit_format (&mode_info);
+    }
+
+  err = grub_video_fb_create_render_target_from_pointer (&sdl_render_target,
+                                                        &mode_info,
+                                                        window->pixels);
+  if (err)
+    return err;
+
+  /* Copy default palette to initialize emulated palette.  */
+  grub_video_sdl_set_palette (0, (sizeof (grub_video_fbstd_colors)
+                                 / sizeof (grub_video_fbstd_colors[0])),
+                             grub_video_fbstd_colors);
+
+  /* Reset render target to SDL one.  */
+  return grub_video_fb_set_active_render_target (sdl_render_target);
+}
+
+static grub_err_t
+grub_video_sdl_set_palette (unsigned int start, unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned i;
+  if (window->format->palette)
+    {
+      SDL_Color *tmp = grub_malloc (count * sizeof (tmp[0]));
+      for (i = 0; i < count; i++)
+       {
+         tmp[i].r = palette_data[i].r;
+         tmp[i].g = palette_data[i].g;
+         tmp[i].b = palette_data[i].b;
+         tmp[i].unused = palette_data[i].a;
+       }
+      SDL_SetColors (window, tmp, start, count);
+      grub_free (tmp);
+    }
+
+  return grub_video_fb_set_palette (start, count, palette_data);
+}
+
+static grub_err_t
+grub_video_sdl_swap_buffers (void)
+{
+  if (SDL_Flip (window) < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't swap buffers: %s",
+                      SDL_GetError ());
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_sdl_set_active_render_target (struct grub_video_render_target *target)
+{
+  if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
+    return grub_video_fb_set_active_render_target (sdl_render_target);
+
+  return grub_video_fb_set_active_render_target (target);
+}
+
+static struct grub_video_adapter grub_video_sdl_adapter =
+  {
+    .name = "SDL Video Driver",
+
+    .init = grub_video_sdl_init,
+    .fini = grub_video_sdl_fini,
+    .setup = grub_video_sdl_setup,
+    .get_info = grub_video_fb_get_info,
+    .set_palette = grub_video_sdl_set_palette,
+    .get_palette = grub_video_fb_get_palette,
+    .set_viewport = grub_video_fb_set_viewport,
+    .get_viewport = grub_video_fb_get_viewport,
+    .map_color = grub_video_fb_map_color,
+    .map_rgb = grub_video_fb_map_rgb,
+    .map_rgba = grub_video_fb_map_rgba,
+    .unmap_color = grub_video_fb_unmap_color,
+    .fill_rect = grub_video_fb_fill_rect,
+    .blit_bitmap = grub_video_fb_blit_bitmap,
+    .blit_render_target = grub_video_fb_blit_render_target,
+    .scroll = grub_video_fb_scroll,
+    .swap_buffers = grub_video_sdl_swap_buffers,
+    .create_render_target = grub_video_fb_create_render_target,
+    .delete_render_target = grub_video_fb_delete_render_target,
+    .set_active_render_target = grub_video_sdl_set_active_render_target,
+    .get_active_render_target = grub_video_fb_get_active_render_target,
+
+    .next = 0
+  };
+
+GRUB_MOD_INIT(sdl)
+{
+  grub_video_register (&grub_video_sdl_adapter);
+}
+
+GRUB_MOD_FINI(sdl)
+{
+  grub_video_unregister (&grub_video_sdl_adapter);
+}