merge mainline into usb

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-08-01 21:23:18 +02:00
commit fafc23e90a
39 changed files with 1436 additions and 229 deletions

View file

@ -1,5 +1,6 @@
00_header 00_header
10_* 10_*
20_linux_xen
30_os-prober 30_os-prober
40_custom 40_custom
41_custom 41_custom

333
ChangeLog
View file

@ -1,3 +1,336 @@
2010-08-01 Vladimir Serbinenko <phcoder@gmail.com>
* lib/arg.c (grub_arg_show_help): Add the necessary spacing.
2010-08-01 Vladimir Serbinenko <phcoder@gmail.com>
* kern/emu/getroot.c (find_mount_point_from_dir): Compile only if
[HAVE_LIBZFS && HAVE_LIBNVPAIR]
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* util/grub-mkrescue.in: Remove ${efi_dir} after building efi.img.
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* script/yylex.l (NAME): Remove [:digit:], redundant with [:alnum:].
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* docs/grub.texi (Simple configuration): Document GRUB_CMDLINE_XEN
and GRUB_CMDLINE_XEN_DEFAULT. Recommend setting
GRUB_GFXPAYLOAD_LINUX=text rather than unsetting it in order to
disable gfxpayload.
(Shell-like scripting): Add real content.
(Serial terminal): Suggest `terminal_input serial; terminal_output
serial' rather than putting the two commands on separate lines,
since console input will be inoperative after the first command.
(menuentry): Document --class, --users, and --hotkey options.
(terminfo): Describe what `visually-ordered UTF-8' means (thanks,
Vladimir Serbinenko).
2010-08-01 Vladimir Serbinenko <phcoder@gmail.com>
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* kern/misc.c (grub_memset): Optimise to reduce cache stalls.
2010-08-01 Robert Millan <rmh@gnu.org>
Prevent accidental use of uninitialized libzfs_handle.
* util/grub-probe.c (main): Move grub_util_init_libzfs() call to ...
* kern/emu/getroot.c (find_root_device_from_libzfs): ... here.
* util/misc.c (grub_util_init_libzfs): Make this function idempotent.
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* util/grub.d/20_linux_xen.in: Don't use UUID for LVM root (matching
util/grub.d/10_linux.in). Fixes Debian bug #591093.
2010-08-01 Robert Millan <rmh@gnu.org>
* kern/emu/getroot.c: Include `<grub/util/misc.h>'.
2010-07-31 Robert Millan <rmh@gnu.org>
* util/grub.d/10_kfreebsd.in: Make module handling more generic.
2010-07-31 Robert Millan <rmh@gnu.org>
* kern/emu/misc.c: Add missing license header.
2010-07-31 Robert Millan <rmh@gnu.org>
* configure.ac: Check for `libzfs.h' and `libnvpair.h'.
* include/grub/util/libnvpair.h: Include `<config.h>'.
[HAVE_LIBNVPAIR_H]: Include `<libnvpair.h>' instead of
declaring libnvpair prototypes ourselves.
* include/grub/util/libzfs.h: Include `<config.h>'.
[HAVE_LIBZFS_H]: Include `<libzfs.h>' instead of
declaring libzfs prototypes ourselves.
(libzfs_handle): Moved to ...
* include/grub/util/misc.h (libzfs_handle): ... here.
Include `<grub/util/libzfs.h>'.
2010-07-30 Robert Millan <rmh@gnu.org>
* include/grub/emu/misc.h: Add missing license header.
2010-07-30 Robert Millan <rmh@gnu.org>
Enable `grub-probe -t device' resolution on ZFS.
* configure.ac: Check for getfsstat(), libzfs and libnvpair.
* include/grub/util/libnvpair.h: New file.
* include/grub/util/libzfs.h: New file.
* kern/emu/getroot.c: Include `<assert.h>' and `<error.h>'.
[HAVE_LIBZFS && HAVE_LIBNVPAIR]: Include `<grub/util/libzfs.h>' and
`<grub/util/libnvpair.h>'.
[HAVE_GETFSSTAT]: Include `<sys/mount.h>'.
(find_mount_point_from_dir): New static function.
[HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_root_device_from_libzfs): New
function.
[HAVE_LIBZFS && HAVE_LIBNVPAIR] (grub_guess_root_device): Use
find_root_device_from_libzfs() before ressorting to find_root_device().
* include/grub/util/misc.h (grub_util_init_libzfs): New function
prototype.
* util/misc.c: Include `<grub/util/libzfs.h>'.
(grub_util_init_libzfs): New function.
[HAVE_LIBZFS] (libzfs_handle): New global variable.
[HAVE_LIBZFS] (fini_libzfs): New static function.
(grub_util_init_libzfs): New function.
* util/grub-probe.c (main): Call grub_util_init_libzfs().
2010-07-30 Robert Millan <rmh@gnu.org>
* include/grub/emu/misc.h (grub_make_system_path_relative_to_its_root)
(xmalloc, xrealloc, xstrdup, xasprintf): Add
`warn_unused_result' attribute.
* include/grub/misc.h (grub_strdup, grub_strndup, grub_strlen)
(grub_xasprintf, grub_xvasprintf): Likewise.
* include/grub/emu/misc.h (xasprintf): Remove duplicate prototype.
2010-07-29 Robert Millan <rmh@gnu.org>
* util/grub-probe.c (PRINT_FS_LABEL): New enum value.
(probe): Handle `PRINT_FS_LABEL'.
(main): Handle `-t fs_label'.
2010-07-29 Robert Millan <rmh@gnu.org>
* configure.ac: Remove grub-mkisofs checks.
2010-07-28 Vladimir Serbinenko <phcoder@gmail.com>
* util/ieee1275/grub-install.in: Don't use empty grub_device.
Reported by: Lennart Sorensen.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub.d/00_header.in: Remove compatibility with terminal.mod
prior to terminal_input/terminal_output separation. It's been over 1.5
years and those versions weren't widely deployed.
2010-07-22 Colin Watson <cjwatson@ubuntu.com>
* disk/raid.c (insert_array): Don't count named arrays when looking
for unused array numbers.
Reported and tested by: Michael Guntsche.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* bus/usb/emu/usb.c (grub_usb_poll_devices): Add a dummy
implementation of this so that grub-emu links again, with a note
that this should support hotplugging in the future.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* kern/emu/getroot.c (grub_util_get_grub_dev): Use xasprintf.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* disk/loopback.c (grub_cmd_loopback): Don't leak a grub_file_t
handle on failure.
(grub_loopback_close): Remove empty function.
(grub_loopback_dev): Remove close method.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
Disable EFI cursor when the EFI console becomes inactive.
* term/efi/console.c (grub_efi_console_init): New function.
(grub_efi_console_fini): New function.
(grub_console_term_output): Register init and fini methods.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* tests/util/grub-shell-tester.in: Remove bashism and declare as
sh script.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* disk/loopback.c (grub_loopback): Replace filename with file.
(delete_loopback): Handle new semantics.
(grub_cmd_loopback): Likewise.
(grub_loopback_iterate): Likewise.
(grub_loopback_close): Likewise.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* util/i386/efi/grub-install.in: Revert to platform-specific behaviour
with -p "".
Reported by: Tito Keitel.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* docs/grub.texi (Naming convention): Document new naming convention.
2010-07-20 Vadim Solomin <vadic052@gmail.com>
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
Generate device.map in something closer to the old ordering.
* util/deviceiter.c (struct device): New declaration.
(compare_file_names): Rename to ...
(compare_devices): ... this. Sort by kernel name in preference to
the stable by-id name, but keep the latter as a fallback comparison.
Update header comment.
(grub_util_iterate_devices) [__linux__]: Construct and sort an array
of `struct device' rather than of plain file names.
2010-07-20 Thomas Frauendorfer <Thomas.Frauendorfer@googlemail.com>
* lib/i386/relocator_asm.S [! __x86_64__]: Don't try to disable amd64
on i386.
2010-07-20 Vladimir Serbinenko <phcoder@gmail.com>
* commands/acpi.c (setup_common_tables): Use sizeof instead of
hardcoding size.
(setv1table): Likewise.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* disk/raid.c (insert_array): Use md/%s to name mdadm 1.x devices,
removing the homehost if present.
* kern/emu/getroot.c (get_mdadm_name) [__linux__]: New function.
(grub_util_get_grub_dev): Use md/%s to name mdadm 1.x devices,
removing the homehost if present.
(grub_util_get_grub_dev) [__linux__]: Get the array name from mdadm
if possible.
* util/i386/pc/grub-setup.c (main): Handle md/* devices.
* disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Add start_sector
parameter. Set its pointer target to 0.
* disk/mdraid_linux.c (grub_mdraid_detect): Add start_sector
parameter. Set its pointer target to 0 for 0.9 metadata, or to the
`data_offset' value from the superblock for 1.x metadata.
* disk/raid.c (grub_raid_read): Offset reads by the start sector of
data on the device.
(insert_array): Record the start sector of data on the device.
(grub_raid_register): Pass start_sector parameters to
grub_raid_list->detect and insert_array.
* include/grub/raid.h (struct grub_raid_array): Add start_sector
member.
(struct grub_raid): Add start_sector parameter to `detect'.
* disk/mdraid_linux.c (struct grub_raid_super_1x): Remove
__attribute__ ((packed)), leaving a comment.
(grub_mdraid_detect): Split out 0.9 and 1.x detection to ...
(grub_mdraid_detect_09): ... here and ...
(grub_mdraid_detect_1x): ... here.
2010-07-20 Peter Henn <peter.henn@web.de>
* disk/mdraid_linux.c (grub_mdraid_detect): Fix calculation of 1.x
chunk size and disk size, which are already given as sector counts
as distinct from the 0.90 units. Fetch the correct device number
from the role table instead of using the table index.
2010-07-20 Felix Zielcke <fzielcke@z-51.de>
* disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Set array->name to NULL.
* disk/mdraid_linux.c (grub_raid_super_1x): New structure.
(WriteMostly1): New macro.
Set array->name to NULL for metadata format 0.90. Add support for
metadata 1.x. Fix some comments.
* disk/raid.c (): Add support for name based RAID arrays. Fix a
few comments.
* util/getroot.c (grub_util_get_grub_dev): Add support for
/dev/md/name style devices.
2010-07-20 Colin Watson <cjwatson@ubuntu.com>
* .bzrignore: Ignore 20_linux_xen.
2010-07-17 Colin Watson <cjwatson@ubuntu.com>
* util/import_unicode.py: Remove unnecessary imports.
2010-07-17 Aleš Nesrsta <starous@volny.cz>
Hotplugging and USB hub support.
* bus/usb/ohci.c (grub_ohci_td): Add convenience fields.
(grub_ohci): Likewise.
(GRUB_OHCI_REG_CONTROL_BULK_ENABLE): New definition.
(GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE): Likewise.
(GRUB_OHCI_RESET_CONNECT_CHANGE): Likewise.
(GRUB_OHCI_CTRL_EDS): Likewise.
(GRUB_OHCI_BULK_EDS): Likewise.
(GRUB_OHCI_TDS): Likewise.
(GRUB_OHCI_ED_ADDR_MASK): Likewise.
(grub_ohci_ed_phys2virt): New function.
(grub_ohci_virt_to_phys): Likewise.
(grub_ohci_td_phys2virt): Likewise.
(grub_ohci_td_virt2phys): Likewise.
(grub_ohci_pci_iter): Allocate memory and don't wait for stable
attachment.
(grub_ohci_find_ed): New function.
(grub_ohci_alloc_td): Likewise.
(grub_ohci_free_td): Likewise.
(grub_ohci_free_tds): Likewise.
(grub_ohci_transfer): Use previously allocated memory.
(grub_ohci_portstatus): Reset status changed bit.
(grub_ohci_detect_dev): Supply status changed.
(grub_ohci_fini_hw): Free memory.
(grub_ohci_restore_hw): Reallocate memory.
* bus/usb/uhci.c (grub_uhci_portstatus): Don't reset on disable.
Reset status change.
(grub_uhci_detect_dev): Supply status_change.
* bus/usb/usb.c (attach_hooks): New var.
(grub_usb_device_attach): New function.
(grub_usb_register_attach_hook_class): Likewise.
(grub_usb_unregister_attach_hook_class): Likewise.
* bus/usb/usbhub.c (grub_usb_hub_add_dev): Handle errors correctly.
(grub_usb_add_hub): Reset connection changed bit.
(attach_root_port): New function.
(grub_usb_root_hub): Likewise.
(poll_nonroot_hub): Likewise.
(grub_usb_poll_devices): Likewise.
* commands/usbtest.c (grub_cmd_usbtest): Poll devices before listing.
* disk/usbms.c (grub_usbms_open): Use device hooks.
(grub_usbms_iterate) :Poll devices.
(grub_usbms_finddevs): Split into ...
(grub_usbms_attach): ... this ...
(grub_usbms_attach): ... and this.
* include/grub/usb.h (grub_usb_controller_dev): Supply status_changed
in detect_dev.
(grub_usb_interface): New fields attached and detach_hook.
(grub_usb_attach_hook_class): New type.
(grub_usb_attach_desc): New struct.
(grub_usb_register_attach_hook_class): New function.
(grub_usb_unregister_attach_hook_class): Likewise.
(grub_usb_poll_devices): Likewise.
(grub_usb_device_attach): Likewise.
* include/grub/usbtrans.h (GRUB_USB_HUB_FEATURE_C_CONNECTED): New const.
(GRUB_USB_HUB_STATUS_C_CONNECTED): Likewise.
2010-07-17 Vladimir Serbinenko <phcoder@gmail.com> 2010-07-17 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/bsdlabel.h (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION): New definition. * include/grub/bsdlabel.h (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION): New definition.

View file

@ -20,7 +20,8 @@
#include <grub/mips/yeeloong/pci.h> #include <grub/mips/yeeloong/pci.h>
#include <grub/mips/loongson.h> #include <grub/mips/loongson.h>
#include <grub/pci.h> #include <grub/pci.h>
#include <grub/serial.h> #include <grub/machine/serial.h>
#include <grub/ns8250.h>
#include <grub/cs5536.h> #include <grub/cs5536.h>
#include <grub/smbus.h> #include <grub/smbus.h>

View file

@ -78,6 +78,12 @@ grub_libusb_devices (void)
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
void
grub_usb_poll_devices (void)
{
/* TODO: recheck grub_usb_devs */
}
int int
grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) grub_usb_iterate (int (*hook) (grub_usb_device_t dev))

