--- /dev/null
+/* 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 ();
+}
--- /dev/null
+/* 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;
+}
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
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)
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)
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
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 \
\
# 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 \
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/* 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 */
--- /dev/null
+#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 */
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/* 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 */
--- /dev/null
+#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
--- /dev/null
+/* 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 ();
+}
--- /dev/null
+/*
+ * 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; */
+/* } */
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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));
+}
--- /dev/null
+/*
+ * 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");
+}
+++ /dev/null
-/* 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 ();
-}
+++ /dev/null
-/* 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;
-}
-
+++ /dev/null
-/*
- * 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;
-}
#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>
#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>
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-/* 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 ();
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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");
-}
+++ /dev/null
-/* 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;
-}
--- /dev/null
+/*
+ * 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);
+}