From ec824e0f2a399ce2ab3a2e3353d372a236595059 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Tue, 17 Dec 2013 14:39:48 +0100 Subject: [PATCH] Implement grub_file tool and use it to implement generating of config in separate root. --- ChangeLog | 5 + Makefile.util.def | 37 +- configure.ac | 7 +- docs/man/grub-file.h2m | 2 + grub-core/Makefile.core.def | 31 +- grub-core/commands/file.c | 641 +++++++++++++++++++++++++++++++ grub-core/commands/file32.c | 5 + grub-core/commands/file64.c | 5 + grub-core/commands/fileXX.c | 68 ++++ grub-core/io/xzio.c | 10 +- grub-core/loader/i386/linux.c | 2 +- grub-core/loader/i386/xen_file.c | 9 +- include/grub/elf.h | 2 +- include/grub/fileid.h | 29 ++ util/grub-file.c | 107 ++++++ util/grub-mkconfig.in | 56 ++- util/grub-mkconfig_lib.in | 3 + util/grub-pe2elf.c | 10 - util/grub.d/00_header.in | 2 +- util/grub.d/10_hurd.in | 26 +- util/grub.d/10_illumos.in | 17 +- util/grub.d/10_kfreebsd.in | 30 +- util/grub.d/10_linux.in | 51 ++- util/grub.d/10_netbsd.in | 37 +- util/grub.d/10_xnu.in | 15 +- util/grub.d/20_linux_xen.in | 28 +- 26 files changed, 1113 insertions(+), 122 deletions(-) create mode 100644 docs/man/grub-file.h2m create mode 100644 grub-core/commands/file.c create mode 100644 grub-core/commands/file32.c create mode 100644 grub-core/commands/file64.c create mode 100644 grub-core/commands/fileXX.c create mode 100644 include/grub/fileid.h create mode 100644 util/grub-file.c diff --git a/ChangeLog b/ChangeLog index b24b9eb35..d84b0aca3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-12-17 Vladimir Serbinenko + + Implement grub_file tool and use it to implement generating of config + in separate root. + 2013-12-17 Vladimir Serbinenko Change to v1 xen grants. diff --git a/Makefile.util.def b/Makefile.util.def index 470191700..2720f6bd3 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -154,6 +154,7 @@ library = { common = grub-core/script/script.c; common = grub-core/script/argv.c; common = grub-core/io/gzio.c; + common = grub-core/io/xzio.c; common = grub-core/io/lzopio.c; common = grub-core/kern/ia64/dl_helper.c; common = grub-core/kern/arm/dl_helper.c; @@ -422,49 +423,42 @@ script = { name = '10_hurd'; common = util/grub.d/10_hurd.in; installdir = grubconf; - condition = COND_HOST_HURD; }; script = { name = '10_kfreebsd'; common = util/grub.d/10_kfreebsd.in; installdir = grubconf; - condition = COND_HOST_KFREEBSD; }; script = { name = '10_illumos'; common = util/grub.d/10_illumos.in; installdir = grubconf; - condition = COND_HOST_ILLUMOS; }; script = { name = '10_netbsd'; common = util/grub.d/10_netbsd.in; installdir = grubconf; - condition = COND_HOST_NETBSD; }; script = { name = '10_linux'; common = util/grub.d/10_linux.in; installdir = grubconf; - condition = COND_HOST_LINUX; }; script = { name = '10_xnu'; common = util/grub.d/10_xnu.in; installdir = grubconf; - condition = COND_HOST_XNU; }; script = { name = '20_linux_xen'; common = util/grub.d/20_linux_xen.in; installdir = grubconf; - condition = COND_HOST_LINUX; }; script = { @@ -1255,3 +1249,32 @@ program = { ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; + +program = { + name = grub-file; + mansection = 1; + + common = util/grub-file.c; + common = util/render-label.c; + common = grub-core/commands/file.c; + common = grub-core/commands/file32.c; + common = grub-core/commands/file64.c; + common = grub-core/loader/i386/xen_file.c; + common = grub-core/loader/i386/xen_file32.c; + common = grub-core/loader/i386/xen_file64.c; + common = grub-core/io/offset.c; + common = grub-core/kern/elf.c; + common = grub-core/loader/lzss.c; + common = grub-core/loader/macho.c; + common = grub-core/loader/macho32.c; + common = grub-core/loader/macho64.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; diff --git a/configure.ac b/configure.ac index e803b2a1a..dfb4f69ce 100644 --- a/configure.ac +++ b/configure.ac @@ -69,6 +69,7 @@ grub_TRANSFORM([grub-script-check]) grub_TRANSFORM([grub-set-default]) grub_TRANSFORM([grub-sparc64-setup]) grub_TRANSFORM([grub-render-label]) +grub_TRANSFORM([grub-file]) # Optimization flag. Allow user to override. if test "x$TARGET_CFLAGS" = x; then @@ -1608,13 +1609,7 @@ AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi]) AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ]) AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi]) -AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) -AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) -AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd]) AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows]) -AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd]) -AM_CONDITIONAL([COND_HOST_XNU], [test x$host_kernel = xxnu]) -AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos]) AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x]) AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) diff --git a/docs/man/grub-file.h2m b/docs/man/grub-file.h2m new file mode 100644 index 000000000..e09bb4d31 --- /dev/null +++ b/docs/man/grub-file.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-file \- check file type diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e7e38a853..3d70d0241 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1659,10 +1659,6 @@ module = { name = linux; x86 = loader/i386/linux.c; xen = loader/i386/xen.c; - xen = loader/i386/xen_file.c; - xen = loader/i386/xen_file32.c; - xen = loader/i386/xen_file64.c; - extra_dist = loader/i386/xen_fileXX.c; xen_cppflags = '$(CPPFLAGS_XEN)'; i386_pc = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; @@ -1680,16 +1676,21 @@ module = { name = xnu; x86 = loader/xnu_resume.c; x86 = loader/i386/xnu.c; - x86 = loader/macho32.c; - x86 = loader/macho64.c; - x86 = loader/macho.c; x86 = loader/xnu.c; - x86 = loader/lzss.c; - extra_dist = loader/machoXX.c; enable = x86; }; +module = { + name = macho; + + common = loader/macho.c; + common = loader/macho32.c; + common = loader/macho64.c; + common = loader/lzss.c; + extra_dist = loader/machoXX.c; +}; + module = { name = appleldr; common = loader/efi/appleloader.c; @@ -2269,3 +2270,15 @@ module = { name = progress; common = lib/progress.c; }; + +module = { + name = file; + common = commands/file.c; + common = commands/file32.c; + common = commands/file64.c; + extra_dist = commands/fileXX.c; + common = loader/i386/xen_file.c; + common = loader/i386/xen_file32.c; + common = loader/i386/xen_file64.c; + extra_dist = loader/i386/xen_fileXX.c; +}; diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c new file mode 100644 index 000000000..c27df0c50 --- /dev/null +++ b/grub-core/commands/file.c @@ -0,0 +1,641 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options[] = { + {"is-i386-xen-pae-domu", 0, 0, + N_("Check if FILE can be booted as i386 PAE xen unprivilegied guest"), + 0, 0}, + {"is-x86_64-xen-domu", 0, 0, + N_("Check if FILE can be booted as x86_64 xen unprivilegied guest"), 0, 0}, + {"is-x86-xen-dom0", 0, 0, + N_("Check if FILE can be used as xen x86 privilegied guest kernel"), 0, 0}, + {"is-x86-multiboot", 0, 0, + N_("Check if FILE can be used as x86 multiboot kernel"), 0, 0}, + {"is-x86-multiboot2", 0, 0, + N_("Check if FILE can be used as x86 multiboot2 kernel"), 0, 0}, + {"is-arm-linux", 0, 0, + N_("Check if FILE is ARM linux"), 0, 0}, + {"is-ia64-linux", 0, 0, + N_("Check if FILE is IA64 linux"), 0, 0}, + {"is-mips-linux", 0, 0, + N_("Check if FILE is MIPS linux"), 0, 0}, + {"is-mipsel-linux", 0, 0, + N_("Check if FILE is MIPSEL linux"), 0, 0}, + {"is-sparc64-linux", 0, 0, + N_("Check if FILE is SPARC64 linux"), 0, 0}, + {"is-powerpc-linux", 0, 0, + N_("Check if FILE is POWERPC linux"), 0, 0}, + {"is-x86-linux", 0, 0, + N_("Check if FILE is x86 linux"), 0, 0}, + {"is-x86-linux32", 0, 0, + N_("Check if FILE is x86 linux supporting 32-bit protocol"), 0, 0}, + {"is-x86-kfreebsd", 0, 0, + N_("Check if FILE is x86 kfreebsd"), 0, 0}, + {"is-i386-kfreebsd", 0, 0, + N_("Check if FILE is i386 kfreebsd"), 0, 0}, + {"is-x86_64-kfreebsd", 0, 0, + N_("Check if FILE is x86_64 kfreebsd"), 0, 0}, + + {"is-x86-knetbsd", 0, 0, + N_("Check if FILE is x86 knetbsd"), 0, 0}, + {"is-i386-knetbsd", 0, 0, + N_("Check if FILE is i386 knetbsd"), 0, 0}, + {"is-x86_64-knetbsd", 0, 0, + N_("Check if FILE is x86_64 knetbsd"), 0, 0}, + + {"is-i386-efi", 0, 0, + N_("Check if FILE is i386 EFI file"), 0, 0}, + {"is-x86_64-efi", 0, 0, + N_("Check if FILE is x86-64 EFI file"), 0, 0}, + {"is-ia64-efi", 0, 0, + N_("Check if FILE is IA64 EFI file"), 0, 0}, + {"is-arm-efi", 0, 0, + N_("Check if FILE is ARM EFI file"), 0, 0}, + {"is-hibernated-hiberfil", 0, 0, + N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0}, + {"is-x86_64-xnu", 0, 0, + N_("Check if FILE is x86_64 xnu (Mac OS X kernel)"), 0, 0}, + {"is-i386-xnu", 0, 0, + N_("Check if FILE is i386 xnu (Mac OS X kernel)"), 0, 0}, + {"is-xnu-hibr", 0, 0, + N_("Check if FILE is xnu (Mac OS X kernel) hibernated image"), 0, 0}, + {"is-x86-bios-bootsector", 0, 0, + N_("Check if FILE is BIOS bootsector"), 0, 0}, + {0, 0, 0, 0, 0, 0} +}; + +enum +{ + IS_PAE_DOMU, + IS_64_DOMU, + IS_DOM0, + IS_MULTIBOOT, + IS_MULTIBOOT2, + IS_ARM_LINUX, + IS_IA64_LINUX, + IS_MIPS_LINUX, + IS_MIPSEL_LINUX, + IS_SPARC64_LINUX, + IS_POWERPC_LINUX, + IS_X86_LINUX, + IS_X86_LINUX32, + IS_X86_KFREEBSD, + IS_X86_KFREEBSD32, + IS_X86_KFREEBSD64, + IS_X86_KNETBSD, + IS_X86_KNETBSD32, + IS_X86_KNETBSD64, + IS_32_EFI, + IS_64_EFI, + IS_IA_EFI, + IS_ARM_EFI, + IS_HIBERNATED, + IS_XNU64, + IS_XNU32, + IS_XNU_HIBR, + IS_BIOS_BOOTSECTOR, + OPT_TYPE_MIN = IS_PAE_DOMU, + OPT_TYPE_MAX = IS_BIOS_BOOTSECTOR +}; + + +static grub_err_t +grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file = 0; + grub_elf_t elf = 0; + grub_err_t err; + int type = -1, i; + int ret = 0; + grub_macho_t macho = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + for (i = OPT_TYPE_MIN; i <= OPT_TYPE_MAX; i++) + if (ctxt->state[i].set) + { + if (type == -1) + { + type = i; + continue; + } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple types specified"); + } + if (type == -1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no type specified"); + + file = grub_file_open (args[0]); + if (!file) + return grub_errno; + switch (type) + { + case IS_BIOS_BOOTSECTOR: + { + grub_uint16_t sig; + if (grub_file_size (file) != 512) + break; + if (grub_file_seek (file, 510) == (grub_size_t) -1) + break; + if (grub_file_read (file, &sig, 2) != 2) + break; + if (sig != grub_cpu_to_le16_compile_time (0xaa55)) + break; + ret = 1; + break; + } + case IS_IA64_LINUX: + { + Elf64_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 + || ehdr.e_ident[EI_DATA] != ELFDATA2LSB + || ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_IA_64)) + break; + + ret = 1; + + break; + } + + case IS_SPARC64_LINUX: + { + Elf64_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 + || ehdr.e_ident[EI_DATA] != ELFDATA2MSB) + break; + + if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_SPARCV9) + || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + + case IS_POWERPC_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB + || (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_PPC) + && ehdr.e_machine != + grub_cpu_to_le16_compile_time (EM_PPC64))) + break; + + if (ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC) + && ehdr.e_type != grub_cpu_to_be16_compile_time (ET_DYN)) + break; + + ret = 1; + + break; + } + + case IS_MIPS_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB + || ehdr.e_machine != grub_cpu_to_be16_compile_time (EM_MIPS) + || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + + case IS_X86_KNETBSD: + case IS_X86_KNETBSD32: + case IS_X86_KNETBSD64: + { + int is32, is64; + + elf = grub_elf_file (file, file->name); + + if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) + || elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB) + break; + + is32 = grub_elf_is_elf32 (elf); + is64 = grub_elf_is_elf64 (elf); + if (!is32 && !is64) + break; + if (!is32 && type == IS_X86_KNETBSD32) + break; + if (!is64 && type == IS_X86_KNETBSD64) + break; + if (is64) + ret = grub_file_check_netbsd64 (elf); + if (is32) + ret = grub_file_check_netbsd32 (elf); + break; + } + + case IS_X86_KFREEBSD: + case IS_X86_KFREEBSD32: + case IS_X86_KFREEBSD64: + { + Elf32_Ehdr ehdr; + int is32, is64; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) + || ehdr.e_ident[EI_DATA] != ELFDATA2LSB) + break; + + if (ehdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD) + break; + + is32 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_386) + && ehdr.e_ident[EI_CLASS] == ELFCLASS32); + is64 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_X86_64) + && ehdr.e_ident[EI_CLASS] == ELFCLASS64); + if (!is32 && !is64) + break; + if (!is32 && (type == IS_X86_KFREEBSD32 || type == IS_X86_KNETBSD32)) + break; + if (!is64 && (type == IS_X86_KFREEBSD64 || type == IS_X86_KNETBSD64)) + break; + ret = 1; + + break; + } + + + case IS_MIPSEL_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_MIPS) + || ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + case IS_ARM_LINUX: + { + grub_uint32_t sig; + if (grub_file_seek (file, 0x24) == (grub_size_t) -1) + break; + if (grub_file_read (file, &sig, 4) != 4) + break; + if (sig != grub_cpu_to_le32_compile_time (0x016f2818)) + break; + ret = 1; + break; + } + case IS_PAE_DOMU ... IS_DOM0: + { + struct grub_xen_file_info xen_inf; + elf = grub_xen_file (file); + if (!elf) + break; + err = grub_xen_get_info (elf, &xen_inf); + if (err) + break; + /* Unfortuntely no way to check if kernel supports dom0. */ + if (type == IS_DOM0) + ret = 1; + if (type == IS_PAE_DOMU) + ret = (xen_inf.arch == GRUB_XEN_FILE_I386_PAE + || xen_inf.arch == GRUB_XEN_FILE_I386_PAE_BIMODE); + if (type == IS_64_DOMU) + ret = (xen_inf.arch == GRUB_XEN_FILE_X86_64); + break; + } + case IS_MULTIBOOT: + case IS_MULTIBOOT2: + { + grub_uint32_t *buffer; + grub_ssize_t len; + grub_size_t search_size; + grub_uint32_t *header; + grub_uint32_t magic; + grub_size_t step; + + if (type == IS_MULTIBOOT2) + { + search_size = 32768; + magic = grub_cpu_to_le32_compile_time (0xe85250d6); + step = 2; + } + else + { + search_size = 8192; + magic = grub_cpu_to_le32_compile_time (0x1BADB002); + step = 1; + } + + buffer = grub_malloc (search_size); + if (!buffer) + break; + + len = grub_file_read (file, buffer, search_size); + if (len < 32) + { + grub_free (buffer); + break; + } + + /* Look for the multiboot header in the buffer. The header should + be at least 12 bytes and aligned on a 4-byte boundary. */ + for (header = buffer; + ((char *) header <= + (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12)) + || (header = 0); header += step) + { + if (header[0] == magic + && !(grub_le_to_cpu32 (header[0]) + + grub_le_to_cpu32 (header[1]) + + grub_le_to_cpu32 (header[2]) + + (type == IS_MULTIBOOT2 + ? grub_le_to_cpu32 (header[3]) : 0))) + break; + } + + if (header != 0) + ret = 1; + grub_free (buffer); + break; + } + case IS_X86_LINUX32: + case IS_X86_LINUX: + { + struct linux_kernel_header lh; + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + break; + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + break; + + if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) + break; + + /* FIXME: some really old kernels (< 1.3.73) will fail this. */ + if (lh.header != + grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0200) + break; + + if (type == IS_X86_LINUX) + { + ret = 1; + break; + } + + /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and + still not support 32-bit boot. */ + if (lh.header != + grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0203) + break; + + if (!(lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL)) + break; + ret = 1; + break; + } + case IS_HIBERNATED: + { + grub_uint8_t hibr_file_magic[4]; + if (grub_file_read (file, &hibr_file_magic, sizeof (hibr_file_magic)) + != sizeof (hibr_file_magic)) + break; + if (grub_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) == + 0 + || grub_memcmp ("HIBR", hibr_file_magic, + sizeof (hibr_file_magic)) == 0) + ret = 1; + break; + } + case IS_XNU64: + case IS_XNU32: + { + macho = grub_macho_open (args[0], (type == IS_XNU64)); + if (!macho) + break; + /* FIXME: more checks? */ + ret = 1; + break; + } + case IS_XNU_HIBR: + { + struct grub_xnu_hibernate_header hibhead; + if (grub_file_read (file, &hibhead, sizeof (hibhead)) + != sizeof (hibhead)) + break; + if (hibhead.magic != + grub_cpu_to_le32_compile_time (GRUB_XNU_HIBERNATE_MAGIC)) + break; + ret = 1; + break; + } + case IS_32_EFI: + case IS_64_EFI: + case IS_IA_EFI: + case IS_ARM_EFI: + { + char signature[4]; + grub_uint32_t pe_offset; + struct grub_pe32_coff_header coff_head; + + if (grub_file_read (file, signature, 2) != 2) + break; + if (signature[0] != 'M' || signature[1] != 'Z') + break; + if ((grub_ssize_t) grub_file_seek (file, 0x3c) == -1) + break; + if (grub_file_read (file, &pe_offset, 4) != 4) + break; + if ((grub_ssize_t) grub_file_seek (file, grub_le_to_cpu32 (pe_offset)) + == -1) + break; + if (grub_file_read (file, signature, 4) != 4) + break; + if (signature[0] != 'P' || signature[1] != 'E' + || signature[2] != '\0' || signature[3] != '\0') + break; + + if (grub_file_read (file, &coff_head, sizeof (coff_head)) + != sizeof (coff_head)) + break; + if (type == IS_32_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_I386)) + break; + if (type == IS_64_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_X86_64)) + break; + if (type == IS_IA_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_IA64)) + break; + if (type == IS_ARM_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED)) + break; + if (type == IS_64_EFI || type == IS_64_EFI) + { + struct grub_pe64_optional_header o64; + if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64)) + break; + if (o64.magic != + grub_cpu_to_le16_compile_time (GRUB_PE32_PE64_MAGIC)) + break; + if (o64.subsystem != + grub_cpu_to_le16_compile_time + (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) + break; + ret = 1; + break; + } + if (type == IS_32_EFI || type == IS_ARM_EFI) + { + struct grub_pe32_optional_header o32; + if (grub_file_read (file, &o32, sizeof (o32)) != sizeof (o32)) + break; + if (o32.magic != + grub_cpu_to_le16_compile_time (GRUB_PE32_PE32_MAGIC)) + break; + if (o32.subsystem != + grub_cpu_to_le16_compile_time + (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) + break; + ret = 1; + break; + } + break; + } + } + + if (elf) + grub_elf_close (elf); + else if (macho) + grub_macho_close (macho); + else if (file) + grub_file_close (file); + + if (!ret && (grub_errno == GRUB_ERR_BAD_OS || grub_errno == GRUB_ERR_NONE)) + /* TRANSLATORS: it's a standalone boolean value, + opposite of "true". */ + grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); + return grub_errno; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(file) +{ + cmd = grub_register_extcmd ("file", grub_cmd_file, 0, + "OPTIONS FILE", + N_("Check if FILE is of specified type."), + options); +} + +GRUB_MOD_FINI(file) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/file32.c b/grub-core/commands/file32.c new file mode 100644 index 000000000..0861c458d --- /dev/null +++ b/grub-core/commands/file32.c @@ -0,0 +1,5 @@ +#define GRUB_TARGET_WORDSIZE 32 +#define XX 32 +#define ehdrXX ehdr32 +#define grub_file_check_netbsdXX grub_file_check_netbsd32 +#include "fileXX.c" diff --git a/grub-core/commands/file64.c b/grub-core/commands/file64.c new file mode 100644 index 000000000..90890d481 --- /dev/null +++ b/grub-core/commands/file64.c @@ -0,0 +1,5 @@ +#define GRUB_TARGET_WORDSIZE 64 +#define XX 64 +#define ehdrXX ehdr64 +#define grub_file_check_netbsdXX grub_file_check_netbsd64 +#include "fileXX.c" diff --git a/grub-core/commands/fileXX.c b/grub-core/commands/fileXX.c new file mode 100644 index 000000000..4d5c9d7ef --- /dev/null +++ b/grub-core/commands/fileXX.c @@ -0,0 +1,68 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 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 . + */ + +#include +#include + +int +grub_file_check_netbsdXX (grub_elf_t elf) +{ + Elf_Shdr *s, *s0; + + grub_size_t shnum = elf->ehdr.ehdrXX.e_shnum; + grub_size_t shentsize = elf->ehdr.ehdrXX.e_shentsize; + grub_size_t shsize = shnum * shentsize; + grub_off_t stroff; + + if (!shnum || !shentsize) + return 0; + + s0 = grub_malloc (shsize); + if (!s0) + return 0; + + if (grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (grub_off_t) -1) + return 0; + + if (grub_file_read (elf->file, s0, shsize) != (grub_ssize_t) shsize) + return 0; + + s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize); + stroff = s->sh_offset; + + for (s = s0; s < (Elf_Shdr *) ((char *) s0 + shnum * shentsize); + s = (Elf_Shdr *) ((char *) s + shentsize)) + { + char name[sizeof(".note.netbsd.ident")]; + grub_memset (name, 0, sizeof (name)); + if (grub_file_seek (elf->file, stroff + s->sh_name) == (grub_off_t) -1) + return grub_errno; + + if (grub_file_read (elf->file, name, sizeof (name)) != (grub_ssize_t) sizeof (name)) + { + if (grub_errno) + return grub_errno; + continue; + } + if (grub_memcmp (name, ".note.netbsd.ident", + sizeof(".note.netbsd.ident")) != 0) + continue; + return 1; + } + return 0; +} diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index bcce24290..e57f8019e 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -74,15 +74,15 @@ static grub_ssize_t read_vli (grub_file_t file, grub_uint64_t *num) { grub_uint8_t buf[VLI_MAX_DIGITS]; - grub_ssize_t read; + grub_ssize_t read_bytes; grub_size_t dec; - read = grub_file_read (file, buf, VLI_MAX_DIGITS); - if (read < 0) + read_bytes = grub_file_read (file, buf, VLI_MAX_DIGITS); + if (read_bytes < 0) return -1; - dec = decode_vli (buf, read, num); - grub_file_seek (file, file->offset - (read - dec)); + dec = decode_vli (buf, read_bytes, num); + grub_file_seek (file, file->offset - (read_bytes - dec)); return dec; } diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index cbd17eb37..a32c88e97 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -707,7 +707,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) { grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); goto fail; diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c index fb7f692b2..ebbf6aa11 100644 --- a/grub-core/loader/i386/xen_file.c +++ b/grub-core/loader/i386/xen_file.c @@ -77,12 +77,17 @@ grub_xen_get_info (grub_elf_t elf, struct grub_xen_file_info * xi) { grub_memset (xi, 0, sizeof (*xi)); - if (grub_elf_is_elf64 (elf)) + if (grub_elf_is_elf64 (elf) + && elf->ehdr.ehdr64.e_machine + == grub_cpu_to_le16_compile_time (EM_X86_64) + && elf->ehdr.ehdr64.e_ident[EI_DATA] == ELFDATA2LSB) { xi->arch = GRUB_XEN_FILE_X86_64; return grub_xen_get_info64 (elf, xi); } - if (grub_elf_is_elf32 (elf)) + if (grub_elf_is_elf32 (elf) + && elf->ehdr.ehdr32.e_machine == grub_cpu_to_le16_compile_time (EM_386) + && elf->ehdr.ehdr32.e_ident[EI_DATA] == ELFDATA2LSB) { xi->arch = GRUB_XEN_FILE_I386; return grub_xen_get_info32 (elf, xi); diff --git a/include/grub/elf.h b/include/grub/elf.h index 79f56c67b..caa796390 100644 --- a/include/grub/elf.h +++ b/include/grub/elf.h @@ -2467,7 +2467,7 @@ typedef Elf32_Addr Elf32_Conflict; #define R_X86_64_NUM 24 -#ifndef GRUB_UTIL +#ifdef GRUB_TARGET_WORDSIZE #if GRUB_TARGET_WORDSIZE == 32 typedef Elf32_Addr Elf_Addr; diff --git a/include/grub/fileid.h b/include/grub/fileid.h new file mode 100644 index 000000000..ae75b6912 --- /dev/null +++ b/include/grub/fileid.h @@ -0,0 +1,29 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 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 . + */ + +#ifndef GRUB_FILEID_HEADER +#define GRUB_FILEID_HEADER 1 + +#include + +int +grub_file_check_netbsd32 (grub_elf_t elf); +int +grub_file_check_netbsd64 (grub_elf_t elf); + +#endif diff --git a/util/grub-file.c b/util/grub-file.c new file mode 100644 index 000000000..2591ecdd9 --- /dev/null +++ b/util/grub-file.c @@ -0,0 +1,107 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2012,2013 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 . + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include + +#include "progname.h" + +void grub_file_init (void); +void grub_host_init (void); +void grub_hostfs_init (void); + +int +main (int argc, char *argv[]) +{ + char **argv2; + int i; + int had_file = 0, had_separator = 0; + grub_command_t cmd; + grub_err_t err; + + grub_util_host_init (&argc, &argv); + + argv2 = xmalloc (argc * sizeof (argv)); + + if (argc == 2 && strcmp (argv[1], "--version") == 0) + { + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); + } + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == '-' + && argv[i][2] == '\0' && !had_separator) + { + had_separator = 1; + argv2[i - 1] = xstrdup (argv[i]); + continue; + } + if (argv[i][0] == '-' && !had_separator) + { + argv2[i - 1] = xstrdup (argv[i]); + continue; + } + if (had_file) + grub_util_error ("multiple files specified"); + argv2[i - 1] = canonicalize_file_name (argv[i]); + if (!argv2[i - 1]) + { + grub_util_error (_("cannot open `%s': %s"), argv[i], + strerror (errno)); + } + had_file = 1; + } + argv2[i - 1] = NULL; + + /* Initialize all modules. */ + grub_init_all (); + grub_file_init (); + grub_hostfs_init (); + grub_host_init (); + + grub_env_set ("root", "host"); + + cmd = grub_command_find ("file"); + if (! cmd) + grub_util_error (_("can't find command `%s'"), "file"); + + err = (cmd->func) (cmd, argc - 1, argv2); + if (err && err != GRUB_ERR_TEST_FAILURE) + grub_print_error (); + return err; +} diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 3390ba90f..0ca0db189 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -39,6 +39,7 @@ grub_mkconfig_dir="${sysconfdir}"/grub.d self=`basename $0` grub_probe="${sbindir}/@grub_probe@" +grub_file="${bindir}/@grub_file@" grub_editenv="${bindir}/@grub_editenv@" grub_script_check="${bindir}/@grub_script_check@" @@ -54,6 +55,7 @@ usage () { gettext "Generate a grub config file"; echo echo print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")" + print_option_help "-r, --root-directory=$(gettext DIR)" "$(gettext "use DIR as root directory [default=/]")" print_option_help "-h, --help" "$(gettext "print this message and exit")" print_option_help "-v, --version" "$(gettext "print the version information and exit")" echo @@ -71,6 +73,8 @@ argument () { echo $1 } +GRUB_ROOT= + # Check the arguments. while test $# -gt 0 do @@ -89,6 +93,11 @@ do --output=*) grub_cfg=`echo "$option" | sed 's/--output=//'` ;; + -r | --root-directory) + GRUB_ROOT=`argument $option "$@"`; shift;; + --root-directory=*) + GRUB_ROOT=`echo "$option" | sed 's/--output=//'` + ;; -*) gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 usage @@ -128,19 +137,19 @@ else fi # Device containing our userland. Typically used for root= parameter. -GRUB_DEVICE="`${grub_probe} --target=device /`" +GRUB_DEVICE="`${grub_probe} --target=device "$GRUB_ROOT"/`" GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true # Device containing our /boot partition. Usually the same as GRUB_DEVICE. -GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`" +GRUB_DEVICE_BOOT="`${grub_probe} --target=device "$GRUB_ROOT"/boot`" GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true # Filesystem for the device containing our userland. Used for stuff like # choosing Hurd filesystem module. GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`" -if [ x"$GRUB_FS" = xunknown ]; then - GRUB_FS="$(stat -f --printf=%T / || echo unknown)" +if [ x"$GRUB_FS" = x ] || [ x"$GRUB_FS" = xunknown ]; then + GRUB_FS="$(stat -f --printf=%T "$GRUB_ROOT"/ || echo unknown)" fi if test -f ${sysconfdir}/default/grub ; then @@ -177,6 +186,7 @@ if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub # These are defined in this script, export them here so that user can # override them. export GRUB_DEVICE \ + GRUB_ROOT \ GRUB_DEVICE_UUID \ GRUB_DEVICE_BOOT \ GRUB_DEVICE_BOOT_UUID \ @@ -243,18 +253,46 @@ cat << EOF # EOF -for i in ${grub_mkconfig_dir}/* ; do + +for i in "${grub_mkconfig_dir}"/* ; do case "$i" in + "${grub_mkconfig_dir}"/00_header \ + | "${grub_mkconfig_dir}"/30_os-prober \ + | "${grub_mkconfig_dir}"/40_custom \ + | "${grub_mkconfig_dir}"/41_custom) + echo + echo "### BEGIN $i ###" + "$i" + echo "### END $i ###" + ;; # emacsen backup files. FIXME: support other editors *~) ;; # emacsen autosave files. FIXME: support other editors */\#*\#) ;; *) if grub_file_is_not_garbage "$i" && test -x "$i" ; then - echo - echo "### BEGIN $i ###" - "$i" - echo "### END $i ###" + for platform in x86 i386-xen-pae x86_64-xen mips mipsel sparc64 powerpc ia64 arm; do + GRUB_PLATFORM=$platform + export GRUB_PLATFORM + buf="$($i)" + if [ x"$buf" != x ]; then + echo + echo "### BEGIN $i ($platform) ###" + case x$platform in + xx86) + echo "if [ x\"\$grub_platform\" != xxen \\( x\"\$grub_cpu\" = xi386 -o x\"\$grub_cpu\" = xx86_64 -o x\"\$grub_platform\" = x \\) ]; then" ;; + xi386-xen-pae) + echo "if [ x\"\$grub_cpu-\$grub_platform\" = xi386-xen -o x\"\$grub_cpu-\$grub_platform\" = x ]; then" ;; + xx86_64-xen) + echo "if [ x\"\$grub_cpu-\$grub_platform\" = xx86_64-xen -o x\"\$grub_cpu-\$grub_platform\" = x ]; then" ;; + *) + echo "if [ x\"\$grub_cpu\" = x$platform -o x\"\$grub_platform\" = x ]; then" ;; + esac + echo "$buf" + echo "fi" + echo "### END $i ($platform) ###" + fi + done fi ;; esac diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index a9cf7fc55..14fadbcbb 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -27,6 +27,9 @@ fi if test "x$grub_probe" = x; then grub_probe="${sbindir}/@grub_probe@" fi +if test "x$grub_file" = x; then + grub_file="${bindir}/@grub_file@" +fi if test "x$grub_mkrelpath" = x; then grub_mkrelpath="${bindir}/@grub_mkrelpath@" fi diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index a48ef2395..f4abf70a3 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -50,19 +50,9 @@ #if GRUB_TARGET_WORDSIZE == 64 typedef Elf64_Rela elf_reloc_t; -typedef Elf64_Ehdr Elf_Ehdr; -typedef Elf64_Shdr Elf_Shdr; -typedef Elf64_Sym Elf_Sym; -#define ELF_R_INFO ELF64_R_INFO -#define ELF_ST_INFO ELF64_ST_INFO #define GRUB_PE32_MACHINE GRUB_PE32_MACHINE_X86_64 #else typedef Elf32_Rel elf_reloc_t; -typedef Elf32_Ehdr Elf_Ehdr; -typedef Elf32_Shdr Elf_Shdr; -typedef Elf32_Sym Elf_Sym; -#define ELF_R_INFO ELF32_R_INFO -#define ELF_ST_INFO ELF32_ST_INFO #define GRUB_PE32_MACHINE GRUB_PE32_MACHINE_I386 #endif diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index d2e725201..88ce5ac94 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -152,7 +152,7 @@ if [ "x$gfxterm" = x1 ]; then if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT}"` ; then EOF else - for dir in "${pkgdatadir}" "`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"`" /usr/share/grub ; do + for dir in "${pkgdatadir}" "`echo "$GRUB_ROOT"'/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"`" "`echo "$GRUB_ROOT"'/usr/share/grub' | sed "s,//*,/,g"`" ; do for basename in unicode unifont ascii; do path="${dir}/${basename}.pf2" if is_path_readable_by_grub "${path}" > /dev/null ; then diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 82dfe193f..da8069bd3 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -21,6 +21,16 @@ prefix="@prefix@" exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" +if [ x$GRUB_PLATFORM = xx86 ]; then + check=--is-x86-multiboot +elif [ x$GRUB_PLATFORM = xi386-xen-pae ]; then + check=--is-i386-xen-pae-domu +elif [ x$GRUB_PLATFORM = xx86_64-xen ]; then + check=--is-x86_64-xen-domu +else + exit 0 +fi + export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR="@localedir@" @@ -40,11 +50,11 @@ all_of_them=true # FIXME: add l4 here? kernel= -for i in /boot/gnumach* ; do - if test -e $i ; then - basename=`basename $i` - dirname=`dirname $i` - rel_dirname=`make_system_path_relative_to_its_root $dirname` +for i in "$GRUB_ROOT"/boot/gnumach* ; do + if test -f "$i" && "${grub_file}" $check "$i" ; then + basename=`basename "$i"` + dirname=`dirname "$i"` + rel_dirname=`make_system_path_relative_to_its_root "$dirname"` gettext_printf "Found GNU Mach: %s" "$i" >&2 echo >&2 kernels="${kernels} ${rel_dirname}/${basename}" @@ -58,8 +68,8 @@ case "${GRUB_FS}" in *) hurd_fs="${GRUB_FS}fs" ;; esac -for i in /hurd/${hurd_fs}.static /hurd/exec ; do - if test -e "$i" ; then +for i in "$GRUB_ROOT"/hurd/${hurd_fs}.static "$GRUB_ROOT"/hurd/exec ; do + if test -f "$i" ; then gettext_printf "Found Hurd module: %s" "$i" >&2 echo >&2 at_least_one=true @@ -73,7 +83,7 @@ if ${at_least_one} ; then : ; else exit 0 fi -if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else +if ${all_of_them} && test -f "$GRUB_ROOT"/lib/ld.so.1 ; then : ; else gettext "Some Hurd stuff found, but not enough to boot." >&2 echo >&2 exit 1 diff --git a/util/grub.d/10_illumos.in b/util/grub.d/10_illumos.in index 0de616e89..00f1d6816 100644 --- a/util/grub.d/10_illumos.in +++ b/util/grub.d/10_illumos.in @@ -27,6 +27,21 @@ export TEXTDOMAINDIR="@localedir@" CLASS="--class os" +if [ x$GRUB_PLATFORM = xx86 ]; then + check=--is-x86-multiboot +elif [ x$GRUB_PLATFORM = xi386-xen-pae ]; then + check=--is-i386-xen-pae-domu +elif [ x$GRUB_PLATFORM = xx86_64-xen ]; then + check=--is-x86_64-xen-domu +else + exit 0 +fi + +if ! test -f "$GRUB_ROOT"/platform/i86pc/kernel || ! "${grub_file}" $check "$GRUB_ROOT"/platform/i86pc/kernel; then + exit 0 +fi + + case "${GRUB_DISTRIBUTOR}" in *) OS="Illumos" @@ -45,7 +60,7 @@ message="$(gettext_printf "Loading kernel of Illumos ...")" else ISADIR= fi - zfs-bootfs $($grub_mkrelpath /) ZFS_BOOTFS + zfs-bootfs $($grub_mkrelpath "$GRUB_ROOT"/) ZFS_BOOTFS echo '$(echo "$message" | grub_quote)' multiboot $($grub_mkrelpath /platform/i86pc/kernel)/\$ISADIR/unix /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS_BOOTFS,console=text module $($grub_mkrelpath /platform/i86pc)/\$ISADIR/boot_archive /platform/i86pc/\$ISADIR/boot_archive diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index a524762fc..f4aa450bb 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -27,6 +27,16 @@ export TEXTDOMAINDIR="@localedir@" CLASS="--class os" +if [ x$GRUB_PLATFORM = xx86 ]; then + check=--is-x86-kfreebsd +elif [ x$GRUB_PLATFORM = xi386-xen-pae ]; then + check=--is-i386-xen-pae-domu +elif [ x$GRUB_PLATFORM = xx86_64-xen ]; then + check=--is-x86_64-xen-domu +else + exit 0 +fi + case "${GRUB_DISTRIBUTOR}" in Debian) OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" @@ -122,10 +132,10 @@ EOF zfs) load_kfreebsd_module opensolaris false - ls "/boot/zfs/zpool.cache" > /dev/null + ls "$GRUB_ROOT/boot/zfs/zpool.cache" > /dev/null printf '%s\n' "${prepare_boot_cache}" sed "s/^/$submenu_indentation/" << EOF - kfreebsd_module $(make_system_path_relative_to_its_root /boot)/zfs/zpool.cache type=/boot/zfs/zpool.cache + kfreebsd_module $(make_system_path_relative_to_its_root $GRUB_ROOT/boot)/zfs/zpool.cache type=/boot/zfs/zpool.cache EOF ;; esac @@ -143,8 +153,8 @@ EOF EOF } -list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do - if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi +list=`for i in $GRUB_ROOT/boot/kfreebsd-* $GRUB_ROOT/boot/kernel/kernel ; do + if grub_file_is_not_garbage "$i" && ${grub_file} $check "$i"; then echo -n "$i " ; fi done` prepare_boot_cache= boot_device_id= @@ -163,8 +173,8 @@ while [ "x$list" != "x" ] ; do dirname=`dirname $kfreebsd` rel_dirname=`make_system_path_relative_to_its_root $dirname` - if [ -f /boot/device.hints ] ; then - devices=/boot/device.hints + if [ -f "$GRUB_ROOT"/boot/device.hints ] ; then + devices="$GRUB_ROOT"/boot/device.hints devices_basename=`basename $devices` devices_dirname=`dirname $devices` devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname` @@ -181,14 +191,14 @@ while [ "x$list" != "x" ] ; do # zpool name kfreebsd_device=$(${grub_probe} -t fs_label --device ${GRUB_DEVICE}) # filesystem name (empty string for the main filesystem) - kfreebsd_device="${kfreebsd_device}$(${grub_mkrelpath} / | sed -e "s,/*@$,,")" + kfreebsd_device="${kfreebsd_device}$(${grub_mkrelpath} "$GRUB_ROOT"/ | sed -e "s,/*@$,,")" ;; *) kfreebsd_device=${kfreebsd_fs}id/${GRUB_DEVICE_UUID} # Debian GNU/kFreeBSD can't remount root if it's supplied as UUID but # as an UUID if [ "x${GRUB_DISTRIBUTOR}" = "xDebian" ] \ - && ! (cat /etc/fstab | awk '!/^[[:space:]]*#/ && $2=="/" { print $1; }' \ + && ! (cat "$GRUB_ROOT"/etc/fstab | awk '!/^[[:space:]]*#/ && $2=="/" { print $1; }' \ | grep "${kfreebsd_fs}id/${GRUB_DEVICE_UUID}" > /dev/null); then kfreebsd_device=${GRUB_DEVICE} fi @@ -199,8 +209,8 @@ while [ "x$list" != "x" ] ; do alt_version=`echo $version | sed -e "s,\.old$,,g"` module_dir= - for i in "/lib/modules/${version}" "/lib/modules/${alt_version}" \ - "/boot/kernel"; do + for i in "$GRUB_ROOT/lib/modules/${version}" "$GRUB_ROOT/lib/modules/${alt_version}" \ + "$GRUB_ROOT/boot/kernel"; do if test -e "$i" ; then module_dir="$i" break diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 00d193159..e904d1edf 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -26,6 +26,31 @@ datarootdir="@datarootdir@" export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR="@localedir@" +if [ x$GRUB_PLATFORM = xx86 ]; then + check=--is-x86-linux32 +elif [ x$GRUB_PLATFORM = xi386-xen-pae ]; then + check=--is-i386-xen-pae-domu +elif [ x$GRUB_PLATFORM = xx86_64-xen ]; then + check=--is-x86_64-xen-domu +else + check=--is-${GRUB_PLATFORM}-linux +fi + +case "x$GRUB_PLATFORM" in + xx86) + list=`for i in "$GRUB_ROOT"/boot/vmlinuz-* "$GRUB_ROOT"/vmlinuz-* "$GRUB_ROOT"/boot/kernel-* ; do + if grub_file_is_not_garbage "$i" && "${grub_file}" $check "$i" ; then echo -n "$i " ; fi + done` ;; + *) + list=`for i in "$GRUB_ROOT"/boot/vmlinuz-* "$GRUB_ROOT"/boot/vmlinux-* "$GRUB_ROOT"/vmlinuz-* "$GRUB_ROOT"/vmlinux-* "$GRUB_ROOT"/boot/kernel-* ; do + if grub_file_is_not_garbage "$i" && "${grub_file}" $check "$i" ; then echo -n "$i " ; fi + done` ;; +esac + +if [ x"$list" = x ]; then + exit 0 +fi + CLASS="--class gnu-linux --class gnu --class os" if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then @@ -53,14 +78,14 @@ fi case x"$GRUB_FS" in xbtrfs) - rootsubvol="`make_system_path_relative_to_its_root /`" + rootsubvol="`make_system_path_relative_to_its_root "$GRUB_ROOT"/`" rootsubvol="${rootsubvol#/}" if [ "x${rootsubvol}" != x ]; then GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" fi;; xzfs) rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true` - bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`" + bootfs="`make_system_path_relative_to_its_root "$GRUB_ROOT"/ | sed -e "s,@$,,"`" LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs}" ;; esac @@ -115,7 +140,7 @@ linux_entry () echo " insmod gzio" | sed "s/^/$submenu_indentation/" - if [ x$dirname = x/ ]; then + if [ x$dirname = x"$GRUB_ROOT"/ ]; then if [ -z "${prepare_root_cache}" ]; then prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)" fi @@ -144,24 +169,12 @@ EOF EOF } -machine=`uname -m` -case "x$machine" in - xi?86 | xx86_64) - list=`for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do - if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi - done` ;; - *) - list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do - if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi - done` ;; -esac - -case "$machine" in - i?86) GENKERNEL_ARCH="x86" ;; +case "$GRUB_PLATFORM" in + x86 | i386-xen-pae | x86_64-xen) GENKERNEL_ARCH="x86" ;; mips|mips64) GENKERNEL_ARCH="mips" ;; mipsel|mips64el) GENKERNEL_ARCH="mipsel" ;; arm*) GENKERNEL_ARCH="arm" ;; - *) GENKERNEL_ARCH="$machine" ;; + *) GENKERNEL_ARCH="$GRUB_PLATFORM" ;; esac prepare_boot_cache= @@ -200,7 +213,7 @@ while [ "x$list" != "x" ] ; do done config= - for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do + for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "$GRUB_ROOT/etc/kernels/kernel-config-${version}" ; do if test -e "${i}" ; then config="${i}" break diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index 29a0e41a9..b1aba65c1 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -22,6 +22,16 @@ exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" . "@datadir@/@PACKAGE@/grub-mkconfig_lib" +if [ x$GRUB_PLATFORM = xx86 ]; then + check=--is-x86-kfreebsd +elif [ x$GRUB_PLATFORM = xi386-xen-pae ]; then + check=--is-i386-xen-pae-domu +elif [ x$GRUB_PLATFORM = xx86_64-xen ]; then + check=--is-x86_64-xen-domu +else + exit 0 +fi + export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR="@localedir@" @@ -36,19 +46,13 @@ netbsd_load_fs_module () loader="$1" # "knetbsd" or "multiboot" kernel="$2" # absolute path to the kernel file - case $(zcat -f "${kernel}" | file -bL - | cut -d , -f 2 | tr -d ' ') in - Intel80386) - karch="i386" - ;; - x86-64) + if "${grub_file}" --is-x86_64-kfreebsd "${kernel}"; then karch="amd64" - ;; - *) - return - ;; - esac + else + karch="i386" + fi - case $(${grub_probe} --target=fs -d ${GRUB_DEVICE}) in + case $GRUB_FS in ext2) kmod="ext2fs" ;; @@ -67,7 +71,7 @@ netbsd_load_fs_module () esac kversion=$(zcat -f "${kernel}" | strings | sed -n -e '/^@(#)NetBSD/ { s/^@(#)NetBSD \([0-9\.]*\) .*$/\1/g ; p ; q ; }') - kmodule="/stand/${karch}/${kversion}/modules/${kmod}/${kmod}.kmod" + kmodule="$GRUB_ROOT/stand/${karch}/${kversion}/modules/${kmod}/${kmod}.kmod" if test -z "$karch" -o -z "$kversion" -o ! -f "${kmodule}"; then return @@ -94,6 +98,10 @@ netbsd_entry () type="$3" args="$4" # extra arguments appended to loader command + if [ "x${loader}" = xmultiboot ] && [ x$GRUB_PLATFORM = xx86 ] && ! "$grub_file" --is-x86-multiboot "$kernel"; then + return + fi + kroot_device="$(echo ${GRUB_DEVICE} | sed -e 's,^/dev/r,,')" if [ -z "$boot_device_id" ]; then @@ -147,10 +155,13 @@ pattern="^ELF[^,]*executable.*statically linked" submenu_indentation="" is_top_level=true -for k in /netbsd $(ls -t /netbsd?* 2>/dev/null) ; do +for k in "$GRUB_ROOT"/netbsd $(ls -t "$GRUB_ROOT"/netbsd?* 2>/dev/null) ; do if ! grub_file_is_not_garbage "$k" ; then continue fi + if ! "$grub_file" $check "$k"; then + continue + fi if ! (zcat -f "$k" | file -bL - | grep -q "${pattern}") 2>/dev/null ; then continue fi diff --git a/util/grub.d/10_xnu.in b/util/grub.d/10_xnu.in index 4270385f3..54c06135c 100644 --- a/util/grub.d/10_xnu.in +++ b/util/grub.d/10_xnu.in @@ -26,18 +26,28 @@ export TEXTDOMAINDIR="@localedir@" . "@datadir@/@PACKAGE@/grub-mkconfig_lib" +if [ x$GRUB_PLATFORM != xx86 ]; then + exit 0 +fi + osx_entry() { if [ x$2 = x32 ]; then # TRANSLATORS: it refers to kernel architecture (32-bit) bitstr="$(gettext "(32-bit)")" + if ! [ -f "$GRUB_ROOT"/mach_kernel ] || ! "${grub_file}" --is-i386-xnu "$GRUB_ROOT"/mach_kernel; then + return; + fi else # TRANSLATORS: it refers to kernel architecture (64-bit) bitstr="$(gettext "(64-bit)")" + if ! [ -f "$GRUB_ROOT"/mach_kernel ] || ! "${grub_file}" --is-x86_64-xnu "$GRUB_ROOT"/mach_kernel; then + return; + fi fi # TRANSLATORS: it refers on the OS residing on device %s onstr="$(gettext_printf "(on %s)" "${GRUB_DEVICE}")" cat << EOF -menuentry '$(echo "Darwin/Mac OS X $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${GRUB_DEVICE}")' { +menuentry '$(echo "Darwin/Mac OS X $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'xnu-$2-$(grub_get_device_id "${GRUB_DEVICE}")' { EOF save_default_entry | grub_add_tab prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab @@ -50,7 +60,7 @@ EOF fi fi if [ \$do_resume = 0 ]; then - xnu_uuid ${OSXUUID} uuid + xnu_uuid ${GRUB_DEVICE_UUID} uuid if [ -f /Extra/DSDT.aml ]; then acpi -e /Extra/DSDT.aml fi @@ -90,6 +100,5 @@ EOF EOF } -OSXUUID="`${grub_probe} --target=fs_uuid --device ${GRUB_DEVICE} 2> /dev/null`" osx_entry xnu_kernel 32 osx_entry xnu_kernel64 64 diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index a60843500..fbc1ce004 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -26,6 +26,10 @@ datarootdir="@datarootdir@" export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR="@localedir@" +if [ x$GRUB_PLATFORM != xx86 ]; then + exit 0 +fi + CLASS="--class gnu-linux --class gnu --class os --class xen" if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then @@ -61,14 +65,14 @@ fi case x"$GRUB_FS" in xbtrfs) - rootsubvol="`make_system_path_relative_to_its_root /`" + rootsubvol="`make_system_path_relative_to_its_root "$GRUB_ROOT"/`" rootsubvol="${rootsubvol#/}" if [ "x${rootsubvol}" != x ]; then GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" fi;; xzfs) rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true` - bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`" + bootfs="`make_system_path_relative_to_its_root "$GRUB_ROOT"/ | sed -e "s,@$,,"`" LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs}" ;; esac @@ -137,19 +141,9 @@ EOF EOF } -linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do - if grub_file_is_not_garbage "$i"; then - basename=$(basename $i) - version=$(echo $basename | sed -e "s,^[^0-9]*-,,g") - dirname=$(dirname $i) - config= - for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do - if test -e "${j}" ; then - config="${j}" - break - fi - done - if (grep -qx "CONFIG_XEN_DOM0=y" "${config}" 2> /dev/null || grep -qx "CONFIG_XEN_PRIVILEGED_GUEST=y" "${config}" 2> /dev/null); then echo -n "$i " ; fi +linux_list=`for i in "$GRUB_ROOT"/boot/vmlinu[xz]-* "$GRUB_ROOT"/vmlinu[xz]-* "$GRUB_ROOT"/boot/kernel-*; do + if grub_file_is_not_garbage "$i" && "${grub_file}" --is-x86-xen-dom0 "$i"; then + echo -n "$i " ; fi done` if [ "x${linux_list}" = "x" ] ; then @@ -165,8 +159,8 @@ file_is_not_sym () { esac } -xen_list=`for i in /boot/xen*; do - if grub_file_is_not_garbage "$i" && file_is_not_sym "$i" ; then echo -n "$i " ; fi +xen_list=`for i in "$GRUB_ROOT"/boot/xen*; do + if grub_file_is_not_garbage "$i" && file_is_not_sym "$i" && ${grub_file} --is-x86-multiboot "$i"; then echo -n "$i " ; fi done` prepare_boot_cache= boot_device_id=