View file

@ -459,7 +459,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
grub_dma_free (o->hcca_chunk); grub_dma_free (o->hcca_chunk);
grub_free (o); grub_free (o);
return 1; return 0;
} }

View file

@ -325,7 +325,8 @@ setup_common_tables (void)
/* If it's FADT correct DSDT and FACS addresses. */ /* If it's FADT correct DSDT and FACS addresses. */
fadt = (struct grub_acpi_fadt *) cur->addr; fadt = (struct grub_acpi_fadt *) cur->addr;
if (grub_memcmp (fadt->hdr.signature, "FACP", 4) == 0) if (grub_memcmp (fadt->hdr.signature, "FACP",
sizeof (fadt->hdr.signature)) == 0)
{ {
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
fadt->facs_addr = facs_addr; fadt->facs_addr = facs_addr;
@ -357,10 +358,10 @@ setup_common_tables (void)
grub_memcpy (&(rsdt->signature), "RSDT", 4); grub_memcpy (&(rsdt->signature), "RSDT", 4);
rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables; rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables;
rsdt->revision = 1; rsdt->revision = 1;
grub_memcpy (&(rsdt->oemid), root_oemid, 6); grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid));
grub_memcpy (&(rsdt->oemtable), root_oemtable, 4); grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable));
rsdt->oemrev = root_oemrev; rsdt->oemrev = root_oemrev;
grub_memcpy (&(rsdt->creator_id), root_creator_id, 6); grub_memcpy (&(rsdt->creator_id), root_creator_id, sizeof (rsdt->creator_id));
rsdt->creator_rev = root_creator_rev; rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next) for (cur = acpi_tables; cur; cur = cur->next)
@ -378,7 +379,8 @@ setv1table (void)
/* Create RSDP. */ /* Create RSDP. */
rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr; rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr;
playground_ptr += sizeof (struct grub_acpi_rsdp_v10); playground_ptr += sizeof (struct grub_acpi_rsdp_v10);
grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", 8); grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ",
sizeof (rsdpv1_new->signature));
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
rsdpv1_new->revision = 0; rsdpv1_new->revision = 0;
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr); rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);

View file

@ -27,7 +27,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \
video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \ video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \
video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \ video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \
term/gfxterm.c commands/extcmd.c lib/arg.c \ term/gfxterm.c commands/extcmd.c lib/arg.c \
bus/cs5536.c term/serial.c term/terminfo.c term/tparm.c \ bus/cs5536.c term/serial.c term/ns8250.c term/terminfo.c term/tparm.c \
symlist.c symlist.c
kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK
kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS)

View file

@ -246,15 +246,9 @@ else
AC_PATH_PROG(HELP2MAN, help2man) AC_PATH_PROG(HELP2MAN, help2man)
fi fi
# Check for functions. # Check for functions and headers.
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat)
AC_CHECK_HEADERS(libzfs.h libnvpair.h)
# For grub-mkisofs
AC_HEADER_MAJOR
AC_HEADER_DIRENT
AC_CHECK_FUNCS(memmove sbrk strdup lstat getuid getgid)
AC_CHECK_HEADERS(sys/mkdev.h sys/sysmacros.h malloc.h termios.h sys/types.h)
AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h limits.h)
# For opendisk() and getrawpartition() on NetBSD. # For opendisk() and getrawpartition() on NetBSD.
# Used in util/deviceiter.c and in util/hostdisk.c. # Used in util/deviceiter.c and in util/hostdisk.c.
@ -806,6 +800,15 @@ if test x"$device_mapper_excuse" = x ; then
[device_mapper_excuse="need devmapper library"]) [device_mapper_excuse="need devmapper library"])
fi fi
AC_CHECK_LIB([zfs], [libzfs_init],
[LDFLAGS="$LDFLAGS -lzfs"
AC_DEFINE([HAVE_LIBZFS], [1],
[Define to 1 if you have the ZFS library.])],)
AC_CHECK_LIB([nvpair], [nvlist_print],
[LDFLAGS="$LDFLAGS -lnvpair"
AC_DEFINE([HAVE_LIBNVPAIR], [1],
[Define to 1 if you have the NVPAIR library.])],)
AC_SUBST(ASFLAGS) AC_SUBST(ASFLAGS)
# Output files. # Output files.

View file

@ -89,7 +89,8 @@ struct grub_nv_super
} __attribute__ ((packed)); } __attribute__ ((packed));
static grub_err_t static grub_err_t
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array) grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{ {
grub_disk_addr_t sector; grub_disk_addr_t sector;
struct grub_nv_super sb; struct grub_nv_super sb;
@ -132,6 +133,7 @@ grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
"unsupported RAID level: %d", sb.array.raid_level); "unsupported RAID level: %d", sb.array.raid_level);
} }
array->name = NULL;
array->number = 0; array->number = 0;
array->total_devs = sb.array.total_volumes; array->total_devs = sb.array.total_volumes;
array->chunk_size = sb.array.stripe_block_size; array->chunk_size = sb.array.stripe_block_size;
@ -144,6 +146,8 @@ grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
grub_memcpy (array->uuid, (char *) &sb.array.signature, grub_memcpy (array->uuid, (char *) &sb.array.signature,
sizeof (sb.array.signature)); sizeof (sb.array.signature));
*start_sector = 0;
return 0; return 0;
} }

