From cd46aa6cefabd7b0fcb15cd614577e1ab8c7a841 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 16 Nov 2013 20:21:16 +0100 Subject: [PATCH] Rewrite grub-install, grub-mkrescue, grub-mkstandalone and grub-mknetdir the function of these files exceeds what can be sanely handled in shell in posix-comaptible way. Also writing it in C extends the functionality to non-UNIX-like OS and minimal environments. --- ChangeLog | 12 + Makefile.am | 22 + Makefile.util.def | 158 ++- configure.ac | 24 +- grub-core/Makefile.am | 7 + grub-core/kern/emu/hostdisk.c | 75 ++ grub-core/osdep/aros/config.c | 94 ++ grub-core/osdep/aros/hostdisk.c | 62 + grub-core/osdep/basic/compress.c | 21 + grub-core/osdep/basic/init.c | 9 +- grub-core/osdep/basic/no_platform.c | 46 + grub-core/osdep/basic/platform.c | 26 + grub-core/osdep/compress.c | 5 + grub-core/osdep/config.c | 7 + grub-core/osdep/linux/platform.c | 85 ++ grub-core/osdep/platform.c | 7 + grub-core/osdep/platform_unix.c | 3 + grub-core/osdep/unix/compress.c | 41 + grub-core/osdep/unix/config.c | 139 +++ grub-core/osdep/unix/exec.c | 45 + grub-core/osdep/unix/hostdisk.c | 46 + grub-core/osdep/unix/platform.c | 213 ++++ grub-core/osdep/windows/config.c | 57 + grub-core/osdep/windows/hostdisk.c | 111 ++ grub-core/osdep/windows/init.c | 51 +- include/grub/emu/config.h | 48 + include/grub/emu/getroot.h | 12 + include/grub/emu/hostfile.h | 13 + include/grub/osdep/exec_unix.h | 39 + include/grub/osdep/hostfile_aros.h | 10 +- include/grub/osdep/hostfile_unix.h | 6 + include/grub/osdep/hostfile_windows.h | 3 + include/grub/util/install.h | 149 +++ po/Makefile.in.in | 4 +- po/Rules-windowsdir | 11 + tests/util/grub-shell.in | 6 +- util/config.c | 112 ++ util/grub-install-common.c | 863 ++++++++++++++ util/grub-install.c | 1539 +++++++++++++++++++++++++ util/grub-install.in | 829 ------------- util/grub-install_header | 263 ----- util/grub-mkimage.c | 13 +- util/grub-mknetdir.c | 212 ++++ util/grub-mknetdir.in | 183 --- util/grub-mkrescue.c | 827 +++++++++++++ util/grub-mkrescue.in | 493 -------- util/grub-mkstandalone.c | 372 ++++++ util/grub-mkstandalone.in | 130 --- util/grub-probe.c | 175 +-- util/misc.c | 14 +- util/mkimage.c | 48 +- util/probe.c | 172 +++ 52 files changed, 5811 insertions(+), 2101 deletions(-) create mode 100644 grub-core/osdep/aros/config.c create mode 100644 grub-core/osdep/basic/compress.c create mode 100644 grub-core/osdep/basic/no_platform.c create mode 100644 grub-core/osdep/basic/platform.c create mode 100644 grub-core/osdep/compress.c create mode 100644 grub-core/osdep/config.c create mode 100644 grub-core/osdep/linux/platform.c create mode 100644 grub-core/osdep/platform.c create mode 100644 grub-core/osdep/platform_unix.c create mode 100644 grub-core/osdep/unix/compress.c create mode 100644 grub-core/osdep/unix/config.c create mode 100644 grub-core/osdep/unix/platform.c create mode 100644 grub-core/osdep/windows/config.c create mode 100644 include/grub/emu/config.h create mode 100644 include/grub/osdep/exec_unix.h create mode 100644 po/Rules-windowsdir create mode 100644 util/config.c create mode 100644 util/grub-install-common.c create mode 100644 util/grub-install.c delete mode 100644 util/grub-install.in delete mode 100644 util/grub-install_header create mode 100644 util/grub-mknetdir.c delete mode 100644 util/grub-mknetdir.in create mode 100644 util/grub-mkrescue.c delete mode 100644 util/grub-mkrescue.in create mode 100644 util/grub-mkstandalone.c delete mode 100644 util/grub-mkstandalone.in create mode 100644 util/probe.c diff --git a/ChangeLog b/ChangeLog index 9b0a85937..46be8e6d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2013-11-16 Andrey Borzenkov + + * util/grub-install.c (device_map_check_duplicates): Fix incorrect + order of qsort arguments (number of elements vs. element size). + +2013-11-16 Vladimir Serbinenko + + Rewrite grub-install, grub-mkrescue, grub-mkstandalone and grub-mknetdir + the function of these files exceeds what can be sanely handled in shell + in posix-comaptible way. Also writing it in C extends the functionality + to non-UNIX-like OS and minimal environments. + 2013-11-16 Vladimir Serbinenko * grub-core/kern/arm/cache.S: Don't switch back to ARM mode when diff --git a/Makefile.am b/Makefile.am index 03ef96491..114c20045 100644 --- a/Makefile.am +++ b/Makefile.am @@ -397,5 +397,27 @@ default_payload.elf: grub-mkstandalone grub-mkimage pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump setpci lsacpi chain' --fonts= --themes= --locales= -d grub-core/ endif +windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + test -d $(windowsdir) && rm -rf $(windowsdir) || true + test -d $(windowsdir) || mkdir $(windowsdir) + $(MAKE) -C po $(AM_MAKEFLAGS) windowsdir + $(MAKE) -C grub-core $(AM_MAKEFLAGS) windowsdir + test -d $(windowsdir)/themes || mkdir $(windowsdir)/themes + test -d $(windowsdir)/themes/starfield || mkdir $(windowsdir)/themes/starfield + for x in $(PROGRAMS); do \ + $(STRIP) $$x -o $(windowsdir)/$$x; \ + done + for x in $(pkgdata_DATA); do \ + cp -fp $$x $(windowsdir)/$$x; \ + done + for x in $(starfield_DATA); do \ + cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \ + done + +windowszip=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows.zip +windowszip: windowsdir + test -f $(windowszip) && rm $(windowszip) || true + zip -r $(windowszip) $(windowsdir) EXTRA_DIST += linguas.sh diff --git a/Makefile.util.def b/Makefile.util.def index f2a305fd3..ede74687e 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -171,6 +171,10 @@ program = { common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/osdep/init.c; + common = grub-core/osdep/config.c; + extra_dist = grub-core/osdep/windows/config.c; + extra_dist = grub-core/osdep/unix/config.c; + common = util/config.c; common = grub-core/kern/arm/dl_helper.c; @@ -310,6 +314,7 @@ program = { installdir = sbin; mansection = 8; common = util/grub-probe.c; + common = util/probe.c; common = grub-core/osdep/ofpath.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/osdep/init.c; @@ -479,38 +484,165 @@ script = { installdir = grubconf; }; -script = { +program = { mansection = 1; name = grub-mkrescue; - common = util/grub-install_header; - common = util/grub-mkrescue.in; - enable = noemu; + + common = util/grub-mkrescue.c; + common = util/render-label.c; + common = util/glue-efi.c; + common = util/mkimage.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + extra_dist = grub-core/osdep/unix/compress.c; + extra_dist = grub-core/osdep/basic/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + common = grub-core/kern/arm/dl_helper.c; + + common = util/resolve.c; + + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + + condition = COND_HAVE_EXEC; }; -script = { +program = { mansection = 1; name = grub-mkstandalone; - common = util/grub-install_header; - common = util/grub-mkstandalone.in; + common = util/grub-mkstandalone.c; + + common = util/render-label.c; + common = util/glue-efi.c; + common = util/mkimage.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + extra_dist = grub-core/osdep/linux/platform.c; + extra_dist = grub-core/osdep/basic/platform.c; + extra_dist = grub-core/osdep/basic/no_platform.c; + extra_dist = grub-core/osdep/unix/platform.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + common = grub-core/kern/arm/dl_helper.c; + + common = util/resolve.c; + + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; -script = { +program = { mansection = 8; installdir = sbin; name = grub-install; - common = util/grub-install_header; - common = util/grub-install.in; + common = util/grub-install.c; + common = util/probe.c; + common = util/mkimage.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/arm/dl_helper.c; + + common = util/resolve.c; enable = noemu; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; -script = { +program = { mansection = 1; installdir = bin; name = grub-mknetdir; - common = util/grub-install_header; - common = util/grub-mknetdir.in; + common = util/grub-mknetdir.c; + + common = util/mkimage.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/arm/dl_helper.c; + + common = util/resolve.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; script = { diff --git a/configure.ac b/configure.ac index 18429103b..9f8fb8a35 100644 --- a/configure.ac +++ b/configure.ac @@ -75,14 +75,10 @@ if test "x$TARGET_CFLAGS" = x; then TARGET_CFLAGS="$TARGET_CFLAGS -Os" fi -BUILD_CPPFLAGS="$BUILD_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\"" - # Default HOST_CPPFLAGS HOST_CPPFLAGS="$HOST_CPPFLAGS -Wall -W" HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_UTIL=1" -HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_LIBDIR=\\\"\$(pkglibdir)\\\"" -HOST_CPPFLAGS="$HOST_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\"" TARGET_CPPFLAGS="$TARGET_CPPFLAGS -Wall -W" TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include" @@ -192,6 +188,12 @@ case "$host_os" in cygwin | windows* | mingw32*) host_kernel=windows ;; esac +case "$host_os" in + cygwin | windows* | mingw32*) have_exec=n ;; + aros*) have_exec=n ;; + *) have_exec=y;; +esac + case "$platform" in coreboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_COREBOOT=1" ;; multiboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MULTIBOOT=1" ;; @@ -1458,6 +1460,20 @@ AM_CONDITIONAL([COND_HAVE_CXX], [test x$HAVE_CXX = xyes]) AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) AM_CONDITIONAL([COND_CYGWIN], [test x$target_os = xcygwin]) AM_CONDITIONAL([COND_STARFIELD], [test "x$starfield_excuse" = x]) +AM_CONDITIONAL([COND_HAVE_EXEC], [test "x$have_exec" = xy]) + +test "x$prefix" = xNONE && prefix="$ac_default_prefix" +test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" +datarootdir="$(eval echo "$datarootdir")" +grub_libdir="$(eval echo "$libdir")" +grub_localedir="$(eval echo "$localedir")" +grub_datadir="$(eval echo "$datadir")" +grub_sysconfdir="$(eval echo "$sysconfdir")" +AC_DEFINE_UNQUOTED(LOCALEDIR, "$grub_localedir", [Locale dir]) +AC_DEFINE_UNQUOTED(GRUB_LIBDIR, "$grub_libdir", [Library dir]) +AC_DEFINE_UNQUOTED(GRUB_DATADIR, "$grub_datadir", [Data dir]) +AC_DEFINE_UNQUOTED(GRUB_SYSCONFDIR, "$grub_sysconfdir", [Configuration dir]) + # Output files. cpudir="${target_cpu}" diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 025bbded3..151b9339a 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -428,3 +428,10 @@ efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF) platform_DATA += efiemu32.o efiemu64.o CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o endif + +windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform) + for x in $(platform_DATA); do \ + cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \ + done diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index e00c8fbed..08ae65478 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -609,3 +609,78 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk) return map[disk->id].device; } + + +static char * +grub_util_path_concat_real (size_t n, int ext, va_list ap) +{ + size_t totlen = 0; + char **l = xmalloc ((n + ext) * sizeof (l[0])); + char *r, *p, *pi; + size_t i; + int first = 1; + + for (i = 0; i < n + ext; i++) + { + l[i] = va_arg (ap, char *); + if (l[i]) + totlen += strlen (l[i]) + 1; + } + + r = xmalloc (totlen + 10); + + p = r; + for (i = 0; i < n; i++) + { + pi = l[i]; + if (!pi) + continue; + while (*pi == '/') + pi++; + if ((p != r || (pi != l[i] && first)) && (p == r || *(p - 1) != '/')) + *p++ = '/'; + first = 0; + p = grub_stpcpy (p, pi); + while (p != r && p != r + 1 && *(p - 1) == '/') + p--; + } + + if (ext && l[i]) + p = grub_stpcpy (p, l[i]); + + *p = '\0'; + + free (l); + + return r; +} + +char * +grub_util_path_concat (size_t n, ...) +{ + va_list ap; + char *r; + + va_start (ap, n); + + r = grub_util_path_concat_real (n, 0, ap); + + va_end (ap); + + return r; +} + +char * +grub_util_path_concat_ext (size_t n, ...) +{ + va_list ap; + char *r; + + va_start (ap, n); + + r = grub_util_path_concat_real (n, 1, ap); + + va_end (ap); + + return r; +} diff --git a/grub-core/osdep/aros/config.c b/grub-core/osdep/aros/config.c new file mode 100644 index 000000000..99f3009e2 --- /dev/null +++ b/grub-core/osdep/aros/config.c @@ -0,0 +1,94 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,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 +#include +#include + +const char * +grub_util_get_config_filename (void) +{ + static char *value = NULL; + if (!value) + value = grub_util_path_concat (3, GRUB_SYSCONFDIR, + "default", "grub"); + return value; +} + +const char * +grub_util_get_pkgdatadir (void) +{ + const char *ret = getenv ("pkgdatadir"); + if (ret) + return ret; + return GRUB_DATADIR "/" PACKAGE; +} + +const char * +grub_util_get_pkglibdir (void) +{ + return GRUB_LIBDIR "/" PACKAGE; +} + +const char * +grub_util_get_localedir (void) +{ + return LOCALEDIR; +} + +void +grub_util_load_config (struct grub_util_config *cfg) +{ + const char *cfgfile; + FILE *f = NULL; + const char *v; + + memset (cfg, 0, sizeof (*cfg)); + + v = getenv ("GRUB_ENABLE_CRYPTODISK"); + if (v && v[0] == 'y' && v[1] == '\0') + cfg->is_cryptodisk_enabled = 1; + + v = getenv ("GRUB_DISTRIBUTOR"); + if (v) + cfg->grub_distributor = xstrdup (v); + + cfgfile = grub_util_get_config_filename (); + if (!grub_util_is_regular (cfgfile)) + return; + + f = grub_util_fopen (cfgfile, "r"); + if (f) + { + grub_util_parse_config (f, cfg, 0); + fclose (f); + } + else + grub_util_warn (_("cannot open config file `%s': %s"), + cfgfile, strerror (errno)); +} diff --git a/grub-core/osdep/aros/hostdisk.c b/grub-core/osdep/aros/hostdisk.c index 3fe442cf5..9c0a6c895 100644 --- a/grub-core/osdep/aros/hostdisk.c +++ b/grub-core/osdep/aros/hostdisk.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -516,6 +517,17 @@ grub_util_is_directory (const char *path) return S_ISDIR (st.st_mode); } +int +grub_util_is_regular (const char *path) +{ + struct stat st; + + if (stat (path, &st) == -1) + return 0; + + return S_ISREG (st.st_mode); +} + int grub_util_is_special_file (const char *path) { @@ -525,3 +537,53 @@ grub_util_is_special_file (const char *path) return 1; return (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)); } + +static char * +get_temp_name (void) +{ + static int ctr = 0; + char *t; + struct stat st; + + while (1) + { + t = xasprintf ("T:grub.%d.%d.%d.%d", (int) getpid (), (int) getppid (), + ctr++, time (0)); + if (stat (t, &st) == -1) + return t; + free (t); + } +} + +char * +grub_util_make_temporary_file (void) +{ + char *ret = get_temp_name (); + FILE *f; + + f = grub_util_fopen (ret, "wb"); + if (f) + fclose (f); + return ret; +} + +char * +grub_util_make_temporary_dir (void) +{ + char *ret = get_temp_name (); + + grub_util_mkdir (ret); + + return ret; +} + +grub_uint32_t +grub_util_get_mtime (const char *path) +{ + struct stat st; + + if (stat (path, &st) == -1) + return 0; + + return st.st_mtime; +} diff --git a/grub-core/osdep/basic/compress.c b/grub-core/osdep/basic/compress.c new file mode 100644 index 000000000..463ce4242 --- /dev/null +++ b/grub-core/osdep/basic/compress.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int +grub_install_compress_gzip (const char *src, const char *dest) +{ + grub_util_error ("no compression is available for your platform"); +} + +int +grub_install_compress_xz (const char *src, const char *dest) +{ + grub_util_error ("no compression is available for your platform"); +} + +int +grub_install_compress_lzop (const char *src, const char *dest) +{ + grub_util_error ("no compression is available for your platform"); +} diff --git a/grub-core/osdep/basic/init.c b/grub-core/osdep/basic/init.c index f4a673b64..c54c710db 100644 --- a/grub-core/osdep/basic/init.c +++ b/grub-core/osdep/basic/init.c @@ -20,6 +20,7 @@ #include #include +#include #include "progname.h" @@ -29,7 +30,9 @@ grub_util_host_init (int *argc __attribute__ ((unused)), { set_program_name ((*argv)[0]); -#ifdef GRUB_UTIL - grub_util_init_nls (); -#endif +#if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS) + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } diff --git a/grub-core/osdep/basic/no_platform.c b/grub-core/osdep/basic/no_platform.c new file mode 100644 index 000000000..32be5e8e3 --- /dev/null +++ b/grub-core/osdep/basic/no_platform.c @@ -0,0 +1,46 @@ +/* + * 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 "platform.c" + +void +grub_install_register_ieee1275 (int is_prep, const char *install_device, + int partno, const char *relpath) +{ + grub_util_error ("%s", "no IEEE1275 routines are available for your platform"); +} + +void +grub_install_register_efi (const char *efidir_disk, int efidir_part, + const char *efifile_path, + const char *efi_distributor) +{ + grub_util_error ("%s", "no EFI routines are available for your platform"); +} + +void +grub_install_sgi_setup (const char *install_device, + const char *imgfile, const char *destname) +{ + grub_util_error ("%s", "no SGI routines are available for your platform"); +} diff --git a/grub-core/osdep/basic/platform.c b/grub-core/osdep/basic/platform.c new file mode 100644 index 000000000..4b5502aeb --- /dev/null +++ b/grub-core/osdep/basic/platform.c @@ -0,0 +1,26 @@ +/* + * 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 + +const char * +grub_install_get_default_x86_platform (void) +{ + return "i386-pc"; +} + diff --git a/grub-core/osdep/compress.c b/grub-core/osdep/compress.c new file mode 100644 index 000000000..cc808d029 --- /dev/null +++ b/grub-core/osdep/compress.c @@ -0,0 +1,5 @@ +#if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__AROS__) +#include "unix/compress.c" +#else +#include "basic/compress.c" +#endif diff --git a/grub-core/osdep/config.c b/grub-core/osdep/config.c new file mode 100644 index 000000000..b9f781972 --- /dev/null +++ b/grub-core/osdep/config.c @@ -0,0 +1,7 @@ +#if defined (__MINGW32__) && !defined (__CYGWIN__) +#include "windows/config.c" +#elif defined (__AROS__) +#include "aros/config.c" +#else +#include "unix/config.c" +#endif diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c new file mode 100644 index 000000000..ec67aad35 --- /dev/null +++ b/grub-core/osdep/linux/platform.c @@ -0,0 +1,85 @@ +/* + * 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 + +static int +is_not_empty_directory (const char *dir) +{ + DIR *d; + struct dirent *de; + + d = opendir (dir); + if (!d) + return 0; + while ((de = readdir (d))) + { + if (strcmp (de->d_name, ".") == 0 + || strcmp (de->d_name, "..") == 0) + continue; + closedir (d); + return 1; + } + + closedir (d); + return 0; +} + +static int +is_64_kernel (void) +{ + struct utsname un; + + if (uname (&un) < 0) + return 0; + + return strcmp (un.machine, "x86_64") == 0; +} + +const char * +grub_install_get_default_x86_platform (void) +{ + /* + On Linux, we need the efivars kernel modules. + If no EFI is available this module just does nothing + besides a small hello and if we detect efi we'll load it + anyway later. So it should be safe to + try to load it here. + */ + grub_util_exec ((const char * []){ "modprobe", "-q", + "efivars", NULL }); + if (is_not_empty_directory ("/sys/firmware/efi")) + { + if (is_64_kernel ()) + return "x86_64-efi"; + else + return "i386-efi"; + } + else if (is_not_empty_directory ("/proc/device-tree")) + return "i386-ieee1275"; + else + return "i386-pc"; +} diff --git a/grub-core/osdep/platform.c b/grub-core/osdep/platform.c new file mode 100644 index 000000000..f7202642f --- /dev/null +++ b/grub-core/osdep/platform.c @@ -0,0 +1,7 @@ +#ifdef __linux__ +#include "linux/platform.c" +#elif defined (__MINGW32__) || defined (__CYGWIN__) || defined (__AROS__) +#include "basic/no_platform.c" +#else +#include "basic/platform.c" +#endif diff --git a/grub-core/osdep/platform_unix.c b/grub-core/osdep/platform_unix.c new file mode 100644 index 000000000..db6a02dd1 --- /dev/null +++ b/grub-core/osdep/platform_unix.c @@ -0,0 +1,3 @@ +#if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__AROS__) +#include "unix/platform.c" +#endif diff --git a/grub-core/osdep/unix/compress.c b/grub-core/osdep/unix/compress.c new file mode 100644 index 000000000..dee56207f --- /dev/null +++ b/grub-core/osdep/unix/compress.c @@ -0,0 +1,41 @@ +/* + * 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_install_compress_gzip (const char *src, const char *dest) +{ + return grub_util_exec_redirect ((const char * []) { "gzip", "--best", + "--stdout", NULL }, src, dest); +} + +int +grub_install_compress_xz (const char *src, const char *dest) +{ + return grub_util_exec_redirect ((const char * []) { "xz", + "--lzma2=dict=128KiB", "--check=none", "--stdout", NULL }, src, dest); +} + +int +grub_install_compress_lzop (const char *src, const char *dest) +{ + return grub_util_exec_redirect ((const char * []) { "lzop", "-9", "-c", + NULL }, src, dest); +} diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c new file mode 100644 index 000000000..c093e91ad --- /dev/null +++ b/grub-core/osdep/unix/config.c @@ -0,0 +1,139 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,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 +#include +#include + +const char * +grub_util_get_config_filename (void) +{ + static char *value = NULL; + if (!value) + value = grub_util_path_concat (3, GRUB_SYSCONFDIR, + "default", "grub"); + return value; +} + +const char * +grub_util_get_pkgdatadir (void) +{ + const char *ret = getenv ("pkgdatadir"); + if (ret) + return ret; + return GRUB_DATADIR "/" PACKAGE; +} + +const char * +grub_util_get_pkglibdir (void) +{ + return GRUB_LIBDIR "/" PACKAGE; +} + +const char * +grub_util_get_localedir (void) +{ + return LOCALEDIR; +} + +void +grub_util_load_config (struct grub_util_config *cfg) +{ + pid_t pid; + const char *argv[4]; + char *script, *ptr; + const char *cfgfile, *iptr; + FILE *f = NULL; + int fd; + const char *v; + + memset (cfg, 0, sizeof (*cfg)); + + v = getenv ("GRUB_ENABLE_CRYPTODISK"); + if (v && v[0] == 'y' && v[1] == '\0') + cfg->is_cryptodisk_enabled = 1; + + v = getenv ("GRUB_DISTRIBUTOR"); + if (v) + cfg->grub_distributor = xstrdup (v); + + cfgfile = grub_util_get_config_filename (); + if (!grub_util_is_regular (cfgfile)) + return; + + argv[0] = "sh"; + argv[1] = "-c"; + + script = xmalloc (4 * strlen (cfgfile) + 300); + + ptr = script; + memcpy (ptr, ". '", 3); + ptr += 3; + for (iptr = cfgfile; *iptr; iptr++) + { + if (*iptr == '\\') + { + memcpy (ptr, "'\\''", 4); + ptr += 4; + continue; + } + *ptr++ = *iptr; + } + + strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\", " + "\"$GRUB_ENABLE_CRYPTODISK\", \"$GRUB_DISTRIBUTOR\""); + + argv[2] = script; + argv[3] = '\0'; + + pid = grub_util_exec_pipe (argv, &fd); + if (pid) + f = fdopen (fd, "r"); + if (f) + { + grub_util_parse_config (f, cfg, 1); + fclose (f); + } + if (pid) + { + close (fd); + waitpid (pid, NULL, 0); + } + if (f) + return; + + f = grub_util_fopen (cfgfile, "r"); + if (f) + { + grub_util_parse_config (f, cfg, 0); + fclose (f); + } + else + grub_util_warn (_("cannot open config file `%s': %s"), + cfgfile, strerror (errno)); +} diff --git a/grub-core/osdep/unix/exec.c b/grub-core/osdep/unix/exec.c index 239a68b32..9a50e5b9f 100644 --- a/grub-core/osdep/unix/exec.c +++ b/grub-core/osdep/unix/exec.c @@ -38,6 +38,23 @@ grub_util_exec (const char *const *argv) { pid_t pid; int status = -1; + char *str, *pstr; + const char *const *ptr; + grub_size_t strl = 0; + for (ptr = argv; *ptr; ptr++) + strl += grub_strlen (*ptr) + 1; + pstr = str = xmalloc (strl); + for (ptr = argv; *ptr; ptr++) + { + pstr = grub_stpcpy (pstr, *ptr); + *pstr++ = ' '; + } + if (pstr > str) + pstr--; + *pstr = '\0'; + + grub_util_info ("executing %s", str); + grub_free (str); pid = fork (); if (pid < 0) @@ -71,6 +88,29 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file, { pid_t mdadm_pid; int status = -1; + char *str, *pstr; + const char *const *ptr; + grub_size_t strl = 0; + for (ptr = argv; *ptr; ptr++) + strl += grub_strlen (*ptr) + 1; + strl += grub_strlen (stdin_file) + 2; + strl += grub_strlen (stdout_file) + 2; + + pstr = str = xmalloc (strl); + for (ptr = argv; *ptr; ptr++) + { + pstr = grub_stpcpy (pstr, *ptr); + *pstr++ = ' '; + } + *pstr++ = '<'; + pstr = grub_stpcpy (pstr, stdin_file); + *pstr++ = ' '; + *pstr++ = '>'; + pstr = grub_stpcpy (pstr, stdout_file); + *pstr = '\0'; + + grub_util_info ("executing %s", str); + grub_free (str); mdadm_pid = fork (); if (mdadm_pid < 0) @@ -87,6 +127,8 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file, #endif in = open (stdin_file, O_RDONLY); + if (in < 0) + exit (127); dup2 (in, STDIN_FILENO); close (in); @@ -94,6 +136,9 @@ grub_util_exec_redirect (const char *const *argv, const char *stdin_file, dup2 (out, STDOUT_FILENO); close (out); + if (out < 0) + exit (127); + /* Ensure child is not localised. */ setenv ("LC_ALL", "C", 1); diff --git a/grub-core/osdep/unix/hostdisk.c b/grub-core/osdep/unix/hostdisk.c index fe87855e2..1ca1abbfb 100644 --- a/grub-core/osdep/unix/hostdisk.c +++ b/grub-core/osdep/unix/hostdisk.c @@ -246,6 +246,17 @@ grub_util_is_regular (const char *path) return S_ISREG (st.st_mode); } +grub_uint32_t +grub_util_get_mtime (const char *path) +{ + struct stat st; + + if (stat (path, &st) == -1) + return 0; + + return st.st_mtime; +} + int grub_util_is_special_file (const char *path) { @@ -256,4 +267,39 @@ grub_util_is_special_file (const char *path) return (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)); } + +char * +grub_util_make_temporary_file (void) +{ + const char *t = getenv ("TMPDIR"); + size_t tl; + char *tmp; + if (!t) + t = "/tmp"; + tl = strlen (t); + tmp = xmalloc (tl + sizeof ("/grub.XXXXXX")); + memcpy (tmp, t, tl); + memcpy (tmp + tl, "/grub.XXXXXX", + sizeof ("/grub.XXXXXX")); + mkstemp (tmp); + return tmp; +} + +char * +grub_util_make_temporary_dir (void) +{ + const char *t = getenv ("TMPDIR"); + size_t tl; + char *tmp; + if (!t) + t = "/tmp"; + tl = strlen (t); + tmp = xmalloc (tl + sizeof ("/grub.XXXXXX")); + memcpy (tmp, t, tl); + memcpy (tmp + tl, "/grub.XXXXXX", + sizeof ("/grub.XXXXXX")); + mkdtemp (tmp); + return tmp; +} + #endif diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c new file mode 100644 index 000000000..65c93f150 --- /dev/null +++ b/grub-core/osdep/unix/platform.c @@ -0,0 +1,213 @@ +/* + * 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 + +static char * +get_ofpathname (const char *dev) +{ + char *ret = xmalloc (2 * PATH_MAX); + char *end = ret + 2 * PATH_MAX - 1; + int fd; + pid_t pid; + char *ptr = ret; + + pid = grub_util_exec_pipe ((const char * []){ "ofpathname", dev, NULL }, &fd); + if (!pid) + goto fail; + + FILE *fp = fdopen (fd, "r"); + if (!fp) + goto fail; + + while (!feof (fp) && ptr < end) + { + size_t r; + r = fread (ptr, 1, end - ptr, fp); + ptr += r; + } + + fclose (fp); + + return ret; + + fail: + grub_util_error (_("couldn't find IEEE1275 device tree path for %s.\nYou will have to set `boot-device' variable manually"), + dev); +} + +static void +grub_install_remove_efi_entries_by_distributor (const char *efi_distributor) +{ + int fd; + pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd); + char *line = NULL; + size_t len = 0; + + if (!pid) + { + grub_util_warn (_("Unable to open stream from %s: %s"), + "efibootmgr", strerror (errno)); + return; + } + + FILE *fp = fdopen (fd, "r"); + if (!fp) + { + grub_util_warn (_("Unable to open stream from %s: %s"), + "efibootmgr", strerror (errno)); + return; + } + + line = xmalloc (80); + len = 80; + while (1) + { + int ret; + char *bootnum; + ret = getline (&line, &len, fp); + if (ret == -1) + break; + if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0 + || line[sizeof ("Boot") - 1] < '0' + || line[sizeof ("Boot") - 1] > '9') + continue; + if (!strcasestr (line, efi_distributor)) + continue; + bootnum = line + sizeof ("Boot") - 1; + bootnum[4] = '\0'; + if (!verbosity) + grub_util_exec ((const char * []){ "efibootmgr", "-q", + "-b", bootnum, "-B", NULL }); + else + grub_util_exec ((const char * []){ "efibootmgr", + "-b", bootnum, "-B", NULL }); + } + + free (line); +} + +void +grub_install_register_efi (const char *efidir_disk, int efidir_part, + const char *efifile_path, + const char *efi_distributor) +{ + if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL })) + { + /* TRANSLATORS: This message is shown when required executable `%s' + isn't found. */ + grub_util_error (_("%s: not found"), "efibootmgr"); + } + + /* On Linux, we need the efivars kernel modules. */ +#ifdef __linux__ + grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL }); +#endif + /* Delete old entries from the same distributor. */ + grub_install_remove_efi_entries_by_distributor (efi_distributor); + + char *efidir_part_str = xasprintf ("%d", efidir_part); + + if (!verbosity) + grub_util_exec ((const char * []){ "efibootmgr", "-q", + "-c", "-d", efidir_disk, + "-p", efidir_part_str, "-w", + "-L", efi_distributor, "-l", + efifile_path, NULL }); + else + grub_util_exec ((const char * []){ "efibootmgr", + "-c", "-d", efidir_disk, + "-p", efidir_part_str, "-w", + "-L", efi_distributor, "-l", + efifile_path, NULL }); + free (efidir_part_str); +} + +void +grub_install_register_ieee1275 (int is_prep, const char *install_device, + int partno, const char *relpath) +{ + char *boot_device; + + if (grub_util_exec_redirect_null ((const char * []){ "ofpathname", "--version", NULL })) + { + /* TRANSLATORS: This message is shown when required executable `%s' + isn't found. */ + grub_util_error (_("%s: not found"), "ofpathname"); + } + + /* Get the Open Firmware device tree path translation. */ + if (!is_prep) + { + char *ptr; + char *ofpath; + const char *iptr; + + ofpath = get_ofpathname (install_device); + boot_device = xmalloc (strlen (ofpath) + 1 + + sizeof ("XXXXXXXXXXXXXXXXXXXX") + + 1 + strlen (relpath) + 1); + ptr = grub_stpcpy (boot_device, ofpath); + *ptr++ = ':'; + grub_snprintf (ptr, sizeof ("XXXXXXXXXXXXXXXXXXXX"), "%d", + partno); + ptr += strlen (ptr); + *ptr++ = ','; + for (iptr = relpath; *iptr; iptr++, ptr++) + { + if (*iptr == '/') + *ptr = '\\'; + else + *ptr = *iptr; + } + *ptr = '\0'; + } + else + boot_device = get_ofpathname (install_device); + + if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device", + boot_device, NULL })) + { + char *cmd = xasprintf ("setenv boot-device %s", boot_device); + grub_util_error ("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n", + cmd); + free (cmd); + } + + free (boot_device); +} + +void +grub_install_sgi_setup (const char *install_device, + const char *imgfile, const char *destname) +{ + grub_util_exec ((const char * []){ "dvhtool", "-d", + install_device, "--unix-to-vh", + imgfile, destname, NULL }); + grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually.")); +} diff --git a/grub-core/osdep/windows/config.c b/grub-core/osdep/windows/config.c new file mode 100644 index 000000000..823eac884 --- /dev/null +++ b/grub-core/osdep/windows/config.c @@ -0,0 +1,57 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,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 + +void +grub_util_load_config (struct grub_util_config *cfg) +{ + const char *cfgfile; + FILE *f = NULL; + const char *v; + + cfgfile = grub_util_get_config_filename (); + if (!grub_util_is_regular (cfgfile)) + return; + + memset (cfg, 0, sizeof (*cfg)); + + v = getenv ("GRUB_ENABLE_CRYPTODISK"); + if (v && v[0] == 'y' && v[1] == '\0') + cfg->is_cryptodisk_enabled = 1; + + v = getenv ("GRUB_DISTRIBUTOR"); + if (v) + cfg->grub_distributor = xstrdup (v); + + f = grub_util_fopen (cfgfile, "r"); + if (f) + { + grub_util_parse_config (f, cfg, 0); + fclose (f); + } + else + grub_util_warn (_("cannot open config file `%s': %s"), + cfgfile, strerror (errno)); +} diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c index f396c8700..6d7d12097 100644 --- a/grub-core/osdep/windows/hostdisk.c +++ b/grub-core/osdep/windows/hostdisk.c @@ -46,6 +46,7 @@ #include #include +#include #if SIZEOF_TCHAR == 1 @@ -411,6 +412,89 @@ grub_util_unlink (const char *name) return ret; } +int +grub_util_rmdir (const char *name) +{ + LPTSTR name_windows; + int ret; + + name_windows = grub_util_get_windows_path (name); + + ret = !RemoveDirectory (name_windows); + free (name_windows); + return ret; +} + +static char * +get_temp_name (void) +{ + TCHAR rt[1024]; + TCHAR *ptr; + HCRYPTPROV hCryptProv; + grub_uint8_t rnd[5]; + const size_t sz = sizeof (rnd) * GRUB_CHAR_BIT / 5; + int i; + + GetTempPath (ARRAY_SIZE (rt) - 100, rt); + + if (!CryptAcquireContext (&hCryptProv, + NULL, + MS_DEF_PROV, + PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT) + || !CryptGenRandom (hCryptProv, 5, rnd)) + grub_util_error ("%s", _("couldn't retrieve random data")); + + CryptReleaseContext (hCryptProv, 0); + + for (ptr = rt; *ptr; ptr++); + memcpy (ptr, TEXT("\\GRUB."), sizeof (TEXT("\\GRUB."))); + ptr += sizeof ("\\GRUB.") - 1; + + for (i = 0; i < 8; i++) + { + grub_size_t b = i * 5; + grub_uint8_t r; + grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT; + grub_size_t f2; + if (f1 > 5) + f1 = 5; + f2 = 5 - f1; + r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1); + if (f2) + r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1; + if (r < 10) + *ptr++ = '0' + r; + else + *ptr++ = 'a' + (r - 10); + } + *ptr = '\0'; + + return grub_util_tchar_to_utf8 (rt); +} + +char * +grub_util_make_temporary_file (void) +{ + char *ret = get_temp_name (); + FILE *f; + + f = grub_util_fopen (ret, "wb"); + if (f) + fclose (f); + return ret; +} + +char * +grub_util_make_temporary_dir (void) +{ + char *ret = get_temp_name (); + + grub_util_mkdir (ret); + + return ret; +} + int grub_util_is_directory (const char *name) { @@ -444,6 +528,33 @@ grub_util_is_regular (const char *name) && !(attr & FILE_ATTRIBUTE_REPARSE_POINT) && attr; } +grub_uint32_t +grub_util_get_mtime (const char *path) +{ + LPTSTR name_windows; + BOOL b; + WIN32_FILE_ATTRIBUTE_DATA attr; + ULARGE_INTEGER us_ul; + + name_windows = grub_util_get_windows_path (path); + if (!name_windows) + return 0; + + b = GetFileAttributesEx (name_windows, GetFileExInfoStandard, &attr); + grub_free (name_windows); + + if (!b) + return 0; + + us_ul.LowPart = attr.ftLastWriteTime.dwLowDateTime; + us_ul.HighPart = attr.ftLastWriteTime.dwHighDateTime; + + return (us_ul.QuadPart / 10000000) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); +} + + #ifdef __MINGW32__ FILE * diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c index 45554f1b2..98c325c20 100644 --- a/grub-core/osdep/windows/init.c +++ b/grub-core/osdep/windows/init.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -111,10 +112,42 @@ set_console_unicode_font (void) } } +static char *grub_util_base_directory; +static char *locale_dir; + +const char * +grub_util_get_config_filename (void) +{ + static char *value = NULL; + if (!value) + value = grub_util_path_concat (2, grub_util_base_directory, "grub.cfg"); + return value; +} + +const char * +grub_util_get_pkgdatadir (void) +{ + return grub_util_base_directory; +} + +const char * +grub_util_get_localedir (void) +{ + return locale_dir; +} + +const char * +grub_util_get_pkglibdir (void) +{ + return grub_util_base_directory; +} + void grub_util_host_init (int *argc __attribute__ ((unused)), char ***argv) { + char *ptr; + SetConsoleOutputCP (CP_UTF8); SetConsoleCP (CP_UTF8); @@ -137,9 +170,21 @@ grub_util_host_init (int *argc __attribute__ ((unused)), #error "Unsupported TCHAR size" #endif + grub_util_base_directory = canonicalize_file_name ((*argv)[0]); + if (!grub_util_base_directory) + grub_util_base_directory = xstrdup ((*argv)[0]); + for (ptr = grub_util_base_directory + strlen (grub_util_base_directory) - 1; + ptr >= grub_util_base_directory && *ptr != '/' && *ptr != '\\'; ptr--); + if (ptr >= grub_util_base_directory) + *ptr = '\0'; + + locale_dir = grub_util_path_concat (2, grub_util_base_directory, "locale"); + set_program_name ((*argv)[0]); -#ifdef GRUB_UTIL - grub_util_init_nls (); -#endif +#if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS) + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, locale_dir); + textdomain (PACKAGE); +#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } diff --git a/include/grub/emu/config.h b/include/grub/emu/config.h new file mode 100644 index 000000000..875d5896c --- /dev/null +++ b/include/grub/emu/config.h @@ -0,0 +1,48 @@ +/* + * 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_CONFIG_EMU_HEADER +#define GRUB_CONFIG_EMU_HEADER 1 + +#include +#include +#include +#include + +const char * +grub_util_get_config_filename (void); +const char * +grub_util_get_pkgdatadir (void); +const char * +grub_util_get_pkglibdir (void); +const char * +grub_util_get_localedir (void); + +struct grub_util_config +{ + int is_cryptodisk_enabled; + char *grub_distributor; +}; + +void +grub_util_load_config (struct grub_util_config *cfg); + +void +grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple); + +#endif diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 675cf78be..73fa2d34a 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -20,8 +20,10 @@ #define GRUB_UTIL_GETROOT_HEADER 1 #include +#include #include +#include enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, @@ -89,4 +91,14 @@ grub_util_get_grub_dev_os (const char *os_dev); grub_disk_addr_t grub_util_find_partition_start_os (const char *dev); +char * +grub_util_guess_bios_drive (const char *orig_path); +char * +grub_util_guess_efi_drive (const char *orig_path); +char * +grub_util_guess_baremetal_drive (const char *orig_path); +void +grub_util_fprint_full_disk_name (FILE *f, + const char *drive, grub_device_t dev); + #endif /* ! GRUB_UTIL_GETROOT_HEADER */ diff --git a/include/grub/emu/hostfile.h b/include/grub/emu/hostfile.h index 3ca1ab248..ab01fbce8 100644 --- a/include/grub/emu/hostfile.h +++ b/include/grub/emu/hostfile.h @@ -31,6 +31,11 @@ grub_util_is_special_file (const char *path); int grub_util_is_regular (const char *path); +char * +grub_util_path_concat (size_t n, ...); +char * +grub_util_path_concat_ext (size_t n, ...); + int grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off); ssize_t @@ -49,5 +54,13 @@ EXPORT_FUNC(grub_util_fd_close) (grub_util_fd_t fd); grub_uint64_t grub_util_get_fd_size (grub_util_fd_t fd, const char *name, unsigned *log_secsize); +char * +grub_util_make_temporary_file (void); +char * +grub_util_make_temporary_dir (void); +void +grub_util_unlink_recursive (const char *name); +grub_uint32_t +grub_util_get_mtime (const char *name); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/include/grub/osdep/exec_unix.h b/include/grub/osdep/exec_unix.h new file mode 100644 index 000000000..ecc3adc30 --- /dev/null +++ b/include/grub/osdep/exec_unix.h @@ -0,0 +1,39 @@ +/* + * 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_EMU_EXEC_H +#define GRUB_EMU_EXEC_H 1 + +#include +#include + +#include +pid_t +grub_util_exec_pipe (const char *const *argv, int *fd); +pid_t +grub_util_exec_pipe_stderr (const char *const *argv, int *fd); + +int +grub_util_exec (const char *const *argv); +int +grub_util_exec_redirect (const char *const *argv, const char *stdin_file, + const char *stdout_file); +int +grub_util_exec_redirect_null (const char *const *argv); + +#endif diff --git a/include/grub/osdep/hostfile_aros.h b/include/grub/osdep/hostfile_aros.h index 3a5043587..4ec211b48 100644 --- a/include/grub/osdep/hostfile_aros.h +++ b/include/grub/osdep/hostfile_aros.h @@ -50,6 +50,12 @@ grub_util_fd_readdir (grub_util_fd_dir_t dirp) return readdir (dirp); } +static inline int +grub_util_rmdir (const char *pathname) +{ + return rmdir (pathname); +} + static inline int grub_util_unlink (const char *pathname) { @@ -62,7 +68,7 @@ grub_util_rename (const char *from, const char *to) return rename (from, to); } -#define grub_util_mkdir(a) mkdir (a) +#define grub_util_mkdir(a) mkdir (a, 0700) struct grub_util_fd { @@ -86,7 +92,7 @@ enum grub_util_fd_open_flags_t GRUB_UTIL_FD_O_RDONLY = O_RDONLY, GRUB_UTIL_FD_O_WRONLY = O_WRONLY, GRUB_UTIL_FD_O_RDWR = O_RDWR, - GRUB_UTIL_FD_O_CREAT = O_CREAT, + GRUB_UTIL_FD_O_CREATTRUNC = O_CREAT | O_TRUNC, GRUB_UTIL_FD_O_SYNC = (0 #ifdef O_SYNC | O_SYNC diff --git a/include/grub/osdep/hostfile_unix.h b/include/grub/osdep/hostfile_unix.h index 50883f44f..e4e89398c 100644 --- a/include/grub/osdep/hostfile_unix.h +++ b/include/grub/osdep/hostfile_unix.h @@ -59,6 +59,12 @@ grub_util_unlink (const char *pathname) return unlink (pathname); } +static inline int +grub_util_rmdir (const char *pathname) +{ + return rmdir (pathname); +} + static inline int grub_util_rename (const char *from, const char *to) { diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h index ff21b6f93..e928b3f96 100644 --- a/include/grub/osdep/hostfile_windows.h +++ b/include/grub/osdep/hostfile_windows.h @@ -55,6 +55,9 @@ grub_util_fd_closedir (grub_util_fd_dir_t dirp); grub_util_fd_dirent_t grub_util_fd_readdir (grub_util_fd_dir_t dirp); +int +grub_util_rmdir (const char *pathname); + enum grub_util_fd_open_flags_t { GRUB_UTIL_FD_O_RDONLY = 1, diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 7eb6141a5..c1cd6b339 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -26,6 +26,104 @@ #include #include +#define GRUB_INSTALL_OPTIONS \ + { "modules", GRUB_INSTALL_OPTIONS_MODULES, N_("MODULES"), \ + 0, N_("pre-load specified modules MODULES"), 1 }, \ + { "install-modules", GRUB_INSTALL_OPTIONS_INSTALL_MODULES, \ + N_("MODULES"), 0, \ + N_("install only MODULES and their dependencies [default=all]"), 1 }, \ + { "themes", GRUB_INSTALL_OPTIONS_INSTALL_THEMES, N_("THEMES"), \ + 0, N_("install THEMES [default=%s]"), 1 }, \ + { "fonts", GRUB_INSTALL_OPTIONS_INSTALL_FONTS, N_("FONTS"), \ + 0, N_("install FONTS [default=%s]"), 1 }, \ + { "locales", GRUB_INSTALL_OPTIONS_INSTALL_LOCALES, N_("LOCALES"),\ + 0, N_("install only LOCALES [default=all]"), 1 }, \ + { "compress", GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS, \ + "no,xz,gz,lzo", OPTION_ARG_OPTIONAL, \ + N_("compress GRUB files [optional]"), 1 }, \ + /* TRANSLATORS: platform here isn't identifier. It can be translated. */ \ + { "directory", 'd', N_("DIR"), 0, \ + N_("use images and modules under DIR [default=%s/]"), 1 }, \ + { "override-directory", GRUB_INSTALL_OPTIONS_DIRECTORY2, \ + N_("DIR"), OPTION_HIDDEN, \ + N_("use images and modules under DIR [default=%s/]"), 1 }, \ + { "grub-mkimage", GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE, \ + "FILE", OPTION_HIDDEN, 0, 1 }, \ + /* TRANSLATORS: "embed" is a verb (command description). "*/ \ + { "pubkey", 'k', N_("FILE"), 0, \ + N_("embed FILE as public key for signature checking"), 0}, \ + { "verbose", 'v', 0, 0, \ + N_("increase verbosity"), 1 } + +int +grub_install_parse (int key, char *arg); + +void +grub_install_push_module (const char *val); + +void +grub_install_pop_module (void); + +char * +grub_install_help_filter (int key, const char *text, + void *input __attribute__ ((unused))); + +enum grub_install_plat + { + GRUB_INSTALL_PLATFORM_I386_PC, + GRUB_INSTALL_PLATFORM_I386_EFI, + GRUB_INSTALL_PLATFORM_I386_QEMU, + GRUB_INSTALL_PLATFORM_I386_COREBOOT, + GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, + GRUB_INSTALL_PLATFORM_I386_IEEE1275, + GRUB_INSTALL_PLATFORM_X86_64_EFI, + GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, + GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275, + GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, + GRUB_INSTALL_PLATFORM_MIPSEL_ARC, + GRUB_INSTALL_PLATFORM_MIPS_ARC, + GRUB_INSTALL_PLATFORM_IA64_EFI, + GRUB_INSTALL_PLATFORM_ARM_UBOOT, + GRUB_INSTALL_PLATFORM_ARM_EFI, + GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, + GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, + GRUB_INSTALL_PLATFORM_MAX + }; + +enum grub_install_options { + GRUB_INSTALL_OPTIONS_DIRECTORY = 'd', + GRUB_INSTALL_OPTIONS_VERBOSITY = 'v', + GRUB_INSTALL_OPTIONS_MODULES = 0x201, + GRUB_INSTALL_OPTIONS_INSTALL_MODULES, + GRUB_INSTALL_OPTIONS_INSTALL_THEMES, + GRUB_INSTALL_OPTIONS_INSTALL_FONTS, + GRUB_INSTALL_OPTIONS_INSTALL_LOCALES, + GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS, + GRUB_INSTALL_OPTIONS_DIRECTORY2, + GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE +}; + +extern char *grub_install_source_directory; + +enum grub_install_plat +grub_install_get_target (const char *src); +void +grub_install_mkdir_p (const char *dst); + +void +grub_install_copy_files (const char *src, + const char *dst, + enum grub_install_plat platid); +char * +grub_install_get_platform_name (enum grub_install_plat platid); + +const char * +grub_install_get_platform_cpu (enum grub_install_plat platid); + +const char * +grub_install_get_platform_platform (enum grub_install_plat platid); + + typedef enum { GRUB_COMPRESSION_AUTO, GRUB_COMPRESSION_NONE, @@ -33,6 +131,25 @@ typedef enum { GRUB_COMPRESSION_LZMA } grub_compression_t; +void +grub_install_make_image_wrap (const char *dir, const char *prefix, + const char *outname, char *memdisk_path, + char *config_path, + const char *format, int note, + grub_compression_t comp); +void +grub_install_make_image_wrap_file (const char *dir, const char *prefix, + FILE *fp, const char *outname, + char *memdisk_path, + char *config_path, + const char *mkimage_target, int note, + grub_compression_t comp); + +int +grub_install_copy_file (const char *src, + const char *dst, + int is_critical); + struct grub_install_image_target_desc; void @@ -66,6 +183,32 @@ grub_install_get_image_targets_string (void); const char * grub_util_get_target_dirname (const struct grub_install_image_target_desc *t); +void +grub_install_create_envblk_file (const char *name); + +const char * +grub_install_get_default_x86_platform (void); + +void +grub_install_register_efi (const char *efidir_disk, int efidir_part, + const char *efifile_path, + const char *efi_distributor); + +void +grub_install_register_ieee1275 (int is_prep, const char *install_device, + int partno, const char *relpath); + +void +grub_install_sgi_setup (const char *install_device, + const char *imgfile, const char *destname); + +int +grub_install_compress_gzip (const char *src, const char *dest); +int +grub_install_compress_lzop (const char *src, const char *dest); +int +grub_install_compress_xz (const char *src, const char *dest); + void grub_install_get_blocklist (grub_device_t root_dev, const char *core_path, const char *core_img, @@ -89,4 +232,10 @@ grub_util_render_label (const char *label_font, const char *label_string, const char *label); +const char * +grub_util_get_target_name (const struct grub_install_image_target_desc *t); + +extern char *grub_install_copy_buffer; +#define GRUB_INSTALL_COPY_BUFFER_SIZE 1048576 + #endif diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 83a3220d6..3619458e8 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -68,10 +68,10 @@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in remove-potcdate.sin \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) \ -$(DISTFILES.common.extra3) $(DISTFILES.common.extra4) +$(DISTFILES.common.extra3) $(DISTFILES.common.extra4) $(DISTFILES.common.extra5) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in POTFILES-shell.in \ $(POFILES) $(GMOFILES) \ -$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) $(DISTFILES.extra4) grub.d.sed README +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) $(DISTFILES.extra4) $(DISTFILES.extra5) grub.d.sed README POTFILES = \ diff --git a/po/Rules-windowsdir b/po/Rules-windowsdir new file mode 100644 index 000000000..fe47b1060 --- /dev/null +++ b/po/Rules-windowsdir @@ -0,0 +1,11 @@ +# generate windowsdir + +DISTFILES.common.extra5 = Rules-windowsdir + +windowsdir="$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows" +windowsdir: $(GMOFILES) + test -d "$(windowsdir)/locale" || mkdir "$(windowsdir)/locale" + for x in $(CATALOGS); do \ + test -d "$(windowsdir)/locale/$${x%.gmo}" || mkdir "$(windowsdir)/locale/$${x%.gmo}"; \ + cp -fp "$(srcdir)/$$x" "$(windowsdir)/locale/$${x%.gmo}/grub.mo"; \ + done diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in index fc435b68a..22277fbdf 100644 --- a/tests/util/grub-shell.in +++ b/tests/util/grub-shell.in @@ -347,8 +347,8 @@ fi if [ x$boot != xnet ] && [ x$boot != xemu ]; then cp -R "@srcdir@/themes" "@builddir@" - pkgdatadir="@builddir@" sh "@builddir@/grub-mkrescue" "--grub-mkimage=${builddir}/grub-mkimage" "--grub-render-label=${builddir}/grub-render-label" "--output=${isofile}" "--override-directory=${builddir}/grub-core" \ - --rom-directory="${rom_directory}" "--grub-mkimage-extra=$mkimage_extra_arg" ${mkrescue_args} \ + pkgdatadir="@builddir@" "@builddir@/grub-mkrescue" "--output=${isofile}" "--override-directory=${builddir}/grub-core" \ + --rom-directory="${rom_directory}" $mkimage_extra_arg ${mkrescue_args} \ "/boot/grub/grub.cfg=${cfgfile}" "/boot/grub/testcase.cfg=${source}" \ ${files} >/dev/null 2>&1 fi @@ -418,7 +418,7 @@ do_trim () if [ x$boot = xnet ]; then netdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - pkgdatadir="@builddir@" sh "@builddir@/grub-mknetdir" "--grub-mkimage=${builddir}/grub-mkimage" "--directory=${builddir}/grub-core" "--net-directory=$netdir" ${mkrescue_args} > /dev/null + pkgdatadir="@builddir@" "@builddir@/grub-mknetdir" "--grub-mkimage=${builddir}/grub-mkimage" "--directory=${builddir}/grub-core" "--net-directory=$netdir" ${mkrescue_args} > /dev/null cp "${cfgfile}" "$netdir/boot/grub/grub.cfg" cp "${source}" "$netdir/boot/grub/testcase.cfg" timeout -s KILL $timeout "${qemu}" ${qemuopts} ${serial_null} -serial file:/dev/stdout -boot n -net "user,tftp=$netdir,bootfile=/boot/grub/${grub_modinfo_target_cpu}-${grub_modinfo_platform}/core.$netbootext" -net nic | cat | tr -d "\r" | do_trim diff --git a/util/config.c b/util/config.c new file mode 100644 index 000000000..f313714db --- /dev/null +++ b/util/config.c @@ -0,0 +1,112 @@ +/* + * 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 + +void +grub_util_parse_config (FILE *f, struct grub_util_config *cfg, int simple) +{ + char *buffer = NULL; + size_t sz = 0; + while (getline (&buffer, &sz, f) >= 0) + { + const char *ptr; + for (ptr = buffer; *ptr && grub_isspace (*ptr); ptr++); + if (grub_strncmp (ptr, "GRUB_ENABLE_CRYPTODISK=", + sizeof ("GRUB_ENABLE_CRYPTODISK=") - 1) == 0) + { + ptr += sizeof ("GRUB_ENABLE_CRYPTODISK=") - 1; + if (*ptr == '"' || *ptr == '\'') + ptr++; + if (*ptr == 'y') + cfg->is_cryptodisk_enabled = 1; + continue; + } + if (grub_strncmp (ptr, "GRUB_DISTRIBUTOR=", + sizeof ("GRUB_DISTRIBUTOR=") - 1) == 0) + { + char *optr; + enum { NONE, SNGLQUOT, DBLQUOT } state; + if (simple) + { + free (cfg->grub_distributor); + cfg->grub_distributor = xstrdup (ptr); + continue; + } + free (cfg->grub_distributor); + cfg->grub_distributor = xmalloc (strlen (ptr) + 1); + optr = cfg->grub_distributor; + state = NONE; + + for (; *ptr; ptr++) + switch (*ptr) + { + case '\\': + if (state == SNGLQUOT) + { + *optr++ = *ptr; + continue; + } + if (ptr[1]) + { + *optr++ = ptr[1]; + ptr++; + continue; + } + ptr++; + break; + case '"': + if (state == NONE) + { + state = DBLQUOT; + continue; + } + if (state == DBLQUOT) + { + state = NONE; + continue; + } + *optr++ = *ptr; + continue; + case '\'': + if (state == SNGLQUOT) + { + state = NONE; + continue; + } + if (state == NONE) + { + state = SNGLQUOT; + continue; + } + *optr++ = *ptr; + continue; + default: + *optr++ = *ptr; + continue; + } + *optr = '\0'; + } + } +} + diff --git a/util/grub-install-common.c b/util/grub-install-common.c new file mode 100644 index 000000000..75a315d06 --- /dev/null +++ b/util/grub-install-common.c @@ -0,0 +1,863 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +char * +grub_install_help_filter (int key, const char *text, + void *input __attribute__ ((unused))) +{ + switch (key) + { + case GRUB_INSTALL_OPTIONS_INSTALL_THEMES: + return xasprintf(text, "starfield"); + case GRUB_INSTALL_OPTIONS_INSTALL_FONTS: + return xasprintf(text, "unicode"); + case GRUB_INSTALL_OPTIONS_DIRECTORY: + case GRUB_INSTALL_OPTIONS_DIRECTORY2: + return xasprintf(text, grub_util_get_pkglibdir ()); + default: + return (char *) text; + } +} + +static int (*compress_func) (const char *src, const char *dest) = NULL; +char *grub_install_copy_buffer; + +int +grub_install_copy_file (const char *src, + const char *dst, + int is_needed) +{ + grub_util_fd_t in, out; + ssize_t r; + + grub_util_info ("copying `%s' -> `%s'", src, dst); + + in = grub_util_fd_open (src, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (in)) + { + if (is_needed) + grub_util_error (_("cannot open `%s': %s"), src, grub_util_fd_strerror ()); + else + grub_util_info (_("cannot open `%s': %s"), src, grub_util_fd_strerror ()); + return 0; + } + out = grub_util_fd_open (dst, GRUB_UTIL_FD_O_WRONLY + | GRUB_UTIL_FD_O_CREATTRUNC); + if (!GRUB_UTIL_FD_IS_VALID (out)) + { + grub_util_error (_("cannot open `%s': %s"), dst, + grub_util_fd_strerror ()); + grub_util_fd_close (in); + return 0; + } + + if (!grub_install_copy_buffer) + grub_install_copy_buffer = xmalloc (GRUB_INSTALL_COPY_BUFFER_SIZE); + + while (1) + { + r = grub_util_fd_read (in, grub_install_copy_buffer, GRUB_INSTALL_COPY_BUFFER_SIZE); + if (r <= 0) + break; + grub_util_fd_write (out, grub_install_copy_buffer, r); + } + grub_util_fd_sync (out); + grub_util_fd_close (in); + grub_util_fd_close (out); + + if (r < 0) + grub_util_error ("cannot copy `%s' to `%s': %s", + src, dst, grub_util_fd_strerror ()); + + return 1; +} + +int +grub_install_compress_file (const char *in_name, + const char *out_name, + int is_needed) +{ + int ret; + + if (!compress_func) + ret = grub_install_copy_file (in_name, out_name, is_needed); + else + { + grub_util_info ("compressing `%s' -> `%s'", in_name, out_name); + ret = !compress_func (in_name, out_name); + if (!ret && is_needed) + grub_util_warn ("can't compress `%s' to `%s'", in_name, out_name); + } + + if (!ret && is_needed) + grub_util_error ("cannot copy `%s' to `%s': %s", + in_name, out_name, grub_util_fd_strerror ()); + + return ret; +} + +static int +is_path_separator (char c) +{ +#if defined (__MINGW32__) || defined (__CYGWIN__) + if (c == '\\') + return 1; +#endif + if (c == '/') + return 1; + return 0; +} + +void +grub_install_mkdir_p (const char *dst) +{ + char *t = xstrdup (dst); + char *p; + for (p = t; *p; p++) + { + if (is_path_separator (*p)) + { + char s = *p; + *p = '\0'; + grub_util_mkdir (t); + *p = s; + } + } + grub_util_mkdir (t); + free (t); +} + +static void +clean_grub_dir (const char *di) +{ + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + + d = grub_util_fd_opendir (di); + if (!d) + grub_util_error (_("cannot open directory `%s': %s"), + di, grub_util_fd_strerror ()); + + while ((de = grub_util_fd_readdir (d))) + { + const char *ext = strrchr (de->d_name, '.'); + if ((ext && (strcmp (ext, ".mod") == 0 + || strcmp (ext, ".lst") == 0 + || strcmp (ext, ".img") == 0 + || strcmp (ext, ".mo") == 0) + && strcmp (de->d_name, "menu.lst") != 0) + || strcmp (de->d_name, "efiemu32.o") == 0 + || strcmp (de->d_name, "efiemu64.o") == 0) + { + char *x = grub_util_path_concat (2, di, de->d_name); + if (grub_util_unlink (x) < 0) + grub_util_error ("cannont delete `%s': %s", x, + grub_util_fd_strerror ()); + free (x); + } + } + grub_util_fd_closedir (d); +} + +struct install_list +{ + int is_default; + char **entries; + size_t n_entries; + size_t n_alloc; +}; + +struct install_list install_modules = { 1, 0, 0, 0 }; +struct install_list modules = { 1, 0, 0, 0 }; +struct install_list install_locales = { 1, 0, 0, 0 }; +struct install_list install_fonts = { 1, 0, 0, 0 }; +struct install_list install_themes = { 1, 0, 0, 0 }; +char *grub_install_source_directory = NULL; + +void +grub_install_push_module (const char *val) +{ + modules.is_default = 0; + if (modules.n_entries + 1 >= modules.n_alloc) + { + modules.n_alloc <<= 1; + if (modules.n_alloc < 16) + modules.n_alloc = 16; + modules.entries = xrealloc (modules.entries, + modules.n_alloc * sizeof (modules.entries)); + } + modules.entries[modules.n_entries++] = xstrdup (val); + modules.entries[modules.n_entries] = NULL; +} + +void +grub_install_pop_module (void) +{ + modules.n_entries--; + free (modules.entries[modules.n_entries]); + modules.entries[modules.n_entries] = NULL; +} + + +static void +handle_install_list (struct install_list *il, const char *val, + int default_all) +{ + const char *ptr; + char **ce; + il->is_default = 0; + free (il->entries); + il->entries = NULL; + il->n_entries = 0; + if (strcmp (val, "all") == 0 && default_all) + { + il->is_default = 1; + return; + } + ptr = val; + while (1) + { + while (*ptr && grub_isspace (*ptr)) + ptr++; + if (!*ptr) + break; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + il->n_entries++; + } + il->n_alloc = il->n_entries + 1; + il->entries = xmalloc (il->n_alloc * sizeof (il->entries[0])); + for (ce = il->entries; ; ce++) + { + const char *bptr; + while (*ptr && grub_isspace (*ptr)) + ptr++; + if (!*ptr) + break; + bptr = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + *ce = xmalloc (ptr - bptr + 1); + memcpy (*ce, bptr, ptr - bptr); + (*ce)[ptr - bptr] = '\0'; + ce++; + } + *ce = NULL; +} + +static char **pubkeys; +static size_t npubkeys; + +int +grub_install_parse (int key, char *arg) +{ + switch (key) + { + case 'k': + pubkeys = xrealloc (pubkeys, + sizeof (pubkeys[0]) + * (npubkeys + 1)); + pubkeys[npubkeys++] = xstrdup (arg); + return 1; + + case GRUB_INSTALL_OPTIONS_VERBOSITY: + verbosity++; + return 1; + + case GRUB_INSTALL_OPTIONS_DIRECTORY: + case GRUB_INSTALL_OPTIONS_DIRECTORY2: + free (grub_install_source_directory); + grub_install_source_directory = xstrdup (arg); + return 1; + case GRUB_INSTALL_OPTIONS_INSTALL_MODULES: + handle_install_list (&install_modules, arg, 0); + return 1; + case GRUB_INSTALL_OPTIONS_MODULES: + handle_install_list (&modules, arg, 0); + return 1; + case GRUB_INSTALL_OPTIONS_INSTALL_LOCALES: + handle_install_list (&install_locales, arg, 0); + return 1; + case GRUB_INSTALL_OPTIONS_INSTALL_THEMES: + handle_install_list (&install_themes, arg, 0); + return 1; + case GRUB_INSTALL_OPTIONS_INSTALL_FONTS: + handle_install_list (&install_fonts, arg, 0); + return 1; + case GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS: + if (strcmp (arg, "no") == 0) + { + compress_func = NULL; + return 1; + } + if (strcmp (arg, "gz") == 0) + { + compress_func = grub_install_compress_gzip; + return 1; + } + if (strcmp (arg, "xz") == 0) + { + compress_func = grub_install_compress_xz; + return 1; + } + if (strcmp (arg, "lzo") == 0) + { + compress_func = grub_install_compress_lzop; + return 1; + } + grub_util_error (_("Unrecognized compression `%s'"), arg); + case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE: + return 1; + default: + return 0; + } +} + +static int +decompressors (void) +{ + if (compress_func == grub_install_compress_gzip) + { + grub_install_push_module ("gzio"); + return 1; + } + if (compress_func == grub_install_compress_xz) + { + grub_install_push_module ("xzio"); + grub_install_push_module ("gcry_crc"); + return 2; + } + if (compress_func == grub_install_compress_lzop) + { + grub_install_push_module ("lzopio"); + grub_install_push_module ("adler32"); + grub_install_push_module ("gcry_crc"); + return 3; + } + return 0; +} + +void +grub_install_make_image_wrap_file (const char *dir, const char *prefix, + FILE *fp, const char *outname, + char *memdisk_path, + char *config_path, + const char *mkimage_target, int note, + grub_compression_t comp) +{ + const struct grub_install_image_target_desc *tgt; + const char *const compnames[] = + { + [GRUB_COMPRESSION_AUTO] = "auto", + [GRUB_COMPRESSION_NONE] = "none", + [GRUB_COMPRESSION_XZ] = "xz", + [GRUB_COMPRESSION_LZMA] = "lzma", + }; + grub_size_t slen = 1; + char *s, *p; + char **pk, **md; + int dc = decompressors (); + + if (memdisk_path) + slen += 20 + grub_strlen (memdisk_path); + if (config_path) + slen += 20 + grub_strlen (config_path); + + for (pk = pubkeys; pk < pubkeys + npubkeys; pk++) + slen += 20 + grub_strlen (*pk); + + for (md = modules.entries; *md; md++) + { + slen += 10 + grub_strlen (*md); + } + + p = s = xmalloc (slen); + if (memdisk_path) + { + p = grub_stpcpy (p, "--memdisk '"); + p = grub_stpcpy (p, memdisk_path); + *p++ = '\''; + *p++ = ' '; + } + if (config_path) + { + p = grub_stpcpy (p, "--config '"); + p = grub_stpcpy (p, config_path); + *p++ = '\''; + *p++ = ' '; + } + for (pk = pubkeys; pk < pubkeys + npubkeys; pk++) + { + p = grub_stpcpy (p, "--pubkey '"); + p = grub_stpcpy (p, *pk); + *p++ = '\''; + *p++ = ' '; + } + + for (md = modules.entries; *md; md++) + { + *p++ = '\''; + p = grub_stpcpy (p, *md); + *p++ = '\''; + *p++ = ' '; + } + + *p = '\0'; + + grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'" + " --output '%s' " + "--format '%s' --compression '%s' %s %s\n", + dir, prefix, + outname, mkimage_target, + compnames[comp], note ? "--note" : "", s); + + tgt = grub_install_get_image_target (mkimage_target); + if (!tgt) + grub_util_error (_("unknown target format %s\n"), mkimage_target); + + grub_install_generate_image (dir, prefix, fp, outname, + modules.entries, memdisk_path, + pubkeys, npubkeys, config_path, tgt, + note, comp); + while (dc--) + grub_install_pop_module (); +} + +void +grub_install_make_image_wrap (const char *dir, const char *prefix, + const char *outname, char *memdisk_path, + char *config_path, + const char *mkimage_target, int note, + grub_compression_t comp) +{ + FILE *fp; + + fp = grub_util_fopen (outname, "wb"); + if (! fp) + grub_util_error (_("cannot open `%s': %s"), outname, + strerror (errno)); + grub_install_make_image_wrap_file (dir, prefix, fp, outname, + memdisk_path, config_path, + mkimage_target, note, comp); + fflush (fp); + fsync (fileno (fp)); + fclose (fp); +} + +static void +copy_by_ext (const char *srcd, + const char *dstd, + const char *extf, + int req) +{ + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + + d = grub_util_fd_opendir (srcd); + if (!d && !req) + return; + if (!d) + grub_util_error (_("cannot open directory `%s': %s"), + srcd, grub_util_fd_strerror ()); + + while ((de = grub_util_fd_readdir (d))) + { + const char *ext = strrchr (de->d_name, '.'); + if (ext && strcmp (ext, extf) == 0) + { + char *srcf = grub_util_path_concat (2, srcd, de->d_name); + char *dstf = grub_util_path_concat (2, dstd, de->d_name); + grub_install_compress_file (srcf, dstf, 1); + free (srcf); + free (dstf); + } + } + grub_util_fd_closedir (d); +} + +static void +copy_all (const char *srcd, + const char *dstd) +{ + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + + d = grub_util_fd_opendir (srcd); + if (!d) + grub_util_error (_("cannot open directory `%s': %s"), + srcd, grub_util_fd_strerror ()); + + while ((de = grub_util_fd_readdir (d))) + { + char *srcf; + char *dstf; + if (strcmp (de->d_name, ".") == 0 + || strcmp (de->d_name, "..") == 0) + continue; + srcf = grub_util_path_concat (2, srcd, de->d_name); + if (grub_util_is_special_file (srcf) + || grub_util_is_directory (srcf)) + continue; + dstf = grub_util_path_concat (2, dstd, de->d_name); + grub_install_compress_file (srcf, dstf, 1); + free (srcf); + free (dstf); + } + grub_util_fd_closedir (d); +} + +static void +copy_locales (const char *dstd) +{ + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + const char *locale_dir = grub_util_get_localedir (); + + d = grub_util_fd_opendir (LOCALEDIR); + if (!d) + { + grub_util_warn (_("cannot open directory `%s': %s"), + locale_dir, grub_util_fd_strerror ()); + return; + } + + while ((de = grub_util_fd_readdir (d))) + { + char *srcf; + char *dstf; + if (strcmp (de->d_name, ".") == 0) + continue; + if (strcmp (de->d_name, "..") == 0) + continue; + srcf = grub_util_path_concat_ext (4, locale_dir, de->d_name, + "LC_MESSAGES", PACKAGE, ".mo"); + dstf = grub_util_path_concat_ext (2, dstd, de->d_name, ".mo"); + grub_install_compress_file (srcf, dstf, 0); + free (srcf); + free (dstf); + } + grub_util_fd_closedir (d); +} + +static struct +{ + enum grub_install_plat val; + const char *cpu; + const char *platform; +} platforms[] = + { + { GRUB_INSTALL_PLATFORM_I386_PC, "i386", "pc" }, + { GRUB_INSTALL_PLATFORM_I386_EFI, "i386", "efi" }, + { GRUB_INSTALL_PLATFORM_I386_QEMU, "i386", "qemu" }, + { GRUB_INSTALL_PLATFORM_I386_COREBOOT, "i386", "coreboot" }, + { GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, "i386", "multiboot" }, + { GRUB_INSTALL_PLATFORM_I386_IEEE1275, "i386", "ieee1275" }, + { GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64", "efi" }, + { GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel", "loongson" }, + { GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "mipsel", "qemu_mips" }, + { GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "mips", "qemu_mips" }, + { GRUB_INSTALL_PLATFORM_MIPSEL_ARC, "mipsel", "arc" }, + { GRUB_INSTALL_PLATFORM_MIPS_ARC, "mips", "arc" }, + { GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275, "sparc64", "ieee1275" }, + { GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc", "ieee1275" }, + { GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64", "efi" }, + { GRUB_INSTALL_PLATFORM_ARM_EFI, "arm", "efi" }, + { GRUB_INSTALL_PLATFORM_ARM_UBOOT, "arm", "uboot" }, + }; + +char * +grub_install_get_platform_name (enum grub_install_plat platid) +{ + return xasprintf ("%s-%s", platforms[platid].cpu, + platforms[platid].platform); +} + +const char * +grub_install_get_platform_cpu (enum grub_install_plat platid) +{ + return platforms[platid].cpu; +} + +const char * +grub_install_get_platform_platform (enum grub_install_plat platid) +{ + return platforms[platid].platform; +} + + +void +grub_install_copy_files (const char *src, + const char *dst, + enum grub_install_plat platid) +{ + char *dst_platform, *dst_locale, *dst_fonts; + const char *pkgdatadir = grub_util_get_pkgdatadir (); + + { + char *platform; + platform = xasprintf ("%s-%s", platforms[platid].cpu, + platforms[platid].platform); + dst_platform = grub_util_path_concat (2, dst, platform); + free (platform); + } + dst_locale = grub_util_path_concat (2, dst, "locale"); + dst_fonts = grub_util_path_concat (2, dst, "fonts"); + grub_install_mkdir_p (dst_platform); + grub_install_mkdir_p (dst_locale); + clean_grub_dir (dst); + clean_grub_dir (dst_platform); + clean_grub_dir (dst_locale); + + if (install_modules.is_default) + copy_by_ext (src, dst_platform, ".mod", 1); + else + { + struct grub_util_path_list *path_list, *p; + + path_list = grub_util_resolve_dependencies (src, "moddep.lst", + install_modules.entries); + for (p = path_list; p; p = p->next) + { + char *srcf = grub_util_path_concat_ext (2, src, p->name, ".mo"); + char *dstf = grub_util_path_concat_ext (2, dst, p->name, ".mo"); + grub_install_compress_file (srcf, dstf, 1); + free (srcf); + free (dstf); + } + } + + const char *pkglib_DATA[] = {"efiemu32.o", "efiemu64.o", + "moddep.lst", "command.lst", + "fs.lst", "partmap.lst", + "parttool.lst", + "video.lst", "crypto.lst", + "terminal.lst" }; + size_t i; + + for (i = 0; i < ARRAY_SIZE (pkglib_DATA); i++) + { + char *srcf = grub_util_path_concat (2, src, pkglib_DATA[i]); + char *dstf = grub_util_path_concat (2, dst_platform, pkglib_DATA[i]); + if (i == 0 || i == 1) + grub_install_compress_file (srcf, dstf, 0); + else + grub_install_compress_file (srcf, dstf, 1); + free (srcf); + free (dstf); + } + + if (install_locales.is_default) + { + char *srcd = grub_util_path_concat (2, src, "po"); + copy_by_ext (srcd, dst_locale, ".mo", 0); + copy_locales (dst_locale); + free (srcd); + } + else + { + for (i = 0; i < install_locales.n_entries; i++) + { + char *srcf = grub_util_path_concat_ext (3, src, + "po", + install_locales.entries[i], + ".mo"); + char *dstf = grub_util_path_concat_ext (2, dst_locale, + install_locales.entries[i], + ".mo"); + if (grub_install_compress_file (srcf, dstf, 0)) + { + free (srcf); + free (dstf); + continue; + } + free (srcf); + srcf = grub_util_path_concat_ext (4, + LOCALEDIR, + install_locales.entries[i], + "LC_MESSAGES", + PACKAGE, + ".mo"); + if (grub_install_compress_file (srcf, dstf, 0)) + { + free (srcf); + free (dstf); + continue; + } + grub_util_error (_("cannot find locale `%s'"), + install_locales.entries[i]); + } + } + + if (install_themes.is_default) + { + install_themes.is_default = 0; + install_themes.n_entries = 1; + install_themes.entries = xmalloc (2 * sizeof (install_themes.entries[0])); + install_themes.entries[0] = xstrdup ("starfield"); + install_themes.entries[1] = NULL; + } + + for (i = 0; i < install_themes.n_entries; i++) + { + char *srcf = grub_util_path_concat (4, pkgdatadir, "themes", + install_themes.entries[i], + "theme.txt"); + if (grub_util_is_regular (srcf)) + { + char *srcd = grub_util_path_concat (3, pkgdatadir, "themes", + install_themes.entries[i]); + char *dstd = grub_util_path_concat (3, dst, "themes", + install_themes.entries[i]); + grub_install_mkdir_p (dstd); + copy_all (srcd, dstd); + free (srcd); + free (dstd); + } + free (srcf); + } + + if (install_fonts.is_default) + { + install_fonts.is_default = 0; + install_fonts.n_entries = 1; + install_fonts.entries = xmalloc (2 * sizeof (install_fonts.entries[0])); + install_fonts.entries[0] = xstrdup ("unicode"); + install_fonts.entries[1] = NULL; + } + + grub_install_mkdir_p (dst_fonts); + + for (i = 0; i < install_fonts.n_entries; i++) + { + char *srcf = grub_util_path_concat_ext (2, pkgdatadir, + install_fonts.entries[i], + ".pf2"); + char *dstf = grub_util_path_concat_ext (2, dst_fonts, + install_fonts.entries[i], + ".pf2"); + + grub_install_compress_file (srcf, dstf, 0); + free (srcf); + free (dstf); + } + + free (dst_platform); + free (dst_locale); + free (dst_fonts); +} + +enum grub_install_plat +grub_install_get_target (const char *src) +{ + char *fn; + grub_util_fd_t f; + char buf[2048]; + size_t r; + char *c, *pl, *p; + size_t i; + fn = grub_util_path_concat (2, src, "modinfo.sh"); + f = grub_util_fd_open (fn, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (f)) + grub_util_error (_("%s doesn't exist. Please specify --target or --directory"), + fn); + r = grub_util_fd_read (f, buf, sizeof (buf) - 1); + grub_util_fd_close (f); + buf[r] = '\0'; + c = strstr (buf, "grub_modinfo_target_cpu="); + if (!c || (c != buf && !grub_isspace (*(c-1)))) + grub_util_error (_("invalid modinfo file `%s'"), fn); + pl = strstr (buf, "grub_modinfo_platform="); + if (!pl || (pl != buf && !grub_isspace (*(pl-1)))) + grub_util_error (_("invalid modinfo file `%s'"), fn); + c += sizeof ("grub_modinfo_target_cpu=") - 1; + pl += sizeof ("grub_modinfo_platform=") - 1; + for (p = c; *p && !grub_isspace (*p); p++); + *p = '\0'; + for (p = pl; *p && !grub_isspace (*p); p++); + *p = '\0'; + + for (i = 0; i < ARRAY_SIZE (platforms); i++) + if (strcmp (platforms[i].cpu, c) == 0 + && strcmp (platforms[i].platform, pl) == 0) + { + free (fn); + return platforms[i].val; + } + grub_util_error (_("Unknown platform `%s-%s'"), c, pl); +} + + +void +grub_util_unlink_recursive (const char *name) +{ + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + + d = grub_util_fd_opendir (name); + + while ((de = grub_util_fd_readdir (d))) + { + char *fp; + if (strcmp (de->d_name, ".") == 0) + continue; + if (strcmp (de->d_name, "..") == 0) + continue; + fp = grub_util_path_concat (2, name, de->d_name); + if (grub_util_is_special_file (fp)) + { + free (fp); + continue; + } + if (grub_util_is_regular (fp)) + grub_util_unlink (fp); + else if (grub_util_is_directory (fp)) + grub_util_unlink_recursive (fp); + free (fp); + } + grub_util_rmdir (name); + grub_util_fd_closedir (d); +} diff --git a/util/grub-install.c b/util/grub-install.c new file mode 100644 index 000000000..100f09379 --- /dev/null +++ b/util/grub-install.c @@ -0,0 +1,1539 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "argp.h" + +#include "progname.h" + +static char *target; +static int removable = 0; +static int recheck = 0; +static int update_nvram = 1; +static char *install_device = NULL; +static char *debug_image = NULL; +static char *rootdir = NULL; +static char *bootdir = NULL; +static int allow_floppy = 0; +static int force_file_id = 0; +static char *disk_module = NULL; +static char *efidir = NULL; +static int force = 0; +static int have_abstractions = 0; +static int have_cryptodisk = 0; +static char * bootloader_id; +static int have_load_cfg = 0; +static FILE * load_cfg_f = NULL; +static char *load_cfg; + +enum + { + OPTION_BOOT_DIRECTORY = 0x301, + OPTION_ROOT_DIRECTORY, + OPTION_TARGET, + OPTION_SETUP, + OPTION_MKRELPATH, + OPTION_MKDEVICEMAP, + OPTION_PROBE, + OPTION_EDITENV, + OPTION_ALLOW_FLOPPY, + OPTION_RECHECK, + OPTION_FORCE, + OPTION_FORCE_FILE_ID, + OPTION_MODULE, + OPTION_NO_NVRAM, + OPTION_REMOVABLE, + OPTION_BOOTLOADER_ID, + OPTION_EFI_DIRECTORY, + OPTION_FONT, + OPTION_DEBUG, + OPTION_DEBUG_IMAGE, + OPTION_NO_FLOPPY, + OPTION_DISK_MODULE + }; + +static int fs_probe = 1; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + if (grub_install_parse (key, arg)) + return 0; + switch (key) + { + case OPTION_FORCE_FILE_ID: + force_file_id = 1; + return 0; + case 's': + fs_probe = 0; + return 0; + + /* Accept and ignore for compatibility. */ + case OPTION_FONT: + case OPTION_SETUP: + case OPTION_MKRELPATH: + case OPTION_PROBE: + case OPTION_EDITENV: + case OPTION_MKDEVICEMAP: + case OPTION_NO_FLOPPY: + return 0; + case OPTION_ROOT_DIRECTORY: + /* Accept for compatibility. */ + free (rootdir); + rootdir = xstrdup (arg); + return 0; + + case OPTION_BOOT_DIRECTORY: + free (bootdir); + bootdir = xstrdup (arg); + return 0; + + case OPTION_EFI_DIRECTORY: + free (efidir); + efidir = xstrdup (arg); + return 0; + + case OPTION_DISK_MODULE: + free (disk_module); + disk_module = xstrdup (arg); + return 0; + + case OPTION_TARGET: + free (target); + target = xstrdup (arg); + return 0; + + case OPTION_DEBUG_IMAGE: + free (debug_image); + debug_image = xstrdup (arg); + return 0; + + case OPTION_NO_NVRAM: + update_nvram = 0; + return 0; + + case OPTION_FORCE: + force = 1; + return 0; + + case OPTION_RECHECK: + recheck = 1; + return 0; + + case OPTION_REMOVABLE: + removable = 1; + return 0; + + case OPTION_ALLOW_FLOPPY: + allow_floppy = 1; + return 0; + + case OPTION_DEBUG: + verbosity++; + return 0; + + case OPTION_BOOTLOADER_ID: + free (bootloader_id); + bootloader_id = xstrdup (arg); + return 0; + + case ARGP_KEY_ARG: + if (install_device) + grub_util_error ("%s", _("More than one install device?")); + install_device = xstrdup (arg); + return 0; + + default: + return ARGP_ERR_UNKNOWN; + } +} + + +static struct argp_option options[] = { + GRUB_INSTALL_OPTIONS, + {"boot-directory", OPTION_BOOT_DIRECTORY, N_("DIR"), + 0, N_("install GRUB images under the directory DIR/%s instead of the %s directory"), 2}, + {"root-directory", OPTION_ROOT_DIRECTORY, N_("DIR"), + OPTION_HIDDEN, 0, 2}, + {"font", OPTION_FONT, N_("FILE"), + OPTION_HIDDEN, 0, 2}, + {"target", OPTION_TARGET, N_("TARGET"), + /* TRANSLATORS: "TARGET" as in "target platform". */ + 0, N_("install GRUB for TARGET platform [default=%s]"), 2}, + {"grub-setup", OPTION_SETUP, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-mkrelpath", OPTION_MKRELPATH, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-mkdevicemap", OPTION_MKDEVICEMAP, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-probe", OPTION_PROBE, "FILE", OPTION_HIDDEN, 0, 2}, + {"grub-editenv", OPTION_EDITENV, "FILE", OPTION_HIDDEN, 0, 2}, + {"allow-floppy", OPTION_ALLOW_FLOPPY, 0, 0, + /* TRANSLATORS: "may break" doesn't just mean that option wouldn't have any + effect but that it will make the resulting install unbootable from HDD. */ + N_("make the drive also bootable as floppy (default for fdX devices)." + " May break on some BIOSes."), 2}, + {"recheck", OPTION_RECHECK, 0, 0, + N_("delete device map if it already exists"), 2}, + {"force", OPTION_FORCE, 0, 0, + N_("install even if problems are detected"), 2}, + {"force-file-id", OPTION_FORCE_FILE_ID, 0, 0, + N_("use identifier file even if UUID is available"), 2}, + {"disk-module", OPTION_MODULE, N_("MODULE"), 0, + N_("disk module to use (biosdisk or native). " + "This option is only available on BIOS target."), 2}, + {"no-nvram", OPTION_NO_NVRAM, 0, 0, + N_("don't update the `boot-device' NVRAM variable. " + "This option is only available on IEEE1275 targets."), 2}, + + {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, + {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2}, + {"debug-image", OPTION_DEBUG_IMAGE, "STR", OPTION_HIDDEN, 0, 2}, + {"removable", OPTION_REMOVABLE, 0, 0, + N_("the installation device is removable. " + "This option is only available on EFI."), 2}, + {"bootloader-id", OPTION_BOOTLOADER_ID, N_("ID"), 0, + N_("the ID of bootloader. This option is only available on EFI."), 2}, + {"efi-directory", OPTION_EFI_DIRECTORY, N_("DIR"), 0, + N_("use DIR as the EFI System Partition root."), 2}, + {"skip-fs-probe",'s',0, 0, + N_("do not probe for filesystems in DEVICE"), 0}, + + {0, 0, 0, 0, 0, 0} +}; + +static const char * +get_default_platform (void) +{ +#ifdef __powerpc__ + return "powerpc-ieee1275"; +#elif defined (__sparc__) || defined (__sparc64__) + return "sparc64-ieee1275"; +#elif defined (__MIPSEL__) + return "mipsel-loongson"; +#elif defined (__MIPSEB__) + return "mips-arc"; +#elif defined (__ia64__) + return "ia64-efi"; +#elif defined (__arm__) + return "arm-uboot"; +#elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__) + return grub_install_get_default_x86_platform (); +#else + return NULL; +#endif +} + +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) +{ + switch (key) + { + case OPTION_BOOT_DIRECTORY: + return xasprintf (text, GRUB_DIR_NAME, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME); + case OPTION_TARGET: + return xasprintf (text, get_default_platform ()); + case ARGP_KEY_HELP_POST_DOC: + return xasprintf (text, program_name, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME); + default: + return grub_install_help_filter (key, text, input); + } +} + +/* TRANSLATORS: INSTALL_DEVICE isn't an identifier and is the DEVICE you + install to. */ +struct argp argp = { + options, argp_parser, N_("[OPTION] [INSTALL_DEVICE]"), + N_("Install GRUB on your drive.")"\v" + N_("INSTALL_DEVICE must be system device filename.\n" + "%s copies GRUB images into %s. On some platforms, it" + " may also install GRUB into the boot sector."), + NULL, help_filter, NULL +}; + +static int +probe_raid_level (grub_disk_t disk) +{ + /* disk might be NULL in the case of a LVM physical volume with no LVM + signature. Ignore such cases here. */ + if (!disk) + return -1; + + if (disk->dev->id != GRUB_DISK_DEVICE_DISKFILTER_ID) + return -1; + + if (disk->name[0] != 'm' || disk->name[1] != 'd') + return -1; + + if (!((struct grub_diskfilter_lv *) disk->data)->segments) + return -1; + return ((struct grub_diskfilter_lv *) disk->data)->segments->type; +} + +static void +probe_mods (grub_disk_t disk) +{ + grub_partition_t part; + grub_disk_memberlist_t list = NULL, tmp; + int raid_level; + + if (disk->partition == NULL) + grub_util_info ("no partition map found for %s", disk->name); + + for (part = disk->partition; part; part = part->parent) + { + char buf[50]; + if (strcmp (part->partmap->name, "openbsd") == 0 + || strcmp (part->partmap->name, "netbsd") == 0) + { + grub_install_push_module ("part_bsd"); + continue; + } + snprintf (buf, sizeof (buf), "part_%s", part->partmap->name); + grub_install_push_module (buf); + } + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID) + { + grub_diskfilter_get_partmap (disk, grub_install_push_module); + have_abstractions = 1; + } + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 || + grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0)) + grub_install_push_module ("lvm"); + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0) + grub_install_push_module ("ldm"); + + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + { + grub_util_cryptodisk_get_abstraction (disk, + grub_install_push_module); + have_abstractions = 1; + have_cryptodisk = 1; + } + + raid_level = probe_raid_level (disk); + if (raid_level >= 0) + { + grub_install_push_module ("diskfilter"); + if (disk->dev->raidname) + grub_install_push_module (disk->dev->raidname (disk)); + } + if (raid_level == 5) + grub_install_push_module ("raid5rec"); + if (raid_level == 6) + grub_install_push_module ("raid6rec"); + + /* In case of LVM/RAID, check the member devices as well. */ + if (disk->dev->memberlist) + list = disk->dev->memberlist (disk); + while (list) + { + probe_mods (list->disk); + tmp = list->next; + free (list); + list = tmp; + } +} + +static int +have_bootdev (enum grub_install_plat pl) +{ + switch (pl) + { + case GRUB_INSTALL_PLATFORM_I386_PC: + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + return 1; + + case GRUB_INSTALL_PLATFORM_I386_QEMU: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + return 0; + + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + return 0; + } + return 0; +} + +static void +probe_cryptodisk_uuid (grub_disk_t disk) +{ + grub_disk_memberlist_t list = NULL, tmp; + + /* In case of LVM/RAID, check the member devices as well. */ + if (disk->dev->memberlist) + { + list = disk->dev->memberlist (disk); + } + while (list) + { + probe_cryptodisk_uuid (list->disk); + tmp = list->next; + free (list); + list = tmp; + } + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + { + const char *uuid = grub_util_cryptodisk_get_uuid (disk); + if (!load_cfg_f) + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + + fprintf (load_cfg_f, "cryptomount -u %s\n", + uuid); + } +} + +static int +is_same_disk (const char *a, const char *b) +{ + while (1) + { + if ((*a == ',' || *a == '\0') && (*b == ',' || *b == '\0')) + return 1; + if (*a != *b) + return 0; + if (*a == '\\') + { + if (a[1] != b[1]) + return 0; + a += 2; + b += 2; + continue; + } + a++; + b++; + } +} + +char * +get_rndstr (void) +{ + grub_uint8_t rnd[15]; + const size_t sz = sizeof (rnd) * GRUB_CHAR_BIT / 5; + char * ret = xmalloc (sz + 1); + size_t i; + if (grub_get_random (rnd, sizeof (rnd))) + grub_util_error ("%s", _("couldn't retrieve random data")); + for (i = 0; i < sz; i++) + { + grub_size_t b = i * 5; + grub_uint8_t r; + grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT; + grub_size_t f2; + if (f1 > 5) + f1 = 5; + f2 = 5 - f1; + r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1); + if (f2) + r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1; + if (r < 10) + ret[i] = '0' + r; + else + ret[i] = 'a' + (r - 10); + } + ret[sz] = '\0'; + return ret; +} + +static char * +escape (const char *in) +{ + char *ptr; + char *ret; + int overhead = 0; + + for (ptr = (char*)in; *ptr; ptr++) + if (*ptr == '\'') + overhead += 3; + ret = grub_malloc (ptr - in + overhead + 1); + if (!ret) + return NULL; + + grub_strchrsub (ret, in, '\'', "'\\''"); + return ret; +} + +static struct grub_util_config config; + +static void +device_map_check_duplicates (const char *dev_map) +{ + FILE *fp; + char buf[1024]; /* XXX */ + size_t alloced = 8; + size_t filled = 0; + char **d; + size_t i; + + d = xmalloc (alloced * sizeof (d[0])); + + if (dev_map[0] == '\0') + return; + + fp = grub_util_fopen (dev_map, "r"); + if (! fp) + return; + + while (fgets (buf, sizeof (buf), fp)) + { + char *p = buf; + char *e; + + /* Skip leading spaces. */ + while (*p && grub_isspace (*p)) + p++; + + /* If the first character is `#' or NUL, skip this line. */ + if (*p == '\0' || *p == '#') + continue; + + if (*p != '(') + continue; + + p++; + + e = p; + p = strchr (p, ')'); + if (! p) + continue; + + if (filled >= alloced) + { + alloced *= 2; + d = xrealloc (d, alloced * sizeof (d[0])); + } + + *p = '\0'; + + d[filled++] = xstrdup (e); + } + + fclose (fp); + + qsort (d, filled, sizeof (d[0]), (int (*) (const void *, const void *))strcmp); + + for (i = 0; i + 1 < filled; i++) + if (strcmp (d[i], d[i+1]) == 0) + { + grub_util_error ("the drive %s is defined multiple times in the device map %s", + d[i], dev_map); + } + + for (i = 0; i < filled; i++) + free (d[i]); + + free (d); +} + +static grub_err_t +write_to_disk (grub_device_t dev, const char *fn) +{ + char *core_img; + size_t core_size; + grub_err_t err; + + core_size = grub_util_get_image_size (fn); + + core_img = grub_util_read_image (fn); + + err = grub_disk_write (dev->disk, 0, 0, + core_size, core_img); + free (core_img); + return err; +} + +static int +is_prep_partition (grub_device_t dev) +{ + if (!dev->disk) + return 0; + if (!dev->disk->partition) + return 0; + if (strcmp(dev->disk->partition->partmap->name, "msdos") == 0) + return (dev->disk->partition->msdostype == 0x41); + + if (strcmp (dev->disk->partition->partmap->name, "gpt") == 0) + { + struct grub_gpt_partentry gptdata; + grub_partition_t p = dev->disk->partition; + int ret = 0; + dev->disk->partition = dev->disk->partition->parent; + + if (grub_disk_read (dev->disk, p->offset, p->index, + sizeof (gptdata), &gptdata) == 0) + { + const grub_gpt_part_type_t template = { + grub_cpu_to_le32_compile_time (0x9e1a2d38), + grub_cpu_to_le16_compile_time (0xc612), + grub_cpu_to_le16_compile_time (0x4316), + { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b } + }; + + ret = grub_memcmp (&template, &gptdata.type, + sizeof (template)) == 0; + } + dev->disk->partition = p; + return ret; + } + + return 0; +} + +static int +is_prep_empty (grub_device_t dev) +{ + grub_disk_addr_t dsize, addr; + grub_uint32_t buffer[32768]; + + dsize = grub_disk_get_size (dev->disk); + for (addr = 0; addr < dsize; + addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE) + { + grub_size_t sz = sizeof (buffer); + grub_uint32_t *ptr; + + if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr) + sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE; + grub_disk_read (dev->disk, addr, 0, sz, buffer); + + if (addr == 0 && grub_memcmp (buffer, ELFMAG, SELFMAG) == 0) + return 1; + + for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++) + if (*ptr) + return 0; + } + + return 1; +} + +int +main (int argc, char *argv[]) +{ + int is_efi = 0; + const char *efi_distributor = NULL; + const char *efi_file = NULL; + char **grub_devices; + grub_fs_t grub_fs; + grub_device_t grub_dev = NULL; + enum grub_install_plat platform; + char *grubdir, *device_map; + char **curdev, **curdrive; + char **grub_drives; + char *relative_grubdir; + char **efidir_device_names = NULL; + grub_device_t efidir_grub_dev = NULL; + char *efidir_grub_devname; + + grub_util_host_init (&argc, &argv); + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (verbosity > 1) + grub_env_set ("debug", "all"); + + grub_util_load_config (&config); + + if (!bootloader_id && config.grub_distributor) + { + char *ptr; + bootloader_id = xstrdup (config.grub_distributor); + for (ptr = bootloader_id; *ptr && *ptr != ' '; ptr++) + if (*ptr >= 'A' && *ptr <= 'Z') + *ptr = *ptr - 'A' + 'a'; + *ptr = '\0'; + } + if (!bootloader_id || bootloader_id[0] == '\0') + { + free (bootloader_id); + bootloader_id = xstrdup ("grub"); + } + + if (!grub_install_source_directory) + { + if (!target) + { + const char * t; + t = get_default_platform (); + if (!t) + grub_util_error ("%s", + _("Unable to determine your platform." + " Use --target.") + ); + target = xstrdup (t); + } + grub_install_source_directory + = grub_util_path_concat (2, grub_util_get_pkglibdir (), target); + } + + platform = grub_install_get_target (grub_install_source_directory); + + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_PC: + if (!disk_module) + disk_module = xstrdup ("biosdisk"); + break; + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + break; + + case GRUB_INSTALL_PLATFORM_I386_QEMU: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + disk_module = xstrdup ("native"); + break; + + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_PC: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + if (!install_device) + grub_util_error ("%s", _("install device isn't specified")); + break; + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + break; + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + case GRUB_INSTALL_PLATFORM_I386_QEMU: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + free (install_device); + install_device = NULL; + break; + + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + if (!bootdir) + bootdir = grub_util_path_concat (3, "/", rootdir, GRUB_BOOT_DIR_NAME); + + { + char * t = grub_util_path_concat (2, bootdir, GRUB_DIR_NAME); + grub_install_mkdir_p (t); + grubdir = canonicalize_file_name (t); + if (!grubdir) + grub_util_error (_("failed to get canonical path of `%s'"), t); + free (t); + } + device_map = grub_util_path_concat (2, grubdir, "device.map"); + + if (recheck) + grub_util_unlink (device_map); + + device_map_check_duplicates (device_map); + grub_util_biosdisk_init (device_map); + + /* Initialize all modules. */ + grub_init_all (); + grub_gcry_init_all (); + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + is_efi = 1; + break; + default: + is_efi = 0; + break; + + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + /* Find the EFI System Partition. */ + + if (is_efi) + { + grub_fs_t fs; + free (install_device); + install_device = NULL; + if (!efidir) + { + char *d = grub_util_path_concat (2, bootdir, "efi"); + char *dr = NULL; + if (!grub_util_is_directory (d)) + { + free (d); + d = grub_util_path_concat (2, bootdir, "EFI"); + } + /* + The EFI System Partition may have been given directly using + --root-directory. + */ + if (!grub_util_is_directory (d) + && rootdir && grub_strcmp (rootdir, "/") != 0) + { + free (d); + d = xstrdup (rootdir); + } + if (grub_util_is_directory (d)) + dr = grub_make_system_path_relative_to_its_root (d); + /* Is it a mount point? */ + if (dr && dr[0] == '\0') + efidir = d; + else + free (d); + free (dr); + } + if (!efidir) + grub_util_error ("%s", _("cannot find EFI directory")); + efidir_device_names = grub_guess_root_devices (efidir); + if (!efidir_device_names || !efidir_device_names[0]) + grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), + efidir); + install_device = efidir_device_names[0]; + + for (curdev = efidir_device_names; *curdev; curdev++) + grub_util_pull_device (*curdev); + + efidir_grub_devname = grub_util_get_grub_dev (efidir_device_names[0]); + if (!efidir_grub_devname) + grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), + efidir_device_names[0]); + + efidir_grub_dev = grub_device_open (efidir_grub_devname); + if (! efidir_grub_dev) + grub_util_error ("%s", grub_errmsg); + + fs = grub_fs_probe (efidir_grub_dev); + if (! fs) + grub_util_error ("%s", grub_errmsg); + + if (grub_strcmp (fs->name, "fat") != 0) + grub_util_error (_("%s doesn't look like an EFI partition.\n"), efidir); + + /* The EFI specification requires that an EFI System Partition must + contain an "EFI" subdirectory, and that OS loaders are stored in + subdirectories below EFI. Vendors are expected to pick names that do + not collide with other vendors. To minimise collisions, we use the + name of our distributor if possible. + */ + char *t; + efi_distributor = bootloader_id; + if (removable) + { + /* The specification makes stricter requirements of removable + devices, in order that only one image can be automatically loaded + from them. The image must always reside under /EFI/BOOT, and it + must have a specific file name depending on the architecture. + */ + efi_distributor = "BOOT"; + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_EFI: + efi_file = "BOOTIA32.EFI"; + break; + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + efi_file = "BOOTX64.EFI"; + break; + case GRUB_INSTALL_PLATFORM_IA64_EFI: + efi_file = "BOOTIA64.EFI"; + break; + case GRUB_INSTALL_PLATFORM_ARM_EFI: + efi_file = "BOOTARM.EFI"; + break; + default: + grub_util_error ("%s", _("You've found a bug")); + break; + } + } + else + { + /* It is convenient for each architecture to have a different + efi_file, so that different versions can be installed in parallel. + */ + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_EFI: + efi_file = "grubia32.efi"; + break; + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + efi_file = "grubx64.efi"; + break; + case GRUB_INSTALL_PLATFORM_IA64_EFI: + efi_file = "grubia64.efi"; + break; + case GRUB_INSTALL_PLATFORM_ARM_EFI: + efi_file = "grubarm.efi"; + break; + default: + efi_file = "grub.efi"; + break; + } + } + t = grub_util_path_concat (3, efidir, "EFI", efi_distributor); + free (efidir); + efidir = t; + grub_install_mkdir_p (efidir); + } + + grub_install_copy_files (grub_install_source_directory, + grubdir, platform); + + char *envfile = grub_util_path_concat (2, grubdir, "grubenv"); + if (!grub_util_is_regular (envfile)) + grub_util_create_envblk_file (envfile); + + size_t ndev = 0; + + /* Write device to a variable so we don't have to traverse /dev every time. */ + grub_devices = grub_guess_root_devices (grubdir); + if (!grub_devices || !grub_devices[0]) + grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), + grubdir); + + for (curdev = grub_devices; *curdev; curdev++) + { + grub_util_pull_device (*curdev); + ndev++; + } + + grub_drives = xmalloc (sizeof (grub_drives[0]) * (ndev + 1)); + + for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++, + curdrive++) + { + *curdrive = grub_util_get_grub_dev (*curdev); + if (! *curdrive) + grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), + *curdev); + } + *curdrive = 0; + + grub_dev = grub_device_open (grub_drives[0]); + if (! grub_dev) + grub_util_error ("%s", grub_errmsg); + + grub_fs = grub_fs_probe (grub_dev); + if (! grub_fs) + grub_util_error ("%s", grub_errmsg); + + grub_install_push_module (grub_fs->name); + + if (grub_dev->disk) + probe_mods (grub_dev->disk); + + for (curdrive = grub_drives + 1; *curdrive; curdrive++) + { + grub_device_t dev = grub_device_open (*curdrive); + if (!dev) + continue; + if (dev->disk) + probe_mods (dev->disk); + grub_device_close (dev); + } + + if (!config.is_cryptodisk_enabled && have_cryptodisk) + grub_util_error (_("attempt to install to cryptodisk without cryptodisk enabled. " + "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=1", + grub_util_get_config_filename ()); + + if (disk_module && grub_strcmp (disk_module, "ata") == 0) + grub_install_push_module ("pata"); + else if (disk_module && grub_strcmp (disk_module, "native") == 0) + { + grub_install_push_module ("pata"); + grub_install_push_module ("ahci"); + grub_install_push_module ("ohci"); + grub_install_push_module ("uhci"); + grub_install_push_module ("usbms"); + } + else if (disk_module && disk_module[0]) + grub_install_push_module (disk_module); + + relative_grubdir = grub_make_system_path_relative_to_its_root (grubdir); + if (relative_grubdir[0] == '\0') + { + free (relative_grubdir); + relative_grubdir = xstrdup ("/"); + } + + char *platname = grub_install_get_platform_name (platform); + char *platdir; + { + char *t = grub_util_path_concat (2, grubdir, + platname); + platdir = canonicalize_file_name (t); + if (!platdir) + grub_util_error (_("failed to get canonical path of `%s'"), + t); + free (t); + } + load_cfg = grub_util_path_concat (2, platdir, + "load.cfg"); + + grub_util_unlink (load_cfg); + + if (debug_image && debug_image[0]) + { + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + fprintf (load_cfg_f, "set debug='%s'\n", + debug_image); + } + char *prefix_drive = NULL; + char *install_drive = NULL; + + if (install_device) + { + if (install_device[0] == '(' + && install_device[grub_strlen (install_device) - 1] == ')') + install_drive = xstrdup (install_device); + else + { + grub_util_pull_device (install_device); + install_drive = grub_util_get_grub_dev (install_device); + if (!install_drive) + grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), + install_device); + } + } + + if (!have_abstractions) + { + if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0) + || grub_drives[1] + || (!install_drive + && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275) + || (install_drive && !is_same_disk (grub_drives[0], install_drive)) + || !have_bootdev (platform)) + { + char *uuid = NULL; + /* generic method (used on coreboot and ata mod). */ + if (!force_file_id && grub_fs->uuid && grub_fs->uuid (grub_dev, + &uuid)) + { + grub_print_error (); + grub_errno = 0; + uuid = NULL; + } + + if (!load_cfg_f) + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + if (uuid) + { + fprintf (load_cfg_f, "search.fs_uuid %s root ", + uuid); + grub_install_push_module ("search_fs_uuid"); + } + else + { + char *rndstr = get_rndstr (); + char *fl = grub_util_path_concat (3, grubdir, + "uuid", rndstr); + char *fldir = grub_util_path_concat (2, grubdir, + "uuid"); + char *relfl; + FILE *flf; + grub_install_mkdir_p (fldir); + flf = grub_util_fopen (fl, "w"); + if (!flf) + grub_util_error ("Can't create file: %s", strerror (errno)); + fclose (flf); + relfl = grub_make_system_path_relative_to_its_root (fl); + fprintf (load_cfg_f, "search.file %s root ", + relfl); + grub_install_push_module ("search_fs_file"); + } + for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++, + curdrive++) + { + const char *map; + char *g = NULL; + grub_device_t dev; + if (curdrive == grub_drives) + dev = grub_dev; + else + dev = grub_device_open (*curdrive); + if (!dev) + continue; + + if (dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) + { + grub_util_fprint_full_disk_name (load_cfg_f, + dev->disk->name, + dev); + fprintf (load_cfg_f, " "); + if (dev != grub_dev) + grub_device_close (dev); + continue; + } + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + + if (map) + { + grub_util_fprint_full_disk_name (load_cfg_f, map, dev); + fprintf (load_cfg_f, " "); + } + + + if (disk_module && disk_module[0] + && grub_strcmp (disk_module, "biosdisk") != 0) + g = grub_util_guess_baremetal_drive (*curdev); + else + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_PC: + g = grub_util_guess_bios_drive (*curdev); + break; + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + g = grub_util_guess_efi_drive (*curdev); + break; + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + { + const char * ofpath = grub_util_devname_to_ofpath (*curdev); + g = xasprintf ("ieee1275/%s", ofpath); + break; + } + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_I386_QEMU: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + g = grub_util_guess_baremetal_drive (*curdev); + break; + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + grub_util_warn ("%s", _("no hints available for your platform. Expect reduced performance")); + break; + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + if (g) + { + grub_util_fprint_full_disk_name (load_cfg_f, g, dev); + fprintf (load_cfg_f, " "); + } + if (dev != grub_dev) + grub_device_close (dev); + } + fprintf (load_cfg_f, "\n"); + char *escaped_relpath = escape (relative_grubdir); + fprintf (load_cfg_f, "set prefix=($root)'%s'\n", + escaped_relpath); + } + else + { + /* We need to hardcode the partition number in the core image's prefix. */ + char *p; + for (p = grub_drives[0]; *p; ) + { + if (*p == '\\' && p[1]) + { + p += 2; + continue; + } + if (*p == ',' || *p == '\0') + break; + p++; + } + prefix_drive = xasprintf ("(%s)", p); + } + } + else + { + if (config.is_cryptodisk_enabled) + { + if (grub_dev->disk) + probe_cryptodisk_uuid (grub_dev->disk); + + for (curdrive = grub_drives + 1; *curdrive; curdrive++) + { + grub_device_t dev = grub_device_open (*curdrive); + if (!dev) + continue; + if (dev->disk) + probe_cryptodisk_uuid (dev->disk); + grub_device_close (dev); + } + } + prefix_drive = xasprintf ("(%s)", grub_drives[0]); + } + + char mkimage_target[200]; + const char *core_name = NULL; + + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + core_name = "core.efi"; + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s", + grub_install_get_platform_cpu (platform), + grub_install_get_platform_platform (platform)); + break; + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + core_name = "core.elf"; + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s-elf", + grub_install_get_platform_cpu (platform), + grub_install_get_platform_platform (platform)); + break; + + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + core_name = "core.elf"; + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s", + grub_install_get_platform_cpu (platform), + grub_install_get_platform_platform (platform)); + break; + + + case GRUB_INSTALL_PLATFORM_I386_PC: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + case GRUB_INSTALL_PLATFORM_I386_QEMU: + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s", + grub_install_get_platform_cpu (platform), + grub_install_get_platform_platform (platform)); + core_name = "core.img"; + break; + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + strcpy (mkimage_target, "sparc64-ieee1275-raw"); + core_name = "core.img"; + break; + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + if (!core_name) + grub_util_error ("%s", _("You've found a bug")); + + if (load_cfg_f) + fclose (load_cfg_f); + + char *imgfile = grub_util_path_concat (2, platdir, + core_name); + char *prefix = xasprintf ("%s%s", prefix_drive ? : "", + relative_grubdir); + grub_install_make_image_wrap (/* source dir */ grub_install_source_directory, + /*prefix */ prefix, + /* output */ imgfile, + /* memdisk */ NULL, + have_load_cfg ? load_cfg : NULL, + /* image target */ mkimage_target, + 0, GRUB_COMPRESSION_AUTO); + /* Backward-compatibility kludges. */ + switch (platform) + { + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + { + char *dst = grub_util_path_concat (2, bootdir, "grub.elf"); + grub_install_copy_file (imgfile, dst, 1); + free (dst); + } + break; + + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + { + char *dst = grub_util_path_concat (2, grubdir, "grub"); + grub_install_copy_file (imgfile, dst, 1); + free (dst); + } + break; + + case GRUB_INSTALL_PLATFORM_I386_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + { + char *dst = grub_util_path_concat (2, platdir, "grub.efi"); + grub_install_make_image_wrap (/* source dir */ grub_install_source_directory, + /* prefix */ "", + /* output */ dst, + /* memdisk */ NULL, + have_load_cfg ? load_cfg : NULL, + /* image target */ mkimage_target, + 0, GRUB_COMPRESSION_AUTO); + } + break; + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_I386_PC: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + case GRUB_INSTALL_PLATFORM_I386_QEMU: + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + break; + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + /* Perform the platform-dependent install */ + + switch (platform) + { + case GRUB_INSTALL_PLATFORM_I386_PC: + { + char *boot_img_src = grub_util_path_concat (2, + grub_install_source_directory, + "boot.img"); + char *boot_img = grub_util_path_concat (2, platdir, + "boot.img"); + grub_install_copy_file (boot_img_src, boot_img, 1); + + grub_util_info ("grub_bios_setup %s %s %s %s --directory='%s' --device-map='%s' '%s'", + allow_floppy ? "--allow-floppy " : "", + verbosity ? "--verbose " : "", + force ? "--force " : "", + !fs_probe ? "--skip-fs-probe" : "", + platdir, + device_map, + install_device); + + /* Now perform the installation. */ + grub_util_bios_setup (platdir, "boot.img", "core.img", + install_drive, force, + fs_probe, allow_floppy); + break; + } + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: + { + char *boot_img_src = grub_util_path_concat (2, + grub_install_source_directory, + "boot.img"); + char *boot_img = grub_util_path_concat (2, platdir, + "boot.img"); + grub_install_copy_file (boot_img_src, boot_img, 1); + + grub_util_info ("grub_sparc_setup %s %s %s %s --directory='%s' --device-map='%s' '%s'", + allow_floppy ? "--allow-floppy " : "", + verbosity ? "--verbose " : "", + force ? "--force " : "", + !fs_probe ? "--skip-fs-probe" : "", + platdir, + device_map, + install_drive); + + /* Now perform the installation. */ + grub_util_sparc_setup (platdir, "boot.img", "core.img", + install_device, force, + fs_probe, allow_floppy); + break; + } + + case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275: + /* If a install device is defined, copy the core.elf to PReP partition. */ + if (install_device && install_device[0]) + { + grub_device_t ins_dev; + ins_dev = grub_device_open (install_drive); + if (!ins_dev || !is_prep_partition (ins_dev)) + { + grub_util_error ("%s", _("the chosen partition is not a PReP partition")); + } + if (is_prep_empty (ins_dev)) + { + if (write_to_disk (ins_dev, imgfile)) + grub_util_error ("%s", _("failed to copy Grub to the PReP partition")); + } + else + { + char *s = xasprintf ("dd if=/dev/zero of=%s", install_device); + grub_util_error ("the PReP partition is not empty. If you are sure you want to use it, run dd to clear it: `%s'", + s); + } + grub_device_close (ins_dev); + } + /* fallthrough. */ + case GRUB_INSTALL_PLATFORM_I386_IEEE1275: + if (update_nvram) + { + if (platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275 + || !install_device + || install_device[0] == '\0') + { + const char *dev; + char *relpath; + int partno; + relpath = grub_make_system_path_relative_to_its_root (imgfile); + partno = grub_dev->disk->partition + ? grub_dev->disk->partition->number + 1 : 0; + dev = grub_util_get_os_disk (grub_devices[0]); + grub_install_register_ieee1275 (0, dev, + partno, relpath); + } + else + grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device), + 0, NULL); + } + break; + case GRUB_INSTALL_PLATFORM_MIPS_ARC: + grub_install_sgi_setup (install_device, imgfile, "grub"); + break; + + case GRUB_INSTALL_PLATFORM_I386_EFI: + { + char *dst = grub_util_path_concat (2, efidir, "grub.efi"); + /* For old macs. Suggested by Peter Jones. */ + grub_install_copy_file (imgfile, dst, 1); + free (dst); + } + + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_ARM_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: + { + char *dst = grub_util_path_concat (2, efidir, efi_file); + grub_install_copy_file (imgfile, dst, 1); + free (dst); + } + if (!removable) + { + char * efidir_disk; + int efidir_part; + char * efifile_path; + + /* Try to make this image bootable using the EFI Boot Manager, if available. */ + if (!efi_distributor || efi_distributor[0] == '\0') + grub_util_error ("%s", "EFI distributor id isn't specified."); + efidir_disk = grub_util_get_os_disk (efidir_device_names[0]); + efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1; + efifile_path = xasprintf ("\\EFI\\%s\\%s", + efi_distributor, + efi_file); + grub_install_register_efi (efidir_disk, efidir_part, + efifile_path, efi_distributor); + } + break; + + case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON: + case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS: + case GRUB_INSTALL_PLATFORM_I386_COREBOOT: + case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT: + case GRUB_INSTALL_PLATFORM_MIPSEL_ARC: + case GRUB_INSTALL_PLATFORM_ARM_UBOOT: + case GRUB_INSTALL_PLATFORM_I386_QEMU: + grub_util_warn ("%s", + _("WARNING: no platform-specific install was performed")); + break; + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: + break; + } + + fprintf (stderr, "%s\n", _("Installation finished. No error reported.")); + + /* Free resources. */ + grub_gcry_fini_all (); + grub_fini_all (); + + return 0; +} diff --git a/util/grub-install.in b/util/grub-install.in deleted file mode 100644 index c022a6bb9..000000000 --- a/util/grub-install.in +++ /dev/null @@ -1,829 +0,0 @@ -#! /bin/sh - -# Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# Initialize some variables. -sbindir="@sbindir@" -sysconfdir="@sysconfdir@" - -host_os=@host_os@ -target= - -grub_probe="${sbindir}/@grub_probe@" -grub_editenv="${bindir}/@grub_editenv@" -grub_mkrelpath="${bindir}/@grub_mkrelpath@" -rootdir= -bootdir= -grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`" - -install_device= -force_lba= -recheck=no -debug=no -debug_image= - -update_nvram=yes - -removable=no -efi_quiet=-q - -# Get GRUB_DISTRIBUTOR. -if test -f "${sysconfdir}/default/grub" ; then - . "${sysconfdir}/default/grub" -fi - -bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr 'A-Z' 'a-z' | cut -d' ' -f1)" -if test -z "$bootloader_id"; then - bootloader_id=grub -fi - -disk_module=unspecified - -# Usage: usage -# Print the usage. -usage () { - # TRANSLATORS: INSTALL_DEVICE isn't an identifier and is the DEVICE you - # install to. - gettext_printf "Usage: %s [OPTION] [INSTALL_DEVICE]" "$self" - echo - gettext "Install GRUB on your drive." ; echo - echo - print_option_help "-h, --help" "$(gettext "print this message and exit")" - grub_print_install_files_help - - dirmsg="$(gettext_printf "install GRUB images under the directory DIR/%s instead of the %s directory" "@grubdirname@" "$grubdir")" - print_option_help "--boot-directory=$(gettext "DIR")" "$dirmsg" - # TRANSLATORS: "TARGET" as in "target platform". - target_trans="$(gettext "TARGET")" - # TRANSLATORS: "current" refers to the platform user's currently running on - print_option_help "--target=$target_trans" "$(gettext "install GRUB for TARGET platform [default=current]")" - print_option_help "--grub-setup=$(gettext "FILE")" "$(gettext "use FILE as grub-setup")" - print_option_help "--grub-mkrelpath=$(gettext "FILE")" "$(gettext "use FILE as grub-mkrelpath")" - print_option_help "--grub-probe=$(gettext "FILE")" "$(gettext "use FILE as grub-probe")" - print_option_help "--grub-editenv=$(gettext "FILE")" "$(gettext "use FILE as grub-editenv")" - # TRANSLATORS: "may break" doesn't just mean that option wouldn't have any - # effect but that it will make the resulting install unbootable from HDD. - print_option_help "--allow-floppy" "$(gettext "make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes.")" - print_option_help "--recheck" "$(gettext "delete device map if it already exists")" - print_option_help "--force" "$(gettext "install even if problems are detected")" - print_option_help "--force-file-id" "$(gettext "use identifier file even if UUID is available")" - print_option_help "--disk-module=$(gettext "MODULE")" "$(gettext "disk module to use (biosdisk or native). This option is only available on BIOS target.")" - print_option_help "--no-nvram" "$(gettext "don't update the \`boot-device' NVRAM variable. This option is only available on IEEE1275 targets.")" - print_option_help "--removable" "$(gettext "the installation device is removable. This option is only available on EFI.")" - print_option_help "--bootloader-id=$(gettext "ID")" "$(gettext "the ID of bootloader. This option is only available on EFI.")" - print_option_help "--efi-directory=$(gettext "DIR")" "$(gettext "use DIR as the EFI System Partition root.")" -echo -gettext "INSTALL_DEVICE must be system device filename.";echo -echo - -gettext_printf "%s copies GRUB images into %s. On some platforms, it -may also install GRUB into the boot sector.\n" "$self" "$grubdir";echo -echo -gettext "Report bugs to ."; echo -} - -allow_floppy="" -force_file_id= -efidir= - -# Check the arguments. -while test $# -gt 0 -do - grub_process_install_options "$@" - case "$grub_process_install_options_consumed" in - 1) shift; continue;; - 2) shift; shift; continue;; - esac - - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - - --force-file-id) - force_file_id=y ;; - -# Accept and ignore for compatibility - --font) - shift;; - --font=*) - ;; - -# Accept for compatibility - --root-directory) - rootdir="`argument $option "$@"`"; shift;; - --root-directory=*) - rootdir="`echo "$option" | sed 's/--root-directory=//'`" ;; - - --boot-directory) - bootdir="`argument $option "$@"`"; shift;; - --boot-directory=*) - bootdir="`echo "$option" | sed 's/--boot-directory=//'`" ;; - - --efi-directory) - efidir="`argument $option "$@"`"; shift;; - --efi-directory=*) - efidir="`echo "$option" | sed 's/--efi-directory=//'`" ;; - - --target) - target="`argument $option "$@"`"; shift;; - --target=*) - target="`echo "$option" | sed 's/--target=//'`" ;; - - --grub-setup) - grub_setup="`argument "$option" "$@"`"; shift;; - --grub-setup=*) - grub_setup="`echo "$option" | sed 's/--grub-setup=//'`" ;; - - --bootloader-id) - bootloader_id="`argument $option "$@"`"; shift;; - --bootloader-id=*) - bootloader_id="`echo "$option" | sed 's/--bootloader-id=//'`" ;; - - --grub-mkrelpath) - grub_mkrelpath="`argument "$option" "$@"`"; shift;; - --grub-mkrelpath=*) - grub_mkrelpath="`echo "$option" | sed 's/--grub-mkrelpath=//'`" ;; - - # Ignore: for compatibility - --grub-mkdevicemap) - shift;; - --grub-mkdevicemap=*) - ;; - - --grub-probe) - grub_probe="`argument "$option" "$@"`"; shift;; - --grub-probe=*) - grub_probe="`echo "$option" | sed 's/--grub-probe=//'`" ;; - - --grub-editenv) - grub_editenv="`argument "$option" "$@"`"; shift;; - --grub-editenv=*) - grub_editenv="`echo "$option" | sed 's/--grub-editenv=//'`" ;; - - --no-floppy) - ;; - --recheck) - recheck=yes ;; - --removable) - removable=yes ;; - - --allow-floppy) - allow_floppy="--allow-floppy" ;; - - --disk-module) - disk_module="`argument "$option" "$@"`"; shift; - ;; - --disk-module=*) - disk_module="`echo "$option" | sed 's/--disk-module=//'`" - ;; - - --no-nvram) - update_nvram=no ;; - - # This is an undocumented feature... - --debug) - debug=yes ;; - --debug-image) - debug_image="`argument "$option" "$@"`"; shift;; - --debug-image=*) - debug_image="`echo "$option" | sed 's/--debug-image=//'`" ;; - - -f | --force) - setup_force="--force" ;; - - -*) - gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 - usage - exit 1 - ;; - *) - if test "x$install_device" != x; then - gettext "More than one install device?" 1>&2 - echo 1>&2 - usage - exit 1 - fi - install_device="${option}" ;; - esac -done - -if [ x$source_directory = x ]; then - if [ x$target = x ]; then - case x"`uname -m`" in - x"powerpc"* | x"ppc"*) - target="powerpc-ieee1275";; - x"sparc"*) - target="sparc64-ieee1275";; - x"mips"*"el") - target="mipsel-loongson";; - x"mips"*) - target="mips-arc";; - x"ia64"*) - target="ia64-efi";; - x"x86_64"* | x"amd64"*) - # On Linux, we need the efivars kernel modules. - # If no EFI is available this module just does nothing - # besides a small hello and if we detect efi we'll load it - # anyway later. So it should be safe to - # try to load it here. - case "$host_os" in - linux*) - modprobe -q efivars 2>/dev/null || true ;; - esac - if [ -d /sys/firmware/efi ]; then - target="x86_64-efi" - else - target=i386-pc - fi - ;; - x"i"?"86"*) - # On Linux, we need the efivars kernel modules. - # If no EFI is available this module just does nothing - # besides a small hello and if we detect efi we'll load it - # anyway later. So it should be safe to - # try to load it here. - case "$host_os" in - linux*) - modprobe -q efivars 2>/dev/null || true ;; - esac - if [ -d /sys/firmware/efi ]; then - target="i386-efi" - elif [ -e /proc/device-tree ]; then - target=i386-pc - for x in /proc/device-tree/*; do - if [ -e "$x" ]; then - target="i386-ieee1275" - fi - done - else - target=i386-pc - fi - ;; - x"arm"*) - target="arm-uboot";; - *) - gettext "Unable to determine your platform. Use --target." ; - echo ;; - esac - fi - source_directory="${libdir}/@PACKAGE@/$target" -fi - -if ! [ -d "$source_directory" ]; then - gettext_printf "%s doesn't exist. Please specify --target or --directory\\n" "$source_directory" - exit 1 -fi - -. "${source_directory}"/modinfo.sh - -if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] ; then - if [ x$disk_module = xunspecified ]; then - disk_module=biosdisk - fi -elif [ "${grub_modinfo_platform}" = "ieee1275" ] || [ "${grub_modinfo_platform}" = "efi" ] || [ "${grub_modinfo_platform}" = "arc" ] || [ "${grub_modinfo_platform}" = "uboot" ] ; then - disk_module= -else - disk_module=native -fi - -if test "x$grub_setup" = x && [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ]; then - grub_setup="${sbindir}/@grub_bios_setup@" -fi - -if test "x$grub_setup" = x && [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ]; then - grub_setup="${sbindir}/@grub_sparc64_setup@" -fi - -if test "x$install_device" = x && ([ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] \ - || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ]); then - gettext "Install device isn't specified." 1>&2 - echo 1>&2 - usage - exit 1 -fi - -if ! ([ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] \ - || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ] \ - || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "powerpc-ieee1275" ] \ - || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "mips-arc" ]); then - install_device= -fi - -# If the debugging feature is enabled, print commands. -setup_verbose= -if test x"$debug" = xyes; then - set -x - setup_verbose="--verbose" - efi_quiet= -fi - -if [ -z "$bootdir" ]; then - # Default bootdir if bootdir not initialized. - bootdir="/@bootdirname@" - - if [ -n "$rootdir" ] ; then - # Initialize bootdir if rootdir was initialized. - bootdir="${rootdir}/@bootdirname@" - fi -fi - -grubdir="`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'`" -device_map="${grubdir}/device.map" - - -# Check if GRUB is installed. -if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ] ; then - set $grub_setup dummy - if test -f "$1"; then - : - else - # TRANSLATORS: This message is shown when required executable `%s' - # isn't found - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 - fi -fi - -set "$grub_mkimage" dummy -if test -f "$1"; then - : -else - # TRANSLATORS: This message is shown when required executable `%s' - # isn't found - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 -fi - -if [ x"$grub_modinfo_platform" = xefi ]; then - # Find the EFI System Partition. - if test -n "$efidir"; then - install_device="`"$grub_probe" --target=device --device-map= "${efidir}"`" - else - if test -d "${bootdir}/efi"; then - install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/efi"`" - # Is it a mount point? - if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then - efidir="${bootdir}/efi" - fi - elif test -d "${bootdir}/EFI"; then - install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/EFI"`" - # Is it a mount point? - if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then - efidir="${bootdir}/EFI" - fi - elif test -n "$rootdir" && test "x$rootdir" != "x/"; then - # The EFI System Partition may have been given directly using - # --root-directory. - install_device="`"$grub_probe" --target=device --device-map= "${rootdir}"`" - # Is it a mount point? - if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${rootdir}/.."`"; then - efidir="${rootdir}" - fi - fi - - if test -n "$efidir"; then - efi_fs=`"$grub_probe" --target=fs "--device-map=${device_map}" "${efidir}"` - if test "x$efi_fs" = xfat; then :; else - gettext_printf "%s doesn't look like an EFI partition.\n" "${efidir}" 1>&2 - efidir= - fi - fi - fi - - if test -n "$efidir"; then - # The EFI specification requires that an EFI System Partition must - # contain an "EFI" subdirectory, and that OS loaders are stored in - # subdirectories below EFI. Vendors are expected to pick names that do - # not collide with other vendors. To minimise collisions, we use the - # name of our distributor if possible. - efi_distributor="$bootloader_id" - if test $removable = yes; then - # The specification makes stricter requirements of removable - # devices, in order that only one image can be automatically loaded - # from them. The image must always reside under /EFI/BOOT, and it - # must have a specific file name depending on the architecture. - efi_distributor=BOOT - case "$grub_modinfo_target_cpu" in - i386) - efi_file=BOOTIA32.EFI ;; - x86_64) - efi_file=BOOTX64.EFI ;; - # GRUB does not yet support these architectures, but they're defined - # by the specification so we include them here to ease future - # expansion. - ia64) - efi_file=BOOTIA64.EFI ;; - arm) - efi_file=BOOTARM.EFI ;; - esac - else - # It is convenient for each architecture to have a different - # efi_file, so that different versions can be installed in parallel. - case "$grub_modinfo_target_cpu" in - i386) - efi_file=grubia32.efi ;; - x86_64) - efi_file=grubx64.efi ;; - # GRUB does not yet support these architectures, but they're defined - # by the specification so we include them here to ease future - # expansion. - ia64) - efi_file=grubia64.efi ;; - arm) - efi_file=grubarm.efi ;; - *) - efi_file=grub.efi ;; - esac - fi - efidir="$efidir/EFI/$efi_distributor" - mkdir -p "$efidir" || exit 1 - else - # We don't know what's going on. Fall back to traditional - # (non-specification-compliant) behaviour. - efidir="$grubdir" - efi_distributor= - efi_file=grub.efi - fi -fi - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 -mkdir -p "$grubdir/${grub_modinfo_target_cpu}-$grub_modinfo_platform" || exit 1 - -# If --recheck is specified, remove the device map, if present. -if test $recheck = yes; then - rm -f "$device_map" -fi - -# Device map file is optional -if test -f "$device_map"; then - # Make sure that there is no duplicated entry. - tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \ - | sort | uniq -d | sed -n 1p` - if test -n "$tmp"; then - gettext_printf "The drive %s is defined multiple times in the device map %s\n" "$tmp" "$device_map" 1>&2 - exit 1 - fi -else - device_map= -fi - -# Copy the GRUB images to the GRUB directory. -grub_install_files "${source_directory}" "${grubdir}" "${grub_modinfo_target_cpu}-$grub_modinfo_platform" all - -if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ] ; then - for file in "${source_directory}"/*.img "${source_directory}"/efiemu??.o; do - if test -f "$file"; then - cp -f "$file" "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform" || exit 1 - fi - done -fi - -if ! is_path_readable_by_grub "${grubdir}"; then - gettext_printf "Path \`%s' is not readable by GRUB on boot. Installation is impossible. Aborting.\n" "${grubdir}" 1>&2 - exit 1 -fi - -# Write device to a variable so we don't have to traverse /dev every time. -grub_device="`"$grub_probe" --device-map="${device_map}" --target=device "${grubdir}"`" || exit 1 - -if ! test -f "${grubdir}"/grubenv; then - "$grub_editenv" "${grubdir}"/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=fs --device `" -if test "x$fs_module" = x ; then - gettext_printf "Auto-detection of a filesystem of %s failed.\n" "${grub_device}" 1>&2 - gettext "Try with --recheck." 1>&2 - echo 1>&2 - gettext_printf "If the problem persists please report this together with the output of %s to <%s>" "\"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\"" "bug-grub@gnu.org" 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=partmap --device 2> /dev/null`; do - case "$x" in - netbsd | openbsd) - partmap_module="$partmap_module part_bsd";; - "") ;; - *) - partmap_module="$partmap_module part_$x";; - esac -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=abstraction --device`" - -if [ "x$disk_module" = xata ]; then - disk_module=pata -fi - -if [ "x$disk_module" = xnative ]; then - disk_module="pata ahci ohci" - if [ "x$grub_modinfo_target_cpu" = "xi386" ] || [ "x$grub_modinfo_target_cpu" = "xx86_64" ]; then - disk_module="$disk_module uhci" - fi - disk_module="$disk_module usbms" -fi - -# The order in this list is critical. Be careful when modifying it. -modules="$modules $disk_module" -modules="$modules $fs_module $partmap_module $devabstraction_module" - -relative_grubdir="`"$grub_mkrelpath" "${grubdir}"`" || exit 1 -if [ "x${relative_grubdir}" = "x" ] ; then - relative_grubdir=/ -fi - -prefix_drive= -config_opt_file= - -rm -f "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - -if [ "x${debug_image}" != x ]; then - echo "set debug='${debug_image}'" >> "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - config_opt_file="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" -fi - -if [ "x${devabstraction_module}" = "x" ] ; then - if [ x"${install_device}" != x ]; then - if echo "${install_device}" | grep -qx "(.*)" ; then - install_drive="${install_device}" - else - install_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${install_device}"`" || exit 1 - fi - install_drive="`echo "${install_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\1/'`" - fi - grub_drive="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=drive --device`" || exit 1 - - # Strip partition number - grub_partition="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\3/'`" - grub_drive="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\1/'`" - - if [ x"${install_device}" = x ] && [ x"${grub_modinfo_target_cpu}-$grub_modinfo_platform" = x"powerpc-ieee1275" ]; then - install_drive="$grub_drive" - fi - - if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$grub_modinfo_platform" != xefi ] && [ "x$grub_modinfo_platform" != xpc ] && [ x"${grub_modinfo_platform}" != x"ieee1275" ]); then - # generic method (used on coreboot and ata mod) - uuid= - if [ x"$force_file_id" != xy ]; then - uuid="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=fs_uuid --device`" - fi - - if [ x"$disk_module" != x ] && [ x"$disk_module" != xbiosdisk ]; then - hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`" - elif [ x"$grub_modinfo_platform" = xpc ]; then - hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=bios_hints --device`" - elif [ x"$grub_modinfo_platform" = xefi ]; then - hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=efi_hints --device`" - elif [ x"$grub_modinfo_platform" = xieee1275 ]; then - hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=ieee1275_hints --device`" - elif [ x"$grub_modinfo_platform" = xloongson ] || [ x"$grub_modinfo_platform" = xqemu ] || [ x"$grub_modinfo_platform" = xcoreboot ] || [ x"$grub_modinfo_platform" = xmultiboot ] || [ x"$grub_modinfo_platform" = xqemu-mips ]; then - hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`" - else - gettext "No hints available for your platform. Expect reduced performance." 1>&2 - echo 1>&2 - hints= - fi - if [ x"$uuid" != x ]; then - echo "search.fs_uuid ${uuid} root $hints " >> "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - search_module=search_fs_uuid - else - mkdir -p "${grubdir}/uuid" - file="`mktemp "${grubdir}/uuid/XXXXXXXXXXXXXXXXXXXXXXXXX"`" - relfile="`${grub_mkrelpath} "$file"`" - echo "search.file '${relfile}' root $hints " >> "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - search_module=search_fs_file - fi - echo 'set prefix=($root)'"$(echo "${relative_grubdir}" | sed "s,\\([ \"'\\\\]\\),\\\\\\1,g")" >> "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - config_opt_file="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - modules="$modules $search_module" - else - # we need to hardcode the partition number in the core image's prefix. - if [ x"$grub_partition" = x ]; then - prefix_drive="()" - else - # Comma is already there - prefix_drive="($grub_partition)" - fi - fi -else - if [ x$GRUB_ENABLE_CRYPTODISK = xy ]; then - for uuid in "`echo "${grub_device}" | xargs "${grub_probe}" --target=cryptodisk_uuid --device`"; do - echo "cryptomount -u $uuid" >> "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - done - config_opt_file="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" - fi - - prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1 -fi - -case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in - sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; - mipsel-loongson) mkimage_target=mipsel-loongson-elf ;; - mips-qemu_mips | mipsel-qemu_mips) mkimage_target="${grub_modinfo_target_cpu}-${grub_modinfo_platform}"-elf ;; - *) mkimage_target="${grub_modinfo_target_cpu}-${grub_modinfo_platform}" ;; -esac - -case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in - i386-efi | x86_64-efi | ia64-efi) imgext=efi ;; - mipsel-loongson | i386-coreboot | i386-multiboot | i386-ieee1275 \ - | powerpc-ieee1275 | mips-qemu_mips | mipsel-qemu_mips) imgext=elf ;; - *) imgext=img ;; -esac - -if [ x"$config_opt_file" = x ]; then - "$grub_mkimage" -d "${source_directory}" -O "${mkimage_target}" --output="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $grub_decompression_module $modules || exit 1 -else - "$grub_mkimage" -c "${config_opt_file}" -d "${source_directory}" -O "${mkimage_target}" --output="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $grub_decompression_module $modules || exit 1 -fi - -# Backward-compatibility kludges -if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "mipsel-loongson" ]; then - cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${bootdir}"/grub.elf -elif [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-ieee1275" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "powerpc-ieee1275" ]; then - cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${grubdir}/grub" -elif [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-efi" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "x86_64-efi" ]; then - - if [ x"$config_opt_file" = x ]; then - "$grub_mkimage" -d "${source_directory}" -O "${mkimage_target}" --output="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/grub.efi" --prefix="" $grub_decompression_module $modules || exit 1 - else - "$grub_mkimage" -c "${config_opt_file}" -d "${source_directory}" -O "${mkimage_target}" --output="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/grub.efi" --prefix="" $grub_decompression_module $modules || exit 1 - fi -fi - - -# Perform the grub_modinfo_platform-dependent install -if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "sparc64-ieee1275" ] ; then - # Now perform the installation. - "$grub_setup" ${allow_floppy} ${setup_verbose} ${setup_force} --directory="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform" \ - --device-map="${device_map}" "${install_device}" || exit 1 -elif [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-ieee1275" ] || [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "powerpc-ieee1275" ]; then - - # If a install device is defined, copy the core.elf to PReP partition. - if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "powerpc-ieee1275" ] && [ -n "${install_device}" ]; then - - if [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t msdos_parttype)" != "41" ] \ - && [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t gpt_parttype)" != "9e1a2d38-c612-4316-aa26-8b49521e5a8b" ]; then - gettext "The chosen partition is not a PReP partition." 1>&2 - echo 1>&2 - exit 1 - fi - - if [ "$(file -s -b -L "${install_device}" | awk '{ print $1 }')" = ELF ] || [ x$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t zero_check) = xtrue ]; then - dd if="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" of="${install_device}" status=noxfer || { - gettext "Failed to copy Grub to the PReP partition." 1>&2 - echo 1>&2 - exit 1 - } - else - gettext "The PReP partition is not empty. If you are sure you want to use it, run dd to clear it:" 1>&2 - echo 1>&2 - echo " dd if=/dev/zero of=${install_device}" - exit 1 - fi - fi - - if [ x"$update_nvram" = xyes ]; then - ofpathname="`which ofpathname`" - nvsetenv="`which nvsetenv`" - set "$ofpathname" dummy - if test -f "$1"; then - : - else - # TRANSLATORS: This message is shown when required executable `%s' - # isn't found - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 - fi - set "$nvsetenv" dummy - if test -f "$1"; then - : - else - # TRANSLATORS: This message is shown when required executable `%s' - # isn't found - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 - fi - if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" != "powerpc-ieee1275" ] \ - || [ -z "${install_device}" ]; then - # Get the Open Firmware device tree path translation. - dev="`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`" - partno="`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'`" - ofpath="`$ofpathname $dev`" || { - # TRANSLATORS: "device tree path" is the name of the device - # for IEEE1275 - gettext_printf "Couldn't find IEEE1275 device tree path for %s.\nYou will have to set \`boot-device' variable manually.\n" "$dev" 1>&2 - exit 1 - } - - # Point boot-device at the new grub install - boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" | sed 's,/,\\\\,g'` - - else - - dev="`echo "${install_device}" | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`" - boot_device="`$ofpathname "$dev"`" || { - # TRANSLATORS: "device tree path" is the name of the device - # for IEEE1275 - gettext_printf "Couldn't find IEEE1275 device tree path for %s.\nYou will have to set \`boot-device' variable manually.\n" "$dev" 1>&2 - exit 1 - } - fi - - "$nvsetenv" boot-device "$boot_device" || { - # TRANSLATORS: The %s will be replaced by an external program name. - gettext_printf "\`%s' failed.\n" "$nvsetenv" 1>&2 - gettext "You will have to set \`boot-device' variable manually. At the IEEE1275 prompt, type:" 1>&2 - echo 1>&2 - echo " setenv boot-device $boot_device" 1>&2 - exit 1 - } - fi -elif [ x"${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = xmips-arc ]; then - dvhtool -d "${install_device}" --unix-to-vh "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" grub - gettext "You will have to set \`SystemPartition' and \`OSLoader' manually." 1>&2 - echo 1>&2 -elif [ x"$grub_modinfo_platform" = xefi ]; then - cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/${efi_file}" - # For old macs. Suggested by Peter Jones. - if [ x$grub_modinfo_target_cpu = xi386 ]; then - cp "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" "${efidir}/boot.efi" - fi - - # Try to make this image bootable using the EFI Boot Manager, if available. - if test "$removable" = no; then - - efibootmgr="`which efibootmgr`" || { - # TRANSLATORS: This message is shown when required executable `%s' - # isn't found - gettext_printf "%s: Not found.\n" "efibootmgr" 1>&2 - exit 1 - } - - test -n "$efi_distributor" || { - gettext "EFI distributor id isn't specified." 1>&2 - echo 1>&2 - exit 1 - } - - # On Linux, we need the efivars kernel modules. - case "$host_os" in - linux*) - modprobe -q efivars 2>/dev/null || true ;; - esac - - # Delete old entries from the same distributor. - for bootnum in `efibootmgr | grep '^Boot[0-9]' | \ - fgrep -i " $efi_distributor" | cut -b5-8`; do - efibootmgr $efi_quiet -b "$bootnum" -B - done - - # Add a new entry for the image we just created. efibootmgr needs to be - # given the disk device and partition number separately, so we have to - # fiddle about with grub-probe to get hold of this reasonably reliably. - # Use fresh device map text to avoid any problems with stale data, since - # all we need here is a one-to-one mapping. - efidir_drive="$("$grub_probe" --target=drive --device-map= "$efidir")" - efidir_disk="$("$grub_probe" --target=disk --device-map= "$efidir")" - if test -z "$efidir_drive" || test -z "$efidir_disk"; then - gettext_printf "Can't find GRUB drive for %s; unable to create EFI Boot Manager entry.\n" "$efidir" >&2 - else - efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" - efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ - -L "$bootloader_id" -l "\\EFI\\$efi_distributor\\$efi_file" - fi - fi -else - gettext "WARNING: no platform-specific install was performed" 1>&2 - echo 1>&2 -fi - -gettext "Installation finished. No error reported." 1>&2 -echo 1>&2 - -# Bye. -exit 0 diff --git a/util/grub-install_header b/util/grub-install_header deleted file mode 100644 index 2759ae89e..000000000 --- a/util/grub-install_header +++ /dev/null @@ -1,263 +0,0 @@ -#! /bin/sh -set -e - -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012 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 . - -prefix="@prefix@" -exec_prefix="@exec_prefix@" -datarootdir="@datarootdir@" -bindir="@bindir@" - -libdir="@libdir@" -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -datadir="@datadir@" -if [ "x$pkgdatadir" = x ]; then - pkgdatadir="${datadir}/@PACKAGE@" -fi -localedir="@datadir@/locale" - -self=`basename $0` - -export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR="@localedir@" - -. "${pkgdatadir}/grub-mkconfig_lib" - -modules= - -pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst \ -handler.lst video.lst crypto.lst terminal.lst" - -grub_mkimage="${bindir}/@grub_mkimage@" - -grub_compress_file () { - if [ -f "$1" ] ; then - if [ "$compressor" != "" ] ; then - "$compressor" $compressor_opts "$1" > "$2" - else - cp -f "$1" "$2" - fi - else - gettext_printf "Skipping file \`%s': not a plain file\n" "$1" 1>&2 - fi -} - -grub_install_files () { - grub_install_files_source_directory="$1" - grub_install_files_target_directory="$2" - grub_install_files_platform="$3" - - mkdir -p "${grub_install_files_target_directory}"/"${grub_install_files_platform}" - - for file in "${grub_install_files_target_directory}"/*.mod \ -"${grub_install_files_target_directory}"/*.lst \ -"${grub_install_files_target_directory}"/*.img \ -"${grub_install_files_target_directory}"/efiemu??.o \ -"${grub_install_files_target_directory}"/"${grub_install_files_platform}"/*.mod \ -"${grub_install_files_target_directory}"/"${grub_install_files_platform}"/*.lst \ -"${grub_install_files_target_directory}"/"${grub_install_files_platform}"/*.img \ -"${grub_install_files_target_directory}"/"${grub_install_files_platform}"/efiemu??.o; - do - if test -f "$file" && [ "`basename $file`" != menu.lst ]; then - rm -f "$file" || exit 1 - fi - done - - if [ x"$install_modules" = xall ]; then - for file in "${grub_install_files_source_directory}/"*.mod; do - grub_compress_file "$file" "${grub_install_files_target_directory}"/"${grub_install_files_platform}/$(basename "$file")" - done - else - modules1= - modules2="$install_modules" - while [ x"$modules2" != x ]; do - modules3= - for x in $modules2; do - modules3="$modules3 $(grep "^$x:" "${grub_install_files_source_directory}/moddep.lst" | sed 's,^[^:]*:,,')" - done - modules1="$modules1 $modules2" - modules2="$modules3" - done - for file in $(echo "$modules1" | sed 's, ,\n,g' |sort -u); do - grub_compress_file "${grub_install_files_source_directory}/$file.mod" "${grub_install_files_target_directory}"/"${grub_install_files_platform}/$file.mod" - done - fi - - for file in ${pkglib_DATA} efiemu32.o efiemu64.o; do - if test -f "${grub_install_files_source_directory}/${file}"; then - grub_compress_file "${grub_install_files_source_directory}/${file}" "${grub_install_files_target_directory}"/"${grub_install_files_platform}/${file}" - fi - done - - # Copy gettext files - mkdir -p "${grub_install_files_target_directory}"/locale - - for file in "${grub_install_files_target_directory}"/locale/*.mo; do - if test -f "$file"; then - rm -f "$file" || exit 1 - fi - done - - if [ x"$install_locales" = xall ]; then - for file in "${grub_install_files_source_directory}"/po/*.mo; do - if test -f "$file"; then - grub_compress_file "$file" "${grub_install_files_target_directory}"/locale/"$(basename "$file")" - fi - done - for dir in "${localedir}"/*; do - if test -f "$dir/LC_MESSAGES/@PACKAGE@.mo" && ! test -f "${grub_install_files_target_directory}"/locale/"${dir##*/}.mo"; then - grub_compress_file "$dir/LC_MESSAGES/@PACKAGE@.mo" "${grub_install_files_target_directory}"/locale/"${dir##*/}.mo" - fi - done - else - for locale in $install_locales; do - if test -f "${grub_install_files_source_directory}"/po/$locale.mo; then - grub_compress_file "${grub_install_files_source_directory}"/po/locale.mo "${grub_install_files_target_directory}"/locale/$locale.mo - elif test -f "${localedir}/$locale/LC_MESSAGES/@PACKAGE@.mo"; then - grub_compress_file "${localedir}/$locale/LC_MESSAGES/@PACKAGE@.mo" "${grub_install_files_target_directory}"/locale/$locale.mo - fi - done - fi - for theme in ${install_themes} ; do - if test -f "${pkgdatadir}"/themes/"${theme}"/theme.txt; then - mkdir -p "${grub_install_files_target_directory}"/themes/"${theme}" - for file in "${pkgdatadir}"/themes/"${theme}"/*; do - grub_compress_file "$file" "${grub_install_files_target_directory}"/themes/"${theme}"/"$(basename "$file")" - done - fi - done - - for font in ${install_fonts} ; do - if test -f "${pkgdatadir}"/"$font".pf2; then - mkdir -p "${grub_install_files_target_directory}"/fonts - grub_compress_file "${pkgdatadir}"/"$font".pf2 "${grub_install_files_target_directory}"/fonts/"$font".pf2 - fi - done -} - -grub_print_install_files_help () { - print_option_help "--modules=$(gettext "MODULES")" "$(gettext "pre-load specified modules MODULES")" - print_option_help "--install-modules=$(gettext "MODULES")" "$(gettext "install only MODULES and their dependencies [default=all]")" - print_option_help "--themes=THEMES" "$(gettext_printf "install THEMES [default=%s]" "starfield")" - print_option_help "--fonts=FONTS" "$(gettext_printf "install FONTS [default=%s]" "unicode")" - print_option_help "--locales=LOCALES" "$(gettext_printf "install only LOCALES [default=all]")" - print_option_help "--compress[=no,xz,gz,lzo]" "$(gettext "compress GRUB files [optional]")" - # TRANSLATORS: platform here isn't identifier. It can be translated. - dir_msg="$(gettext_printf "use images and modules under DIR [default=%s/]" "${libdir}/@PACKAGE@")" - print_option_help "-d, --directory=$(gettext "DIR")" "$dir_msg" - print_option_help "--grub-mkimage=$(gettext "FILE")" "$(gettext "use FILE as grub-mkimage")" - print_option_help "-v, --version" "$(gettext "print the version information and exit")" -} - -install_modules=all -install_themes=starfield -install_fonts=unicode -install_locales=all -compress=no -grub_decompression_module="" -compressor="" -compressor_opts="" -source_directory="" - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - gettext_printf "%s: option requires an argument -- \`%s'\n" "$0" "$opt" 1>&2 - exit 1 - fi - echo $1 -} - -grub_parse_compress () { - compress="$1" - case x"$compress" in - xno) ;; - xgz) - compressor=`which gzip || true` - grub_decompression_module="gzio" - compressor_opts="--best --stdout";; - xxz) - compressor=`which xz || true` - grub_decompression_module="xzio gcry_crc" - compressor_opts="--lzma2=dict=128KiB --check=none --stdout";; - xlzo) - compressor=`which lzop || true` - grub_decompression_module="lzopio adler32 gcry_crc" - compressor_opts="-9 -c";; - *) - gettext_printf "Unrecognized compression \`%s'\n" "$compress" 1>&2 - usage - exit 1 - esac -} - -grub_process_install_options () { - option=$1 - shift - - grub_process_install_options_consumed=0 - - case "$option" in - --install-modules) - install_modules=`argument $option "$@"`; grub_process_install_options_consumed=2; return ;; - --install-modules=*) - install_modules=`echo "$option" | sed 's/--install-modules=//'`; grub_process_install_options_consumed=1; return ;; - --themes) - install_themes=`argument $option "$@"`; grub_process_install_options_consumed=2; return ;; - --themes=*) - install_themes=`echo "$option" | sed 's/--themes=//'`; grub_process_install_options_consumed=1; return ;; - --fonts) - install_fonts=`argument $option "$@"`; grub_process_install_options_consumed=2; return ;; - --fonts=*) - install_fonts=`echo "$option" | sed 's/--fonts=//'`; grub_process_install_options_consumed=1; return ;; - --locales) - install_locales=`argument $option "$@"`; grub_process_install_options_consumed=2; return ;; - --locales=*) - install_locales=`echo "$option" | sed 's/--locales=//'`; grub_process_install_options_consumed=1; return ;; - --compress) - grub_parse_compress `argument $option "$@"`; grub_process_install_options_consumed=2; return ;; - --compress=*) - grub_parse_compress `echo "${option}" | sed 's/--compress=//'`; grub_process_install_options_consumed=1; return ;; - --directory | -d) - source_directory=`argument $option "$@"`; grub_process_install_options_consumed=2 ;; - --directory=*) - source_directory=`echo "$option" | sed 's/--directory=//'` grub_process_install_options_consumed=1;; - - # For backwards compatibility - --override-directory) - source_directory=`argument $option "$@"`; grub_process_install_options_consumed=2 ;; - --override-directory=*) - source_directory=`echo "$option" | sed 's/--override-directory=//'` grub_process_install_options_consumed=1;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; grub_process_install_options_consumed=2 ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'`;grub_process_install_options_consumed=1 ;; - --modules) - modules=`argument $option "$@"`; grub_process_install_options_consumed=2;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` grub_process_install_options_consumed=1;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - esac -} - -export grub_decompression_module diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 6e1e424db..33cce36ad 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -45,6 +45,7 @@ #include #include #include +#include #define _GNU_SOURCE 1 #include @@ -83,7 +84,7 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) switch (key) { case 'd': - return xasprintf (text, GRUB_PKGLIBDIR); + return xasprintf (text, grub_util_get_pkglibdir ()); case 'p': return xasprintf (text, DEFAULT_DIRECTORY); case 'O': @@ -268,10 +269,12 @@ main (int argc, char *argv[]) if (!arguments.dir) { const char *dn = grub_util_get_target_dirname (arguments.image_target); - arguments.dir = xmalloc (sizeof (GRUB_PKGLIBDIR) + grub_strlen (dn) + 1); - memcpy (arguments.dir, GRUB_PKGLIBDIR, sizeof (GRUB_PKGLIBDIR) - 1); - *(arguments.dir + sizeof (GRUB_PKGLIBDIR) - 1) = '/'; - strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR), dn); + const char *pkglibdir = grub_util_get_pkglibdir (); + char *ptr; + arguments.dir = xmalloc (grub_strlen (pkglibdir) + grub_strlen (dn) + 2); + ptr = grub_stpcpy (arguments.dir, pkglibdir); + *ptr++ = '/'; + strcpy (ptr, dn); } grub_install_generate_image (arguments.dir, diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c new file mode 100644 index 000000000..20130d3cf --- /dev/null +++ b/util/grub-mknetdir.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,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 + +static char *rootdir = NULL, *subdir = NULL; +static char *debug_image = NULL; + +enum + { + OPTION_NET_DIRECTORY = 0x301, + OPTION_SUBDIR, + OPTION_DEBUG, + OPTION_DEBUG_IMAGE + }; + +static struct argp_option options[] = { + GRUB_INSTALL_OPTIONS, + {"net-directory", OPTION_NET_DIRECTORY, N_("DIR"), + 0, N_("root directory of TFTP server"), 2}, + {"subdir", OPTION_SUBDIR, N_("DIR"), + 0, N_("relative subdirectory on network server"), 2}, + {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, + {"debug-image", OPTION_DEBUG_IMAGE, "DEBUG", OPTION_HIDDEN, 0, 2}, + {0, 0, 0, 0, 0, 0} +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + if (grub_install_parse (key, arg)) + return 0; + switch (key) + { + case OPTION_NET_DIRECTORY: + free (rootdir); + rootdir = xstrdup (arg); + return 0; + case OPTION_SUBDIR: + free (subdir); + subdir = xstrdup (arg); + return 0; + /* This is an undocumented feature... */ + case OPTION_DEBUG: + verbosity++; + return 0; + case OPTION_DEBUG_IMAGE: + free (debug_image); + debug_image = xstrdup (arg); + return 0; + + case ARGP_KEY_ARG: + default: + return ARGP_ERR_UNKNOWN; + } +} + + +struct argp argp = { + options, argp_parser, N_("[OPTION]"), + "\v"N_("copies GRUB images into net_directory/subdir/target_cpu-platform."), + NULL, grub_install_help_filter, NULL +}; + +static char *base; + +static const struct +{ + const char *mkimage_target; + const char *netmodule; + const char *ext; +} targets[GRUB_INSTALL_PLATFORM_MAX] = + { + [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386-pc-pxe", "pxe", ".0" }, + [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64-ieee1275-aout", "ofnet", ".img" }, + [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386-ieee1275", "ofnet", ".elf" }, + [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc-ieee1275", "ofnet", ".elf" }, + [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" } + }; + +static void +process_input_dir (const char *input_dir, enum grub_install_plat platform) +{ + char *platsub = grub_install_get_platform_name (platform); + char *grubdir = grub_util_path_concat (3, rootdir, subdir, platsub); + char *load_cfg = grub_util_path_concat (2, grubdir, "load.cfg"); + char *prefix; + char *output; + char *grub_cfg; + FILE *cfg; + + grub_install_copy_files (input_dir, base, platform); + grub_util_unlink (load_cfg); + + if (debug_image) + { + FILE *f = grub_util_fopen (load_cfg, "wb"); + if (!f) + grub_util_error (_("cannot open `%s': %s"), load_cfg, + strerror (errno)); + fprintf (f, "set debug='%s'\n", debug_image); + fclose (f); + } + else + { + free (load_cfg); + load_cfg = 0; + } + + prefix = xasprintf ("/%s", subdir); + if (!targets[platform].mkimage_target) + grub_util_error ("unsupported platform %s\n", platsub); + + grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg"); + cfg = grub_util_fopen (grub_cfg, "wb"); + if (!cfg) + grub_util_error (_("cannot open `%s': %s"), grub_cfg, + strerror (errno)); + fprintf (cfg, "source %s/grub.cfg", subdir); + fclose (cfg); + + grub_install_push_module (targets[platform].netmodule); + + output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext); + grub_install_make_image_wrap (input_dir, prefix, output, + 0, load_cfg, + targets[platform].mkimage_target, 0, + GRUB_COMPRESSION_AUTO); + grub_install_pop_module (); + + /* TRANSLATORS: First %s is replaced by platform name. Second one by filename. */ + printf (_("Netboot directory for %s created. Configure your DHCP server to point to %s\n"), + platsub, output); + + free (platsub); + free (output); + free (prefix); + free (grub_cfg); + free (grubdir); +} + + +int +main (int argc, char *argv[]) +{ + const char *pkgdatadir = grub_util_get_pkgdatadir (); + + grub_util_host_init (&argc, &argv); + rootdir = xstrdup ("/srv/tftp"); + + subdir = grub_util_path_concat (2, GRUB_BOOT_DIR_NAME, GRUB_DIR_NAME); + + argp_parse (&argp, argc, argv, 0, 0, 0); + + base = grub_util_path_concat (2, rootdir, subdir); + /* Create the GRUB directory if it is not present. */ + + grub_install_mkdir_p (base); + + grub_install_push_module ("tftp"); + + if (!grub_install_source_directory) + { + enum grub_install_plat plat; + + for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++) + if (targets[plat].mkimage_target) + { + char *platdir = grub_util_path_concat (2, pkgdatadir, + grub_install_get_platform_name (plat)); + + if (!grub_util_is_directory (platdir)) + { + free (platdir); + continue; + } + process_input_dir (platdir, plat); + } + } + else + { + enum grub_install_plat plat; + plat = grub_install_get_target (grub_install_source_directory); + process_input_dir (grub_install_source_directory, plat); + } + return 0; +} diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in deleted file mode 100644 index b7b59da41..000000000 --- a/util/grub-mknetdir.in +++ /dev/null @@ -1,183 +0,0 @@ -# Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# Initialize some variables. -host_os=@host_os@ - -rootdir=/srv/tftp -modules= - -no_floppy= -recheck=no -debug=no -debug_image= -subdir="`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"`" -pc_dir="${libdir}/@PACKAGE@/i386-pc" -ppc_dir="${libdir}/@PACKAGE@/powerpc-ieee1275" -sparc_dir="${libdir}/@PACKAGE@/sparc64-ieee1275" -i386_ieee1275_dir="${libdir}/@PACKAGE@/i386-ieee1275" -efi32_dir="${libdir}/@PACKAGE@/i386-efi" -efi64_dir="${libdir}/@PACKAGE@/x86_64-efi" -itanium_dir="${libdir}/@PACKAGE@/ia64-efi" - -# Usage: usage -# Print the usage. -usage () { - gettext_printf "Usage: %s [OPTION]\n" "$self" - echo - print_option_help "-h, --help" "$(gettext "print this message and exit")" - grub_print_install_files_help - print_option_help "--net-directory=$(gettext "DIR")" "$(gettext "root directory of TFTP server")" - print_option_help "--subdir=$(gettext "DIR")" "$(gettext "relative subdirectory on network server")" - echo - gettext_printf "%s copies GRUB images into net_directory/subdir/target_cpu-platform\n" "$self" - echo - gettext "Report bugs to ."; echo -} - -# Check the arguments. -while test $# -gt 0 -do - grub_process_install_options "$@" - case "$grub_process_install_options_consumed" in - 1) shift; continue;; - 2) shift; shift; continue;; - esac - - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - - --net-directory) - rootdir=`argument $option "$@"`; shift;; - --net-directory=*) - rootdir=`echo "$option" | sed 's/--net-directory=//'` ;; - - --subdir) - subdir=`argument $option "$@"`; shift;; - --subdir=*) - subdir=`echo "$option" | sed 's/--subdir=//'` ;; - - # This is an undocumented feature... - --debug) - debug=yes ;; - --debug-image) - debug_image=`argument $option "$@"`; shift;; - --debug-image=*) - debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; - - -*) - gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 - usage - exit 1 - ;; - *) - gettext_printf "Unknown extra argument \`%s'." "$option" 1>&2 - echo 1>&2 - usage - exit 1 - ;; - esac -done - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 -fi - -# Create the GRUB directory if it is not present. -mkdir -p "${rootdir}/${subdir}" || exit 1 - -process_input_dir () -{ - input_dir="$1" - platform="$2" - grubdir="${rootdir}/${subdir}/${platform}" - config_opt= - - grub_install_files "${input_dir}" "${rootdir}/${subdir}" "${platform}" - - rm -f "${grubdir}"/load.cfg - - if [ "x${debug_image}" != x ]; then - echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg - config_opt="-c ${grubdir}/load.cfg " - fi - - prefix="/${subdir}"; - case "${platform}" in - i386-pc) mkimage_target=i386-pc-pxe; - netmodules="pxe"; - ext=0 ;; - sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout; - netmodules="ofnet"; - ext=img ;; - *-ieee1275) mkimage_target="${platform}"; - netmodules="ofnet"; - ext=elf ;; - *-efi) mkimage_target="${platform}"; - netmodules="efinet"; - ext=efi ;; - *) gettext_printf "Unsupported platform %s\n" ${platform}; - exit 1;; - esac - - cat << EOF > ${grubdir}/grub.cfg -source ${subdir}/grub.cfg -EOF - - "$grub_mkimage" ${config_opt} -d "${input_dir}" -O ${mkimage_target} "--output=${grubdir}/core.$ext" "--prefix=$prefix" $modules $grub_decompression_module $netmodules tftp || exit 1 - # TRANSLATORS: First %s is replaced by platform name. Second one by filename. - gettext_printf "Netboot directory for %s created. Configure your DHCP server to point to %s\n" "${platform}" "${subdir}/${platform}/core.$ext" -} - -if [ "${source_directory}" = "" ] ; then - if test -e "${pc_dir}" ; then - process_input_dir "${pc_dir}" i386-pc - fi - if test -e "${ppc_dir}" ; then - process_input_dir "${ppc_dir}" powerpc-ieee1275 - fi - if test -e "${sparc_dir}" ; then - process_input_dir ${sparc_dir} sparc64-ieee1275 - fi - if test -e "${i386_ieee1275_dir}" ; then - process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 - fi - if test -e "${efi32_dir}" ; then - process_input_dir "${efi32_dir}" i386-efi - fi - if test -e "${efi64_dir}" ; then - process_input_dir "${efi64_dir}" x86_64-efi - fi - if test -e "${itanium_dir}" ; then - process_input_dir "${itanium_dir}" ia64-efi - fi -else - . "${source_directory}"/modinfo.sh - process_input_dir "${source_directory}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} -fi - - -# Bye. -exit 0 diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c new file mode 100644 index 000000000..0b8c39bcb --- /dev/null +++ b/util/grub-mkrescue.c @@ -0,0 +1,827 @@ +/* + * Make GRUB rescue image + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +static char *source_dirs[GRUB_INSTALL_PLATFORM_MAX]; +static char *rom_directory; +static char *label_font; +static char *label_color; +static char *label_bgcolor; +static char *product_name; +static char *product_version; +static int xorriso_tail_argc; +static int xorriso_tail_arg_alloc; +static char **xorriso_tail_argv; +static char *output_image; +static char *xorriso; +static char *boot_grub; +static int xorriso_argc; +static int xorriso_arg_alloc; +static char **xorriso_argv; +static char *iso_uuid; +static char *iso9660_dir; + +static void +xorriso_push (const char *val) +{ + if (xorriso_arg_alloc <= xorriso_argc + 1) + { + xorriso_arg_alloc = 2 * (4 + xorriso_argc); + xorriso_argv = xrealloc (xorriso_argv, + sizeof (xorriso_argv[0]) + * xorriso_arg_alloc); + } + xorriso_argv[xorriso_argc++] = xstrdup (val); +} + +static void +xorriso_link (const char *from, const char *to) +{ + char *tof = grub_util_path_concat (2, iso9660_dir, to); + char *val = xasprintf ("%s=%s", from, tof); + xorriso_push (val); + free (val); + free (tof); +} + +enum + { + OPTION_OUTPUT = 'o', + OPTION_ROM_DIRECTORY = 0x301, + OPTION_XORRISO, + OPTION_GLUE_EFI, + OPTION_RENDER_LABEL, + OPTION_LABEL_FONT, + OPTION_LABEL_COLOR, + OPTION_LABEL_BGCOLOR, + OPTION_PRODUCT_NAME, + OPTION_PRODUCT_VERSION, + OPTION_SPARC_BOOT, + OPTION_ARCS_BOOT + }; + +static struct argp_option options[] = { + GRUB_INSTALL_OPTIONS, + {"output", 'o', N_("FILE"), + 0, N_("save output in FILE [required]"), 2}, + {"rom-directory", OPTION_ROM_DIRECTORY, N_("DIR"), + 0, N_("save ROM images in DIR [optional]"), 2}, + {"xorriso", OPTION_XORRISO, N_("FILE"), + /* TRANSLATORS: xorriso is a program for creating ISOs and burning CDs. */ + 0, N_("use FILE as xorriso [optional]"), 2}, + {"grub-glue-efi", OPTION_GLUE_EFI, N_("FILE"), OPTION_HIDDEN, 0, 2}, + {"grub-render-label", OPTION_RENDER_LABEL, N_("FILE"), OPTION_HIDDEN, 0, 2}, + {"label-font", OPTION_LABEL_FONT, N_("FILE"), 0, N_("use FILE as font for label"), 2}, + {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2}, + {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2}, + {"product-name", OPTION_PRODUCT_NAME, N_("STRING"), 0, N_("use STRING as product name"), 2}, + {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2}, + {"sparc-boot", OPTION_SPARC_BOOT, 0, 0, N_("enable sparc boot. Disables HFS+, APM, ARCS and boot as disk image for i386-pc"), 2}, + {"arcs-boot", OPTION_ARCS_BOOT, 0, 0, N_("enable ARCS (big-endian mips machines, mostly SGI) boot. Disables HFS+, APM, sparc64 and boot as disk image for i386-pc"), 2}, + {0, 0, 0, 0, 0, 0} +}; + +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) +{ + switch (key) + { + case ARGP_KEY_HELP_POST_DOC: + return xasprintf (text, "xorriso -as mkisofs -help"); + default: + return grub_install_help_filter (key, text, input); + } +} + +enum { + SYS_AREA_AUTO, + SYS_AREA_COMMON, + SYS_AREA_SPARC, + SYS_AREA_ARCS +} system_area = SYS_AREA_AUTO; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + if (grub_install_parse (key, arg)) + return 0; + switch (key) + { + case OPTION_OUTPUT: + free (output_image); + output_image = xstrdup (arg); + return 0; + case OPTION_ROM_DIRECTORY: + free (rom_directory); + rom_directory = xstrdup (arg); + return 0; + + /* + FIXME: + # Intentionally undocumented + --grub-mkimage-extra) + mkimage_extra_arg="$mkimage_extra_arg `argument $option "$@"`"; shift ;; + --grub-mkimage-extra=*) + mkimage_extra_arg="$mkimage_extra_arg `echo "$option" | sed 's/--grub-mkimage-extra=//'`" ;; + */ + case OPTION_SPARC_BOOT: + system_area = SYS_AREA_SPARC; + return 0; + case OPTION_ARCS_BOOT: + system_area = SYS_AREA_ARCS; + return 0; + case OPTION_PRODUCT_NAME: + free (product_name); + product_name = xstrdup (arg); + return 0; + case OPTION_PRODUCT_VERSION: + free (product_version); + product_version = xstrdup (arg); + return 0; + /* Accept and ignore for compatibility. */ + case OPTION_GLUE_EFI: + case OPTION_RENDER_LABEL: + return 0; + case OPTION_LABEL_FONT: + free (label_font); + label_font = xstrdup (arg); + return 0; + + case OPTION_LABEL_COLOR: + free (label_color); + label_color = xstrdup (arg); + return 0; + + case OPTION_LABEL_BGCOLOR: + free (label_bgcolor); + label_bgcolor = xstrdup (arg); + return 0; + + case OPTION_XORRISO: + free (xorriso); + xorriso = xstrdup (arg); + return 0; + + case ARGP_KEY_ARG: + if (xorriso_tail_arg_alloc <= xorriso_tail_argc) + { + xorriso_tail_arg_alloc = 2 * (4 + xorriso_tail_argc); + xorriso_tail_argv = xrealloc (xorriso_tail_argv, + sizeof (xorriso_tail_argv[0]) + * xorriso_tail_arg_alloc); + } + xorriso_tail_argv[xorriso_tail_argc++] = xstrdup (arg); + return 0; + default: + return ARGP_ERR_UNKNOWN; + } +} + +struct argp argp = { + options, argp_parser, N_("[OPTION] SOURCE..."), + /* TRANSLATORS: it generates one single image which is bootable through any method. */ + N_("Make GRUB CD-ROM, disk, pendrive and floppy bootable image.")"\v" + N_("Generates a bootable rescue image with specified source files, source directories, or mkisofs options listed by the output of `%s'.\n\n" + "Option -- switches to native xorriso command mode.\n\n" + "Mail xorriso support requests to ."), + NULL, help_filter, NULL +}; + +static void +write_part (FILE *f, const char *srcdir) +{ + FILE *in; + char *inname = grub_util_path_concat (2, srcdir, "partmap.lst"); + char buf[260]; + in = grub_util_fopen (inname, "rb"); + if (!in) + return; + while (fgets (buf, 256, in)) + { + char *ptr; + for (ptr = buf + strlen (buf) - 1; + ptr >= buf && (*ptr == '\n' || *ptr == '\r'); + ptr--); + ptr[1] = '\0'; + fprintf (f, "insmod %s\n", buf); + } + fclose (in); +} + +static void +make_image_abs (enum grub_install_plat plat, + const char *mkimage_target, + const char *output, + grub_compression_t compress) +{ + char *load_cfg; + FILE *load_cfg_f; + + if (!source_dirs[plat]) + return; + + grub_util_info (N_("enabling %s support ..."), + mkimage_target); + + load_cfg = grub_util_make_temporary_file (); + + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + fprintf (load_cfg_f, "search --fs-uuid --set=root %s\n", iso_uuid); + fprintf (load_cfg_f, "set prefix=(${root})/boot/grub\n"); + + write_part (load_cfg_f, source_dirs[plat]); + fclose (load_cfg_f); + + grub_install_push_module ("search"); + grub_install_push_module ("iso9660"); + grub_install_make_image_wrap (source_dirs[plat], "/boot/grub", output, + 0, load_cfg, + mkimage_target, 0, + compress); + grub_install_pop_module (); + grub_install_pop_module (); + grub_util_unlink (load_cfg); +} + +static void +make_image (enum grub_install_plat plat, + const char *mkimage_target, + const char *output_sub, + grub_compression_t compress) +{ + char *out = grub_util_path_concat (2, boot_grub, output_sub); + make_image_abs (plat, mkimage_target, + out, GRUB_COMPRESSION_AUTO); + free (out); +} + +static void +make_image_fwdisk_abs (enum grub_install_plat plat, + const char *mkimage_target, + const char *output) +{ + if (!source_dirs[plat]) + return; + + grub_install_push_module ("iso9660"); + grub_install_make_image_wrap (source_dirs[plat], "()/boot/grub", output, + 0, 0, mkimage_target, 0, + GRUB_COMPRESSION_AUTO); + grub_install_pop_module (); +} + +static int +check_xorriso (const char *val) +{ + const char *argv[5]; + int fd; + pid_t pid; + FILE *mdadm; + char *buf = NULL; + size_t len = 0; + int ret = 0; + + argv[0] = xorriso; + argv[1] = "-as"; + argv[2] = "mkisofs"; + argv[3] = "-help"; + argv[4] = NULL; + + pid = grub_util_exec_pipe_stderr (argv, &fd); + + if (!pid) + return 0; + + /* Parent. Read mdadm's output. */ + mdadm = fdopen (fd, "r"); + if (! mdadm) + return 0; + + while (getline (&buf, &len, mdadm) > 0) + { + if (grub_strstr (buf, val)) + ret = 1; + } + + close (fd); + waitpid (pid, NULL, 0); + free (buf); + return ret; +} + +static void +make_image_fwdisk (enum grub_install_plat plat, + const char *mkimage_target, + const char *output_sub) +{ + char *out = grub_util_path_concat (2, boot_grub, output_sub); + make_image_fwdisk_abs (plat, mkimage_target, out); + free (out); +} + +int +main (int argc, char *argv[]) +{ + char *romdir; + char *sysarea_img = NULL; + const char *pkgdatadir; + + grub_util_host_init (&argc, &argv); + + pkgdatadir = grub_util_get_pkgdatadir (); + + product_name = xstrdup (PACKAGE_NAME); + product_version = xstrdup (PACKAGE_VERSION); + xorriso = xstrdup ("xorriso"); + label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2"); + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (!output_image) + grub_util_error ("%s", _("output file must be specified")); + + xorriso_push (xorriso); + xorriso_push ("-as"); + xorriso_push ("mkisofs"); + xorriso_push ("-graft-points"); + + iso9660_dir = grub_util_make_temporary_dir (); + grub_util_info ("temporaray iso9660 dir is `%s'", + iso9660_dir); + boot_grub = grub_util_path_concat (3, iso9660_dir, "boot", "grub"); + grub_install_mkdir_p (boot_grub); + romdir = grub_util_path_concat (2, boot_grub, "roms"); + grub_util_mkdir (romdir); + + if (!grub_install_source_directory) + { + enum grub_install_plat plat; + + for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++) + { + char *platdir = grub_util_path_concat (2, pkgdatadir, + grub_install_get_platform_name (plat)); + + if (!grub_util_is_directory (platdir)) + { + free (platdir); + continue; + } + source_dirs[plat] = platdir; + grub_install_copy_files (platdir, + boot_grub, plat); + } + } + else + { + enum grub_install_plat plat; + plat = grub_install_get_target (grub_install_source_directory); + grub_install_copy_files (grub_install_source_directory, + boot_grub, plat); + source_dirs[plat] = xstrdup (grub_install_source_directory); + } + if (system_area == SYS_AREA_AUTO || grub_install_source_directory) + { + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC] + || source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] + || source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) + system_area = SYS_AREA_COMMON; + else if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275]) + system_area = SYS_AREA_SPARC; + else if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC]) + system_area = SYS_AREA_ARCS; + } + + /* obtain date-based UUID. */ + { + time_t tim; + struct tm *tmm; + tim = time (NULL); + tmm = gmtime (&tim); + iso_uuid = xmalloc (55); + grub_snprintf (iso_uuid, 50, + "%04d-%02d-%02d-%02d-%02d-%02d-00", + tmm->tm_year + 1900, + tmm->tm_mon + 1, + tmm->tm_mday, + tmm->tm_hour, + tmm->tm_min, + tmm->tm_sec); + } + { + char *uuid_out = xmalloc (strlen (iso_uuid) + 1 + 40); + char *optr; + const char *iptr; + optr = grub_stpcpy (uuid_out, "--modification-date="); + for (iptr = iso_uuid; *iptr; iptr++) + if (*iptr != '-') + *optr++ = *iptr; + *optr = '\0'; + xorriso_push (uuid_out); + free (uuid_out); + } + + /* build BIOS core.img. */ + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]) + { + char *load_cfg; + FILE *load_cfg_f; + char *output = grub_util_path_concat (3, boot_grub, "i386-pc", "eltorito.img"); + load_cfg = grub_util_make_temporary_file (); + + grub_util_info (N_("enabling %s support ..."), "BIOS"); + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + write_part (load_cfg_f, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]); + fclose (load_cfg_f); + + grub_install_push_module ("biosdisk"); + grub_install_push_module ("iso9660"); + grub_install_make_image_wrap (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC], + "/boot/grub", output, + 0, load_cfg, + "i386-pc-eltorito", 0, + GRUB_COMPRESSION_AUTO); + + xorriso_push ("-b"); + xorriso_push ("boot/grub/i386-pc/eltorito.img"); + xorriso_push ("-no-emul-boot"); + xorriso_push ("-boot-load-size"); + xorriso_push ("4"); + xorriso_push ("-boot-info-table"); + if (system_area == SYS_AREA_COMMON) + { + if (check_xorriso ("grub2-boot-info")) + { + char *boot_hybrid = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC], + "boot_hybrid.img"); + xorriso_push ("--grub2-boot-info"); + xorriso_push ("--grub2-mbr"); + xorriso_push (boot_hybrid); + } + else + { + FILE *sa, *bi; + size_t sz; + char buf[512]; + char *bin = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC], + "boot.img"); + grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Some features are disabled. Please use xorriso 1.2.9 or later.")); + sysarea_img = grub_util_make_temporary_file (); + sa = grub_util_fopen (sysarea_img, "wb"); + if (!sa) + grub_util_error (_("cannot open `%s': %s"), sysarea_img, + strerror (errno)); + bi = grub_util_fopen (sysarea_img, "wb"); + if (!bi) + grub_util_error (_("cannot open `%s': %s"), bin, + strerror (errno)); + fread (buf, 1, 512, bi); + fclose (bi); + fwrite (buf, 1, 512, sa); + + grub_install_make_image_wrap (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC], + "/boot/grub", output, + 0, load_cfg, + "i386-pc", 0, + GRUB_COMPRESSION_AUTO); + sz = ftello (sa); + fflush (sa); + fsync (fileno (sa)); + fclose (sa); + + if (sz > 32768) + { + grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Your core image is too big. Boot as disk is disabled. Please use xorriso 1.2.9 or later.")); + } + else + { + xorriso_push ("-G"); + xorriso_push (sysarea_img); + } + } + } + grub_install_pop_module (); + grub_install_pop_module (); + } + + /** build multiboot core.img */ + grub_install_push_module ("pata"); + grub_install_push_module ("ahci"); + grub_install_push_module ("at_keyboard"); + make_image (GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, "i386-multiboot", "i386-multiboot/core.elf", GRUB_COMPRESSION_AUTO); + grub_install_pop_module (); + grub_install_pop_module (); + grub_install_pop_module (); + + make_image_fwdisk (GRUB_INSTALL_PLATFORM_I386_IEEE1275, "i386-ieee1275", "ofwx86.elf"); + + char *core_services = NULL; + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275]) + { + char *mach_ker, *sv, *label, *label_text; + FILE *f; + core_services = grub_util_path_concat (4, iso9660_dir, "System", "Library", "CoreServices"); + grub_install_mkdir_p (core_services); + + mach_ker = grub_util_path_concat (2, iso9660_dir, "mach_kernel"); + f = grub_util_fopen (mach_ker, "wb"); + fclose (f); + free (mach_ker); + + sv = grub_util_path_concat (2, core_services, "SystemVersion.plist"); + f = grub_util_fopen (sv, "wb"); + fprintf (f, "\n" + "\n" + " ProductBuildVersion\n" + " \n" + " ProductName\n" + " %s\n" + " ProductVersion\n" + " %s\n" + "\n" + "\n", product_name, product_version); + fclose (f); + free (sv); + label = grub_util_path_concat (2, core_services, ".disk_label"); + char *label_string = xasprintf ("%s %s", product_name, product_version); + grub_util_render_label (label_font, label_bgcolor ? : "white", + label_color ? : "black", label_string, label); + free (label); + label_text = grub_util_path_concat (2, core_services, ".disk_label.contentDetails"); + f = grub_util_fopen (label_text, "wb"); + fprintf (f, "%s", label_string); + fclose (f); + free (label_string); + free (label_text); + if (system_area == SYS_AREA_COMMON) + { + xorriso_push ("-hfsplus"); + xorriso_push ("-apm-block-size"); + xorriso_push ("2048"); + xorriso_push ("-hfsplus-file-creator-type"); + xorriso_push ("chrp"); + xorriso_push ("tbxj"); + xorriso_push ("/System/Library/CoreServices/.disk_label"); + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) + { + xorriso_push ("-hfs-bless-by"); + xorriso_push ("i"); + xorriso_push ("/System/Library/CoreServices/boot.efi"); + } + } + } + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]) + { + char *efidir = grub_util_make_temporary_dir (); + char *efidir_efi = grub_util_path_concat (2, efidir, "efi"); + char *efidir_efi_boot = grub_util_path_concat (3, efidir, "efi", "boot"); + char *imgname, *img32, *img64, *img_mac = NULL; + char *efiimgfat; + grub_install_mkdir_p (efidir_efi_boot); + + imgname = grub_util_path_concat (2, efidir_efi_boot, "bootia64.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname); + free (imgname); + + img64 = grub_util_path_concat (2, efidir_efi_boot, "bootx64.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64-efi", img64); + + img32 = grub_util_path_concat (2, efidir_efi_boot, "bootia32.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_I386_EFI, "i386-efi", img32); + + imgname = grub_util_path_concat (2, efidir_efi_boot, "bootarm.efi"); + make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname); + free (imgname); + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]) + { + imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi"); + /* For old macs. Suggested by Peter Jones. */ + grub_install_copy_file (img32, imgname, 1); + } + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) + img_mac = grub_util_path_concat (2, core_services, "boot.efi"); + + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI] + && source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) + grub_util_glue_efi (img32, img64, img_mac); + else if (source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) + grub_install_copy_file (img64, img_mac, 1); + else if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]) + grub_install_copy_file (img32, img_mac, 1); + + free (img_mac); + free (img32); + free (img64); + free (efidir_efi_boot); + + efiimgfat = grub_util_path_concat (2, iso9660_dir, "efi.img"); + grub_util_exec ((const char * []) { "mformat", "-C", "-f", "2880", "-L", "16", "-i", + efiimgfat, "::", NULL }); + grub_util_exec ((const char * []) { "mcopy", "-s", "-i", efiimgfat, efidir_efi, "::/", NULL }); + xorriso_push ("--efi-boot"); + xorriso_push ("efi.img"); + xorriso_push ("-efi-boot-part"); + xorriso_push ("--efi-boot-image"); + + grub_util_unlink_recursive (efidir); + free (efiimgfat); + free (efidir_efi); + free (efidir); + } + + make_image_fwdisk (GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc-ieee1275", "powerpc-ieee1275/core.elf"); + + if (source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275]) + { + char *grub_chrp = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275], + "grub.chrp"); + char *bisrc = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275], + "grub.chrp"); + char *bootx = grub_util_path_concat (2, core_services, "BootX"); + char *ppc_chrp = grub_util_path_concat (3, iso9660_dir, "ppc", "chrp"); + char *bitgt = grub_util_path_concat (3, iso9660_dir, "ppc", "bootinfo.txt"); + grub_install_copy_file (grub_chrp, bootx, 1); + grub_install_mkdir_p (ppc_chrp); + grub_install_copy_file (bisrc, bitgt, 1); + xorriso_link ("/System/Library/CoreServices/grub.elf", "/boot/grub/powerpc-ieee1275/core.elf"); + xorriso_link ("/boot/grub/powerpc.elf", "/boot/grub/powerpc-ieee1275/core.elf"); + /* FIXME: add PreP */ + if (system_area == SYS_AREA_COMMON) + { + xorriso_push ("-hfsplus-file-creator-type"); + xorriso_push ("chrp"); + xorriso_push ("tbxi"); + xorriso_push ("/System/Library/CoreServices/BootX"); + xorriso_push ("-hfs-bless-by"); + xorriso_push ("p"); + xorriso_push ("/System/Library/CoreServices"); + } + xorriso_push ("-sysid"); + xorriso_push ("PPC"); + } + + make_image_fwdisk (GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275, + "sparc64-ieee1275-cdcore", "sparc64-ieee1275/core.img"); + + if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] + && system_area == SYS_AREA_SPARC) + { + char *cdboot; + FILE *in, *out; + char buf[512]; + sysarea_img = grub_util_make_temporary_file (); + cdboot = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275], + "cdboot.img"); + in = grub_util_fopen (cdboot, "rb"); + out = grub_util_fopen (sysarea_img, "wb"); + memset (buf, 0, 512); + fwrite (buf, 1, 512, out); + fread (buf, 1, 512, in); + fwrite (buf, 1, 512, out); + fclose (in); + fclose (out); + xorriso_push ("-G"); + xorriso_push (sysarea_img); + xorriso_push ("-B"); + xorriso_push (","); + xorriso_push ("--grub2-sparc-core"); + xorriso_push ("/boot/grub/sparc64-ieee1275/core.img"); + } + + make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPS_ARC, "mips-arc", "mips-arc/core.img"); + + if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC]) + { + xorriso_link ("/boot/grub/mips-arc/grub", "/boot/grub/mips-arc/core.img"); + xorriso_link ("/boot/grub/mips-arc/sashARCS", "/boot/grub/mips-arc/core.img"); + xorriso_link ("/boot/grub/mips-arc/sash", "/boot/grub/mips-arc/core.img"); + } + if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC] && system_area == SYS_AREA_ARCS) + { + xorriso_push ("-mips-boot"); + xorriso_push ("/boot/grub/mips-arc/sashARCS"); + xorriso_push ("-mips-boot"); + xorriso_push ("/boot/grub/mips-arc/sash"); + xorriso_push ("-mips-boot"); + xorriso_push ("/boot/grub/mips-arc/grub"); + } + + make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPSEL_ARC, "mipsel-arc", "arc.exe"); + + grub_install_push_module ("pata"); + make_image (GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "mipsel-qemu_mips-elf", "roms/mipsel-qemu_mips.elf", GRUB_COMPRESSION_AUTO); + + make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-loongson-elf", "loongson.elf", GRUB_COMPRESSION_XZ); + + make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-yeeloong-flash", "mipsel-yeeloong.bin", GRUB_COMPRESSION_XZ); + make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-fulong2f-flash", "mipsel-fuloong2f.bin", GRUB_COMPRESSION_XZ); + + make_image (GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "mips-qemu_mips-elf", "roms/mips-qemu_mips.elf", GRUB_COMPRESSION_AUTO); + + grub_install_push_module ("at_keyboard"); + + make_image (GRUB_INSTALL_PLATFORM_I386_QEMU, "i386-qemu", "roms/qemu.img", GRUB_COMPRESSION_AUTO); + + grub_install_push_module ("ahci"); + + make_image (GRUB_INSTALL_PLATFORM_I386_COREBOOT, "i386-coreboot", "roms/coreboot.elf", GRUB_COMPRESSION_AUTO); + grub_install_pop_module (); + grub_install_pop_module (); + grub_install_pop_module (); + + if (rom_directory) + { + const struct + { + enum grub_install_plat plat; + const char *from, *to; + } roms[] = + { + {GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "roms/mipsel-qemu_mips.elf", "mipsel-qemu_mips.elf"}, + {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "loongson.elf", "mipsel-loongson.elf"}, + {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-yeeloong.bin", "mipsel-yeeloong.bin"}, + {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-fulong.bin", "mipsel-fulong.bin"}, + {GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "roms/mips-qemu_mips.elf", "mips-qemu_mips.elf"}, + {GRUB_INSTALL_PLATFORM_I386_QEMU, "roms/qemu.img", "qemu.img"}, + {GRUB_INSTALL_PLATFORM_I386_COREBOOT, "roms/coreboot.elf", "coreboot.elf"}, + }; + grub_size_t i; + for (i = 0; i < ARRAY_SIZE (roms); i++) + { + char *from = grub_util_path_concat (2, boot_grub, roms[i].from); + char *to = grub_util_path_concat (2, rom_directory, roms[i].to); + grub_install_copy_file (from, to, 0); + } + } + + xorriso_push ("--protective-msdos-label"); + xorriso_push ("-o"); + xorriso_push (output_image); + xorriso_push ("-r"); + xorriso_push (iso9660_dir); + xorriso_push ("--sort-weight"); + xorriso_push ("0"); + xorriso_push ("/"); + xorriso_push ("--sort-weight"); + xorriso_push ("1"); + xorriso_push ("/boot"); + int i; + for (i = 0; i < xorriso_tail_argc; i++) + xorriso_push (xorriso_tail_argv[i]); + + xorriso_argv[xorriso_argc] = NULL; + + grub_util_exec ((const char *const *)xorriso_argv); + + grub_util_unlink_recursive (iso9660_dir); + + if (sysarea_img) + grub_util_unlink (sysarea_img); + + free (core_services); + free (romdir); + return 0; +} diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in deleted file mode 100644 index 444ef85fd..000000000 --- a/util/grub-mkrescue.in +++ /dev/null @@ -1,493 +0,0 @@ -#!/bin/sh - -# Make GRUB rescue image -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# Initialize some variables. - -multiboot_dir="${libdir}/@PACKAGE@/i386-multiboot" -coreboot_dir="${libdir}/@PACKAGE@/i386-coreboot" -qemu_dir="${libdir}/@PACKAGE@/i386-qemu" -mipsel_qemu_dir="${libdir}/@PACKAGE@/mipsel-qemu_mips" -loongson_dir="${libdir}/@PACKAGE@/mipsel-loongson" -mips_qemu_dir="${libdir}/@PACKAGE@/mips-qemu_mips" -pc_dir="${libdir}/@PACKAGE@/i386-pc" -i386_ieee1275_dir="${libdir}/@PACKAGE@/i386-ieee1275" -efi32_dir="${libdir}/@PACKAGE@/i386-efi" -efi64_dir="${libdir}/@PACKAGE@/x86_64-efi" -ia64_dir="${libdir}/@PACKAGE@/ia64-efi" -sparc64_dir="${libdir}/@PACKAGE@/sparc64-ieee1275" -arcs_dir="${libdir}/@PACKAGE@/mips-arc" -arc_dir="${libdir}/@PACKAGE@/mipsel-arc" -ppc_dir="${libdir}/@PACKAGE@/powerpc-ieee1275" -rom_directory= -grub_render_label="${bindir}/@grub_render_label@" -grub_glue_efi="${bindir}/@grub_glue_efi@" -label_font="${pkgdatadir}/unicode.pf2" -label_color="black" -label_bgcolor="white" -product_name="${PACKAGE_NAME}" -product_version="${PACKAGE_VERSION}" - -xorriso=xorriso - -# Usage: usage -# Print the usage. -usage () { - gettext_printf "Usage: %s [OPTION] SOURCE...\n" "$self" - # TRANSLATORS: it generates one single image which is bootable through any method. - gettext "Make GRUB CD-ROM, disk, pendrive and floppy bootable image."; echo - echo - filetrans="$(gettext FILE)" - print_option_help "-h, --help" "$(gettext "print this message and exit")" - print_option_help "-o, --output=$filetrans" "$(gettext "save output in FILE [required]")" - grub_print_install_files_help - print_option_help "--rom-directory=$(gettext "DIR")" "$(gettext "save ROM images in DIR [optional]")" - # TRANSLATORS: xorriso is a program for creating ISOs and burning CDs - print_option_help "--xorriso=$filetrans" "$(gettext "use FILE as xorriso [optional]")" - print_option_help "--grub-glue-efi=$filetrans" "$(gettext "use FILE as grub-glue-efi")" - print_option_help "--grub-render-label=$filetrans" "$(gettext "use FILE as grub-render-label")" - print_option_help "--label-font=$filetrans" "$(gettext "use FILE as font for label")" - print_option_help "--label-color=$(gettext "COLOR")" "$(gettext "use COLOR for label")" - print_option_help "--label-bgcolor=$(gettext "COLOR")" "$(gettext "use COLOR for label background")" - print_option_help "--product-name=$(gettext "STRING")" "$(gettext "use STRING as product name")" - print_option_help "--product-version=$(gettext "STRING")" "$(gettext "use STRING as product version")" - print_option_help "--sparc-boot" "$(gettext "enable sparc boot. Disables HFS+, APM, ARCS and boot as disk image for i386-pc")" - print_option_help "--arcs-boot" "$(gettext "enable ARCS (big-endian mips machines, mostly SGI) boot. Disables HFS+, APM, sparc64 and boot as disk image for i386-pc")" - echo - gettext_printf "%s generates a bootable rescue image with specified source files, source directories, or mkisofs options listed by the output of \`%s'\n" "xorriso -as mkisofs -help" "$self" | grub_fmt - echo - gettext "Option -- switches to native xorriso command mode."; echo - echo - gettext "Report bugs to ."; echo - gettext "Mail xorriso support requests to ."; echo -} - -system_area=auto -mkimage_extra_arg= - -# Check the arguments. -while test $# -gt 0 -do - grub_process_install_options "$@" - case "$grub_process_install_options_consumed" in - 1) shift; continue;; - 2) shift; shift; continue;; - esac - - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - - -o | --output) - output_image=`argument $option "$@"`; shift ;; - --output=*) - output_image=`echo "$option" | sed 's/--output=//'` ;; - - --rom-directory) - rom_directory=`argument $option "$@"`; shift ;; - --rom-directory=*) - rom_directory=`echo "$option" | sed 's/--rom-directory=//'` ;; - - # Intentionally undocumented - --grub-mkimage-extra) - mkimage_extra_arg="$mkimage_extra_arg `argument $option "$@"`"; shift ;; - --grub-mkimage-extra=*) - mkimage_extra_arg="$mkimage_extra_arg `echo "$option" | sed 's/--grub-mkimage-extra=//'`" ;; - - --sparc-boot) - system_area=sparc64 ;; - - --arcs-boot) - system_area=arcs ;; - - --product-name) - product_name=`argument $option "$@"`; shift ;; - --product-name=*) - product_name=`echo "$option" | sed 's/--product-name=//'` ;; - - --product-version) - product_version=`argument $option "$@"`; shift ;; - --product-version=*) - product_version=`echo "$option" | sed 's/--product-version=//'` ;; - - --grub-glue-efi) - grub_glue_efi=`argument $option "$@"`; shift ;; - --grub-glue-efi=*) - grub_glue_efi=`echo "$option" | sed 's/--grub-glue-efi=//'` ;; - - --grub-render-label) - grub_render_label=`argument $option "$@"`; shift ;; - --grub-render-label=*) - grub_render_label=`echo "$option" | sed 's/--grub-render-label=//'` ;; - - --label-font) - label_font=`argument $option "$@"`; shift ;; - --label-font=*) - label_font=`echo "$option" | sed 's/--label-font=//'` ;; - - --label-color) - label_color=`argument $option "$@"`; shift ;; - --label-color=*) - label_color=`echo "$option" | sed 's/--label-color=//'` ;; - - --label-bgcolor) - label_bgcolor=`argument $option "$@"`; shift ;; - --label-bgcolor=*) - label_bgcolor=`echo "$option" | sed 's/--label-bgcolor=//'` ;; - - --xorriso) - xorriso=`argument $option "$@"`; shift ;; - --xorriso=*) - xorriso=`echo "${option}" | sed 's/--xorriso=//'` ;; - - *) - source="${source} ${option} $@"; break ;; - esac -done - -if [ "x${output_image}" = x ] ; then - gettext "output file must be specified" >&2 - echo >&2 - usage - exit 1 -fi - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - gettext_printf "%s: Not found.\n" "$1" 1>&2 - exit 1 -fi - -iso9660_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 -mkdir -p ${iso9660_dir}/boot/grub -mkdir -p ${iso9660_dir}/boot/grub/roms - -process_input_dir () -{ - grub_install_files "$1" "${iso9660_dir}/boot/grub" "$2" -} - -make_image () -{ - source_directory="$1" - platform=$2 - if ! test -e "${source_directory}"; then - return; - fi - - gettext_printf "Enabling %s support ...\n" "$2" - - load_cfg="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" - - (cat << EOF -search --fs-uuid --set=root ${iso_uuid} -set prefix=(\${root})/boot/grub -EOF - for i in $(cat "${source_directory}/partmap.lst") ${modules} ; do - echo "insmod $i" - done ; ) > "${load_cfg}" - - "$grub_mkimage" -O ${platform} -d "${source_directory}" -c "${load_cfg}" -o "$3" \ - $grub_decompression_module search iso9660 $4 - rm -rf "${load_cfg}" -} - -make_image_fwdisk () -{ - source_directory="$1" - platform=$2 - if ! test -e "${source_directory}"; then - return; - fi - - gettext_printf "Enabling %s support ...\n" "$2" - - "$grub_mkimage" -O ${platform} -d "${source_directory}" -p '()/boot/grub' -o "$3" \ - $grub_decompression_module iso9660 $4 -} - -if [ "${source_directory}" = "" ] ; then - if [ "$system_area" = auto ]; then - if test -e "${pc_dir}" || test -e "${ppc_dir}" \ - || test -e "${efi32_dir}" || test -e "${efi64_dir}"; then - system_area=common; - elif test -e "${sparc64_dir}" ; then - system_area=sparc64; - elif test -e "${arcs_dir}" ; then - system_area=arcs; - fi - fi - if test -e "${multiboot_dir}" ; then - process_input_dir "${multiboot_dir}" i386-multiboot - fi - if test -e "${coreboot_dir}" ; then - process_input_dir "${coreboot_dir}" i386-coreboot - fi - if test -e "${qemu_dir}" ; then - process_input_dir "${qemu_dir}" i386-qemu - fi - if test -e "${pc_dir}" ; then - process_input_dir "${pc_dir}" i386-pc - fi - if test -e "${i386_ieee1275_dir}" ; then - process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 - fi - if test -e "${efi32_dir}" ; then - process_input_dir "${efi32_dir}" i386-efi - fi - if test -e "${efi64_dir}" ; then - process_input_dir "${efi64_dir}" x86_64-efi - fi - if test -e "${ia64_dir}" ; then - process_input_dir "${ia64_dir}" ia64-efi - fi - if test -e "${mips_qemu_dir}" ; then - process_input_dir "${mips_qemu_dir}" mips-qemu_mips - fi - if test -e "${mipsel_qemu_dir}" ; then - process_input_dir "${mipsel_qemu_dir}" mipsel-qemu_mips - fi - if test -e "${loongson_dir}" ; then - process_input_dir "${loongson_dir}" mipsel-loongson - fi - if test -e "${ppc_dir}" ; then - process_input_dir "${ppc_dir}" powerpc-ieee1275 - fi - if test -e "${sparc64_dir}" ; then - process_input_dir "${sparc64_dir}" sparc64-ieee1275 - fi - if test -e "${arcs_dir}" ; then - process_input_dir "${arcs_dir}" mips-arc - fi - if test -e "${arc_dir}" ; then - process_input_dir "${arc_dir}" mipsel-arc - fi -else - . "${source_directory}"/modinfo.sh - process_input_dir "${source_directory}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} - multiboot_dir= - pc_dir= - efi32_dir= - efi64_dir= - ia64_dir= - coreboot_dir= - qemu_dir= - mipsel_qemu_dir= - mips_qemu_dir= - loongson_dir= - ppc_dir= - i386_ieee1275_dir= - sparc64_dir= - arcs_dir= - arc_dir= - case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in - i386-multiboot) multiboot_dir="${source_directory}" ;; - i386-coreboot) coreboot_dir="${source_directory}" ;; - i386-qemu) qemu_dir="${source_directory}" ;; - i386-pc) pc_dir="${source_directory}"; system_area=common;; - i386-efi) efi32_dir="${source_directory}"; system_area=common ;; - x86_64-efi) efi64_dir="${source_directory}"; system_area=common ;; - ia64-efi) ia64_dir="${source_directory}" ;; - mipsel-qemu_mips) mipsel_qemu_dir="${source_directory}" ;; - mipsel-loongson) loongson_dir="${source_directory}" ;; - mips-qemu_mips) mips_qemu_dir="${source_directory}" ;; - powerpc-ieee1275) ppc_dir="${source_directory}"; system_area=common ;; - sparc64-ieee1275) sparc64_dir="${source_directory}"; system_area=sparc64 ;; - mips-arc) arcs_dir="${source_directory}"; system_area=arcs ;; - mipsel-arc) arc_dir="${source_directory}" ;; - i386-ieee1275) i386_ieee1275_dir="${source_directory}" ;; - esac -fi - -# obtain date-based UUID -iso_uuid=$(date -u +%Y-%m-%d-%H-%M-%S-00) -grub_mkisofs_arguments="${grub_mkisofs_arguments} --modification-date=$(echo ${iso_uuid} | sed -e s/-//g)" - -# build BIOS core.img -if test -e "${pc_dir}" ; then - gettext_printf "Enabling %s support ...\n" "BIOS" - load_cfg="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" - core_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 - - (for i in $(cat "${pc_dir}/partmap.lst") ${modules} ; do - echo "insmod $i" - done ;) > "${load_cfg}" - - "$grub_mkimage" -O i386-pc -d "${pc_dir}/" -o "${core_img}" -c "$load_cfg" --prefix=/boot/grub \ - $grub_decompression_module iso9660 biosdisk - cat "${pc_dir}/cdboot.img" "${core_img}" > "${iso9660_dir}/boot/grub/i386-pc/eltorito.img" - - grub_mkisofs_arguments="${grub_mkisofs_arguments} -b boot/grub/i386-pc/eltorito.img -no-emul-boot -boot-load-size 4 -boot-info-table" - if [ "$system_area" = common ]; then - if "${xorriso}" -as mkisofs -help 2>&1 | fgrep "grub2-boot-info" >/dev/null; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} --grub2-boot-info --grub2-mbr ${pc_dir}/boot_hybrid.img" - else - gettext "Your xorriso doesn't support \`--grub2-boot-info'. Some features are disabled. Please use xorriso 1.2.9 or later." - echo - sysarea_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 - cat "${pc_dir}/boot.img" "${core_img}" > "${sysarea_img}" - if [ "$(wc -c "${sysarea_img}" | awk '{ print $1; }')" -gt 32768 ]; then - gettext "Your xorriso doesn't support \`--grub2-boot-info'. Your core image is too big. Boot as disk is disabled. Please use xorriso 1.2.9 or later." - echo - else - grub_mkisofs_arguments="${grub_mkisofs_arguments} -G ${sysarea_img}" - fi - fi - fi - - rm -f "${core_img}" -fi - -# build multiboot core.img -make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/grub/i386-multiboot/core.elf" "pata ahci at_keyboard" - -make_image_fwdisk "${i386_ieee1275_dir}" i386-ieee1275 "${iso9660_dir}/boot/grub/ofwx86.elf" "" - -if test -e "${efi64_dir}" || test -e "${efi32_dir}" || test -e "${ia64_dir}"; then - efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - mkdir -p "${efi_dir}/efi/boot" - - # build bootia64.efi - make_image_fwdisk "${ia64_dir}" ia64-efi "${efi_dir}"/efi/boot/bootia64.efi "" - # build bootx64.efi - make_image_fwdisk "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi "" - # build bootia32.efi - make_image_fwdisk "${efi32_dir}" i386-efi "${efi_dir}"/efi/boot/bootia32.efi "" - if [ -e "${efi_dir}"/efi/boot/bootia32.efi ]; then - # For old macs. Suggested by Peter Jones. - cp "${efi_dir}"/efi/boot/bootia32.efi "${efi_dir}"/efi/boot/boot.efi - fi - - if [ -e "${efi_dir}"/efi/boot/bootx64.efi ] || [ -e "${efi_dir}"/efi/boot/bootia32.efi ]; then - mkdir -p "${iso9660_dir}"/System/Library/CoreServices - fi - - if [ -e "${efi_dir}"/efi/boot/bootx64.efi ] && [ -e "${efi_dir}"/efi/boot/bootia32.efi ]; then - "$grub_glue_efi" -6 "${efi_dir}"/efi/boot/bootx64.efi -3 "${efi_dir}"/efi/boot/bootia32.efi -o "${iso9660_dir}"/System/Library/CoreServices/boot.efi - elif [ -e "${efi_dir}"/efi/boot/bootx64.efi ]; then - cp "${efi_dir}"/efi/boot/bootx64.efi "${iso9660_dir}"/System/Library/CoreServices/boot.efi - elif [ -e "${efi_dir}"/efi/boot/bootia32.efi ]; then - cp "${efi_dir}"/efi/boot/bootia32.efi "${iso9660_dir}"/System/Library/CoreServices/boot.efi - fi - - mformat -C -f 2880 -L 16 -i "${iso9660_dir}"/efi.img :: - mcopy -s -i "${iso9660_dir}"/efi.img ${efi_dir}/efi ::/ - rm -rf ${efi_dir} - grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img -efi-boot-part --efi-boot-image" -fi - -make_image_fwdisk "${ppc_dir}" powerpc-ieee1275 "${iso9660_dir}/boot/grub/powerpc-ieee1275/core.elf" "" -if [ -e "${iso9660_dir}"/System/Library/CoreServices/boot.efi ] || [ -e "${iso9660_dir}/boot/grub/powerpc-ieee1275/core.elf" ]; then - mkdir -p "${iso9660_dir}"/System/Library/CoreServices - touch "${iso9660_dir}/mach_kernel" - cat > "${iso9660_dir}/System/Library/CoreServices/SystemVersion.plist" < - - ProductBuildVersion - - ProductName - ${product_name} - ProductVersion - ${product_version} - - -EOF - "$grub_render_label" -f "$label_font" -b "$label_bgcolor" -c "$label_color" -t "${product_name} ${product_version}" -o "${iso9660_dir}/System/Library/CoreServices/.disk_label" - echo "${product_name} ${product_version}" > "${iso9660_dir}/System/Library/CoreServices/.disk_label.contentDetails" - if [ "$system_area" = common ]; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} -hfsplus -apm-block-size 2048 -hfsplus-file-creator-type chrp tbxj /System/Library/CoreServices/.disk_label" - fi -fi - -if [ -e "${iso9660_dir}/boot/grub/powerpc-ieee1275/core.elf" ] ; then - cp "${ppc_dir}/grub.chrp" "${iso9660_dir}"/System/Library/CoreServices/BootX - mkdir -p "${iso9660_dir}"/ppc/chrp - cp "${ppc_dir}/bootinfo.txt" "${iso9660_dir}"/ppc/bootinfo.txt - grub_mkisofs_arguments="${grub_mkisofs_arguments} /System/Library/CoreServices/grub.elf=${iso9660_dir}/boot/grub/powerpc-ieee1275/core.elf /boot/grub/powerpc.elf=${iso9660_dir}/boot/grub/powerpc-ieee1275/core.elf" - # FIXME: add PreP - if [ "$system_area" = common ]; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} -hfsplus-file-creator-type chrp tbxi /System/Library/CoreServices/BootX -hfs-bless-by p /System/Library/CoreServices" - fi - grub_mkisofs_arguments="${grub_mkisofs_arguments} -sysid PPC" -fi - -if [ -e "${iso9660_dir}"/System/Library/CoreServices/boot.efi ] && [ "$system_area" = common ]; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} -hfs-bless-by i /System/Library/CoreServices/boot.efi" -fi - -make_image_fwdisk "${sparc64_dir}" sparc64-ieee1275-cdcore "${iso9660_dir}/boot/grub/sparc64-ieee1275/core.img" "" -if [ -e "${iso9660_dir}"/boot/grub/sparc64-ieee1275/core.img ] && [ "$system_area" = sparc64 ]; then - sysarea_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 - dd if=/dev/zero count=1 bs=512 | cat - "${sparc64_dir}"/cdboot.img > "$sysarea_img" - grub_mkisofs_arguments="${grub_mkisofs_arguments} -G $sysarea_img -B , --grub2-sparc-core /boot/grub/sparc64-ieee1275/core.img" -fi - -make_image_fwdisk "${arcs_dir}" mips-arc "${iso9660_dir}/boot/grub/mips-arc/core.img" "" -if [ -e "${iso9660_dir}/boot/grub/mips-arc/core.img" ]; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} /boot/grub/mips-arc/grub=${iso9660_dir}/boot/grub/mips-arc/core.img /boot/grub/mips-arc/sashARCS=${iso9660_dir}/boot/grub/mips-arc/core.img /boot/grub/mips-arc/sash=${iso9660_dir}/boot/grub/mips-arc/core.img" -fi -if [ -e "${iso9660_dir}/boot/grub/mips-arc/core.img" ] && [ "$system_area" = arcs ]; then - grub_mkisofs_arguments="${grub_mkisofs_arguments} -mips-boot /boot/grub/mips-arc/sashARCS -mips-boot /boot/grub/mips-arc/sash -mips-boot /boot/grub/mips-arc/grub" -fi - -make_image_fwdisk "${arc_dir}" mipsel-arc "${iso9660_dir}/boot/grub/arc.exe" "" - -make_image "${mipsel_qemu_dir}" mipsel-qemu_mips-elf "${iso9660_dir}/boot/grub/roms/mipsel-qemu_mips.elf" "pata" -if [ -e "${iso9660_dir}/boot/grub/roms/mipsel-qemu_mips.elf" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/mipsel-qemu_mips.elf" "${rom_directory}/mipsel-qemu_mips.elf" -fi - -make_image "${loongson_dir}" mipsel-loongson-elf "${iso9660_dir}/boot/grub/loongson.elf" "pata -C xz" -if [ -e "${iso9660_dir}/boot/grub/loongson.elf" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/loongson.elf" "${rom_directory}/mipsel-loongson.elf" -fi -make_image "${loongson_dir}" mipsel-yeeloong-flash "${iso9660_dir}/boot/grub/roms/mipsel-yeeloong.bin" "pata -C xz" -if [ -e "${iso9660_dir}/boot/grub/roms/mipsel-yeeloong.bin" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/mipsel-yeeloong.bin" "${rom_directory}/mipsel-yeeloong.bin" -fi - -make_image "${loongson_dir}" mipsel-fuloong2f-flash "${iso9660_dir}/boot/grub/roms/mipsel-fuloong2f.bin" "pata -C xz" -if [ -e "${iso9660_dir}/boot/grub/roms/mipsel-fulong.bin" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/mipsel-fulong.bin" "${rom_directory}/mipsel-fulong.bin" -fi - -make_image "${mips_qemu_dir}" mips-qemu_mips-elf "${iso9660_dir}/boot/grub/roms/mips-qemu_mips.elf" "pata" -if [ -e "${iso9660_dir}/boot/grub/roms/mips-qemu_mips.elf" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/mips-qemu_mips.elf" "${rom_directory}/mips-qemu_mips.elf" -fi -make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/grub/roms/qemu.img" "pata at_keyboard" -if [ -e "${iso9660_dir}/boot/grub/roms/qemu.img" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/qemu.img" "${rom_directory}/qemu.img" -fi -make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/grub/roms/coreboot.elf" "pata ahci at_keyboard" -if [ -e "${iso9660_dir}/boot/grub/roms/coreboot.elf" ] && [ -d "${rom_directory}" ]; then - cp "${iso9660_dir}/boot/grub/roms/coreboot.elf" "${rom_directory}/coreboot.elf" -fi - -# build iso image -"${xorriso}" -as mkisofs -graft-points ${grub_mkisofs_arguments} --protective-msdos-label -o "${output_image}" -r "${iso9660_dir}" --sort-weight 0 / --sort-weight 1 /boot ${source} -rm -rf "${iso9660_dir}" - -rm -f "${sysarea_img}" - -exit 0 diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c new file mode 100644 index 000000000..774af2f79 --- /dev/null +++ b/util/grub-mkstandalone.c @@ -0,0 +1,372 @@ + +/* + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,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 + +static grub_compression_t compression; +static char *output_image; +static char **files; +static int nfiles; +const struct grub_install_image_target_desc *format; +static FILE *memdisk; + +enum + { + OPTION_OUTPUT = 'o', + OPTION_FORMAT = 'C', + OPTION_COMPRESION = 'C' + }; + +static struct argp_option options[] = { + GRUB_INSTALL_OPTIONS, + {"output", 'o', N_("FILE"), + 0, N_("save output in FILE [required]"), 2}, + {"format", 'O', N_("FILE"), 0, 0, 2}, + {"compression", 'C', N_("xz|none|auto"), + 0, N_("choose the compression to use for core image"), 2}, + {0, 0, 0, 0, 0, 0} +}; + +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) +{ + switch (key) + { + case 'O': + { + char *formats = grub_install_get_image_targets_string (), *ret; + ret = xasprintf ("%s\n%s %s", _("generate an image in FORMAT"), + _("available formats:"), formats); + free (formats); + return ret; + } + default: + return grub_install_help_filter (key, text, input); + } +} + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + if (grub_install_parse (key, arg)) + return 0; + + switch (key) + { + + case 'o': + if (output_image) + free (output_image); + + output_image = xstrdup (arg); + break; + + case 'O': + { + format = grub_install_get_image_target (arg); + if (!format) + { + printf (_("unknown target format %s\n"), arg); + argp_usage (state); + exit (1); + } + break; + } + + case 'C': + if (grub_strcmp (arg, "xz") == 0) + { +#ifdef HAVE_LIBLZMA + compression = GRUB_COMPRESSION_XZ; +#else + grub_util_error ("%s", + _("grub-mkimage is compiled without XZ support")); +#endif + } + else if (grub_strcmp (arg, "none") == 0) + compression = GRUB_COMPRESSION_NONE; + else if (grub_strcmp (arg, "auto") == 0) + compression = GRUB_COMPRESSION_AUTO; + else + grub_util_error (_("Unknown compression format %s"), arg); + break; + case ARGP_KEY_ARG: + files[nfiles++] = xstrdup (arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +struct argp argp = { + options, argp_parser, N_("[OPTION] SOURCE..."), + N_("Generate a standalone image (containing all modules) in the selected format")"\v"N_("Graft point syntax (E.g. /boot/grub/grub.cfg=./grub.cfg) is accepted"), + NULL, help_filter, NULL +}; + +/* tar support */ +#define MAGIC "ustar" +struct head +{ + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; +} __attribute__ ((packed)); + +static void +write_zeros (unsigned rsz) +{ + char buf[512]; + + memset (buf, 0, 512); + fwrite (buf, 1, rsz, memdisk); +} + +static void +write_pad (unsigned sz) +{ + write_zeros ((~sz + 1) & 511); +} + +static void +set_tar_value (char *field, grub_uint32_t val, + unsigned len) +{ + unsigned i; + for (i = 0; i < len - 1; i++) + field[len - 2 - i] = '0' + ((val >> (3 * i)) & 7); +} + +static void +compute_checksum (struct head *hd) +{ + unsigned int chk = 0; + unsigned char *ptr; + memset (hd->chksum, ' ', 8); + for (ptr = (unsigned char *) hd; ptr < (unsigned char *) (hd + 1); ptr++) + chk += *ptr; + set_tar_value (hd->chksum, chk, 8); +} + +static void +add_tar_file (const char *from, + const char *to) +{ + char *tcn; + const char *iptr; + char *optr; + struct head hd; + grub_util_fd_t in; + ssize_t r; + grub_uint32_t mtime = 0; + grub_uint32_t size; + + COMPILE_TIME_ASSERT (sizeof (hd) == 512); + + if (grub_util_is_special_file (from)) + return; + + mtime = grub_util_get_mtime (from); + + optr = tcn = xmalloc (strlen (to) + 1); + for (iptr = to; *iptr == '/'; iptr++); + for (; *iptr; iptr++) + if (!(iptr[0] == '/' && iptr[1] == '/')) + *optr++ = *iptr; + *optr = '\0'; + + if (grub_util_is_directory (from)) + { + grub_util_fd_dir_t d; + grub_util_fd_dirent_t de; + + d = grub_util_fd_opendir (from); + + while ((de = grub_util_fd_readdir (d))) + { + char *fp, *tfp; + if (strcmp (de->d_name, ".") == 0) + continue; + if (strcmp (de->d_name, "..") == 0) + continue; + fp = grub_util_path_concat (2, from, de->d_name); + tfp = xasprintf ("%s/%s", to, de->d_name); + add_tar_file (fp, tfp); + free (fp); + } + grub_util_fd_closedir (d); + free (tcn); + return; + } + + if (optr - tcn > 99) + { + memset (&hd, 0, sizeof (hd)); + memcpy (hd.name, tcn, 99); + memcpy (hd.mode, "0000600", 7); + memcpy (hd.uid, "0001750", 7); + memcpy (hd.gid, "0001750", 7); + + set_tar_value (hd.size, optr - tcn, 12); + set_tar_value (hd.mtime, mtime, 12); + hd.typeflag = 'L'; + memcpy (hd.magic, "ustar ", 7); + memcpy (hd.uname, "grub", 4); + memcpy (hd.gname, "grub", 4); + + compute_checksum (&hd); + + fwrite (&hd, 1, sizeof (hd), memdisk); + fwrite (tcn, 1, optr - tcn, memdisk); + + write_pad (optr - tcn); + } + + in = grub_util_fd_open (from, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (in)) + grub_util_error (_("cannot open `%s': %s"), from, grub_util_fd_strerror ()); + + if (!grub_install_copy_buffer) + grub_install_copy_buffer = xmalloc (GRUB_INSTALL_COPY_BUFFER_SIZE); + + size = grub_util_get_fd_size (in, from, NULL); + + memset (&hd, 0, sizeof (hd)); + memcpy (hd.name, tcn, optr - tcn < 99 ? optr - tcn : 99); + memcpy (hd.mode, "0000600", 7); + memcpy (hd.uid, "0001750", 7); + memcpy (hd.gid, "0001750", 7); + + set_tar_value (hd.size, size, 12); + set_tar_value (hd.mtime, mtime, 12); + hd.typeflag = '0'; + memcpy (hd.magic, "ustar ", 7); + memcpy (hd.uname, "grub", 4); + memcpy (hd.gname, "grub", 4); + + compute_checksum (&hd); + + fwrite (&hd, 1, sizeof (hd), memdisk); + + while (1) + { + r = grub_util_fd_read (in, grub_install_copy_buffer, GRUB_INSTALL_COPY_BUFFER_SIZE); + if (r <= 0) + break; + fwrite (grub_install_copy_buffer, 1, r, memdisk); + } + grub_util_fd_close (in); + + write_pad (size); +} + +int +main (int argc, char *argv[]) +{ + const char *pkglibdir; + int i; + + grub_util_host_init (&argc, &argv); + + files = xmalloc ((argc + 1) * sizeof (files[0])); + + argp_parse (&argp, argc, argv, 0, 0, 0); + + pkglibdir = grub_util_get_pkglibdir (); + + if (!output_image) + grub_util_error ("%s", _("output file must be specified")); + + if (!format) + grub_util_error ("%s", _("Target format not specified (use the -O option).")); + + if (!grub_install_source_directory) + grub_install_source_directory = grub_util_path_concat (2, pkglibdir, grub_util_get_target_dirname (format)); + + enum grub_install_plat plat = grub_install_get_target (grub_install_source_directory); + + char *memdisk_dir = grub_util_make_temporary_dir (); + char *boot_grub = grub_util_path_concat (3, memdisk_dir, "boot", "grub"); + grub_install_copy_files (grub_install_source_directory, + boot_grub, plat); + + char *memdisk_img = grub_util_make_temporary_file (); + + memdisk = grub_util_fopen (memdisk_img, "wb"); + + add_tar_file (memdisk_dir, ""); + for (i = 0; i < nfiles; i++) + { + char *eq = grub_strchr (files[i], '='); + char *from, *to; + if (!eq) + { + from = files[i]; + to = files[i]; + } + else + { + *eq = '\0'; + to = files[i]; + from = eq + 1; + } + while (*to == '/') + to++; + add_tar_file (from, to); + } + write_zeros (512); + + fclose (memdisk); + + grub_util_unlink_recursive (memdisk_dir); + + grub_install_push_module ("memdisk"); + grub_install_push_module ("tar"); + + grub_install_make_image_wrap (grub_install_source_directory, + "(memdisk)/boot/grub", output_image, + memdisk_img, NULL, + grub_util_get_target_name (format), 0, + compression); + + grub_util_unlink (memdisk_img); + return 0; +} diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in deleted file mode 100644 index b692c481c..000000000 --- a/util/grub-mkstandalone.in +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh - -# Make GRUB rescue image -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012 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 . - -# Initialize some variables. - -compression=auto -format= -source= - -# Usage: usage -# Print the usage. -usage () { - formats="i386-coreboot i386-multiboot i386-pc i386-pc-pxe i386-efi i386-ieee1275 i386-qemu x86_64-efi mipsel-yeeloong-flash mipsel-fuloong2f-flash mipsel-loongson-elf powerpc-ieee1275 sparc64-ieee1275-raw sparc64-ieee1275-aout ia64-efi mips-arc mipsel-qemu_mips-elf mips-qemu_mips-flash mipsel-qemu_mips-flash mips-qemu_mips-elf" - gettext_printf "Usage: %s [OPTION] SOURCE...\n" "$self" - gettext "Generate a standalone image (containing all modules) in the selected format" - echo - print_option_help "-h, --help" "$(gettext "print this message and exit")" - print_option_help "-o, --output=$(gettext FILE)" "$(gettext "save output in FILE [required]")" - print_option_help "-O, --format=$(gettext "FORMAT")" "$(gettext "generate an image in FORMAT")"; echo - print_option_help "" "$(gettext "available formats:") $formats" - echo - print_option_help "-C, --compression=(xz|none|auto)" "$(gettext "choose the compression to use for core image")" - grub_print_install_files_help - echo - gettext "Report bugs to ."; echo -} - -# Check the arguments. -while test $# -gt 0 -do - grub_process_install_options "$@" - case "$grub_process_install_options_consumed" in - 1) shift; continue;; - 2) shift; shift; continue;; - esac - - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - - -o | --output) - output_image=`argument $option "$@"`; shift ;; - --output=*) - output_image=`echo "$option" | sed 's/--output=//'` ;; - - --compression | -C) - compression=`argument $option "$@"`; shift ;; - --compression=*) - compression=`echo "${option}" | sed 's/--compression=//'` ;; - - --format | -O) - format=`argument $option "$@"`; shift ;; - --format=*) - format=`echo "${option}" | sed 's/--format=//'` ;; - - *) - source="${source} ${option} $@"; break ;; - esac -done - -if [ "x${output_image}" = x ] ; then - gettext "output file must be specified" >&2 - echo >&2 - usage - exit 1 -fi - -if [ "x${format}" = x ] ; then - gettext "Target format not specified (use the -O option)." >&2 - echo >&2 - exit 1 -fi - -if [ "x$source_directory" = x ] ; then - cpu="`echo $format | awk -F - '{ print $1; }'`" - platform="`echo $format | awk -F - '{ print $2; }'`" - case "$platform" in - yeeloong | fuloong | fuloong2f | fuloong2e) - platform=loongson ;; - esac - case "$cpu-$platform" in - mips-loongson) - cpu=mipsel ;; - esac - source_directory="${libdir}/@PACKAGE@/$cpu-$platform" -fi - -. "${source_directory}"/modinfo.sh - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -memdisk_dir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 -grub_install_files "${source_directory}" "${memdisk_dir}"/boot/grub "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" -for file in $source; do - cp -f "$file" "${memdisk_dir}"/"$file"; -done - -memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - -(cd "${memdisk_dir}"; tar -cf - * $source) > "${memdisk_img}" -rm -rf "${memdisk_dir}" -"$grub_mkimage" -O "${format}" -C "$compression" -d "${source_directory}" -m "${memdisk_img}" -o "$output_image" --prefix='(memdisk)/boot/grub' memdisk tar $grub_decompression_module $modules -rm -rf "${memdisk_img}" - -exit 0 diff --git a/util/grub-probe.c b/util/grub-probe.c index d29d562aa..db68d61f6 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -155,135 +155,6 @@ probe_raid_level (grub_disk_t disk) return ((struct grub_diskfilter_lv *) disk->data)->segments->type; } -/* Since OF path names can have "," characters in them, and GRUB - internally uses "," to indicate partitions (unlike OF which uses - ":" for this purpose) we escape such commas. */ -static char * -escape_of_path (const char *orig_path) -{ - char *new_path, *d, c; - const char *p; - - if (!strchr (orig_path, ',')) - return (char *) xstrdup (orig_path); - - new_path = xmalloc (strlen (orig_path) * 2 + 1); - - p = orig_path; - d = new_path; - while ((c = *p++) != '\0') - { - if (c == ',') - *d++ = '\\'; - *d++ = c; - } - *d = 0; - - return new_path; -} - -static char * -guess_bios_drive (const char *orig_path) -{ - char *canon; - char *ptr; - canon = canonicalize_file_name (orig_path); - if (!canon) - return NULL; - ptr = strrchr (orig_path, '/'); - if (ptr) - ptr++; - else - ptr = canon; - if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') - { - int num = ptr[2] - 'a'; - free (canon); - return xasprintf ("hd%d", num); - } - if (ptr[0] == 'f' && ptr[1] == 'd') - { - int num = atoi (ptr + 2); - free (canon); - return xasprintf ("fd%d", num); - } - free (canon); - return NULL; -} - -static char * -guess_efi_drive (const char *orig_path) -{ - char *canon; - char *ptr; - canon = canonicalize_file_name (orig_path); - if (!canon) - return NULL; - ptr = strrchr (orig_path, '/'); - if (ptr) - ptr++; - else - ptr = canon; - if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') - { - int num = ptr[2] - 'a'; - free (canon); - return xasprintf ("hd%d", num); - } - if (ptr[0] == 'f' && ptr[1] == 'd') - { - int num = atoi (ptr + 2); - free (canon); - return xasprintf ("fd%d", num); - } - free (canon); - return NULL; -} - -static char * -guess_baremetal_drive (const char *orig_path) -{ - char *canon; - char *ptr; - canon = canonicalize_file_name (orig_path); - if (!canon) - return NULL; - ptr = strrchr (orig_path, '/'); - if (ptr) - ptr++; - else - ptr = canon; - if (ptr[0] == 'h' && ptr[1] == 'd') - { - int num = ptr[2] - 'a'; - free (canon); - return xasprintf ("ata%d", num); - } - if (ptr[0] == 's' && ptr[1] == 'd') - { - int num = ptr[2] - 'a'; - free (canon); - return xasprintf ("ahci%d", num); - } - free (canon); - return NULL; -} - -static void -print_full_name (const char *drive, grub_device_t dev) -{ - char *dname = escape_of_path (drive); - if (dev->disk->partition) - { - char *pname = grub_partition_get_name (dev->disk->partition); - printf ("%s,%s", dname, pname); - free (pname); - } - else - printf ("%s", dname); - free (dname); -} - static void probe_abstraction (grub_disk_t disk) { @@ -513,34 +384,34 @@ probe (const char *path, char **device_names, char delim) p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); printf ("--hint-ieee1275='"); - print_full_name (tmp, dev); + grub_util_fprint_full_disk_name (stdout, tmp, dev); printf ("' "); free (tmp); } - biosname = guess_bios_drive (*curdev); + biosname = grub_util_guess_bios_drive (*curdev); if (biosname) { printf ("--hint-bios="); - print_full_name (biosname, dev); + grub_util_fprint_full_disk_name (stdout, biosname, dev); printf (" "); } free (biosname); - efi = guess_efi_drive (*curdev); + efi = grub_util_guess_efi_drive (*curdev); if (efi) { printf ("--hint-efi="); - print_full_name (efi, dev); + grub_util_fprint_full_disk_name (stdout, efi, dev); printf (" "); } free (efi); - bare = guess_baremetal_drive (*curdev); + bare = grub_util_guess_baremetal_drive (*curdev); if (bare) { printf ("--hint-baremetal="); - print_full_name (bare, dev); + grub_util_fprint_full_disk_name (stdout, bare, dev); printf (" "); } free (bare); @@ -551,7 +422,7 @@ probe (const char *path, char **device_names, char delim) if (map) { printf ("--hint='"); - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); printf ("' "); } if (curdrive[1]) @@ -568,7 +439,7 @@ probe (const char *path, char **device_names, char delim) || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) { - print_full_name (dev->disk->name, dev); + grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev); putchar (delim); continue; } @@ -580,16 +451,16 @@ probe (const char *path, char **device_names, char delim) map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); grub_device_close (dev); /* Compatibility hint is one device only. */ break; } - biosname = guess_bios_drive (*curdev); + biosname = grub_util_guess_bios_drive (*curdev); if (biosname) { - print_full_name (biosname, dev); + grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); } free (biosname); @@ -603,10 +474,10 @@ probe (const char *path, char **device_names, char delim) if (print == PRINT_BIOS_HINT) { char *biosname; - biosname = guess_bios_drive (*curdev); + biosname = grub_util_guess_bios_drive (*curdev); if (biosname) { - print_full_name (biosname, dev); + grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); } free (biosname); @@ -622,7 +493,7 @@ probe (const char *path, char **device_names, char delim) map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); } @@ -632,7 +503,7 @@ probe (const char *path, char **device_names, char delim) char *p; p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); - print_full_name (tmp, dev); + grub_util_fprint_full_disk_name (stdout, tmp, dev); free (tmp); putchar (delim); } @@ -644,17 +515,17 @@ probe (const char *path, char **device_names, char delim) { char *biosname; const char *map; - biosname = guess_efi_drive (*curdev); + biosname = grub_util_guess_efi_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); } if (biosname) { - print_full_name (biosname, dev); + grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); } @@ -668,17 +539,17 @@ probe (const char *path, char **device_names, char delim) char *biosname; const char *map; - biosname = guess_baremetal_drive (*curdev); + biosname = grub_util_guess_baremetal_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); } if (biosname) { - print_full_name (biosname, dev); + grub_util_fprint_full_disk_name (stdout, biosname, dev); putchar (delim); } @@ -694,7 +565,7 @@ probe (const char *path, char **device_names, char delim) map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { - print_full_name (map, dev); + grub_util_fprint_full_disk_name (stdout, map, dev); putchar (delim); } diff --git a/util/misc.c b/util/misc.c index 8b6a678fa..0de340bbe 100644 --- a/util/misc.c +++ b/util/misc.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #define ENABLE_RELOCATABLE 0 #ifdef GRUB_BUILD @@ -256,15 +256,3 @@ void grub_register_exported_symbols (void) { } - -#ifdef GRUB_UTIL -void -grub_util_init_nls (void) -{ -#if (defined(ENABLE_NLS) && ENABLE_NLS) - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ -} -#endif diff --git a/util/mkimage.c b/util/mkimage.c index a5a683b98..4a510228c 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -66,7 +66,7 @@ struct grub_install_image_target_desc IMAGE_I386_IEEE1275, IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, - IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN + IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO } id; enum { @@ -174,6 +174,22 @@ static const struct grub_install_image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR, .default_compression = GRUB_COMPRESSION_LZMA }, + { + .dirname = "i386-pc", + .names = { "i386-pc-eltorito", NULL }, + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_I386_PC_ELTORITO, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .total_module_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR, + .default_compression = GRUB_COMPRESSION_LZMA + }, { .dirname = "i386-efi", .names = { "i386-efi", NULL }, @@ -826,6 +842,12 @@ grub_util_get_target_dirname (const struct grub_install_image_target_desc *t) return t->dirname; } +const char * +grub_util_get_target_name (const struct grub_install_image_target_desc *t) +{ + return t->names[0]; +} + char * grub_install_get_image_targets_string (void) { @@ -874,7 +896,8 @@ grub_install_generate_image (const char *dir, const char *prefix, comp = image_target->default_compression; if (image_target->id == IMAGE_I386_PC - || image_target->id == IMAGE_I386_PC_PXE) + || image_target->id == IMAGE_I386_PC_PXE + || image_target->id == IMAGE_I386_PC_ELTORITO) comp = GRUB_COMPRESSION_LZMA; path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); @@ -1105,7 +1128,8 @@ grub_install_generate_image (const char *dir, const char *prefix, decompress_img = grub_util_read_image (decompress_path); if ((image_target->id == IMAGE_I386_PC - || image_target->id == IMAGE_I386_PC_PXE) + || image_target->id == IMAGE_I386_PC_PXE + || image_target->id == IMAGE_I386_PC_ELTORITO) && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200) grub_util_error ("%s", _("Decompressor is too big")); @@ -1149,6 +1173,7 @@ grub_install_generate_image (const char *dir, const char *prefix, { case IMAGE_I386_PC: case IMAGE_I386_PC_PXE: + case IMAGE_I386_PC_ELTORITO: if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000 || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS)) || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)) @@ -1185,6 +1210,7 @@ grub_install_generate_image (const char *dir, const char *prefix, { case IMAGE_I386_PC: case IMAGE_I386_PC_PXE: + case IMAGE_I386_PC_ELTORITO: { unsigned num; char *boot_path, *boot_img; @@ -1219,6 +1245,21 @@ grub_install_generate_image (const char *dir, const char *prefix, } } + if (image_target->id == IMAGE_I386_PC_ELTORITO) + { + char *eltorito_path, *eltorito_img; + size_t eltorito_size; + + eltorito_path = grub_util_get_path (dir, "cdboot.img"); + eltorito_size = grub_util_get_image_size (eltorito_path); + eltorito_img = grub_util_read_image (eltorito_path); + + grub_util_write_image (eltorito_img, eltorito_size, out, + outname); + free (eltorito_img); + free (eltorito_path); + } + boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) @@ -1764,6 +1805,7 @@ grub_install_generate_image (const char *dir, const char *prefix, grub_util_write_image (core_img, core_size, out, outname); free (core_img); free (kernel_path); + free (rel_section); while (path_list) { diff --git a/util/probe.c b/util/probe.c new file mode 100644 index 000000000..c389f5dcf --- /dev/null +++ b/util/probe.c @@ -0,0 +1,172 @@ +/* grub-probe.c - probe device information for a given path */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010,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 +#include +#include +#include +#include +#include +#include + +#include + +/* Since OF path names can have "," characters in them, and GRUB + internally uses "," to indicate partitions (unlike OF which uses + ":" for this purpose) we escape such commas. */ +static char * +escape_of_path (const char *orig_path) +{ + char *new_path, *d, c; + const char *p; + + if (!strchr (orig_path, ',')) + return (char *) xstrdup (orig_path); + + new_path = xmalloc (strlen (orig_path) * 2 + 1); + + p = orig_path; + d = new_path; + while ((c = *p++) != '\0') + { + if (c == ',') + *d++ = '\\'; + *d++ = c; + } + *d = 0; + + return new_path; +} + +char * +grub_util_guess_bios_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("hd%d", num); + } + if (ptr[0] == 'f' && ptr[1] == 'd') + { + int num = atoi (ptr + 2); + free (canon); + return xasprintf ("fd%d", num); + } + free (canon); + return NULL; +} + +char * +grub_util_guess_efi_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("hd%d", num); + } + if (ptr[0] == 'f' && ptr[1] == 'd') + { + int num = atoi (ptr + 2); + free (canon); + return xasprintf ("fd%d", num); + } + free (canon); + return NULL; +} + +char * +grub_util_guess_baremetal_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if (ptr[0] == 'h' && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("ata%d", num); + } + if (ptr[0] == 's' && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("ahci%d", num); + } + free (canon); + return NULL; +} + +void +grub_util_fprint_full_disk_name (FILE *f, + const char *drive, grub_device_t dev) +{ + char *dname = escape_of_path (drive); + if (dev->disk->partition) + { + char *pname = grub_partition_get_name (dev->disk->partition); + fprintf (f, "%s,%s", dname, pname); + free (pname); + } + else + fprintf (f, "%s", dname); + free (dname); +}