View file

@ -28,7 +28,7 @@
struct grub_loopback struct grub_loopback
{ {
char *devname; char *devname;
char *filename; grub_file_t file;
int has_partitions; int has_partitions;
struct grub_loopback *next; struct grub_loopback *next;
}; };
@ -63,7 +63,7 @@ delete_loopback (const char *name)
*prev = dev->next; *prev = dev->next;
grub_free (dev->devname); grub_free (dev->devname);
grub_free (dev->filename); grub_file_close (dev->file);
grub_free (dev); grub_free (dev);
return 0; return 0;
@ -76,6 +76,7 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
struct grub_arg_list *state = state = cmd->state; struct grub_arg_list *state = state = cmd->state;
grub_file_t file; grub_file_t file;
struct grub_loopback *newdev; struct grub_loopback *newdev;
grub_err_t ret;
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
@ -91,9 +92,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
if (! file) if (! file)
return grub_errno; return grub_errno;
/* Close the file, the only reason for opening it is validation. */
grub_file_close (file);
/* First try to replace the old device. */ /* First try to replace the old device. */
for (newdev = loopback_list; newdev; newdev = newdev->next) for (newdev = loopback_list; newdev; newdev = newdev->next)
if (grub_strcmp (newdev->devname, args[0]) == 0) if (grub_strcmp (newdev->devname, args[0]) == 0)
@ -103,10 +101,10 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
{ {
char *newname = grub_strdup (args[1]); char *newname = grub_strdup (args[1]);
if (! newname) if (! newname)
return grub_errno; goto fail;
grub_free (newdev->filename); grub_file_close (newdev->file);
newdev->filename = newname; newdev->file = file;
/* Set has_partitions when `--partitions' was used. */ /* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set; newdev->has_partitions = state[1].set;
@ -117,22 +115,16 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
/* Unable to replace it, make a new entry. */ /* Unable to replace it, make a new entry. */
newdev = grub_malloc (sizeof (struct grub_loopback)); newdev = grub_malloc (sizeof (struct grub_loopback));
if (! newdev) if (! newdev)
return grub_errno; goto fail;
newdev->devname = grub_strdup (args[0]); newdev->devname = grub_strdup (args[0]);
if (! newdev->devname) if (! newdev->devname)
{ {
grub_free (newdev); grub_free (newdev);
return grub_errno; goto fail;
} }
newdev->filename = grub_strdup (args[1]); newdev->file = file;
if (! newdev->filename)
{
grub_free (newdev->devname);
grub_free (newdev);
return grub_errno;
}
/* Set has_partitions when `--partitions' was used. */ /* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set; newdev->has_partitions = state[1].set;
@ -142,6 +134,11 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
loopback_list = newdev; loopback_list = newdev;
return 0; return 0;
fail:
ret = grub_errno;
grub_file_close (file);
return ret;
} }
@ -160,7 +157,6 @@ grub_loopback_iterate (int (*hook) (const char *name))
static grub_err_t static grub_err_t
grub_loopback_open (const char *name, grub_disk_t disk) grub_loopback_open (const char *name, grub_disk_t disk)
{ {
grub_file_t file;
struct grub_loopback *dev; struct grub_loopback *dev;
for (dev = loopback_list; dev; dev = dev->next) for (dev = loopback_list; dev; dev = dev->next)
@ -170,29 +166,17 @@ grub_loopback_open (const char *name, grub_disk_t disk)
if (! dev) if (! dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
file = grub_file_open (dev->filename);
if (! file)
return grub_errno;
/* Use the filesize for the disk size, round up to a complete sector. */ /* Use the filesize for the disk size, round up to a complete sector. */
disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1) disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
/ GRUB_DISK_SECTOR_SIZE); / GRUB_DISK_SECTOR_SIZE);
disk->id = (unsigned long) dev; disk->id = (unsigned long) dev;
disk->has_partitions = dev->has_partitions; disk->has_partitions = dev->has_partitions;
disk->data = file; disk->data = dev->file;
return 0; return 0;
} }
static void
grub_loopback_close (grub_disk_t disk)
{
grub_file_t file = (grub_file_t) disk->data;
grub_file_close (file);
}
static grub_err_t static grub_err_t
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf) grub_size_t size, char *buf)
@ -234,7 +218,6 @@ static struct grub_disk_dev grub_loopback_dev =
.id = GRUB_DISK_DEVICE_LOOPBACK_ID, .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
.iterate = grub_loopback_iterate, .iterate = grub_loopback_iterate,
.open = grub_loopback_open, .open = grub_loopback_open,
.close = grub_loopback_close,
.read = grub_loopback_read, .read = grub_loopback_read,
.write = grub_loopback_write, .write = grub_loopback_write,
.next = 0 .next = 0

View file

@ -1,7 +1,7 @@
/* mdraid_linux.c - module to handle linux softraid. */ /* mdraid_linux.c - module to handle Linux Software RAID. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc. * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -159,63 +159,254 @@ struct grub_raid_super_09
struct grub_raid_disk_09 this_disk; struct grub_raid_disk_09 this_disk;
} __attribute__ ((packed)); } __attribute__ ((packed));
static grub_err_t /*
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array) * The version-1 superblock :
* All numeric fields are little-endian.
*
* Total size: 256 bytes plus 2 per device.
* 1K allows 384 devices.
*/
struct grub_raid_super_1x
{
/* Constant array information - 128 bytes. */
grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
grub_uint32_t major_version; /* 1. */
grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */
grub_uint32_t pad0; /* Always set to 0 when writing. */
grub_uint8_t set_uuid[16]; /* User-space generated. */
char set_name[32]; /* Set and interpreted by user-space. */
grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */
grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */
grub_uint32_t layout; /* only for raid5 and raid10 currently. */
grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */
grub_uint32_t chunksize; /* In 512byte sectors. */
grub_uint32_t raid_disks;
grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
/* These are only valid with feature bit '4'. */
grub_uint32_t new_level; /* New level we are reshaping to. */
grub_uint64_t reshape_position; /* Next address in array-space for reshape. */
grub_uint32_t delta_disks; /* Change in number of raid_disks. */
grub_uint32_t new_layout; /* New layout. */
grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */
grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */
/* Constant this-device information - 64 bytes. */
grub_uint64_t data_offset; /* Sector start of data, often 0. */
grub_uint64_t data_size; /* Sectors in this device that can be used for data. */
grub_uint64_t super_offset; /* Sector start of this superblock. */
grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */
grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */
grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */
grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */
grub_uint8_t devflags; /* Per-device flags. Only one defined... */
grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */
/* Array state information - 64 bytes. */
grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */
grub_uint64_t events; /* Incremented when superblock updated. */
grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */
grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */
grub_uint32_t max_dev; /* Size of devs[] array to consider. */
grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */
/* Device state information. Indexed by dev_number.
* 2 bytes per device.
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */
};
/* Could be __attribute__ ((packed)), but since all members in this struct
are already appropriately aligned, we can omit this and avoid suboptimal
assembly in some cases. */
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
static grub_err_t
grub_mdraid_detect_09 (grub_disk_addr_t sector,
struct grub_raid_super_09 *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{ {
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_09 sb;
grub_uint32_t *uuid; grub_uint32_t *uuid;
/* The sector where the RAID superblock is stored, if available. */ if (sb->major_version != 0 || sb->minor_version != 90)
size = grub_disk_get_size (disk);
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
return grub_errno;
/* Look whether there is a RAID superblock. */
if (sb.md_magic != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
/* FIXME: Also support version 1.0. */
if (sb.major_version != 0 || sb.minor_version != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d", "unsupported RAID version: %d.%d",
sb.major_version, sb.minor_version); sb->major_version, sb->minor_version);
/* FIXME: Check the checksum. */ /* FIXME: Check the checksum. */
/* Multipath. */ /* Multipath. */
if ((int) sb.level == -4) if ((int) sb->level == -4)
sb.level = 1; sb->level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 && if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10) sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level); "unsupported RAID level: %d", sb->level);
array->number = sb.md_minor; array->name = NULL;
array->level = sb.level; array->number = sb->md_minor;
array->layout = sb.layout; array->level = sb->level;
array->total_devs = sb.raid_disks; array->layout = sb->layout;
array->disk_size = (sb.size) ? sb.size * 2 : sector; array->total_devs = sb->raid_disks;
array->chunk_size = sb.chunk_size >> 9; array->disk_size = (sb->size) ? sb->size * 2 : sector;
array->index = sb.this_disk.number; array->chunk_size = sb->chunk_size >> 9;
array->index = sb->this_disk.number;
array->uuid_len = 16; array->uuid_len = 16;
array->uuid = grub_malloc (16); array->uuid = grub_malloc (16);
if (!array->uuid) if (!array->uuid)
return grub_errno; return grub_errno;
uuid = (grub_uint32_t *) array->uuid; uuid = (grub_uint32_t *) array->uuid;
uuid[0] = sb.set_uuid0; uuid[0] = sb->set_uuid0;
uuid[1] = sb.set_uuid1; uuid[1] = sb->set_uuid1;
uuid[2] = sb.set_uuid2; uuid[2] = sb->set_uuid2;
uuid[3] = sb.set_uuid3; uuid[3] = sb->set_uuid3;
*start_sector = 0;
return 0; return 0;
} }
static grub_err_t
grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector,
struct grub_raid_super_1x *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
if (sb->major_version != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb->major_version);
/* Multipath. */
if ((int) sb->level == -4)
sb->level = 1;
if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb->level);
/* 1.x superblocks don't have a fixed size on disk. So we have to
read it again now that we now the max device count. */
sb_size = sizeof (struct grub_raid_super_1x) + 2 * grub_le_to_cpu32 (sb->max_dev);
real_sb = grub_malloc (sb_size);
if (! real_sb)
return grub_errno;
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
{
grub_free (real_sb);
return grub_errno;
}
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
grub_free (real_sb);
return grub_errno;
}
array->number = 0;
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
else
array->index = 0xffff; /* disk will be later not used! */
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
{
grub_free (real_sb);
return grub_errno;
}
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
grub_free (real_sb);
return 0;
}
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_09 sb_09;
struct grub_raid_super_1x sb_1x;
grub_uint8_t minor_version;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb_09))
return grub_errno;
/* Look whether there is a mdraid 0.90 superblock. */
if (sb_09.md_magic == SB_MAGIC)
return grub_mdraid_detect_09 (sector, &sb_09, array, start_sector);
/* Check for an 1.x superblock.
* It's always aligned to a 4K boundary
* and depending on the minor version it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
for (minor_version = 0; minor_version < 3; ++minor_version)
{
switch (minor_version)
{
case 0:
sector = (size - 8 * 2) & ~(4 * 2 - 1);
break;
case 1:
sector = 0;
break;
case 2:
sector = 4 * 2;
break;
}
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
&sb_1x))
return grub_errno;
if (sb_1x.magic == SB_MAGIC)
return grub_mdraid_detect_1x (disk, sector, &sb_1x, array,
start_sector);
}
/* Neither 0.90 nor 1.x. */
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
}
static struct grub_raid grub_mdraid_dev = { static struct grub_raid grub_mdraid_dev = {
.name = "mdraid", .name = "mdraid",
.detect = grub_mdraid_detect, .detect = grub_mdraid_detect,

View file

@ -1,7 +1,7 @@
/* raid.c - module to read RAID arrays. */ /* raid.c - module to read RAID arrays. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -254,6 +254,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[k], err = grub_disk_read (array->device[k],
array->start_sector[k] +
read_sector + j * far_ofs + b, read_sector + j * far_ofs + b,
0, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
@ -366,6 +367,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[disknr], err = grub_disk_read (array->device[disknr],
array->start_sector[disknr] +
read_sector + b, 0, read_sector + b, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
buf); buf);
@ -475,7 +477,7 @@ grub_raid_write (grub_disk_t disk __attribute ((unused)),
static grub_err_t static grub_err_t
insert_array (grub_disk_t disk, struct grub_raid_array *new_array, insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
const char *scanner_name) grub_disk_addr_t start_sector, const char *scanner_name)
{ {
struct grub_raid_array *array = 0, *p; struct grub_raid_array *array = 0, *p;
@ -524,24 +526,27 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
*array = *new_array; *array = *new_array;
array->nr_devs = 0; array->nr_devs = 0;
grub_memset (&array->device, 0, sizeof (array->device)); grub_memset (&array->device, 0, sizeof (array->device));
grub_memset (&array->start_sector, 0, sizeof (array->start_sector));
if (array->name)
goto skip_duplicate_check;
/* Check whether we don't have multiple arrays with the same number. */ /* Check whether we don't have multiple arrays with the same number. */
for (p = array_list; p != NULL; p = p->next) for (p = array_list; p != NULL; p = p->next)
{ {
if (p->number == array->number) if (! p->name && p->number == array->number)
break; break;
} }
if (p) if (p)
{ {
/* The number is already in use, so we need to find an new number. */ /* The number is already in use, so we need to find a new one. */
int i = 0; int i = 0;
while (1) while (1)
{ {
for (p = array_list; p != NULL; p = p->next) for (p = array_list; p != NULL; p = p->next)
{ {
if (p->number == i) if (! p->name && p->number == i)
break; break;
} }
@ -555,7 +560,11 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
i++; i++;
} }
} }
skip_duplicate_check:
/* mdraid 1.x superblocks have only a name stored not a number.
Use it directly as GRUB device. */
if (! array->name)
{
array->name = grub_xasprintf ("md%d", array->number); array->name = grub_xasprintf ("md%d", array->number);
if (! array->name) if (! array->name)
{ {
@ -564,6 +573,25 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
return grub_errno; return grub_errno;
} }
}
else
{
/* Strip off the homehost if present. */
char *colon = grub_strchr (array->name, ':');
char *new_name = grub_xasprintf ("md/%s",
colon ? colon + 1 : array->name);
if (! new_name)
{
grub_free (array->uuid);
grub_free (array);
return grub_errno;
}
grub_free (array->name);
array->name = new_name;
}
grub_dprintf ("raid", "Found array %s (%s)\n", array->name, grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name); scanner_name);
@ -580,6 +608,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* Add the device to the array. */ /* Add the device to the array. */
array->device[new_array->index] = disk; array->device[new_array->index] = disk;
array->start_sector[new_array->index] = start_sector;
array->nr_devs++; array->nr_devs++;
return 0; return 0;
@ -621,6 +650,7 @@ grub_raid_register (grub_raid_t raid)
{ {
grub_disk_t disk; grub_disk_t disk;
struct grub_raid_array array; struct grub_raid_array array;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name); grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name);
@ -629,8 +659,8 @@ grub_raid_register (grub_raid_t raid)
return 0; return 0;
if ((disk->total_sectors != GRUB_ULONG_MAX) && if ((disk->total_sectors != GRUB_ULONG_MAX) &&
(! grub_raid_list->detect (disk, &array)) && (! grub_raid_list->detect (disk, &array, &start_sector)) &&
(! insert_array (disk, &array, grub_raid_list->name))) (! insert_array (disk, &array, start_sector, grub_raid_list->name)))
return 0; return 0;
/* This error usually means it's not raid, no need to display /* This error usually means it's not raid, no need to display

View file

@ -444,12 +444,13 @@ disk. The number @samp{0} is the drive number, which is counted from
disk. disk.
@example @example
(hd0,2) (hd0,msdos2)
@end example @end example
Here, @samp{hd} means it is a hard disk drive. The first integer Here, @samp{hd} means it is a hard disk drive. The first integer
@samp{0} indicates the drive number, that is, the first hard disk, while @samp{0} indicates the drive number, that is, the first hard disk,
the second integer, @samp{1}, indicates the partition number (or the the string @samp{msdos} indicates the partition scheme, while
the second integer, @samp{2}, indicates the partition number (or the
@sc{pc} slice number in the BSD terminology). The partition numbers are @sc{pc} slice number in the BSD terminology). The partition numbers are
counted from @emph{one}, not from zero (as was the case in previous counted from @emph{one}, not from zero (as was the case in previous
versions of GRUB). This expression means the second partition of the versions of GRUB). This expression means the second partition of the
@ -457,7 +458,7 @@ first hard disk drive. In this case, GRUB uses one partition of the
disk, instead of the whole disk. disk, instead of the whole disk.
@example @example
(hd0,5) (hd0,msdos5)
@end example @end example
This specifies the first @dfn{extended partition} of the first hard disk This specifies the first @dfn{extended partition} of the first hard disk
@ -466,18 +467,15 @@ counted from @samp{5}, regardless of the actual number of primary
partitions on your hard disk. partitions on your hard disk.
@example @example
(hd1,a) (hd1,msdos1,bsd1)
@end example @end example
This means the BSD @samp{a} partition of the second hard disk. If you This means the BSD @samp{a} partition on first @sc{pc} slice number
need to specify which @sc{pc} slice number should be used, use something of the second hard disk.
like this: @samp{(hd1,1,a)}. If the @sc{pc} slice number is omitted,
GRUB searches for the first @sc{pc} slice which has a BSD @samp{a}
partition.
Of course, to actually access the disks or partitions with GRUB, you Of course, to actually access the disks or partitions with GRUB, you
need to use the device specification in a command, like @samp{set need to use the device specification in a command, like @samp{set
root=(fd0)} or @samp{parttool (hd0,3) hidden-}. To help you find out root=(fd0)} or @samp{parttool (hd0,msdos3) hidden-}. To help you find out
which number specifies a partition you want, the GRUB command-line which number specifies a partition you want, the GRUB command-line
(@pxref{Command-line interface}) options have argument (@pxref{Command-line interface}) options have argument
completion. This means that, for example, you only need to type completion. This means that, for example, you only need to type
@ -501,7 +499,7 @@ Now the question is, how to specify a file? Again, consider an
example: example:
@example @example
(hd0,1)/vmlinuz (hd0,msdos1)/vmlinuz
@end example @end example
This specifies the file named @samp{vmlinuz}, found on the first This specifies the file named @samp{vmlinuz}, found on the first
@ -1064,6 +1062,11 @@ only to the default menu entry, after those listed in
As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for
NetBSD. NetBSD.
@item GRUB_CMDLINE_XEN
@itemx GRUB_CMDLINE_XEN_DEFAULT
As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for
Linux and Xen.
@item GRUB_DISABLE_LINUX_UUID @item GRUB_DISABLE_LINUX_UUID
Normally, @command{grub-mkconfig} will generate menu entries that use Normally, @command{grub-mkconfig} will generate menu entries that use
universally-unique identifiers (UUIDs) to identify the root filesystem to universally-unique identifiers (UUIDs) to identify the root filesystem to
@ -1115,8 +1118,8 @@ try several modes in sequence.
Depending on your kernel, your distribution, your graphics card, and the Depending on your kernel, your distribution, your graphics card, and the
phase of the moon, note that using this option may cause GNU/Linux to suffer phase of the moon, note that using this option may cause GNU/Linux to suffer
from various display problems, particularly during the early part of the from various display problems, particularly during the early part of the
boot sequence. If you have problems, simply unset this option and GRUB will boot sequence. If you have problems, set this option to @samp{text} and
tell Linux to boot in normal text mode. GRUB will tell Linux to boot in normal text mode.
@item GRUB_DISABLE_OS_PROBER @item GRUB_DISABLE_OS_PROBER
Normally, @command{grub-mkconfig} will try to use the external Normally, @command{grub-mkconfig} will try to use the external
@ -1145,6 +1148,142 @@ that file, making sure to leave at least the first two lines intact.
@node Shell-like scripting @node Shell-like scripting
@section Writing full configuration files directly @section Writing full configuration files directly
@c Some of this section is derived from the GNU Bash manual page, also
@c copyrighted by the FSF.
@file{grub.cfg} is written in GRUB's built-in scripting language, which has
a syntax quite similar to that of GNU Bash and other Bourne shell
derivatives.
@heading Words
A @dfn{word} is a sequence of characters considered as a single unit by
GRUB. Words are separated by @dfn{metacharacters}, which are the following
plus space, tab, and newline:
@example
@{ @} | & $ ; < >
@end example
Quoting may be used to include metacharacters in words; see below.
@heading Reserved words
Reserved words have a special meaning to GRUB. The following words are
recognised as reserved when unquoted and either the first word of a simple
command or the third word of a @code{for} command:
@example
! [[ ]] @{ @}
case do done elif else esac fi for function
if in menuentry select then time until while
@end example
Not all of these reserved words have a useful purpose yet; some are reserved
for future expansion.
@heading Quoting
Quoting is used to remove the special meaning of certain characters or
words. It can be used to treat metacharacters as part of a word, to prevent
reserved words from being recognised as such, and to prevent variable
expansion.
There are three quoting mechanisms: the escape character, single quotes, and
double quotes.
A non-quoted backslash (\) is the @dfn{escape character}. It preserves the
literal value of the next character that follows, with the exception of
newline.
Enclosing characters in single quotes preserves the literal value of each
character within the quotes. A single quote may not occur between single
quotes, even when preceded by a backslash.
Enclosing characters in double quotes preserves the literal value of all
characters within the quotes, with the exception of @samp{$} and @samp{\}.
The @samp{$} character retains its special meaning within double quotes.
The backslash retains its special meaning only when followed by one of the
following characters: @samp{$}, @samp{"}, @samp{\}, or newline. A
backslash-newline pair is treated as a line continuation (that is, it is
removed from the input stream and effectively ignored). A double quote may
be quoted within double quotes by preceding it with a backslash.
@heading Variable expansion
The @samp{$} character introduces variable expansion. The variable name to
be expanded may be enclosed in braces, which are optional but serve to
protect the variable to be expanded from characters immediately following it
which could be interpreted as part of the name.
Normal variable names begin with an alphabetic character, followed by zero
or more alphanumeric characters.
Positional variable names consist of one or more digits. These are reserved
for future expansion.
The special variable name @samp{?} expands to the exit status of the most
recently executed command.
@heading Comments
A word beginning with @samp{#} causes that word and all remaining characters
on that line to be ignored.
@heading Simple commands
A @dfn{simple command} is a sequence of words separated by spaces or tabs
and terminated by a semicolon or a newline. The first word specifies the
command to be executed. The remaining words are passed as arguments to the
invoked command.
The return value of a simple command is its exit status.
@heading Compound commands
A @dfn{compound command} is one of the following:
@table @asis
@item for @var{name} in @var{word} @dots{}; do @var{list}; done
The list of words following @code{in} is expanded, generating a list of
items. The variable @var{name} is set to each element of this list in turn,
and @var{list} is executed each time. The return value is the exit status
of the last command that executes. If the expansion of the items following
@code{in} results in an empty list, no commands are executed, and the return
status is 0.
@item if @var{list}; then @var{list}; [elif @var{list}; then @var{list};] @dots{} [else @var{list};] fi
The @code{if} @var{list} is executed. If its exit status is zero, the
@code{then} @var{list} is executed. Otherwise, each @code{elif} @var{list}
is executed in turn, and if its exit status is zero, the corresponding
@code{then} @var{list} is executed and the command completes. Otherwise,
the @code{else} @var{list} is executed, if present. The exit status is the
exit status of the last command executed, or zero if no condition tested
true.
@item while @var{cond}; do @var{list}; done
@itemx until @var{cond}; do @var{list}; done
The @code{while} command continuously executes the @code{do} @var{list} as
long as the last command in @var{cond} returns an exit status of zero. The
@code{until} command is identical to the @code{while} command, except that
the test is negated; the @code{do} @var{list} is executed as long as the
last command in @var{cond} returns a non-zero exit status. The exit status
of the @code{while} and @code{until} commands is the exit status of the last
@code{do} @var{list} command executed, or zero if none was executed.
@item function @var{name} @{ @var{command}; @dots{} @}
This defines a function named @var{name}. The @dfn{body} of the function is
the list of commands within braces, each of which must be terminated with a
semicolon or a newline. This list of commands will be executed whenever
@var{name} is specified as the name of a simple command. Function
definitions do not affect the exit status in @code{$?}. When executed, the
exit status of a function is the exit status of the last command executed in
the body.
@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--hotkey=key}] @{ @var{command}; @dots{} @}
@xref{menuentry}.
@end table
@node Embedded configuration @node Embedded configuration
@section Embedding a configuration file into GRUB @section Embedding a configuration file into GRUB
@ -1310,8 +1449,7 @@ simple. Here is an example:
@example @example
@group @group
grub> @kbd{serial --unit=0 --speed=9600} grub> @kbd{serial --unit=0 --speed=9600}
grub> @kbd{terminal_input serial} grub> @kbd{terminal_input serial; terminal_output serial}
grub> @kbd{terminal_output serial}
@end group @end group
@end example @end example
@ -1322,11 +1460,14 @@ command accepts many other options, so please refer to @ref{serial},
for more details. for more details.
The commands @command{terminal_input} (@pxref{terminal_input}) and The commands @command{terminal_input} (@pxref{terminal_input}) and
@command{terminal_output} (@pxref{terminal_output} choose which type of @command{terminal_output} (@pxref{terminal_output}) choose which type of
terminal you want to use. In the case above, the terminal will be a terminal you want to use. In the case above, the terminal will be a
serial terminal, but you can also pass @code{console} to the command, serial terminal, but you can also pass @code{console} to the command,
as @samp{terminal serial console}. In this case, a terminal in which as @samp{terminal serial console}. In this case, a terminal in which
you press any key will be selected as a GRUB terminal. you press any key will be selected as a GRUB terminal. In the example above,
note that you need to put both commands on the same command line, as you
will lose the ability to type commands on the console after the first
command.
However, note that GRUB assumes that your terminal emulator is However, note that GRUB assumes that your terminal emulator is
compatible with VT100 by default. This is true for most terminal compatible with VT100 by default. This is true for most terminal
@ -1791,9 +1932,26 @@ These commands can only be used in the menu:
@node menuentry @node menuentry
@subsection menuentry @subsection menuentry
@deffn Command title name @dots{} @deffn Command menuentry @var{title} @
Start a new boot entry, and set its name to the contents of the rest of [@option{--class=class} @dots{}] [@option{--users=users}] @
the line, starting with the first non-space character. [@option{--hotkey=key}] @
@{ @var{command}; @dots{} @}
This defines a GRUB menu entry named @var{title}. When this entry is
selected from the menu, GRUB will set the @var{chosen} environment variable
to @var{title}, execute the list of commands given within braces, and if the
last command in the list returned successfully and a kernel was loaded it
will execute the @command{boot} command.
The @option{--class} option may be used any number of times to group menu
entries into classes. Menu themes may display different classes using
different styles.
The @option{--users} option grants specific users access to specific menu
entries. @xref{Security}.
The @option{--hotkey} option associates a hotkey with a menu entry.
@var{key} may be a single letter, or one of the aliases @samp{backspace},
@samp{tab}, or @samp{delete}.
@end deffn @end deffn
@ -1887,7 +2045,9 @@ The @option{-a} (@option{--ascii}), @option{-u} (@option{--utf8}), and
@option{-v} (@option{--visual-utf8}) options control how non-ASCII text is @option{-v} (@option{--visual-utf8}) options control how non-ASCII text is
displayed. @option{-a} specifies an ASCII-only terminal; @option{-u} displayed. @option{-a} specifies an ASCII-only terminal; @option{-u}
specifies logically-ordered UTF-8; and @option{-v} specifies specifies logically-ordered UTF-8; and @option{-v} specifies
visually-ordered UTF-8. "visually-ordered UTF-8" (in other words, arranged such that a terminal
emulator without bidirectional text support will display right-to-left text
in the proper order; this is not really proper UTF-8, but a workaround).
If no option or terminal type is specified, the current terminal type is If no option or terminal type is specified, the current terminal type is
printed. printed.

View file

@ -1,3 +1,21 @@
/*
* 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/>.
*/
#ifndef GRUB_EMU_MISC_H #ifndef GRUB_EMU_MISC_H
#define GRUB_EMU_MISC_H 1 #define GRUB_EMU_MISC_H 1
@ -26,12 +44,12 @@ extern const char *program_name;
void grub_init_all (void); void grub_init_all (void);
void grub_fini_all (void); void grub_fini_all (void);
char *grub_make_system_path_relative_to_its_root (const char *path); char *grub_make_system_path_relative_to_its_root (const char *path) __attribute__ ((warn_unused_result));
void * EXPORT_FUNC(xmalloc) (grub_size_t size); void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result));
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size); void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result));
char * EXPORT_FUNC(xstrdup) (const char *str); char * EXPORT_FUNC(xstrdup) (const char *str) __attribute__ ((warn_unused_result));
char * EXPORT_FUNC(xasprintf) (const char *fmt, ...); char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((warn_unused_result));
void EXPORT_FUNC(grub_util_warn) (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_info) (const char *fmt, ...);
@ -45,7 +63,6 @@ int EXPORT_FUNC(vasprintf) (char **buf, const char *fmt, va_list ap);
int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...); int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...);
#endif #endif
char * EXPORT_FUNC(xasprintf) (const char *fmt, ...);
extern char * canonicalize_file_name (const char *path); extern char * canonicalize_file_name (const char *path);
#ifdef HAVE_DEVICE_MAPPER #ifdef HAVE_DEVICE_MAPPER

View file

@ -231,10 +231,10 @@ grub_strtol (const char *str, char **end, int base)
} }
} }
char *EXPORT_FUNC(grub_strdup) (const char *s); char *EXPORT_FUNC(grub_strdup) (const char *s) __attribute__ ((warn_unused_result));
char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n); char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n) __attribute__ ((warn_unused_result));
void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
grub_size_t EXPORT_FUNC(grub_strlen) (const char *s); grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) __attribute__ ((warn_unused_result));
int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
@ -261,8 +261,8 @@ int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...)
int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt, int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
va_list args); va_list args);
char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2))) __attribute__ ((warn_unused_result));
char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args); char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__ ((warn_unused_result));
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,

View file

@ -1,7 +1,7 @@
/* raid.h - On disk structures for RAID. */ /* raid.h - On disk structures for RAID. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. * Copyright (C) 2006,2007,2008,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -51,6 +51,8 @@ struct grub_raid_array
char *name; /* That will be "md<number>". */ char *name; /* That will be "md<number>". */
unsigned int nr_devs; /* The number of devices we've found so far. */ unsigned int nr_devs; /* The number of devices we've found so far. */
grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */ grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */
grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES];
/* Start of each device, in 512 byte sectors. */
struct grub_raid_array *next; struct grub_raid_array *next;
}; };
@ -58,7 +60,8 @@ struct grub_raid
{ {
const char *name; const char *name;
grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array); grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector);
struct grub_raid *next; struct grub_raid *next;
}; };

View file

@ -0,0 +1,39 @@
/*
* 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/>.
*/
#ifndef GRUB_LIBNVPAIR_UTIL_HEADER
#define GRUB_LIBNVPAIR_UTIL_HEADER 1
#include <config.h>
#ifdef HAVE_LIBNVPAIR_H
#include <libnvpair.h>
#else /* ! HAVE_LIBNVPAIR_H */
#include <stdio.h> /* FILE */
typedef void nvlist_t;
int nvlist_lookup_string (nvlist_t *, const char *, char **);
int nvlist_lookup_nvlist (nvlist_t *, const char *, nvlist_t **);
int nvlist_lookup_nvlist_array (nvlist_t *, const char *, nvlist_t ***, unsigned int *);
void nvlist_print (FILE *, nvlist_t *);
#endif /* ! HAVE_LIBNVPAIR_H */
#endif

View file

@ -0,0 +1,45 @@
/*
* 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/>.
*/
#ifndef GRUB_LIBZFS_UTIL_HEADER
#define GRUB_LIBZFS_UTIL_HEADER 1
#include <config.h>
#ifdef HAVE_LIBZFS_H
#include <libzfs.h>
#else /* ! HAVE_LIBZFS_H */
#include <grub/util/libnvpair.h>
typedef void libzfs_handle_t;
typedef void zpool_handle_t;
extern libzfs_handle_t *libzfs_init ();
extern void libzfs_fini (libzfs_handle_t *);
extern zpool_handle_t *zpool_open (libzfs_handle_t *, const char *);
extern void zpool_close (zpool_handle_t *);
extern int zpool_get_physpath (zpool_handle_t *, const char *);
extern nvlist_t *zpool_get_config (zpool_handle_t *, nvlist_t **);
#endif /* ! HAVE_LIBZFS_H */
#endif

View file

@ -29,6 +29,7 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/emu/misc.h> #include <grub/emu/misc.h>
#include <grub/util/libzfs.h>
char *grub_util_get_path (const char *dir, const char *file); char *grub_util_get_path (const char *dir, const char *file);
size_t grub_util_get_fp_size (FILE *fp); size_t grub_util_get_fp_size (FILE *fp);
@ -60,4 +61,7 @@ char *canonicalize_file_name (const char *path);
void grub_util_init_nls (void); void grub_util_init_nls (void);
void grub_util_init_libzfs (void);
extern libzfs_handle_t *libzfs_handle;
#endif /* ! GRUB_UTIL_MISC_HEADER */ #endif /* ! GRUB_UTIL_MISC_HEADER */

View file

@ -1,7 +1,7 @@
/* getroot.c - Get root device */ /* getroot.c - Get root device */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,14 +20,17 @@
#include <config.h> #include <config.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <error.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <grub/util/misc.h>
#ifdef __GNU__ #ifdef __GNU__
#include <hurd.h> #include <hurd.h>
@ -36,6 +39,20 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#ifdef __linux__
# include <sys/types.h>
# include <sys/wait.h>
#endif
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
# include <grub/util/libzfs.h>
# include <grub/util/libnvpair.h>
#endif
#ifdef HAVE_GETFSSTAT
# include <sys/mount.h>
#endif
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/emu/misc.h> #include <grub/emu/misc.h>
@ -81,6 +98,66 @@ xgetcwd (void)
return path; return path;
} }
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
static char *
find_mount_point_from_dir (const char *dir)
{
struct stat st;
typeof (st.st_dev) fs;
char *prev, *next, *slash, *statdir;
if (stat (dir, &st) == -1)
error (1, errno, "stat (%s)", dir);
fs = st.st_dev;
prev = xstrdup (dir);
while (1)
{
/* Remove last slash. */
next = xstrdup (prev);
slash = strrchr (next, '/');
if (! slash)
{
free (next);
free (prev);
return NULL;
}
*slash = '\0';
/* A next empty string counts as /. */
if (next[0] == '\0')
statdir = "/";
else
statdir = next;
if (stat (statdir, &st) == -1)
error (1, errno, "stat (%s)", next);
if (st.st_dev != fs)
{
/* Found mount point. */
free (next);
return prev;
}
free (prev);
prev = next;
/* We've already seen an empty string, which means we
reached /. Nothing left to do. */
if (prev[0] == '\0')
{
free (prev);
return xstrdup ("/");
}
}
}
#endif
#ifdef __linux__ #ifdef __linux__
/* Statting something on a btrfs filesystem always returns a virtual device /* Statting something on a btrfs filesystem always returns a virtual device
@ -161,6 +238,90 @@ find_root_device_from_mountinfo (const char *dir)
#endif /* __linux__ */ #endif /* __linux__ */
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
/* ZFS has similar problems to those of btrfs (see above). */
static char *
find_root_device_from_libzfs (const char *dir)
{
char *device = NULL;
char *poolname = NULL;
char *poolfs = NULL;
char *mnt_point;
char *slash;
mnt_point = find_mount_point_from_dir (dir);
#ifdef HAVE_GETFSSTAT
{
int mnt_count = getfsstat (NULL, 0, MNT_WAIT);
if (mnt_count == -1)
error (1, errno, "getfsstat");
struct statfs *mnt = xmalloc (mnt_count * sizeof (*mnt));
mnt_count = getfsstat (mnt, mnt_count * sizeof (*mnt), MNT_WAIT);
if (mnt_count == -1)
error (1, errno, "getfsstat");
unsigned int i;
for (i = 0; i < (unsigned) mnt_count; i++)
if (!strcmp (mnt[i].f_fstypename, "zfs")
&& !strcmp (mnt[i].f_mntonname, mnt_point))
{
poolname = xstrdup (mnt[i].f_mntfromname);
break;
}
free (mnt);
}
#endif
if (! poolname)
return NULL;
slash = strchr (poolname, '/');
if (slash)
{
*slash = '\0';
poolfs = slash + 1;
}
{
zpool_handle_t *zpool;
nvlist_t *nvlist;
nvlist_t **nvlist_array;
unsigned int nvlist_count;
grub_util_init_libzfs ();
zpool = zpool_open (libzfs_handle, poolname);
nvlist = zpool_get_config (zpool, NULL);
if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0)
error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
if (nvlist_lookup_nvlist_array (nvlist, "children", &nvlist_array, &nvlist_count) != 0)
error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
do
{
assert (nvlist_count > 0);
} while (nvlist_lookup_nvlist_array (nvlist_array[0], "children",
&nvlist_array, &nvlist_count) == 0);
if (nvlist_lookup_string (nvlist_array[0], "path", &device) != 0)
error (1, errno, "nvlist_lookup_string (\"path\")");
zpool_close (zpool);
}
free (poolname);
return device;
}
#endif
#ifdef __MINGW32__ #ifdef __MINGW32__
static char * static char *
@ -453,6 +614,12 @@ grub_guess_root_device (const char *dir)
return os_dev; return os_dev;
#endif /* __linux__ */ #endif /* __linux__ */
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
os_dev = find_root_device_from_libzfs (dir);
if (os_dev)
return os_dev;
#endif
if (stat (dir, &st) < 0) if (stat (dir, &st) < 0)
grub_util_error ("cannot stat `%s'", dir); grub_util_error ("cannot stat `%s'", dir);
@ -516,10 +683,89 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
return GRUB_DEV_ABSTRACTION_NONE; return GRUB_DEV_ABSTRACTION_NONE;
} }
#ifdef __linux__
static char *
get_mdadm_name (const char *os_dev)
{
int mdadm_pipe[2];
pid_t mdadm_pid;
char *name = NULL;
if (pipe (mdadm_pipe) < 0)
{
grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno));
return NULL;
}
mdadm_pid = fork ();
if (mdadm_pid < 0)
grub_util_warn ("Unable to fork mdadm: %s", strerror (errno));
else if (mdadm_pid == 0)
{
/* Child. */
char *argv[5];
close (mdadm_pipe[0]);
dup2 (mdadm_pipe[1], STDOUT_FILENO);
close (mdadm_pipe[1]);
/* execvp has inconvenient types, hence the casts. None of these
strings will actually be modified. */
argv[0] = (char *) "mdadm";
argv[1] = (char *) "--detail";
argv[2] = (char *) "--export";
argv[3] = (char *) os_dev;
argv[4] = NULL;
execvp ("mdadm", argv);
exit (127);
}
else
{
/* Parent. Read mdadm's output. */
FILE *mdadm;
char *buf = NULL;
size_t len = 0;
close (mdadm_pipe[1]);
mdadm = fdopen (mdadm_pipe[0], "r");
if (! mdadm)
{
grub_util_warn ("Unable to open stream from mdadm: %s",
strerror (errno));
goto out;
}
while (getline (&buf, &len, mdadm) > 0)
{
if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0)
{
char *name_start, *colon;
size_t name_len;
free (name);
name_start = buf + sizeof ("MD_NAME=") - 1;
/* Strip off the homehost if present. */
colon = strchr (name_start, ':');
name = strdup (colon ? colon + 1 : name_start);
name_len = strlen (name);
if (name[name_len - 1] == '\n')
name[name_len - 1] = '\0';
}
}
out:
close (mdadm_pipe[0]);
waitpid (mdadm_pid, NULL, 0);
}
return name;
}
#endif /* __linux__ */
char * char *
grub_util_get_grub_dev (const char *os_dev) grub_util_get_grub_dev (const char *os_dev)
{ {
char *grub_dev; char *grub_dev = NULL;
switch (grub_util_get_dev_abstraction (os_dev)) switch (grub_util_get_dev_abstraction (os_dev))
{ {
@ -600,9 +846,36 @@ grub_util_get_grub_dev (const char *os_dev)
grub_dev = xasprintf ("md%s", p); grub_dev = xasprintf ("md%s", p);
free (p); free (p);
} }
else if (os_dev[7] == '/')
{
/* mdraid 1.x with a free name. */
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 else
grub_util_error ("unknown kind of RAID device `%s'", os_dev); grub_util_error ("unknown kind of RAID device `%s'", os_dev);
#ifdef __linux__
{
char *mdadm_name = get_mdadm_name (os_dev);
if (mdadm_name)
{
free (grub_dev);
grub_dev = xasprintf ("md/%s", mdadm_name);
free (mdadm_name);
}
}
#endif /* __linux__ */
break; break;
default: /* GRUB_DEV_ABSTRACTION_NONE */ default: /* GRUB_DEV_ABSTRACTION_NONE */

View file

@ -1,3 +1,21 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,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 <config.h> #include <config.h>
#include <errno.h> #include <errno.h>

View file

@ -518,12 +518,39 @@ grub_strndup (const char *s, grub_size_t n)
} }
void * void *
grub_memset (void *s, int c, grub_size_t n) grub_memset (void *s, int c, grub_size_t len)
{ {
unsigned char *p = (unsigned char *) s; void *p = s;
grub_uint8_t pattern8 = c;
while (n--) if (len >= 3 * sizeof (unsigned long))
*p++ = (unsigned char) c; {
unsigned long patternl = 0;
grub_size_t i;
for (i = 0; i < sizeof (unsigned long); i++)
patternl |= ((unsigned long) pattern8) << (8 * i);
while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1)))
{
*(grub_uint8_t *) p = pattern8;
p = (grub_uint8_t *) p + 1;
len--;
}
while (len >= sizeof (unsigned long))
{
*(unsigned long *) p = patternl;
p = (unsigned long *) p + 1;
len -= sizeof (unsigned long);
}
}
while (len > 0)
{
*(grub_uint8_t *) p = pattern8;
p = (grub_uint8_t *) p + 1;
len--;
}
return s; return s;
} }

View file

@ -144,8 +144,10 @@ grub_arg_show_help (grub_extcmd_t cmd)
} }
} }
/* FIXME: add spacing back. */ while (spacing--)
grub_xputs (_(opt->doc)); grub_xputs (" ");
grub_printf ("%s\n", _(opt->doc));
switch (opt->shortarg) switch (opt->shortarg)
{ {

View file

@ -157,11 +157,13 @@ LOCAL(cont1):
andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax
movl %eax, %cr0 movl %eax, %cr0
#ifdef __x86_64__
/* Disable amd64. */ /* Disable amd64. */
movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx
rdmsr rdmsr
andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax
wrmsr wrmsr
#endif
/* Turn off PAE. */ /* Turn off PAE. */
movl %cr4, %eax movl %cr4, %eax

View file

@ -116,7 +116,7 @@ COMMENT #.*$
CHAR [^{}|&$;<> \t\n\'\"\\] CHAR [^{}|&$;<> \t\n\'\"\\]
DIGITS [[:digit:]]+ DIGITS [[:digit:]]+
NAME [[:alpha:]_][[:alnum:][:digit:]_]* NAME [[:alpha:]_][[:alnum:]_]*
ESC \\. ESC \\.
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}

View file

@ -311,6 +311,20 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
efi_call_2 (o->enable_cursor, o, on); efi_call_2 (o->enable_cursor, o, on);
} }
static grub_err_t
grub_efi_console_init (struct grub_term_output *term)
{
grub_console_setcursor (term, 1);
return 0;
}
static grub_err_t
grub_efi_console_fini (struct grub_term_output *term)
{
grub_console_setcursor (term, 0);
return 0;
}
static struct grub_term_input grub_console_term_input = static struct grub_term_input grub_console_term_input =
{ {
.name = "console", .name = "console",
@ -321,6 +335,8 @@ static struct grub_term_input grub_console_term_input =
static struct grub_term_output grub_console_term_output = static struct grub_term_output grub_console_term_output =
{ {
.name = "console", .name = "console",
.init = grub_efi_console_init,
.fini = grub_efi_console_fini,
.putchar = grub_console_putchar, .putchar = grub_console_putchar,
.getwh = grub_console_getwh, .getwh = grub_console_getwh,
.getxy = grub_console_getxy, .getxy = grub_console_getxy,

View file

@ -210,7 +210,7 @@ static struct grub_serial_port com_ports[GRUB_SERIAL_PORT_NUM];
void void
grub_ns8250_init (void) grub_ns8250_init (void)
{ {
int i; unsigned i;
for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++) for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
if (serial_hw_io_addr[i]) if (serial_hw_io_addr[i])
{ {
@ -231,7 +231,7 @@ char *
grub_serial_ns8250_add_port (grub_port_t port) grub_serial_ns8250_add_port (grub_port_t port)
{ {
struct grub_serial_port *p; struct grub_serial_port *p;
int i; unsigned i;
for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++) for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
if (com_ports[i].port == port) if (com_ports[i].port == port)
return com_names[i]; return com_names[i];

View file

@ -1,4 +1,4 @@
#! /bin/bash -e #! /bin/sh -e
# Compares GRUB script output with BASH output. # Compares GRUB script output with BASH output.
# Copyright (C) 2009,2010 Free Software Foundation, Inc. # Copyright (C) 2009,2010 Free Software Foundation, Inc.
@ -84,7 +84,7 @@ done
if [ "x${source}" = x ] ; then if [ "x${source}" = x ] ; then
tmpfile=`mktemp` tmpfile=`mktemp`
while read; do while read REPLY; do
echo $REPLY >> ${tmpfile} echo $REPLY >> ${tmpfile}
done done
source=${tmpfile} source=${tmpfile}

View file

@ -467,13 +467,30 @@ clear_seen_devices (void)
} }
#ifdef __linux__ #ifdef __linux__
/* Like strcmp, but doesn't require a cast for use as a qsort comparator. */ struct device
static int
compare_file_names (const void *a, const void *b)
{ {
const char *left = *(const char **) a; char *stable;
const char *right = *(const char **) b; char *kernel;
return strcmp (left, right); };
/* Sort by the kernel name for preference since that most closely matches
older device.map files, but sort by stable by-id names as a fallback.
This is because /dev/disk/by-id/ usually has a few alternative
identifications of devices (e.g. ATA vs. SATA).
check_device_readable_unique will ensure that we only get one for any
given disk, but sort the list so that the choice of which one we get is
stable. */
static int
compare_devices (const void *a, const void *b)
{
const struct device *left = (const struct device *) a;
const struct device *right = (const struct device *) b;
int ret;
ret = strcmp (left->kernel, right->kernel);
if (ret)
return ret;
else
return strcmp (left->stable, right->stable);
} }
#endif /* __linux__ */ #endif /* __linux__ */
@ -507,10 +524,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
if (dir) if (dir)
{ {
struct dirent *entry; struct dirent *entry;
char **names; struct device *devs;
size_t names_len = 0, names_max = 1024, i; size_t devs_len = 0, devs_max = 1024, i;
names = xmalloc (names_max * sizeof (*names)); devs = xmalloc (devs_max * sizeof (*devs));
/* Dump all the directory entries into names, resizing if /* Dump all the directory entries into names, resizing if
necessary. */ necessary. */
@ -526,35 +543,34 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
/* Skip RAID entries; they are handled by upper layers. */ /* Skip RAID entries; they are handled by upper layers. */
if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0) if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0)
continue; continue;
if (names_len >= names_max) if (devs_len >= devs_max)
{ {
names_max *= 2; devs_max *= 2;
names = xrealloc (names, names_max * sizeof (*names)); devs = xrealloc (devs, devs_max * sizeof (*devs));
} }
names[names_len++] = xasprintf (entry->d_name); devs[devs_len].stable =
xasprintf ("/dev/disk/by-id/%s", entry->d_name);
devs[devs_len].kernel =
canonicalize_file_name (devs[devs_len].stable);
devs_len++;
} }
/* /dev/disk/by-id/ usually has a few alternative identifications of qsort (devs, devs_len, sizeof (*devs), &compare_devices);
devices (e.g. ATA vs. SATA). check_device_readable_unique will
ensure that we only get one for any given disk, but sort the list
so that the choice of which one we get is stable. */
qsort (names, names_len, sizeof (*names), &compare_file_names);
closedir (dir); closedir (dir);
/* Now add all the devices in sorted order. */ /* Now add all the devices in sorted order. */
for (i = 0; i < names_len; ++i) for (i = 0; i < devs_len; ++i)
{ {
char *path = xasprintf ("/dev/disk/by-id/%s", names[i]); if (check_device_readable_unique (devs[i].stable))
if (check_device_readable_unique (path))
{ {
if (hook (path, 0)) if (hook (devs[i].stable, 0))
goto out; goto out;
} }
free (path); free (devs[i].stable);
free (names[i]); free (devs[i].kernel);
} }
free (names); free (devs);
} }
} }

View file

@ -296,6 +296,7 @@ if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then
mformat -C -f 2880 -L 16 -i "${iso9660_dir}"/efi.img :: mformat -C -f 2880 -L 16 -i "${iso9660_dir}"/efi.img ::
mcopy -s -i "${iso9660_dir}"/efi.img ${efi_dir}/efi ::/ mcopy -s -i "${iso9660_dir}"/efi.img ${efi_dir}/efi ::/
rm -rf ${efi_dir}
grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img" grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img"
fi fi

View file

@ -50,6 +50,7 @@
enum { enum {
PRINT_FS, PRINT_FS,
PRINT_FS_UUID, PRINT_FS_UUID,
PRINT_FS_LABEL,
PRINT_DRIVE, PRINT_DRIVE,
PRINT_DEVICE, PRINT_DEVICE,
PRINT_PARTMAP, PRINT_PARTMAP,
@ -291,6 +292,16 @@ probe (const char *path, char *device_name)
printf ("%s\n", uuid); printf ("%s\n", uuid);
} }
else if (print == PRINT_FS_LABEL)
{
char *label;
if (! fs->label)
grub_util_error ("%s does not support labels", fs->name);
fs->label (dev, &label);
printf ("%s\n", label);
}
end: end:
if (dev) if (dev)
@ -326,7 +337,7 @@ Probe device information for a given path (or device, if the -d option is given)
\n\ \n\
-d, --device given argument is a system device, not a path\n\ -d, --device given argument is a system device, not a path\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\ -m, --device-map=FILE use FILE as the device map [default=%s]\n\
-t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\ -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\
print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\ print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
-h, --help display this message and exit\n\ -h, --help display this message and exit\n\
-V, --version print version information and exit\n\ -V, --version print version information and exit\n\
@ -375,6 +386,8 @@ main (int argc, char *argv[])
print = PRINT_FS; print = PRINT_FS;
else if (!strcmp (optarg, "fs_uuid")) else if (!strcmp (optarg, "fs_uuid"))
print = PRINT_FS_UUID; print = PRINT_FS_UUID;
else if (!strcmp (optarg, "fs_label"))
print = PRINT_FS_LABEL;
else if (!strcmp (optarg, "drive")) else if (!strcmp (optarg, "drive"))
print = PRINT_DRIVE; print = PRINT_DRIVE;
else if (!strcmp (optarg, "device")) else if (!strcmp (optarg, "device"))

View file

@ -137,11 +137,7 @@ case x${GRUB_TERMINAL_INPUT} in
;; ;;
x*) x*)
cat << EOF cat << EOF
if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else terminal_input ${GRUB_TERMINAL_INPUT}
# For backward compatibility with versions of terminal.mod that don't
# understand terminal_input
terminal ${GRUB_TERMINAL_INPUT}
fi
EOF EOF
;; ;;
esac esac
@ -152,11 +148,7 @@ case x${GRUB_TERMINAL_OUTPUT} in
;; ;;
x*) x*)
cat << EOF cat << EOF
if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else terminal_output ${GRUB_TERMINAL_OUTPUT}
# For backward compatibility with versions of terminal.mod that don't
# understand terminal_output
terminal ${GRUB_TERMINAL_OUTPUT}
fi
EOF EOF
;; ;;
esac esac

View file

@ -51,6 +51,10 @@ kfreebsd_entry ()
if [ -z "${prepare_boot_cache}" ]; then if [ -z "${prepare_boot_cache}" ]; then
prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
fi fi
if [ -z "${prepare_module_dir_cache}" ]; then
prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")"
fi
printf '%s\n' "${prepare_boot_cache}" printf '%s\n' "${prepare_boot_cache}"
cat << EOF cat << EOF
echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})' echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})'
@ -63,9 +67,10 @@ EOF
EOF EOF
fi fi
if test -n "${acpi_ko}" ; then if test -e "${module_dir}/acpi.ko" ; then
printf '%s\n' "${prepare_module_dir_cache}"
cat << EOF cat << EOF
kfreebsd_module_elf ${acpi_ko_rel_dirname}/${acpi_ko_basename} kfreebsd_module_elf ${module_dir_rel}/acpi.ko
EOF EOF
fi fi
@ -103,19 +108,17 @@ while [ "x$list" != "x" ] ; do
version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"`
alt_version=`echo $version | sed -e "s,\.old$,,g"` alt_version=`echo $version | sed -e "s,\.old$,,g"`
acpi_ko= module_dir=
for i in "/lib/modules/${version}/acpi.ko" "/lib/modules/${alt_version}/acpi.ko" \ for i in "/lib/modules/${version}" "/lib/modules/${alt_version}" \
"/boot/kernel/acpi.ko"; do "/boot/kernel"; do
if test -e "$i" ; then if test -e "$i" ; then
acpi_ko="$i" module_dir="$i"
break break
fi fi
done done
if test -n "${acpi_ko}" ; then if test -n "${module_dir}" ; then
echo "Found ACPI module: ${acpi_ko}" >&2 echo "Found kernel module directory: ${module_dir}" >&2
acpi_ko_basename=`basename ${acpi_ko}` module_dir_rel=$(make_system_path_relative_to_its_root $module_dir)
acpi_ko_dirname=`dirname ${acpi_ko}`
acpi_ko_rel_dirname=`make_system_path_relative_to_its_root $acpi_ko_dirname`
fi fi
kfreebsd_entry "${OS}" "${version}" kfreebsd_entry "${OS}" "${version}"

View file

@ -44,7 +44,8 @@ case ${GRUB_DEVICE} in
esac esac
if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
|| ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
|| uses_abstraction "${GRUB_DEVICE}" lvm; then
LINUX_ROOT_DEVICE=${GRUB_DEVICE} LINUX_ROOT_DEVICE=${GRUB_DEVICE}
else else
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}

View file

@ -246,7 +246,7 @@ devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_ma
# The order in this list is critical. Be careful when modifying it. # The order in this list is critical. Be careful when modifying it.
modules="$modules $fs_module $partmap_module $devabstraction_module" modules="$modules $fs_module $partmap_module $devabstraction_module"
$grub_mkimage -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1 $grub_mkimage -p "" -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1
# Prompt the user to check if the device map is correct. # Prompt the user to check if the device map is correct.
echo "Installation finished. No error reported." echo "Installation finished. No error reported."

View file

@ -812,14 +812,14 @@ main (int argc, char *argv[])
must_embed = 1; must_embed = 1;
if (root_dev[0] == 'm' && root_dev[1] == 'd' if (root_dev[0] == 'm' && root_dev[1] == 'd'
&& root_dev[2] >= '0' && root_dev[2] <= '9') && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/'))
{ {
/* FIXME: we can avoid this on RAID1. */ /* FIXME: we can avoid this on RAID1. */
must_embed = 1; must_embed = 1;
} }
if (dest_dev[0] == 'm' && dest_dev[1] == 'd' if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
&& dest_dev[2] >= '0' && dest_dev[2] <= '9') && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/'))
{ {
char **devicelist; char **devicelist;
int i; int i;

View file

@ -212,7 +212,7 @@ fi
# this command is allowed to fail (--target=fs already grants us that the # this command is allowed to fail (--target=fs already grants us that the
# filesystem will be accessible). # filesystem will be accessible).
partmap_module= partmap_module=
for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do
partmap_module="$partmap_module part_$x"; partmap_module="$partmap_module part_$x";
done done

View file

@ -18,8 +18,6 @@
import re import re
import sys import sys
import os
import datetime
if len (sys.argv) < 3: if len (sys.argv) < 3:
print ("Usage: %s SOURCE DESTINATION" % sys.argv[0]) print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])

View file

@ -36,6 +36,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/cache.h> #include <grub/cache.h>
#include <grub/util/misc.h> #include <grub/util/misc.h>
#include <grub/util/libzfs.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/time.h> #include <grub/time.h>
@ -293,6 +294,28 @@ grub_util_init_nls (void)
textdomain (PACKAGE); textdomain (PACKAGE);
#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
} }
#ifdef HAVE_LIBZFS
libzfs_handle_t *libzfs_handle;
static void
fini_libzfs (void)
{
libzfs_fini (libzfs_handle);
}
#endif
void
grub_util_init_libzfs (void)
{
#ifdef HAVE_LIBZFS
if (! libzfs_handle)
{
libzfs_handle = libzfs_init ();
atexit (fini_libzfs);
}
#endif
}
#endif #endif
int int