aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorJames <james.mckenzie@citrix.com>2012-11-16 10:41:01 +0000
committerJames <james.mckenzie@citrix.com>2012-11-16 10:41:01 +0000
commit041d1ea37802bf7178a31a53f96c26efa6b8fb7b (patch)
treec193e84ad1237f25a79d0f6a267722e44c73f56a /util
downloadgrub-1.99-041d1ea37802bf7178a31a53f96c26efa6b8fb7b.tar.gz
grub-1.99-041d1ea37802bf7178a31a53f96c26efa6b8fb7b.tar.bz2
grub-1.99-041d1ea37802bf7178a31a53f96c26efa6b8fb7b.zip
fish
Diffstat (limited to 'util')
-rw-r--r--util/bash-completion.d/Makefile.am13
-rw-r--r--util/bash-completion.d/Makefile.in963
-rw-r--r--util/bash-completion.d/grub-completion.bash.in489
-rw-r--r--util/bin2h.c127
-rw-r--r--util/deviceiter.c891
-rw-r--r--util/devicemap.c13
-rw-r--r--util/grub-editenv.c313
-rw-r--r--util/grub-fstest.c557
-rw-r--r--util/grub-install.in666
-rw-r--r--util/grub-kbdcomp.in12
-rw-r--r--util/grub-macho2img.c118
-rw-r--r--util/grub-menulst2cfg.c126
-rw-r--r--util/grub-mkconfig.in308
-rw-r--r--util/grub-mkconfig_lib.in227
-rw-r--r--util/grub-mkdevicemap.c171
-rw-r--r--util/grub-mkfont.c1240
-rw-r--r--util/grub-mkimage.c1620
-rw-r--r--util/grub-mkimagexx.c756
-rw-r--r--util/grub-mklayout.c505
-rw-r--r--util/grub-mknetdir.in230
-rw-r--r--util/grub-mkpasswd-pbkdf2.c314
-rw-r--r--util/grub-mkrelpath.c109
-rw-r--r--util/grub-mkrescue.in315
-rw-r--r--util/grub-pe2elf.c537
-rw-r--r--util/grub-probe.c419
-rw-r--r--util/grub-reboot.in135
-rw-r--r--util/grub-script-check.c201
-rw-r--r--util/grub-set-default.in126
-rw-r--r--util/grub-setup.c1017
-rw-r--r--util/grub.d/00_header.in271
-rw-r--r--util/grub.d/10_hurd.in127
-rw-r--r--util/grub.d/10_kfreebsd.in192
-rw-r--r--util/grub.d/10_linux.in199
-rw-r--r--util/grub.d/10_netbsd.in143
-rw-r--r--util/grub.d/10_windows.in94
-rw-r--r--util/grub.d/20_linux_xen.in174
-rw-r--r--util/grub.d/30_os-prober.in204
-rw-r--r--util/grub.d/40_custom.in5
-rw-r--r--util/grub.d/41_custom.in7
-rw-r--r--util/grub.d/README11
-rw-r--r--util/i386/efi/grub-dumpdevtree22
-rw-r--r--util/ieee1275/devicemap.c49
-rw-r--r--util/ieee1275/grub-ofpathname.c47
-rw-r--r--util/ieee1275/ofpath.c425
-rw-r--r--util/import_gcry.py346
-rw-r--r--util/import_unicode.py189
-rw-r--r--util/lvm.c52
-rw-r--r--util/misc.c379
-rw-r--r--util/powerpc/ieee1275/grub-mkrescue.in143
-rw-r--r--util/raid.c86
-rw-r--r--util/resolve.c270
-rw-r--r--util/update-grub_lib.in23
52 files changed, 15976 insertions, 0 deletions
diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am
new file mode 100644
index 0000000..136287c
--- /dev/null
+++ b/util/bash-completion.d/Makefile.am
@@ -0,0 +1,13 @@
+
+bash_completion_source = grub-completion.bash.in
+bash_completion_script = grub
+
+EXTRA_DIST = $(bash_completion_source)
+
+CLEANFILES = $(bash_completion_script) config.log
+
+bashcompletiondir = $(sysconfdir)/bash_completion.d
+bashcompletion_DATA = $(bash_completion_script)
+
+$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status
+ $(top_builddir)/config.status --file=$@:$<
diff --git a/util/bash-completion.d/Makefile.in b/util/bash-completion.d/Makefile.in
new file mode 100644
index 0000000..960aefc
--- /dev/null
+++ b/util/bash-completion.d/Makefile.in
@@ -0,0 +1,963 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = util/bash-completion.d
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
+ $(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/argp.m4 \
+ $(top_srcdir)/m4/asm-underscore.m4 $(top_srcdir)/m4/btowc.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/dirname.m4 \
+ $(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/double-slash-root.m4 \
+ $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \
+ $(top_srcdir)/m4/extensions.m4 $(top_srcdir)/m4/fcntl-o.m4 \
+ $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fnmatch.m4 \
+ $(top_srcdir)/m4/getdelim.m4 $(top_srcdir)/m4/getline.m4 \
+ $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \
+ $(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/include_next.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \
+ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/langinfo_h.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \
+ $(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \
+ $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/malloc.m4 \
+ $(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbsinit.m4 \
+ $(top_srcdir)/m4/mbsrtowcs.m4 $(top_srcdir)/m4/mbstate_t.m4 \
+ $(top_srcdir)/m4/memchr.m4 $(top_srcdir)/m4/mempcpy.m4 \
+ $(top_srcdir)/m4/mmap-anon.m4 $(top_srcdir)/m4/multiarch.m4 \
+ $(top_srcdir)/m4/nl_langinfo.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/rawmemchr.m4 \
+ $(top_srcdir)/m4/realloc.m4 $(top_srcdir)/m4/regex.m4 \
+ $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/sleep.m4 \
+ $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stdbool.m4 \
+ $(top_srcdir)/m4/stddef_h.m4 $(top_srcdir)/m4/stdint.m4 \
+ $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/stdio_h.m4 \
+ $(top_srcdir)/m4/stdlib_h.m4 $(top_srcdir)/m4/strcase.m4 \
+ $(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strerror.m4 \
+ $(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/strings_h.m4 \
+ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \
+ $(top_srcdir)/m4/sys_wait_h.m4 $(top_srcdir)/m4/sysexits.m4 \
+ $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/vasnprintf.m4 \
+ $(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/warn-on-use.m4 \
+ $(top_srcdir)/m4/wchar_h.m4 $(top_srcdir)/m4/wchar_t.m4 \
+ $(top_srcdir)/m4/wcrtomb.m4 $(top_srcdir)/m4/wctype_h.m4 \
+ $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config-util.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(bashcompletiondir)"
+DATA = $(bashcompletion_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADDR32 = @ADDR32@
+ALLOCA = @ALLOCA@
+ALLOCA_H = @ALLOCA_H@
+AMTAR = @AMTAR@
+APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
+ASM_SYMBOL_PREFIX = @ASM_SYMBOL_PREFIX@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
+BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
+BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
+BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
+BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
+BSS_START_SYMBOL = @BSS_START_SYMBOL@
+BUILD_CC = @BUILD_CC@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CMP = @CMP@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATA32 = @DATA32@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
+EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
+END_SYMBOL = @END_SYMBOL@
+ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
+ENOLINK_VALUE = @ENOLINK_VALUE@
+EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
+EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
+ERRNO_H = @ERRNO_H@
+EXEEXT = @EXEEXT@
+FLOAT_H = @FLOAT_H@
+FNMATCH_H = @FNMATCH_H@
+FONT_SOURCE = @FONT_SOURCE@
+FREETYPE = @FREETYPE@
+GETOPT_H = @GETOPT_H@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNULIB_ATOLL = @GNULIB_ATOLL@
+GNULIB_BTOWC = @GNULIB_BTOWC@
+GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
+GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@
+GNULIB_CHOWN = @GNULIB_CHOWN@
+GNULIB_CLOSE = @GNULIB_CLOSE@
+GNULIB_DPRINTF = @GNULIB_DPRINTF@
+GNULIB_DUP2 = @GNULIB_DUP2@
+GNULIB_DUP3 = @GNULIB_DUP3@
+GNULIB_ENVIRON = @GNULIB_ENVIRON@
+GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
+GNULIB_FACCESSAT = @GNULIB_FACCESSAT@
+GNULIB_FCHDIR = @GNULIB_FCHDIR@
+GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@
+GNULIB_FCLOSE = @GNULIB_FCLOSE@
+GNULIB_FFLUSH = @GNULIB_FFLUSH@
+GNULIB_FOPEN = @GNULIB_FOPEN@
+GNULIB_FPRINTF = @GNULIB_FPRINTF@
+GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
+GNULIB_FPURGE = @GNULIB_FPURGE@
+GNULIB_FPUTC = @GNULIB_FPUTC@
+GNULIB_FPUTS = @GNULIB_FPUTS@
+GNULIB_FREOPEN = @GNULIB_FREOPEN@
+GNULIB_FSEEK = @GNULIB_FSEEK@
+GNULIB_FSEEKO = @GNULIB_FSEEKO@
+GNULIB_FSYNC = @GNULIB_FSYNC@
+GNULIB_FTELL = @GNULIB_FTELL@
+GNULIB_FTELLO = @GNULIB_FTELLO@
+GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
+GNULIB_FWRITE = @GNULIB_FWRITE@
+GNULIB_GETCWD = @GNULIB_GETCWD@
+GNULIB_GETDELIM = @GNULIB_GETDELIM@
+GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
+GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
+GNULIB_GETGROUPS = @GNULIB_GETGROUPS@
+GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
+GNULIB_GETLINE = @GNULIB_GETLINE@
+GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
+GNULIB_GETLOGIN = @GNULIB_GETLOGIN@
+GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
+GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
+GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
+GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
+GNULIB_GRANTPT = @GNULIB_GRANTPT@
+GNULIB_LCHOWN = @GNULIB_LCHOWN@
+GNULIB_LINK = @GNULIB_LINK@
+GNULIB_LINKAT = @GNULIB_LINKAT@
+GNULIB_LSEEK = @GNULIB_LSEEK@
+GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
+GNULIB_MBRLEN = @GNULIB_MBRLEN@
+GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
+GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
+GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
+GNULIB_MBSCHR = @GNULIB_MBSCHR@
+GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
+GNULIB_MBSINIT = @GNULIB_MBSINIT@
+GNULIB_MBSLEN = @GNULIB_MBSLEN@
+GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
+GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
+GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
+GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
+GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
+GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
+GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
+GNULIB_MBSSEP = @GNULIB_MBSSEP@
+GNULIB_MBSSPN = @GNULIB_MBSSPN@
+GNULIB_MBSSTR = @GNULIB_MBSSTR@
+GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
+GNULIB_MEMCHR = @GNULIB_MEMCHR@
+GNULIB_MEMMEM = @GNULIB_MEMMEM@
+GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
+GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
+GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
+GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@
+GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@
+GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
+GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@
+GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@
+GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
+GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
+GNULIB_PERROR = @GNULIB_PERROR@
+GNULIB_PIPE2 = @GNULIB_PIPE2@
+GNULIB_POPEN = @GNULIB_POPEN@
+GNULIB_PREAD = @GNULIB_PREAD@
+GNULIB_PRINTF = @GNULIB_PRINTF@
+GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
+GNULIB_PTSNAME = @GNULIB_PTSNAME@
+GNULIB_PUTC = @GNULIB_PUTC@
+GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
+GNULIB_PUTENV = @GNULIB_PUTENV@
+GNULIB_PUTS = @GNULIB_PUTS@
+GNULIB_PWRITE = @GNULIB_PWRITE@
+GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
+GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
+GNULIB_READLINK = @GNULIB_READLINK@
+GNULIB_READLINKAT = @GNULIB_READLINKAT@
+GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
+GNULIB_REALPATH = @GNULIB_REALPATH@
+GNULIB_REMOVE = @GNULIB_REMOVE@
+GNULIB_RENAME = @GNULIB_RENAME@
+GNULIB_RENAMEAT = @GNULIB_RENAMEAT@
+GNULIB_RMDIR = @GNULIB_RMDIR@
+GNULIB_RPMATCH = @GNULIB_RPMATCH@
+GNULIB_SETENV = @GNULIB_SETENV@
+GNULIB_SLEEP = @GNULIB_SLEEP@
+GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
+GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
+GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
+GNULIB_STPCPY = @GNULIB_STPCPY@
+GNULIB_STPNCPY = @GNULIB_STPNCPY@
+GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
+GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
+GNULIB_STRDUP = @GNULIB_STRDUP@
+GNULIB_STRERROR = @GNULIB_STRERROR@
+GNULIB_STRNCAT = @GNULIB_STRNCAT@
+GNULIB_STRNDUP = @GNULIB_STRNDUP@
+GNULIB_STRNLEN = @GNULIB_STRNLEN@
+GNULIB_STRPBRK = @GNULIB_STRPBRK@
+GNULIB_STRSEP = @GNULIB_STRSEP@
+GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
+GNULIB_STRSTR = @GNULIB_STRSTR@
+GNULIB_STRTOD = @GNULIB_STRTOD@
+GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
+GNULIB_STRTOLL = @GNULIB_STRTOLL@
+GNULIB_STRTOULL = @GNULIB_STRTOULL@
+GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
+GNULIB_SYMLINK = @GNULIB_SYMLINK@
+GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@
+GNULIB_TMPFILE = @GNULIB_TMPFILE@
+GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@
+GNULIB_UNISTD_H_GETOPT = @GNULIB_UNISTD_H_GETOPT@
+GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
+GNULIB_UNLINK = @GNULIB_UNLINK@
+GNULIB_UNLINKAT = @GNULIB_UNLINKAT@
+GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@
+GNULIB_UNSETENV = @GNULIB_UNSETENV@
+GNULIB_USLEEP = @GNULIB_USLEEP@
+GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
+GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
+GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
+GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
+GNULIB_VPRINTF = @GNULIB_VPRINTF@
+GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
+GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
+GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
+GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
+GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
+GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
+GNULIB_WCTOB = @GNULIB_WCTOB@
+GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
+GNULIB_WRITE = @GNULIB_WRITE@
+GNULIB__EXIT = @GNULIB__EXIT@
+GREP = @GREP@
+GRUB_BOOT_MACHINE_LINK_ADDR = @GRUB_BOOT_MACHINE_LINK_ADDR@
+HAVE_ASM_USCORE = @HAVE_ASM_USCORE@
+HAVE_ATOLL = @HAVE_ATOLL@
+HAVE_BTOWC = @HAVE_BTOWC@
+HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
+HAVE_CHOWN = @HAVE_CHOWN@
+HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
+HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
+HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
+HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
+HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
+HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
+HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@
+HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@
+HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
+HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
+HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
+HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
+HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
+HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
+HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
+HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
+HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
+HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
+HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
+HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
+HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
+HAVE_DPRINTF = @HAVE_DPRINTF@
+HAVE_DUP2 = @HAVE_DUP2@
+HAVE_DUP3 = @HAVE_DUP3@
+HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
+HAVE_FACCESSAT = @HAVE_FACCESSAT@
+HAVE_FCHDIR = @HAVE_FCHDIR@
+HAVE_FCHOWNAT = @HAVE_FCHOWNAT@
+HAVE_FSEEKO = @HAVE_FSEEKO@
+HAVE_FSYNC = @HAVE_FSYNC@
+HAVE_FTELLO = @HAVE_FTELLO@
+HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
+HAVE_GETDOMAINNAME = @HAVE_GETDOMAINNAME@
+HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
+HAVE_GETGROUPS = @HAVE_GETGROUPS@
+HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
+HAVE_GETLOGIN = @HAVE_GETLOGIN@
+HAVE_GETOPT_H = @HAVE_GETOPT_H@
+HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
+HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
+HAVE_GRANTPT = @HAVE_GRANTPT@
+HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
+HAVE_ISWBLANK = @HAVE_ISWBLANK@
+HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
+HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@
+HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@
+HAVE_LANGINFO_H = @HAVE_LANGINFO_H@
+HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@
+HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@
+HAVE_LCHOWN = @HAVE_LCHOWN@
+HAVE_LINK = @HAVE_LINK@
+HAVE_LINKAT = @HAVE_LINKAT@
+HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
+HAVE_MBRLEN = @HAVE_MBRLEN@
+HAVE_MBRTOWC = @HAVE_MBRTOWC@
+HAVE_MBSINIT = @HAVE_MBSINIT@
+HAVE_MBSLEN = @HAVE_MBSLEN@
+HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
+HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
+HAVE_MEMCHR = @HAVE_MEMCHR@
+HAVE_MEMPCPY = @HAVE_MEMPCPY@
+HAVE_MKDTEMP = @HAVE_MKDTEMP@
+HAVE_MKOSTEMP = @HAVE_MKOSTEMP@
+HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@
+HAVE_MKSTEMP = @HAVE_MKSTEMP@
+HAVE_MKSTEMPS = @HAVE_MKSTEMPS@
+HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@
+HAVE_OS_H = @HAVE_OS_H@
+HAVE_PIPE2 = @HAVE_PIPE2@
+HAVE_PREAD = @HAVE_PREAD@
+HAVE_PTSNAME = @HAVE_PTSNAME@
+HAVE_PWRITE = @HAVE_PWRITE@
+HAVE_RANDOM_H = @HAVE_RANDOM_H@
+HAVE_RANDOM_R = @HAVE_RANDOM_R@
+HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
+HAVE_READLINK = @HAVE_READLINK@
+HAVE_READLINKAT = @HAVE_READLINKAT@
+HAVE_REALPATH = @HAVE_REALPATH@
+HAVE_RENAMEAT = @HAVE_RENAMEAT@
+HAVE_RPMATCH = @HAVE_RPMATCH@
+HAVE_SETENV = @HAVE_SETENV@
+HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
+HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
+HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
+HAVE_SLEEP = @HAVE_SLEEP@
+HAVE_STDINT_H = @HAVE_STDINT_H@
+HAVE_STPCPY = @HAVE_STPCPY@
+HAVE_STPNCPY = @HAVE_STPNCPY@
+HAVE_STRCASECMP = @HAVE_STRCASECMP@
+HAVE_STRCASESTR = @HAVE_STRCASESTR@
+HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
+HAVE_STRPBRK = @HAVE_STRPBRK@
+HAVE_STRSEP = @HAVE_STRSEP@
+HAVE_STRTOD = @HAVE_STRTOD@
+HAVE_STRTOLL = @HAVE_STRTOLL@
+HAVE_STRTOULL = @HAVE_STRTOULL@
+HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
+HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
+HAVE_SYMLINK = @HAVE_SYMLINK@
+HAVE_SYMLINKAT = @HAVE_SYMLINKAT@
+HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@
+HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
+HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
+HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
+HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
+HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
+HAVE_TTYNAME_R = @HAVE_TTYNAME_R@
+HAVE_UNISTD_H = @HAVE_UNISTD_H@
+HAVE_UNLINKAT = @HAVE_UNLINKAT@
+HAVE_UNLOCKPT = @HAVE_UNLOCKPT@
+HAVE_UNSETENV = @HAVE_UNSETENV@
+HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
+HAVE_USLEEP = @HAVE_USLEEP@
+HAVE_VASPRINTF = @HAVE_VASPRINTF@
+HAVE_VDPRINTF = @HAVE_VDPRINTF@
+HAVE_WCHAR_H = @HAVE_WCHAR_H@
+HAVE_WCHAR_T = @HAVE_WCHAR_T@
+HAVE_WCRTOMB = @HAVE_WCRTOMB@
+HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
+HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
+HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
+HAVE_WINT_T = @HAVE_WINT_T@
+HAVE__BOOL = @HAVE__BOOL@
+HAVE__EXIT = @HAVE__EXIT@
+HELP2MAN = @HELP2MAN@
+HOST_CC = @HOST_CC@
+HOST_CCASFLAGS = @HOST_CCASFLAGS@
+HOST_CFLAGS = @HOST_CFLAGS@
+HOST_CPPFLAGS = @HOST_CPPFLAGS@
+HOST_LDFLAGS = @HOST_LDFLAGS@
+INCLUDE_NEXT = @INCLUDE_NEXT@
+INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCURSES = @LIBCURSES@
+LIBDEVMAPPER = @LIBDEVMAPPER@
+LIBGEOM = @LIBGEOM@
+LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
+LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBLZMA = @LIBLZMA@
+LIBNVPAIR = @LIBNVPAIR@
+LIBOBJS = @LIBOBJS@
+LIBPCIACCESS = @LIBPCIACCESS@
+LIBS = @LIBS@
+LIBSDL = @LIBSDL@
+LIBUSB = @LIBUSB@
+LIBUTIL = @LIBUTIL@
+LIBZFS = @LIBZFS@
+LN_S = @LN_S@
+LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@
+LOCALE_FR = @LOCALE_FR@
+LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
+LOCALE_JA = @LOCALE_JA@
+LOCALE_ZH_CN = @LOCALE_ZH_CN@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NEED_ENABLE_EXECUTE_STACK = @NEED_ENABLE_EXECUTE_STACK@
+NEED_REGISTER_FRAME_INFO = @NEED_REGISTER_FRAME_INFO@
+NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@
+NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@
+NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@
+NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@
+NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@
+NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@
+NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@
+NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@
+NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@
+NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@
+NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H = @NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H@
+NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H@
+NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@
+NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@
+NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@
+NEXT_ERRNO_H = @NEXT_ERRNO_H@
+NEXT_FLOAT_H = @NEXT_FLOAT_H@
+NEXT_GETOPT_H = @NEXT_GETOPT_H@
+NEXT_LANGINFO_H = @NEXT_LANGINFO_H@
+NEXT_STDDEF_H = @NEXT_STDDEF_H@
+NEXT_STDINT_H = @NEXT_STDINT_H@
+NEXT_STDIO_H = @NEXT_STDIO_H@
+NEXT_STDLIB_H = @NEXT_STDLIB_H@
+NEXT_STRINGS_H = @NEXT_STRINGS_H@
+NEXT_STRING_H = @NEXT_STRING_H@
+NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@
+NEXT_SYS_WAIT_H = @NEXT_SYS_WAIT_H@
+NEXT_UNISTD_H = @NEXT_UNISTD_H@
+NEXT_WCHAR_H = @NEXT_WCHAR_H@
+NEXT_WCTYPE_H = @NEXT_WCTYPE_H@
+NM = @NM@
+OBJCONV = @OBJCONV@
+OBJCOPY = @OBJCOPY@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
+PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
+RANLIB = @RANLIB@
+REPLACE_BTOWC = @REPLACE_BTOWC@
+REPLACE_CALLOC = @REPLACE_CALLOC@
+REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
+REPLACE_CHOWN = @REPLACE_CHOWN@
+REPLACE_CLOSE = @REPLACE_CLOSE@
+REPLACE_DPRINTF = @REPLACE_DPRINTF@
+REPLACE_DUP = @REPLACE_DUP@
+REPLACE_DUP2 = @REPLACE_DUP2@
+REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
+REPLACE_FCLOSE = @REPLACE_FCLOSE@
+REPLACE_FFLUSH = @REPLACE_FFLUSH@
+REPLACE_FOPEN = @REPLACE_FOPEN@
+REPLACE_FPRINTF = @REPLACE_FPRINTF@
+REPLACE_FPURGE = @REPLACE_FPURGE@
+REPLACE_FREOPEN = @REPLACE_FREOPEN@
+REPLACE_FSEEK = @REPLACE_FSEEK@
+REPLACE_FSEEKO = @REPLACE_FSEEKO@
+REPLACE_FTELL = @REPLACE_FTELL@
+REPLACE_FTELLO = @REPLACE_FTELLO@
+REPLACE_GETCWD = @REPLACE_GETCWD@
+REPLACE_GETDELIM = @REPLACE_GETDELIM@
+REPLACE_GETGROUPS = @REPLACE_GETGROUPS@
+REPLACE_GETLINE = @REPLACE_GETLINE@
+REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
+REPLACE_ISWBLANK = @REPLACE_ISWBLANK@
+REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
+REPLACE_LCHOWN = @REPLACE_LCHOWN@
+REPLACE_LINK = @REPLACE_LINK@
+REPLACE_LINKAT = @REPLACE_LINKAT@
+REPLACE_LSEEK = @REPLACE_LSEEK@
+REPLACE_MALLOC = @REPLACE_MALLOC@
+REPLACE_MBRLEN = @REPLACE_MBRLEN@
+REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
+REPLACE_MBSINIT = @REPLACE_MBSINIT@
+REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
+REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
+REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
+REPLACE_MEMCHR = @REPLACE_MEMCHR@
+REPLACE_MEMMEM = @REPLACE_MEMMEM@
+REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
+REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@
+REPLACE_NULL = @REPLACE_NULL@
+REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
+REPLACE_PERROR = @REPLACE_PERROR@
+REPLACE_POPEN = @REPLACE_POPEN@
+REPLACE_PREAD = @REPLACE_PREAD@
+REPLACE_PRINTF = @REPLACE_PRINTF@
+REPLACE_PUTENV = @REPLACE_PUTENV@
+REPLACE_PWRITE = @REPLACE_PWRITE@
+REPLACE_READLINK = @REPLACE_READLINK@
+REPLACE_REALLOC = @REPLACE_REALLOC@
+REPLACE_REALPATH = @REPLACE_REALPATH@
+REPLACE_REMOVE = @REPLACE_REMOVE@
+REPLACE_RENAME = @REPLACE_RENAME@
+REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
+REPLACE_RMDIR = @REPLACE_RMDIR@
+REPLACE_SETENV = @REPLACE_SETENV@
+REPLACE_SLEEP = @REPLACE_SLEEP@
+REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
+REPLACE_SPRINTF = @REPLACE_SPRINTF@
+REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
+REPLACE_STPNCPY = @REPLACE_STPNCPY@
+REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
+REPLACE_STRDUP = @REPLACE_STRDUP@
+REPLACE_STRERROR = @REPLACE_STRERROR@
+REPLACE_STRNCAT = @REPLACE_STRNCAT@
+REPLACE_STRNDUP = @REPLACE_STRNDUP@
+REPLACE_STRNLEN = @REPLACE_STRNLEN@
+REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
+REPLACE_STRSTR = @REPLACE_STRSTR@
+REPLACE_STRTOD = @REPLACE_STRTOD@
+REPLACE_STRTOK_R = @REPLACE_STRTOK_R@
+REPLACE_SYMLINK = @REPLACE_SYMLINK@
+REPLACE_TMPFILE = @REPLACE_TMPFILE@
+REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
+REPLACE_UNLINK = @REPLACE_UNLINK@
+REPLACE_UNLINKAT = @REPLACE_UNLINKAT@
+REPLACE_UNSETENV = @REPLACE_UNSETENV@
+REPLACE_USLEEP = @REPLACE_USLEEP@
+REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
+REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
+REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
+REPLACE_VPRINTF = @REPLACE_VPRINTF@
+REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
+REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
+REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
+REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@
+REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
+REPLACE_WCTOB = @REPLACE_WCTOB@
+REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
+REPLACE_WRITE = @REPLACE_WRITE@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
+SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
+STDBOOL_H = @STDBOOL_H@
+STDDEF_H = @STDDEF_H@
+STDINT_H = @STDINT_H@
+STRIP = @STRIP@
+SYSEXITS_H = @SYSEXITS_H@
+TARGET_APPLE_CC = @TARGET_APPLE_CC@
+TARGET_CC = @TARGET_CC@
+TARGET_CCAS = @TARGET_CCAS@
+TARGET_CCASFLAGS = @TARGET_CCASFLAGS@
+TARGET_CFLAGS = @TARGET_CFLAGS@
+TARGET_CPP = @TARGET_CPP@
+TARGET_CPPFLAGS = @TARGET_CPPFLAGS@
+TARGET_IMG_BASE_LDOPT = @TARGET_IMG_BASE_LDOPT@
+TARGET_IMG_CFLAGS = @TARGET_IMG_CFLAGS@
+TARGET_IMG_LDFLAGS = @TARGET_IMG_LDFLAGS@
+TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@
+TARGET_LDFLAGS = @TARGET_LDFLAGS@
+TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@
+TARGET_OBJ2ELF = @TARGET_OBJ2ELF@
+UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
+UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
+UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
+USE_APPLE_CC_FIXES = @USE_APPLE_CC_FIXES@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
+WINT_T_SUFFIX = @WINT_T_SUFFIX@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_TARGET_CC = @ac_ct_TARGET_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+bootdirname = @bootdirname@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_efiemu = @enable_efiemu@
+enable_grub_emu_pci = @enable_grub_emu_pci@
+enable_grub_emu_sdl = @enable_grub_emu_sdl@
+enable_grub_emu_usb = @enable_grub_emu_usb@
+enable_grub_mkfont = @enable_grub_mkfont@
+exec_prefix = @exec_prefix@
+freetype_cflags = @freetype_cflags@
+freetype_libs = @freetype_libs@
+gl_LIBOBJS = @gl_LIBOBJS@
+gl_LTLIBOBJS = @gl_LTLIBOBJS@
+gltests_LIBOBJS = @gltests_LIBOBJS@
+gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
+gltests_WITNESS = @gltests_WITNESS@
+grubdirname = @grubdirname@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_kernel = @host_kernel@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkglibrootdir = @pkglibrootdir@
+platform = @platform@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+bash_completion_source = grub-completion.bash.in
+bash_completion_script = grub
+EXTRA_DIST = $(bash_completion_source)
+CLEANFILES = $(bash_completion_script) config.log
+bashcompletiondir = $(sysconfdir)/bash_completion.d
+bashcompletion_DATA = $(bash_completion_script)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu util/bash-completion.d/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu util/bash-completion.d/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-bashcompletionDATA: $(bashcompletion_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(bashcompletiondir)" || $(MKDIR_P) "$(DESTDIR)$(bashcompletiondir)"
+ @list='$(bashcompletion_DATA)'; test -n "$(bashcompletiondir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(bashcompletiondir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(bashcompletiondir)" || exit $$?; \
+ done
+
+uninstall-bashcompletionDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bashcompletion_DATA)'; test -n "$(bashcompletiondir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bashcompletiondir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bashcompletiondir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(bashcompletiondir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-bashcompletionDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-bashcompletionDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-bashcompletionDATA install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-bashcompletionDATA
+
+
+$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status
+ $(top_builddir)/config.status --file=$@:$<
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
new file mode 100644
index 0000000..65cbb80
--- /dev/null
+++ b/util/bash-completion.d/grub-completion.bash.in
@@ -0,0 +1,489 @@
+#
+# Bash completion for grub
+#
+# Copyright (C) 2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+# bash completion for grub
+
+__grub_dir() {
+ local i c=1 boot_dir
+
+ for (( c=1; c <= ${#COMP_WORDS[@]}; c++ )); do
+ i="${COMP_WORDS[c]}"
+ case "$i" in
+ --boot-directory)
+ c=$((++c))
+ i="${COMP_WORDS[c]}"
+ boot_dir="${i##*=}";
+ break
+ ;;
+ esac
+ done
+ boot_dir=${boot_dir-/@bootdirname@}
+ echo "${boot_dir%/}/@grubdirname@"
+}
+
+
+# This function generates completion reply with compgen
+# - arg: accepts 1, 2, 3, or 4 arguments
+# $1 wordlist separate by space, tab or newline
+# $2 (optional) prefix to add
+# $3 (optional) current word to complete
+# $4 (optional) suffix to add
+__grubcomp () {
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ if [ $# -gt 2 ]; then
+ cur="$3"
+ fi
+ case "$cur" in
+ --*=)
+ COMPREPLY=()
+ ;;
+ *)
+ local IFS=' '$'\t'$'\n'
+ COMPREPLY=($(compgen -P "${2-}" -W "${1-}" -S "${4-}" -- "$cur"))
+ ;;
+ esac
+}
+
+# Function that return long options from the help of the command
+# - arg: $1 (optional) command to get the long options from
+__grub_get_options_from_help () {
+ local prog
+
+ if [ $# -ge 1 ]; then
+ prog="$1"
+ else
+ prog="${COMP_WORDS[0]}"
+ fi
+
+ local i IFS=" "$'\t'$'\n'
+ for i in $(LC_ALL=C $prog --help)
+ do
+ case $i in
+ --*) echo "${i%=*}";;
+ esac
+ done
+}
+
+# Function that return long options from the usage of the command
+# - arg: $1 (optional) command to get the long options from
+__grub_get_options_from_usage () {
+ local prog
+
+ if [ $# -ge 1 ]; then
+ prog="$1"
+ else
+ prog="${COMP_WORDS[0]}"
+ fi
+
+ local i IFS=" "$'\t'$'\n'
+ for i in $(LC_ALL=C $prog --usage)
+ do
+ case $i in
+ \[--*\]) i=${i#[} # Remove leading [
+ echo ${i%%?(=*)]} # Remove optional value and trailing ]
+ ;;
+ esac
+ done
+}
+
+__grub_get_last_option () {
+ local i
+ for (( i=$COMP_CWORD-1; i > 0; i-- )); do
+ if [[ "${COMP_WORDS[i]}" == -* ]]; then
+ echo "${COMP_WORDS[i]}"
+ break;
+ fi
+ done
+}
+
+__grub_list_menuentries () {
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ local config_file=$(__grub_dir)/grub.cfg
+
+ if [ -f "$config_file" ];then
+ local IFS=$'\n'
+ COMPREPLY=( $(compgen \
+ -W "$( awk -F "[\"']" '/menuentry/ { print $2 }' $config_file )" \
+ -- "$cur" )) #'# Help emacs syntax highlighting
+ fi
+}
+
+__grub_list_modules () {
+ local grub_dir=$(__grub_dir)
+ local IFS=$'\n'
+ COMPREPLY=( $( compgen -f -X '!*/*.mod' -- "${grub_dir}/$cur" | {
+ while read -r tmp; do
+ [ -n $tmp ] && {
+ tmp=${tmp##*/}
+ printf '%s\n' ${tmp%.mod}
+ }
+ done
+ }
+ ))
+}
+
+#
+# grub-set-default & grub-reboot
+#
+_grub_set_entry () {
+ local cur prev split=false
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ --boot-directory)
+ _filedir -d
+ return
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a menuentry
+ __grub_list_menuentries
+ fi
+}
+
+__grub_set_default_program=$( echo grub-set-default | sed "@program_transform_name@" )
+have ${__grub_set_default_program} && \
+ complete -F _grub_set_entry -o filenames ${__grub_set_default_program}
+unset __grub_set_default_program
+
+__grub_reboot_program=$( echo grub-reboot | sed "@program_transform_name@" )
+have ${__grub_reboot_program} && \
+ complete -F _grub_set_entry -o filenames ${__grub_reboot_program}
+unset __grub_reboot_program
+
+
+#
+# grub-editenv
+#
+_grub_editenv () {
+ local cur prev
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ case "$prev" in
+ create|list|set|unset)
+ COMPREPLY=( "" )
+ return
+ ;;
+ esac
+
+ __grubcomp "$(__grub_get_options_from_help)
+ create list set unset"
+}
+
+__grub_editenv_program=$( echo grub-editenv | sed "@program_transform_name@" )
+have ${__grub_editenv_program} && \
+ complete -F _grub_editenv -o filenames ${__grub_editenv_program}
+unset __grub_editenv_program
+
+
+#
+# grub-mkconfig
+#
+_grub_mkconfig () {
+ local cur prev
+
+ COMPREPLY=()
+ cur=`_get_cword`
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ _filedir
+ fi
+}
+__grub_mkconfig_program=$( echo grub-mkconfig | sed "@program_transform_name@" )
+have ${__grub_mkconfig_program} && \
+ complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program}
+unset __grub_mkconfig_program
+
+
+#
+# grub-setup
+#
+_grub_setup () {
+ local cur prev split=false
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ -d|--directory)
+ _filedir -d
+ return
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_setup_program=$( echo grub-setup | sed "@program_transform_name@" )
+have ${__grub_setup_program} && \
+ complete -F _grub_setup -o filenames ${__grub_setup_program}
+unset __grub_setup_program
+
+
+#
+# grub-install
+#
+_grub_install () {
+ local cur prev last split=false
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+ last=$(__grub_get_last_option)
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ --boot-directory)
+ _filedir -d
+ return
+ ;;
+ --disk-module)
+ __grubcomp "biosdisk ata"
+ return
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ case "$last" in
+ --modules)
+ __grub_list_modules
+ return
+ ;;
+ esac
+
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_install_program=$( echo grub-install | sed "@program_transform_name@" )
+have ${__grub_install_program} && \
+ complete -F _grub_install -o filenames ${__grub_install_program}
+unset __grub_install_program
+
+
+#
+# grub-mkfont
+#
+_grub_mkfont () {
+ local cur
+
+ COMPREPLY=()
+ cur=`_get_cword`
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_mkfont_program=$( echo grub-mkfont | sed "@program_transform_name@" )
+have ${__grub_mkfont_program} && \
+ complete -F _grub_mkfont -o filenames ${__grub_mkfont_program}
+unset __grub_mkfont_program
+
+
+#
+# grub-mkrescue
+#
+_grub_mkrescue () {
+ local cur prev last
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+ last=$(__grub_get_last_option)
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ case "$last" in
+ --modules)
+ __grub_list_modules
+ return
+ ;;
+ esac
+
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_mkrescue_program=$( echo grub-mkrescue | sed "@program_transform_name@" )
+have ${__grub_mkrescue_program} && \
+ complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program}
+unset __grub_mkrescue_program
+
+
+#
+# grub-mkimage
+#
+_grub_mkimage () {
+ local cur prev split=false
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ -d|--directory|-p|--prefix)
+ _filedir -d
+ return
+ ;;
+ -O|--format)
+ # Get available format from help
+ local prog=${COMP_WORDS[0]}
+ __grubcomp "$(LC_ALL=C $prog --help | \
+ awk -F ":" '/available formats/ { print $2 }' | \
+ sed 's/, / /g')"
+ return
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_mkimage_program=$( echo grub-mkimage | sed "@program_transform_name@" )
+have ${__grub_mkimage_program} && \
+ complete -F _grub_mkimage -o filenames ${__grub_mkimage_program}
+unset __grub_mkimage_program
+
+
+#
+# grub-mkpasswd-pbkdf2
+#
+_grub_mkpasswd-pbkdf2 () {
+ local cur
+
+ COMPREPLY=()
+ cur=`_get_cword`
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" )
+have ${__grub_mkpasswd_pbkdf2_program} && \
+ complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program}
+unset __grub_mkpasswd_pbkdf2_program
+
+
+#
+# grub-probe
+#
+_grub_probe () {
+ local cur prev split=false
+
+ COMPREPLY=()
+ cur=`_get_cword`
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+
+ _split_longopt && split=true
+
+ case "$prev" in
+ -t|--target)
+ # Get target type from help
+ local prog=${COMP_WORDS[0]}
+ __grubcomp "$(LC_ALL=C $prog --help | \
+ awk -F "[()]" '/--target=/ { print $2 }' | \
+ sed 's/|/ /g')"
+ return
+ ;;
+ esac
+
+ $split && return 0
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_probe_program=$( echo grub-probe | sed "@program_transform_name@" )
+have ${__grub_probe_program} && \
+ complete -F _grub_probe -o filenames ${__grub_probe_program}
+unset __grub_probe_program
+
+
+#
+# grub-script-check
+#
+_grub_script-check () {
+ local cur
+
+ COMPREPLY=()
+ cur=`_get_cword`
+
+ if [[ "$cur" == -* ]]; then
+ __grubcomp "$(__grub_get_options_from_help)"
+ else
+ # Default complete with a filename
+ _filedir
+ fi
+}
+__grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" )
+have ${__grub_script_check_program} && \
+ complete -F _grub_script-check -o filenames ${__grub_script_check_program}
+
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/util/bin2h.c b/util/bin2h.c
new file mode 100644
index 0000000..ee1c7fd
--- /dev/null
+++ b/util/bin2h.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE 1
+#include <getopt.h>
+
+#include "progname.h"
+
+static struct option options[] =
+ {
+ {"help", no_argument, 0, 'h' },
+ {"version", no_argument, 0, 'V' },
+ {0, 0, 0, 0 }
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr,
+ "Try ``%s --help'' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS] SYMBOL-NAME\n\
+\n\
+Convert a binary file to a C header.\n\
+\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+\n\
+Report bugs to <%s>.\n\
+", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int b, i;
+ char *sym;
+
+ set_program_name (argv[0]);
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (optind >= argc)
+ usage (1);
+
+ if (optind + 1 != argc)
+ usage (1);
+
+ sym = argv[optind];
+
+ b = getchar ();
+ if (b == EOF)
+ goto abort;
+
+ printf ("/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n"
+ "unsigned char %s[] =\n{\n", sym);
+
+ while (1)
+ {
+ printf ("0x%02x", b);
+
+ b = getchar ();
+ if (b == EOF)
+ goto end;
+
+ for (i = 0; i < 16 - 1; i++)
+ {
+ printf (", 0x%02x", b);
+
+ b = getchar ();
+ if (b == EOF)
+ goto end;
+ }
+
+ printf (",\n");
+ }
+
+end:
+ printf ("\n};\n");
+
+abort:
+ exit (0);
+}
diff --git a/util/deviceiter.c b/util/deviceiter.c
new file mode 100644
index 0000000..30c18be
--- /dev/null
+++ b/util/deviceiter.c
@@ -0,0 +1,891 @@
+/* deviceiter.c - iterate over system devices */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <dirent.h>
+
+#include <grub/util/misc.h>
+#include <grub/util/deviceiter.h>
+#include <grub/list.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+
+#ifdef __linux__
+# if !defined(__GLIBC__) || \
+ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
+/* Maybe libc doesn't have large file support. */
+# include <linux/unistd.h> /* _llseek */
+# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
+# include <sys/ioctl.h> /* ioctl */
+# ifndef HDIO_GETGEO
+# define HDIO_GETGEO 0x0301 /* get device geometry */
+/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
+ defined. */
+struct hd_geometry
+{
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ unsigned long start;
+};
+# endif /* ! HDIO_GETGEO */
+# ifndef FLOPPY_MAJOR
+# define FLOPPY_MAJOR 2 /* the major number for floppy */
+# endif /* ! FLOPPY_MAJOR */
+# ifndef MAJOR
+# define MAJOR(dev) \
+ ({ \
+ unsigned long long __dev = (dev); \
+ (unsigned) ((__dev >> 8) & 0xfff) \
+ | ((unsigned int) (__dev >> 32) & ~0xfff); \
+ })
+# endif /* ! MAJOR */
+# ifndef MINOR
+# define MINOR(dev) \
+ ({ \
+ unsigned long long __dev = (dev); \
+ (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \
+ })
+# endif /* ! MINOR */
+# ifndef CDROM_GET_CAPABILITY
+# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
+# endif /* ! CDROM_GET_CAPABILITY */
+# ifndef BLKGETSIZE
+# define BLKGETSIZE _IO(0x12,96) /* return device size */
+# endif /* ! BLKGETSIZE */
+
+#ifdef HAVE_DEVICE_MAPPER
+# include <libdevmapper.h>
+#endif
+#endif /* __linux__ */
+
+/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
+ kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
+#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
+# define __FreeBSD_kernel__
+#endif
+#ifdef __FreeBSD_kernel__
+ /* Obtain version of kFreeBSD headers */
+# include <osreldate.h>
+# ifndef __FreeBSD_kernel_version
+# define __FreeBSD_kernel_version __FreeBSD_version
+# endif
+
+ /* Runtime detection of kernel */
+# include <sys/utsname.h>
+int
+get_kfreebsd_version (void)
+{
+ struct utsname uts;
+ int major;
+ int minor;
+ int v[2];
+
+ uname (&uts);
+ sscanf (uts.release, "%d.%d", &major, &minor);
+
+ if (major >= 9)
+ major = 9;
+ if (major >= 5)
+ {
+ v[0] = minor/10; v[1] = minor%10;
+ }
+ else
+ {
+ v[0] = minor%10; v[1] = minor/10;
+ }
+ return major*100000+v[0]*10000+v[1]*1000;
+}
+#endif /* __FreeBSD_kernel__ */
+
+#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# include <sys/ioctl.h> /* ioctl */
+# include <sys/disklabel.h>
+# include <sys/cdio.h> /* CDIOCCLRDEBUG */
+# if defined(__FreeBSD_kernel__)
+# include <sys/param.h>
+# if __FreeBSD_kernel_version >= 500040
+# include <sys/disk.h>
+# endif
+# endif /* __FreeBSD_kernel__ */
+#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
+
+#ifdef HAVE_OPENDISK
+# include <util.h>
+#endif /* HAVE_OPENDISK */
+
+#ifdef __linux__
+/* Check if we have devfs support. */
+static int
+have_devfs (void)
+{
+ struct stat st;
+ return stat ("/dev/.devfsd", &st) == 0;
+}
+#endif /* __linux__ */
+
+/* These three functions are quite different among OSes. */
+static void
+get_floppy_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+ /* GNU/Linux */
+ if (have_devfs ())
+ sprintf (name, "/dev/floppy/%d", unit);
+ else
+ sprintf (name, "/dev/fd%d", unit);
+#elif defined(__GNU__)
+ /* GNU/Hurd */
+ sprintf (name, "/dev/fd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+ /* kFreeBSD */
+ if (get_kfreebsd_version () >= 400000)
+ sprintf (name, "/dev/fd%d", unit);
+ else
+ sprintf (name, "/dev/rfd%d", unit);
+#elif defined(__NetBSD__)
+ /* NetBSD */
+ /* opendisk() doesn't work for floppies. */
+ sprintf (name, "/dev/rfd%da", unit);
+#elif defined(__OpenBSD__)
+ /* OpenBSD */
+ sprintf (name, "/dev/rfd%dc", unit);
+#elif defined(__QNXNTO__)
+ /* QNX RTP */
+ sprintf (name, "/dev/fd%d", unit);
+#elif defined(__CYGWIN__)
+ /* Cygwin */
+ sprintf (name, "/dev/fd%d", unit);
+#elif defined(__MINGW32__)
+ (void) unit;
+ *name = 0;
+#else
+# warning "BIOS floppy drives cannot be guessed in your operating system."
+ /* Set NAME to a bogus string. */
+ *name = 0;
+#endif
+}
+
+static void
+get_ide_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+ /* GNU/Linux */
+ sprintf (name, "/dev/hd%c", unit + 'a');
+#elif defined(__GNU__)
+ /* GNU/Hurd */
+ sprintf (name, "/dev/hd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+ /* kFreeBSD */
+ if (get_kfreebsd_version () >= 400000)
+ sprintf (name, "/dev/ad%d", unit);
+ else
+ sprintf (name, "/dev/rwd%d", unit);
+#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
+ /* NetBSD */
+ char shortname[16];
+ int fd;
+
+ sprintf (shortname, "wd%d", unit);
+ fd = opendisk (shortname, O_RDONLY, name,
+ 16, /* length of NAME */
+ 0 /* char device */
+ );
+ close (fd);
+#elif defined(__OpenBSD__)
+ /* OpenBSD */
+ sprintf (name, "/dev/rwd%dc", unit);
+#elif defined(__QNXNTO__)
+ /* QNX RTP */
+ /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
+ contain SCSI disks. */
+ sprintf (name, "/dev/hd%d", unit);
+#elif defined(__CYGWIN__)
+ /* Cygwin emulates all disks as /dev/sdX. */
+ (void) unit;
+ *name = 0;
+#elif defined(__MINGW32__)
+ sprintf (name, "//./PHYSICALDRIVE%d", unit);
+#else
+# warning "BIOS IDE drives cannot be guessed in your operating system."
+ /* Set NAME to a bogus string. */
+ *name = 0;
+#endif
+}
+
+static void
+get_scsi_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+ /* GNU/Linux */
+ sprintf (name, "/dev/sd%c", unit + 'a');
+#elif defined(__GNU__)
+ /* GNU/Hurd */
+ sprintf (name, "/dev/sd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+ /* kFreeBSD */
+ if (get_kfreebsd_version () >= 400000)
+ sprintf (name, "/dev/da%d", unit);
+ else
+ sprintf (name, "/dev/rda%d", unit);
+#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
+ /* NetBSD */
+ char shortname[16];
+ int fd;
+
+ sprintf (shortname, "sd%d", unit);
+ fd = opendisk (shortname, O_RDONLY, name,
+ 16, /* length of NAME */
+ 0 /* char device */
+ );
+ close (fd);
+#elif defined(__OpenBSD__)
+ /* OpenBSD */
+ sprintf (name, "/dev/rsd%dc", unit);
+#elif defined(__QNXNTO__)
+ /* QNX RTP */
+ /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
+ disable the detection of SCSI disks here. */
+ *name = 0;
+#elif defined(__CYGWIN__)
+ /* Cygwin emulates all disks as /dev/sdX. */
+ sprintf (name, "/dev/sd%c", unit + 'a');
+#elif defined(__MINGW32__)
+ (void) unit;
+ *name = 0;
+#else
+# warning "BIOS SCSI drives cannot be guessed in your operating system."
+ /* Set NAME to a bogus string. */
+ *name = 0;
+#endif
+}
+
+#ifdef __linux__
+static void
+get_virtio_disk_name (char *name, int unit)
+{
+#ifdef __sparc__
+ sprintf (name, "/dev/vdisk%c", unit + 'a');
+#else
+ sprintf (name, "/dev/vd%c", unit + 'a');
+#endif
+}
+
+static void
+get_dac960_disk_name (char *name, int controller, int drive)
+{
+ sprintf (name, "/dev/rd/c%dd%d", controller, drive);
+}
+
+static void
+get_acceleraid_disk_name (char *name, int controller, int drive)
+{
+ sprintf (name, "/dev/rs/c%dd%d", controller, drive);
+}
+
+static void
+get_ataraid_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/ataraid/d%c", unit + '0');
+}
+
+static void
+get_i2o_disk_name (char *name, char unit)
+{
+ sprintf (name, "/dev/i2o/hd%c", unit);
+}
+
+static void
+get_cciss_disk_name (char *name, int controller, int drive)
+{
+ sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
+}
+
+static void
+get_ida_disk_name (char *name, int controller, int drive)
+{
+ sprintf (name, "/dev/ida/c%dd%d", controller, drive);
+}
+
+static void
+get_mmc_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/mmcblk%d", unit);
+}
+
+static void
+get_xvd_disk_name (char *name, int unit)
+{
+ sprintf (name, "/dev/xvd%c", unit + 'a');
+}
+#endif
+
+static struct seen_device
+{
+ struct seen_device *next;
+ const char *name;
+} *seen;
+
+/* Check if DEVICE can be read. Skip any DEVICE that we have already seen.
+ If an error occurs, return zero, otherwise return non-zero. */
+static int
+check_device_readable_unique (const char *device)
+{
+ char *real_device;
+ char buf[512];
+ FILE *fp;
+ struct seen_device *seen_elt;
+
+ /* If DEVICE is empty, just return error. */
+ if (*device == 0)
+ return 0;
+
+ /* Have we seen this device already? */
+ real_device = canonicalize_file_name (device);
+ if (! real_device)
+ return 0;
+ if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), real_device))
+ {
+ grub_dprintf ("deviceiter", "Already seen %s (%s)\n",
+ device, real_device);
+ goto fail;
+ }
+
+ fp = fopen (device, "r");
+ if (! fp)
+ {
+ switch (errno)
+ {
+#ifdef ENOMEDIUM
+ case ENOMEDIUM:
+# if 0
+ /* At the moment, this finds only CDROMs, which can't be
+ read anyway, so leave it out. Code should be
+ reactivated if `removable disks' and CDROMs are
+ supported. */
+ /* Accept it, it may be inserted. */
+ return 1;
+# endif
+ break;
+#endif /* ENOMEDIUM */
+ default:
+ /* Break case and leave. */
+ break;
+ }
+ /* Error opening the device. */
+ goto fail;
+ }
+
+ /* Make sure CD-ROMs don't get assigned a BIOS disk number
+ before SCSI disks! */
+#ifdef __linux__
+# ifdef CDROM_GET_CAPABILITY
+ if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
+ goto fail;
+# else /* ! CDROM_GET_CAPABILITY */
+ /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
+ {
+ struct hd_geometry hdg;
+ struct stat st;
+
+ if (fstat (fileno (fp), &st))
+ goto fail;
+
+ /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
+ succeeds. */
+ if (S_ISBLK (st.st_mode)
+ && MAJOR (st.st_rdev) != FLOPPY_MAJOR
+ && ioctl (fileno (fp), HDIO_GETGEO, &hdg))
+ goto fail;
+ }
+# endif /* ! CDROM_GET_CAPABILITY */
+#endif /* __linux__ */
+
+#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# ifdef CDIOCCLRDEBUG
+ if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
+ goto fail;
+# endif /* CDIOCCLRDEBUG */
+#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
+
+ /* Attempt to read the first sector. */
+ if (fread (buf, 1, 512, fp) != 512)
+ {
+ fclose (fp);
+ goto fail;
+ }
+
+ /* Remember that we've seen this device. */
+ seen_elt = xmalloc (sizeof (*seen_elt));
+ seen_elt->name = real_device; /* steal memory */
+ grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt));
+
+ fclose (fp);
+ return 1;
+
+fail:
+ free (real_device);
+ return 0;
+}
+
+static void
+clear_seen_devices (void)
+{
+ while (seen)
+ {
+ struct seen_device *seen_elt = seen;
+ seen = seen->next;
+ free (seen_elt);
+ }
+ seen = NULL;
+}
+
+#ifdef __linux__
+struct device
+{
+ char *stable;
+ char *kernel;
+};
+
+/* Sort by the kernel name for preference since that most closely matches
+ older device.map files, but sort by stable by-id names as a fallback.
+ This is because /dev/disk/by-id/ usually has a few alternative
+ identifications of devices (e.g. ATA vs. SATA).
+ check_device_readable_unique will ensure that we only get one for any
+ given disk, but sort the list so that the choice of which one we get is
+ stable. */
+static int
+compare_devices (const void *a, const void *b)
+{
+ const struct device *left = (const struct device *) a;
+ const struct device *right = (const struct device *) b;
+
+ if (left->kernel && right->kernel)
+ {
+ int ret = strcmp (left->kernel, right->kernel);
+ if (ret)
+ return ret;
+ }
+
+ return strcmp (left->stable, right->stable);
+}
+#endif /* __linux__ */
+
+void
+grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
+ int floppy_disks)
+{
+ int i;
+
+ clear_seen_devices ();
+
+ /* Floppies. */
+ for (i = 0; i < floppy_disks; i++)
+ {
+ char name[16];
+ struct stat st;
+
+ get_floppy_disk_name (name, i);
+ if (stat (name, &st) < 0)
+ break;
+ /* In floppies, write the map, whether check_device_readable_unique
+ succeeds or not, because the user just may not insert floppies. */
+ if (hook (name, 1))
+ goto out;
+ }
+
+#ifdef __linux__
+ {
+ DIR *dir = opendir ("/dev/disk/by-id");
+
+ if (dir)
+ {
+ struct dirent *entry;
+ struct device *devs;
+ size_t devs_len = 0, devs_max = 1024, i;
+
+ devs = xmalloc (devs_max * sizeof (*devs));
+
+ /* Dump all the directory entries into names, resizing if
+ necessary. */
+ for (entry = readdir (dir); entry; entry = readdir (dir))
+ {
+ /* Skip current and parent directory entries. */
+ if (strcmp (entry->d_name, ".") == 0 ||
+ strcmp (entry->d_name, "..") == 0)
+ continue;
+ /* Skip partition entries. */
+ if (strstr (entry->d_name, "-part"))
+ continue;
+ /* Skip device-mapper entries; we'll handle the ones we want
+ later. */
+ if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0)
+ continue;
+ /* Skip RAID entries; they are handled by upper layers. */
+ if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0)
+ continue;
+ if (devs_len >= devs_max)
+ {
+ devs_max *= 2;
+ devs = xrealloc (devs, devs_max * sizeof (*devs));
+ }
+ devs[devs_len].stable =
+ xasprintf ("/dev/disk/by-id/%s", entry->d_name);
+ devs[devs_len].kernel =
+ canonicalize_file_name (devs[devs_len].stable);
+ devs_len++;
+ }
+
+ qsort (devs, devs_len, sizeof (*devs), &compare_devices);
+
+ closedir (dir);
+
+ /* Now add all the devices in sorted order. */
+ for (i = 0; i < devs_len; ++i)
+ {
+ if (check_device_readable_unique (devs[i].stable))
+ {
+ if (hook (devs[i].stable, 0))
+ goto out;
+ }
+ free (devs[i].stable);
+ free (devs[i].kernel);
+ }
+ free (devs);
+ }
+ }
+
+ if (have_devfs ())
+ {
+ i = 0;
+ while (1)
+ {
+ char discn[32];
+ char name[PATH_MAX];
+ struct stat st;
+
+ /* Linux creates symlinks "/dev/discs/discN" for convenience.
+ The way to number disks is the same as GRUB's. */
+ sprintf (discn, "/dev/discs/disc%d", i++);
+ if (stat (discn, &st) < 0)
+ break;
+
+ if (realpath (discn, name))
+ {
+ strcat (name, "/disc");
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ goto out;
+ }
+#endif /* __linux__ */
+
+ /* IDE disks. */
+ for (i = 0; i < 96; i++)
+ {
+ char name[16];
+
+ get_ide_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+#ifdef __linux__
+ /* Virtio disks. */
+ for (i = 0; i < 26; i++)
+ {
+ char name[16];
+
+ get_virtio_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+ /* ATARAID disks. */
+ for (i = 0; i < 8; i++)
+ {
+ char name[20];
+
+ get_ataraid_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+ /* Xen virtual block devices. */
+ for (i = 0; i < 26; i++)
+ {
+ char name[16];
+
+ get_xvd_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+#endif /* __linux__ */
+
+ /* The rest is SCSI disks. */
+ for (i = 0; i < 48; i++)
+ {
+ char name[16];
+
+ get_scsi_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+#ifdef __linux__
+ /* This is for DAC960 - we have
+ /dev/rd/c<controller>d<logical drive>p<partition>.
+
+ DAC960 driver currently supports up to 8 controllers, 32 logical
+ drives, and 7 partitions. */
+ {
+ int controller, drive;
+
+ for (controller = 0; controller < 8; controller++)
+ {
+ for (drive = 0; drive < 15; drive++)
+ {
+ char name[24];
+
+ get_dac960_disk_name (name, controller, drive);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* This is for Mylex Acceleraid - we have
+ /dev/rd/c<controller>d<logical drive>p<partition>. */
+ {
+ int controller, drive;
+
+ for (controller = 0; controller < 8; controller++)
+ {
+ for (drive = 0; drive < 15; drive++)
+ {
+ char name[24];
+
+ get_acceleraid_disk_name (name, controller, drive);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* This is for CCISS - we have
+ /dev/cciss/c<controller>d<logical drive>p<partition>. */
+ {
+ int controller, drive;
+
+ for (controller = 0; controller < 3; controller++)
+ {
+ for (drive = 0; drive < 16; drive++)
+ {
+ char name[24];
+
+ get_cciss_disk_name (name, controller, drive);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* This is for Compaq Intelligent Drive Array - we have
+ /dev/ida/c<controller>d<logical drive>p<partition>. */
+ {
+ int controller, drive;
+
+ for (controller = 0; controller < 3; controller++)
+ {
+ for (drive = 0; drive < 16; drive++)
+ {
+ char name[24];
+
+ get_ida_disk_name (name, controller, drive);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ }
+ }
+
+ /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
+ {
+ char unit;
+
+ for (unit = 'a'; unit < 'f'; unit++)
+ {
+ char name[24];
+
+ get_i2o_disk_name (name, unit);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+ }
+
+ /* MultiMediaCard (MMC). */
+ for (i = 0; i < 10; i++)
+ {
+ char name[16];
+
+ get_mmc_disk_name (name, i);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ goto out;
+ }
+ }
+
+# ifdef HAVE_DEVICE_MAPPER
+# define dmraid_check(cond, ...) \
+ if (! (cond)) \
+ { \
+ grub_dprintf ("deviceiter", __VA_ARGS__); \
+ goto dmraid_end; \
+ }
+
+ /* DM-RAID. */
+ if (grub_device_mapper_supported ())
+ {
+ struct dm_tree *tree = NULL;
+ struct dm_task *task = NULL;
+ struct dm_names *names = NULL;
+ unsigned int next = 0;
+ void *top_handle, *second_handle;
+ struct dm_tree_node *root, *top, *second;
+
+ /* Build DM tree for all devices. */
+ tree = dm_tree_create ();
+ dmraid_check (tree, "dm_tree_create failed\n");
+ task = dm_task_create (DM_DEVICE_LIST);
+ dmraid_check (task, "dm_task_create failed\n");
+ dmraid_check (dm_task_run (task), "dm_task_run failed\n");
+ names = dm_task_get_names (task);
+ dmraid_check (names, "dm_task_get_names failed\n");
+ dmraid_check (names->dev, "No DM devices found\n");
+ do
+ {
+ names = (void *) names + next;
+ dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev),
+ MINOR (names->dev)),
+ "dm_tree_add_dev (%s) failed\n", names->name);
+ next = names->next;
+ }
+ while (next);
+
+ /* Walk the second-level children of the inverted tree; that is, devices
+ which are directly composed of non-DM devices such as hard disks.
+ This class includes all DM-RAID disks and excludes all DM-RAID
+ partitions. */
+ root = dm_tree_find_node (tree, 0, 0);
+ top_handle = NULL;
+ top = dm_tree_next_child (&top_handle, root, 1);
+ while (top)
+ {
+ second_handle = NULL;
+ second = dm_tree_next_child (&second_handle, top, 1);
+ while (second)
+ {
+ const char *node_name, *node_uuid;
+ char *name;
+
+ node_name = dm_tree_node_get_name (second);
+ dmraid_check (node_name, "dm_tree_node_get_name failed\n");
+ node_uuid = dm_tree_node_get_uuid (second);
+ dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n");
+ if (strncmp (node_uuid, "DMRAID-", 7) != 0)
+ {
+ grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name);
+ goto dmraid_next_child;
+ }
+
+ name = xasprintf ("/dev/mapper/%s", node_name);
+ if (check_device_readable_unique (name))
+ {
+ if (hook (name, 0))
+ {
+ free (name);
+ if (task)
+ dm_task_destroy (task);
+ if (tree)
+ dm_tree_free (tree);
+ goto out;
+ }
+ }
+ free (name);
+
+dmraid_next_child:
+ second = dm_tree_next_child (&second_handle, top, 1);
+ }
+ top = dm_tree_next_child (&top_handle, root, 1);
+ }
+
+dmraid_end:
+ if (task)
+ dm_task_destroy (task);
+ if (tree)
+ dm_tree_free (tree);
+ }
+# endif /* HAVE_DEVICE_MAPPER */
+#endif /* __linux__ */
+
+out:
+ clear_seen_devices ();
+}
+
diff --git a/util/devicemap.c b/util/devicemap.c
new file mode 100644
index 0000000..c618644
--- /dev/null
+++ b/util/devicemap.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+#include <grub/util/deviceiter.h>
+
+void
+grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
+ int *num_fd, int *num_hd)
+{
+ if (is_floppy)
+ fprintf (fp, "(fd%d)\t%s\n", (*num_fd)++, name);
+ else
+ fprintf (fp, "(hd%d)\t%s\n", (*num_hd)++, name);
+}
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
new file mode 100644
index 0000000..5199454
--- /dev/null
+++ b/util/grub-editenv.c
@@ -0,0 +1,313 @@
+/* grub-editenv.c - tool to edit environment block. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/lib/envblk.h>
+#include <grub/i18n.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <argp.h>
+
+#include "progname.h"
+
+#define DEFAULT_ENVBLK_SIZE 1024
+#define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG
+
+static struct argp_option options[] = {
+ {0, 0, 0, OPTION_DOC, N_("Commands:"), 1},
+ {"create", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
+ N_("Create a blank environment block file."), 0},
+ {"list", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
+ N_("List the current variables."), 0},
+ {"set [name=value ...]", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
+ N_("Set variables."), 0},
+ {"unset [name ....]", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
+ N_("Delete variables."), 0},
+
+ {0, 0, 0, OPTION_DOC, N_("Options:"), -1},
+ {"verbose", 'v', 0, 0, N_("Print verbose messages."), 0},
+
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+/* Print the version information. */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+ fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+}
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Set the bug report address */
+const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">";
+
+error_t argp_parser (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'v':
+ verbosity++;
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ fprintf (stderr, "%s",
+ _("You need to specify at least one command.\n"));
+ argp_usage (state);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 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, DEFAULT_ENVBLK_PATH);
+
+ default:
+ return (char *) text;
+ }
+}
+
+struct argp argp = {
+ options, argp_parser, N_("FILENAME COMMAND"),
+ "\n"N_("\
+Tool to edit environment block.")
+"\v"N_("\
+If FILENAME is '-', the default value %s is used."),
+ NULL, help_filter, NULL
+};
+
+static void
+create_envblk_file (const char *name)
+{
+ FILE *fp;
+ char *buf;
+ char *namenew;
+
+ buf = malloc (DEFAULT_ENVBLK_SIZE);
+ if (! buf)
+ grub_util_error ("out of memory");
+
+ namenew = xasprintf ("%s.new", name);
+ fp = fopen (namenew, "wb");
+ if (! fp)
+ grub_util_error ("cannot open the file %s", namenew);
+
+ memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
+ memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#',
+ DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
+
+ if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE)
+ grub_util_error ("cannot write to the file %s", namenew);
+
+ fsync (fileno (fp));
+ free (buf);
+ fclose (fp);
+
+ if (rename (namenew, name) < 0)
+ grub_util_error ("cannot rename the file %s to %s", namenew, name);
+ free (namenew);
+}
+
+static grub_envblk_t
+open_envblk_file (const char *name)
+{
+ FILE *fp;
+ char *buf;
+ size_t size;
+ grub_envblk_t envblk;
+
+ fp = fopen (name, "rb");
+ if (! fp)
+ {
+ /* Create the file implicitly. */
+ create_envblk_file (name);
+ fp = fopen (name, "rb");
+ if (! fp)
+ grub_util_error ("cannot open the file %s", name);
+ }
+
+ if (fseek (fp, 0, SEEK_END) < 0)
+ grub_util_error ("cannot seek the file %s", name);
+
+ size = (size_t) ftell (fp);
+
+ if (fseek (fp, 0, SEEK_SET) < 0)
+ grub_util_error ("cannot seek the file %s", name);
+
+ buf = malloc (size);
+ if (! buf)
+ grub_util_error ("out of memory");
+
+ if (fread (buf, 1, size, fp) != size)
+ grub_util_error ("cannot read the file %s", name);
+
+ fclose (fp);
+
+ envblk = grub_envblk_open (buf, size);
+ if (! envblk)
+ grub_util_error ("invalid environment block");
+
+ return envblk;
+}
+
+static void
+list_variables (const char *name)
+{
+ grub_envblk_t envblk;
+
+ auto int print_var (const char *name, const char *value);
+ int print_var (const char *name, const char *value)
+ {
+ printf ("%s=%s\n", name, value);
+ return 0;
+ }
+
+ envblk = open_envblk_file (name);
+ grub_envblk_iterate (envblk, print_var);
+ grub_envblk_close (envblk);
+}
+
+static void
+write_envblk (const char *name, grub_envblk_t envblk)
+{
+ FILE *fp;
+
+ fp = fopen (name, "wb");
+ if (! fp)
+ grub_util_error ("cannot open the file %s", name);
+
+ if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp)
+ != grub_envblk_size (envblk))
+ grub_util_error ("cannot write to the file %s", name);
+
+ fsync (fileno (fp));
+ fclose (fp);
+}
+
+static void
+set_variables (const char *name, int argc, char *argv[])
+{
+ grub_envblk_t envblk;
+
+ envblk = open_envblk_file (name);
+ while (argc)
+ {
+ char *p;
+
+ p = strchr (argv[0], '=');
+ if (! p)
+ grub_util_error ("invalid parameter %s", argv[0]);
+
+ *(p++) = 0;
+
+ if (! grub_envblk_set (envblk, argv[0], p))
+ grub_util_error ("environment block too small");
+
+ argc--;
+ argv++;
+ }
+
+ write_envblk (name, envblk);
+ grub_envblk_close (envblk);
+}
+
+static void
+unset_variables (const char *name, int argc, char *argv[])
+{
+ grub_envblk_t envblk;
+
+ envblk = open_envblk_file (name);
+ while (argc)
+ {
+ grub_envblk_delete (envblk, argv[0]);
+
+ argc--;
+ argv++;
+ }
+
+ write_envblk (name, envblk);
+ grub_envblk_close (envblk);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *filename;
+ char *command;
+ int index, arg_count;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Parse our arguments */
+ if (argp_parse (&argp, argc, argv, 0, &index, 0) != 0)
+ {
+ fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
+ exit(1);
+ }
+
+ arg_count = argc - index;
+
+ if (arg_count == 1)
+ {
+ filename = DEFAULT_ENVBLK_PATH;
+ command = argv[index++];
+ }
+ else
+ {
+ filename = argv[index++];
+ if (strcmp (filename, "-") == 0)
+ filename = DEFAULT_ENVBLK_PATH;
+ command = argv[index++];
+ }
+
+ if (strcmp (command, "create") == 0)
+ create_envblk_file (filename);
+ else if (strcmp (command, "list") == 0)
+ list_variables (filename);
+ else if (strcmp (command, "set") == 0)
+ set_variables (filename, argc - index, argv + index);
+ else if (strcmp (command, "unset") == 0)
+ unset_variables (filename, argc - index, argv + index);
+ else
+ {
+ char *program = xstrdup(program_name);
+ fprintf (stderr, _("Unknown command `%s'.\n"), command);
+ argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
+ free(program);
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
new file mode 100644
index 0000000..293bdf7
--- /dev/null
+++ b/util/grub-fstest.c
@@ -0,0 +1,557 @@
+/* grub-fstest.c - debug tool for filesystem driver */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/term.h>
+#include <grub/mm.h>
+#include <grub/lib/hexdump.h>
+#include <grub/crypto.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "progname.h"
+#include "argp.h"
+
+static grub_err_t
+execute_command (char *name, int n, char **args)
+{
+ grub_command_t cmd;
+
+ cmd = grub_command_find (name);
+ if (! cmd)
+ grub_util_error (_("can\'t find command %s"), name);
+
+ return (cmd->func) (cmd, n, args);
+}
+
+#define CMD_LS 1
+#define CMD_CP 2
+#define CMD_CMP 3
+#define CMD_HEX 4
+#define CMD_CRC 6
+#define CMD_BLOCKLIST 7
+
+#define BUF_SIZE 32256
+
+static grub_disk_addr_t skip, leng;
+
+static void
+read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
+{
+ static char buf[BUF_SIZE];
+ grub_file_t file;
+ grub_off_t ofs, len;
+
+ if ((pathname[0] == '-') && (pathname[1] == 0))
+ {
+ grub_device_t dev;
+
+ dev = grub_device_open (0);
+ if ((! dev) || (! dev->disk))
+ grub_util_error (_("can\'t open device"));
+
+ grub_util_info ("total sectors : %lld",
+ (unsigned long long) dev->disk->total_sectors);
+
+ if (! leng)
+ leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
+
+ while (leng)
+ {
+ grub_size_t len;
+
+ len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
+
+ if (grub_disk_read (dev->disk, 0, skip, len, buf))
+ grub_util_error (_("disk read fails at offset %lld, length %d"),
+ skip, len);
+
+ if (hook (skip, buf, len))
+ break;
+
+ skip += len;
+ leng -= len;
+ }
+
+ grub_device_close (dev);
+ return;
+ }
+
+ grub_file_filter_disable_compression ();
+ file = grub_file_open (pathname);
+ if (!file)
+ {
+ grub_util_error (_("cannot open file %s:%s"), pathname,
+ grub_errmsg);
+ return;
+ }
+
+ grub_util_info ("file size : %lld", (unsigned long long) file->size);
+
+ if (skip > file->size)
+ {
+ grub_util_error (_("invalid skip value %lld"), (unsigned long long) skip);
+ return;
+ }
+
+ ofs = skip;
+ len = file->size - skip;
+ if ((leng) && (leng < len))
+ len = leng;
+
+ file->offset = skip;
+
+ while (len)
+ {
+ grub_ssize_t sz;
+
+ sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
+ if (sz < 0)
+ {
+ grub_util_error (_("read error at offset %llu: %s"), ofs,
+ grub_errmsg);
+ break;
+ }
+
+ if ((sz == 0) || (hook (ofs, buf, sz)))
+ break;
+
+ ofs += sz;
+ len -= sz;
+ }
+
+ grub_file_close (file);
+}
+
+static void
+cmd_cp (char *src, char *dest)
+{
+ FILE *ff;
+
+ auto int cp_hook (grub_off_t ofs, char *buf, int len);
+ int cp_hook (grub_off_t ofs, char *buf, int len)
+ {
+ (void) ofs;
+
+ if ((int) fwrite (buf, 1, len, ff) != len)
+ {
+ grub_util_error (_("write error"));
+ return 1;
+ }
+
+ return 0;
+ }
+
+ ff = fopen (dest, "wb");
+ if (ff == NULL)
+ {
+ grub_util_error (_("open error"));
+ return;
+ }
+ read_file (src, cp_hook);
+ fclose (ff);
+}
+
+static void
+cmd_cmp (char *src, char *dest)
+{
+ FILE *ff;
+ static char buf_1[BUF_SIZE];
+
+ auto int cmp_hook (grub_off_t ofs, char *buf, int len);
+ int cmp_hook (grub_off_t ofs, char *buf, int len)
+ {
+ if ((int) fread (buf_1, 1, len, ff) != len)
+ {
+ grub_util_error (_("read error at offset %llu: %s"), ofs, grub_errmsg);
+ return 1;
+ }
+
+ if (grub_memcmp (buf, buf_1, len))
+ {
+ int i;
+
+ for (i = 0; i < len; i++, ofs++)
+ if (buf_1[i] != buf[i])
+ {
+ grub_util_error (_("compare fail at offset %llu"), ofs);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ ff = fopen (dest, "rb");
+ if (ff == NULL)
+ {
+ grub_util_error (_("open error"));
+ return;
+ }
+
+ if ((skip) && (fseeko (ff, skip, SEEK_SET)))
+ grub_util_error (_("seek error"));
+
+ read_file (src, cmp_hook);
+
+ {
+ grub_uint64_t pre;
+ pre = ftell (ff);
+ fseek (ff, 0, SEEK_END);
+ if (pre != ftell (ff))
+ grub_util_error (_("unexpected end of file"));
+ }
+ fclose (ff);
+}
+
+static void
+cmd_hex (char *pathname)
+{
+ auto int hex_hook (grub_off_t ofs, char *buf, int len);
+ int hex_hook (grub_off_t ofs, char *buf, int len)
+ {
+ hexdump (ofs, buf, len);
+ return 0;
+ }
+
+ read_file (pathname, hex_hook);
+}
+
+static void
+cmd_crc (char *pathname)
+{
+ grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
+ GRUB_MD_CRC32->init(crc32_context);
+
+ auto int crc_hook (grub_off_t ofs, char *buf, int len);
+ int crc_hook (grub_off_t ofs, char *buf, int len)
+ {
+ (void) ofs;
+
+ GRUB_MD_CRC32->write(crc32_context, buf, len);
+ return 0;
+ }
+
+ read_file (pathname, crc_hook);
+ GRUB_MD_CRC32->final(crc32_context);
+ printf ("%08x\n",
+ grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)));
+}
+
+static char *root = NULL;
+static int args_count = 0;
+static int nparm = 0;
+static int num_disks = 1;
+static char **images = NULL;
+static int cmd = 0;
+static char *debug_str = NULL;
+static char **args = NULL;
+
+static void
+fstest (int n, char **args)
+{
+ char *host_file;
+ char *loop_name;
+ int i;
+
+ for (i = 0; i < num_disks; i++)
+ {
+ char *argv[2];
+ loop_name = grub_xasprintf ("loop%d", i);
+ if (!loop_name)
+ grub_util_error (grub_errmsg);
+
+ host_file = grub_xasprintf ("(host)%s", images[i]);
+ if (!host_file)
+ grub_util_error (grub_errmsg);
+
+ argv[0] = loop_name;
+ argv[1] = host_file;
+
+ if (execute_command ("loopback", 2, argv))
+ grub_util_error (_("loopback command fails"));
+
+ grub_free (loop_name);
+ grub_free (host_file);
+ }
+
+ grub_lvm_fini ();
+ grub_mdraid09_fini ();
+ grub_mdraid1x_fini ();
+ grub_raid_fini ();
+ grub_raid_init ();
+ grub_mdraid09_init ();
+ grub_mdraid1x_init ();
+ grub_lvm_init ();
+
+ switch (cmd)
+ {
+ case CMD_LS:
+ execute_command ("ls", n, args);
+ break;
+ case CMD_CP:
+ cmd_cp (args[0], args[1]);
+ break;
+ case CMD_CMP:
+ cmd_cmp (args[0], args[1]);
+ break;
+ case CMD_HEX:
+ cmd_hex (args[0]);
+ break;
+ case CMD_CRC:
+ cmd_crc (args[0]);
+ break;
+ case CMD_BLOCKLIST:
+ execute_command ("blocklist", n, args);
+ grub_printf ("\n");
+ }
+
+ for (i = 0; i < num_disks; i++)
+ {
+ char *argv[2];
+
+ loop_name = grub_xasprintf ("loop%d", i);
+ if (!loop_name)
+ grub_util_error (grub_errmsg);
+
+ argv[0] = "-d";
+ argv[1] = loop_name;
+
+ execute_command ("loopback", 2, argv);
+
+ grub_free (loop_name);
+ }
+}
+
+static struct argp_option options[] = {
+ {0, 0, 0 , OPTION_DOC, N_("Commands:"), 1},
+ {N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1},
+ {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1},
+ {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1},
+ {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1},
+ {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1},
+ {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1},
+
+ {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2},
+ {"skip", 's', "N", 0, N_("Skip N bytes from output file."), 2},
+ {"length", 'n', "N", 0, N_("Handle N bytes in output file."), 2},
+ {"diskcount", 'c', "N", 0, N_("N input files."), 2},
+ {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2},
+ {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2},
+ {0, 0, 0, 0, 0, 0}
+};
+
+/* Print the version information. */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+ fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+}
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ char *p;
+
+ switch (key)
+ {
+ case 'r':
+ root = arg;
+ return 0;
+
+ case 's':
+ skip = grub_strtoul (arg, &p, 0);
+ if (*p == 's')
+ skip <<= GRUB_DISK_SECTOR_BITS;
+ return 0;
+
+ case 'n':
+ leng = grub_strtoul (arg, &p, 0);
+ if (*p == 's')
+ leng <<= GRUB_DISK_SECTOR_BITS;
+ return 0;
+
+ case 'c':
+ num_disks = grub_strtoul (arg, NULL, 0);
+ if (num_disks < 1)
+ {
+ fprintf (stderr, "%s", _("Invalid disk count.\n"));
+ argp_usage (state);
+ }
+ if (args_count != 0)
+ {
+ fprintf (stderr, "%s", _("Disk count must precede disks list.\n"));
+ argp_usage (state);
+ }
+ return 0;
+
+ case 'd':
+ debug_str = arg;
+ return 0;
+
+ case 'v':
+ verbosity++;
+ return 0;
+
+ case ARGP_KEY_END:
+ if (args_count < num_disks)
+ {
+ fprintf (stderr, "%s", _("No command is specified.\n"));
+ argp_usage (state);
+ }
+ if (args_count - 1 - num_disks < nparm)
+ {
+ fprintf (stderr, "%s", _("Not enough parameters to command.\n"));
+ argp_usage (state);
+ }
+ return 0;
+
+ case ARGP_KEY_ARG:
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ if (args_count < num_disks)
+ {
+ if (arg[0] != '/')
+ {
+ fprintf (stderr, "%s", _("Must use absolute path.\n"));
+ argp_usage (state);
+ }
+ if (args_count == 0)
+ images = xmalloc (num_disks * sizeof (images[0]));
+ images[args_count] = xstrdup (arg);
+ args_count++;
+ return 0;
+ }
+
+ if (args_count == num_disks)
+ {
+ if (!grub_strcmp (arg, "ls"))
+ {
+ cmd = CMD_LS;
+ }
+ else if (!grub_strcmp (arg, "cp"))
+ {
+ cmd = CMD_CP;
+ nparm = 2;
+ }
+ else if (!grub_strcmp (arg, "cmp"))
+ {
+ cmd = CMD_CMP;
+ nparm = 2;
+ }
+ else if (!grub_strcmp (arg, "hex"))
+ {
+ cmd = CMD_HEX;
+ nparm = 1;
+ }
+ else if (!grub_strcmp (arg, "crc"))
+ {
+ cmd = CMD_CRC;
+ nparm = 1;
+ }
+ else if (!grub_strcmp (arg, "blocklist"))
+ {
+ cmd = CMD_BLOCKLIST;
+ nparm = 1;
+ }
+ else
+ {
+ fprintf (stderr, _("Invalid command %s.\n"), arg);
+ argp_usage (state);
+ }
+ args_count++;
+ return 0;
+ }
+
+ args[args_count - 1 - num_disks] = xstrdup (arg);
+ args_count++;
+ return 0;
+}
+
+struct argp argp = {
+ options, argp_parser, N_("IMAGE_PATH COMMANDS"),
+ N_("Debug tool for filesystem driver."),
+ NULL, NULL, NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+ char *default_root, *alloc_root;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ args = xmalloc (argc * sizeof (args[0]));
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ /* Initialize all modules. */
+ grub_init_all ();
+
+ if (debug_str)
+ grub_env_set ("debug", debug_str);
+
+ default_root = (num_disks == 1) ? "loop0" : "md0";
+ alloc_root = 0;
+ if (root)
+ {
+ if ((*root >= '0') && (*root <= '9'))
+ {
+ alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
+
+ sprintf (alloc_root, "%s,%s", default_root, root);
+ root = alloc_root;
+ }
+ }
+ else
+ root = default_root;
+
+ grub_env_set ("root", root);
+
+ if (alloc_root)
+ free (alloc_root);
+
+ /* Do it. */
+ fstest (args_count - 1 - num_disks, args);
+
+ /* Free resources. */
+ grub_fini_all ();
+
+ return 0;
+}
diff --git a/util/grub-install.in b/util/grub-install.in
new file mode 100644
index 0000000..ff8bea8
--- /dev/null
+++ b/util/grub-install.in
@@ -0,0 +1,666 @@
+#! /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 <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+sbindir="@sbindir@"
+bindir="@bindir@"
+libdir="@libdir@"
+sysconfdir="@sysconfdir@"
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+host_os=@host_os@
+pkglibdir="${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`"
+localedir="@datadir@/locale"
+
+self="`basename $0`"
+
+grub_setup="${sbindir}/`echo grub-setup | sed ${transform}`"
+grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`"
+grub_mkdevicemap="${sbindir}/`echo grub-mkdevicemap | sed ${transform}`"
+grub_probe="${sbindir}/`echo grub-probe | sed ${transform}`"
+grub_editenv="${bindir}/`echo grub-editenv | sed ${transform}`"
+grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed ${transform}`"
+rootdir=
+bootdir=
+grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`"
+modules=
+
+install_device=
+no_floppy=
+force_lba=
+recheck=no
+debug=no
+debug_image=
+
+update_nvram=yes
+
+removable=no
+efi_quiet=
+
+# 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
+
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+ disk_module=biosdisk
+elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then
+ disk_module=
+else
+ disk_module=ata
+fi
+
+# Usage: usage
+# Print the usage.
+usage () {
+if [ "${target_cpu}-${platform}" = "i386-pc" ] \
+ || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then
+ cat <<EOF
+Usage: $self [OPTION] install_device
+EOF
+else
+ cat <<EOF
+Usage: $self [OPTION] [install_device]
+EOF
+fi
+cat <<EOF
+Install GRUB on your drive.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ --modules=MODULES pre-load specified modules MODULES
+ --boot-directory=DIR install GRUB images under the directory DIR/@grubdirname@
+ instead of the $grubdir directory
+ --grub-setup=FILE use FILE as grub-setup
+ --grub-mkimage=FILE use FILE as grub-mkimage
+ --grub-mkrelpath=FILE use FILE as grub-mkrelpath
+ --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+ --grub-probe=FILE use FILE as grub-probe
+ --no-floppy do not probe any floppy drive
+ --allow-floppy Make the drive also bootable as floppy
+ (default for fdX devices). May break on some BIOSes.
+ --recheck probe a device map even if it already exists
+ --force install even if problems are detected
+EOF
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+ cat <<EOF
+ --disk-module=MODULE disk module to use
+EOF
+fi
+if [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] ; then
+ cat <<EOF
+ --no-nvram don't update the boot-device NVRAM variable
+EOF
+fi
+if [ "${platform}" = "efi" ]; then
+ cat <<EOF
+ --removable the installation device is removable
+ --bootloader-id=ID the ID of bootloader.
+EOF
+fi
+ cat <<EOF
+
+INSTALL_DEVICE can be a GRUB device name or a system device filename.
+
+$self copies GRUB images into $grubdir, and uses grub-setup
+to install grub into the boot sector.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt="$1"
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo "$1"
+}
+
+allow_floppy=""
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --modules)
+ modules=`argument $option "$@"`; shift;;
+ --modules=*)
+ modules=`echo "$option" | sed 's/--modules=//'` ;;
+
+# 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=//'`" ;;
+
+ --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-mkimage)
+ grub_mkimage="`argument $option "$@"`"; shift;;
+ --grub-mkimage=*)
+ grub_mkimage="`echo "$option" | sed 's/--grub-mkimage=//'`" ;;
+
+ --grub-mkrelpath)
+ grub_mkrelpath="`argument "$option" "$@"`"; shift;;
+ --grub-mkrelpath=*)
+ grub_mkrelpath="`echo "$option" | sed 's/--grub-mkrelpath=//'`" ;;
+
+ --grub-mkdevicemap)
+ grub_mkdevicemap="`argument "$option" "$@"`"; shift;;
+ --grub-mkdevicemap=*)
+ grub_mkdevicemap="`echo "$option" | sed 's/--grub-mkdevicemap=//'`" ;;
+
+ --grub-probe)
+ grub_probe="`argument "$option" "$@"`"; shift;;
+ --grub-probe=*)
+ grub_probe="`echo "$option" | sed 's/--grub-probe=//'`" ;;
+
+ --no-floppy)
+ no_floppy="--no-floppy" ;;
+ --recheck)
+ recheck=yes ;;
+ --removable)
+ removable=yes ;;
+
+ --allow-floppy)
+ allow_floppy="--allow-floppy" ;;
+
+ --disk-module)
+ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+ disk_module="`argument "$option" "$@"`"; shift;
+ fi ;;
+ --disk-module=*)
+ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+ disk_module="`echo "$option" | sed 's/--disk-module=//'`"
+ fi ;;
+
+ --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" ;;
+
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ *)
+ if test "x$install_device" != x; then
+ echo "More than one install_devices?" 1>&2
+ usage
+ exit 1
+ fi
+ install_device="${option}" ;;
+ esac
+done
+
+if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \
+ || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then
+ echo "install_device not specified." 1>&2
+ usage
+ exit 1
+fi
+
+if ! ([ "${target_cpu}-${platform}" = "i386-pc" ] \
+ || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); 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=-q
+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 [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
+ set $grub_setup dummy
+ if test -f "$1"; then
+ :
+ else
+ echo "$1: Not found." 1>&2
+ exit 1
+ fi
+fi
+
+set "$grub_mkimage" dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+set "$grub_mkdevicemap" dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+if [ x"$platform" = xefi ]; then
+ # Find the EFI System Partition.
+ efidir=
+ if test -d "${bootdir}/efi"; then
+ install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/efi"`"
+ # Is it a mount point?
+ if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${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_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${rootdir}"`"
+ # Is it a mount point?
+ if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${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
+ echo "${efidir} doesn't look like an EFI partition." 1>&2
+ efidir=
+ 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 "$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 ;;
+ esac
+ else
+ # It is convenient for each architecture to have a different
+ # efi_file, so that different versions can be installed in parallel.
+ case "$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 ;;
+ *)
+ efi_file=grub.efi ;;
+ esac
+ # TODO: We should also use efibootmgr, if available, to add a Boot
+ # entry for ourselves.
+ 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
+
+# If --recheck is specified, remove the device map, if present.
+if test $recheck = yes; then
+ rm -f "$device_map"
+fi
+
+# Create the device map file if it is not present.
+if test -f "$device_map"; then
+ :
+else
+ # Create a safe temporary file.
+ test -n "$mklog" && log_file=`$mklog`
+
+ "$grub_mkdevicemap" "--device-map=$device_map" $no_floppy || exit 1
+fi
+
+# 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
+ echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
+ exit 1
+fi
+
+# Copy the GRUB images to the GRUB directory.
+for file in "${grubdir}"/*.mod "${grubdir}"/*.lst "${grubdir}"/*.img "${grubdir}"/efiemu??.o; do
+ if test -f "$file" && [ "`basename $file`" != menu.lst ]; then
+ rm -f "$file" || exit 1
+ fi
+done
+for file in "${pkglibdir}"/*.mod "${pkglibdir}"/*.lst; do
+ cp -f "$file" "${grubdir}" || exit 1
+done
+if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
+ for file in "${pkglibdir}"/*.img "${pkglibdir}"/efiemu??.o; do
+ if test -f "$file"; then
+ cp -f "$file" "${grubdir}" || exit 1
+ fi
+ done
+fi
+
+# Copy gettext files
+mkdir -p "${grubdir}"/locale/
+for dir in "${localedir}"/*; do
+ if test -f "$dir/LC_MESSAGES/grub.mo"; then
+ cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
+ fi
+done
+
+# 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="`"$grub_probe" --device-map="${device_map}" --target=fs --device "${grub_device}"`"
+if test "x$fs_module" = x ; then
+ echo "Auto-detection of a filesystem of ${grub_device} failed." 1>&2
+ echo "Try with --recheck." 1>&2
+ echo "If the problem persists please report this together with the output of \"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\" to <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 `"$grub_probe" --device-map="${device_map}" --target=partmap --device "${grub_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="`"$grub_probe" --device-map="${device_map}" --target=abstraction --device "${grub_device}"`"
+
+# 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=
+
+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
+
+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-z0-9,]*//g`"
+ fi
+ grub_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"`" || exit 1
+
+ # Strip partition number
+ grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`"
+ grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`"
+ if [ "$disk_module" = ata ] || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]) ; then
+ # generic method (used on coreboot and ata mod)
+ uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`"
+ if [ "x${uuid}" = "x" ] ; then
+ if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]; then
+ echo "UUID needed with $platform, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+ elif [ "$disk_module" = ata ]; then
+ echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+ else
+ echo "UUID needed with cross-disk installs, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+ fi
+
+ exit 1
+ fi
+ echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg"
+ echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg"
+ config_opt="-c ${grubdir}/load.cfg "
+ modules="$modules search_fs_uuid"
+ elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then
+ # we need to hardcode the partition number in the core image's prefix.
+ if [ x"$grub_partition" = x ]; then
+ prefix_drive="()"
+ else
+ prefix_drive="(,$grub_partition)"
+ fi
+ fi
+else
+ prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1
+fi
+
+case "${target_cpu}-${platform}" in
+ sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;;
+ mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;;
+ *) mkimage_target="${target_cpu}-${platform}" ;;
+esac
+
+case "${target_cpu}-${platform}" in
+ i386-efi | x86_64-efi) imgext=efi ;;
+ mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \
+ | powerpc-ieee1275) imgext=elf ;;
+ *) imgext=img ;;
+esac
+
+
+"$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1
+
+# Backward-compatibility kludges
+if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then
+ cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf
+elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then
+ cp "${grubdir}/core.${imgext}" "${grubdir}/grub"
+elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then
+ "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/grub.efi" --prefix="" $modules || exit 1
+fi
+
+
+# Perform the platform-dependent install
+if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then
+ # Now perform the installation.
+ "$grub_setup" ${allow_floppy} ${setup_verbose} ${setup_force} --directory="${grubdir}" \
+ --device-map="${device_map}" "${install_device}" || exit 1
+elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then
+ if [ x"$update_nvram" = xyes ]; then
+ ofpathname="`which ofpathname`"
+ nvsetenv="`which nvsetenv`"
+ set "$ofpathname" dummy
+ if test -f "$1"; then
+ :
+ else
+ echo "$1: Not found." 1>&2
+ exit 1
+ fi
+ set "$nvsetenv" dummy
+ if test -f "$1"; then
+ :
+ else
+ echo "$1: Not found." 1>&2
+ exit 1
+ fi
+ # 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`" || {
+ echo "Couldn't find Open Firmware device tree path for $dev."
+ echo "You will have to set boot-device manually."
+ exit 1
+ }
+
+ # Point boot-device at the new grub install
+ boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/core.${imgext}" | sed 's,/,\\\\,g'`
+ "$nvsetenv" boot-device "$boot_device" || {
+ echo "$nvsetenv failed."
+ echo "You will have to set boot-device manually. At the Open Firmware prompt, type:"
+ echo " setenv boot-device $boot_device"
+ exit 1
+ }
+ fi
+elif [ x"$platform" = xefi ]; then
+ cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}"
+ # For old macs. Suggested by Peter Jones.
+ if [ x$target_cpu = xi386 ]; then
+ cp "${grubdir}/core.${imgext}" "${efidir}/boot.efi"
+ fi
+
+ # Try to make this image bootable using the EFI Boot Manager, if available.
+ efibootmgr="`which efibootmgr`"
+ if test "$removable" = no && test -n "$efi_distributor" && \
+ test -n "$efibootmgr"; then
+ # 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.
+ clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)"
+ efidir_drive="$(echo "$clean_devmap" | "$grub_probe" --device-map="${device_map}" --target=drive --device-map=/dev/stdin "$efidir")"
+ if test -z "$efidir_drive"; then
+ echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2
+ else
+ efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)"
+ 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
+fi
+
+echo "Installation finished. No error reported."
+
+# Bye.
+exit 0
diff --git a/util/grub-kbdcomp.in b/util/grub-kbdcomp.in
new file mode 100644
index 0000000..05e516d
--- /dev/null
+++ b/util/grub-kbdcomp.in
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+transform="@program_transform_name@"
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+
+grub_mklayout=${bindir}/`echo grub-mklayout | sed ${transform}`
+
+ckbcomp "$@" | $grub_mklayout -o "$1".gkb
+
diff --git a/util/grub-macho2img.c b/util/grub-macho2img.c
new file mode 100644
index 0000000..bce0a06
--- /dev/null
+++ b/util/grub-macho2img.c
@@ -0,0 +1,118 @@
+/* macho2img.c - tool to convert Mach-O to raw imagw. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/types.h>
+#include <grub/macho.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* XXX: this file assumes particular Mach-O layout and does no checks. */
+/* However as build system ensures correct usage of this tool this
+ shouldn't be a problem. */
+
+int
+main (int argc, char **argv)
+{
+ FILE *in, *out;
+ int do_bss = 0;
+ char *buf;
+ int bufsize;
+ struct grub_macho_header32 *head;
+ struct grub_macho_segment32 *curcmd;
+ unsigned i;
+ unsigned bssstart = 0;
+ unsigned bssend = 0;
+
+ if (argc && strcmp (argv[1], "--bss") == 0)
+ do_bss = 1;
+ if (argc < 2 + do_bss)
+ {
+ printf ("Usage: %s [--bss] filename.exec filename.img\n"
+ "Convert Mach-O into raw image\n", argv[0]);
+ return 0;
+ }
+ in = fopen (argv[1 + do_bss], "rb");
+ if (! in)
+ {
+ printf ("Couldn't open %s\n", argv[1 + do_bss]);
+ return 1;
+ }
+ out = fopen (argv[2 + do_bss], "wb");
+ if (! out)
+ {
+ fclose (in);
+ printf ("Couldn't open %s\n", argv[2 + do_bss]);
+ return 2;
+ }
+ fseek (in, 0, SEEK_END);
+ bufsize = ftell (in);
+ fseek (in, 0, SEEK_SET);
+ buf = malloc (bufsize);
+ if (! buf)
+ {
+ fclose (in);
+ fclose (out);
+ printf ("Couldn't allocate buffer\n");
+ return 3;
+ }
+ fread (buf, 1, bufsize, in);
+ head = (struct grub_macho_header32 *) buf;
+ if (grub_le_to_cpu32 (head->magic) != GRUB_MACHO_MAGIC32)
+ {
+ fclose (in);
+ fclose (out);
+ free (buf);
+ printf ("Invalid Mach-O file\n");
+ return 4;
+ }
+ curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head));
+ for (i = 0; i < grub_le_to_cpu32 (head->ncmds); i++,
+ curcmd = (struct grub_macho_segment32 *)
+ (((char *) curcmd) + curcmd->cmdsize))
+ {
+ if (curcmd->cmd != GRUB_MACHO_CMD_SEGMENT32)
+ continue;
+ fwrite (buf + grub_le_to_cpu32 (curcmd->fileoff), 1,
+ grub_le_to_cpu32 (curcmd->filesize), out);
+ if (grub_le_to_cpu32 (curcmd->vmsize)
+ > grub_le_to_cpu32 (curcmd->filesize))
+ {
+ bssstart = grub_le_to_cpu32 (curcmd->vmaddr)
+ + grub_le_to_cpu32 (curcmd->filesize) ;
+ bssend = grub_le_to_cpu32 (curcmd->vmaddr)
+ + grub_le_to_cpu32 (curcmd->vmsize) ;
+ }
+ }
+ if (do_bss)
+ {
+ grub_uint32_t tmp;
+ fseek (out, 0x5c, SEEK_SET);
+ tmp = grub_cpu_to_le32 (bssstart);
+ fwrite (&tmp, 4, 1, out);
+ tmp = grub_cpu_to_le32 (bssend);
+ fwrite (&tmp, 4, 1, out);
+ }
+ fclose (in);
+ fclose (out);
+ printf("macho2img complete\n");
+ return 0;
+}
diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c
new file mode 100644
index 0000000..513af47
--- /dev/null
+++ b/util/grub-menulst2cfg.c
@@ -0,0 +1,126 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/legacy_parse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+
+int
+main (int argc, char **argv)
+{
+ FILE *in, *out;
+ char *entryname = NULL;
+ char *buf = NULL;
+ size_t bufsize = 0;
+ char *suffix = xstrdup ("");
+ int suffixlen = 0;
+
+ if (argc >= 2 && argv[1][0] == '-')
+ {
+ fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]);
+ return 0;
+ }
+
+ if (argc >= 2)
+ {
+ in = fopen (argv[1], "r");
+ if (!in)
+ {
+ fprintf (stderr, "Couldn't open %s for reading: %s\n",
+ argv[1], strerror (errno));
+ return 1;
+ }
+ }
+ else
+ in = stdin;
+
+ if (argc >= 3)
+ {
+ out = fopen (argv[2], "w");
+ if (!out)
+ {
+ if (in != stdin)
+ fclose (in);
+ fprintf (stderr, "Couldn't open %s for writing: %s\n",
+ argv[2], strerror (errno));
+ return 1;
+ }
+ }
+ else
+ out = stdout;
+
+ while (1)
+ {
+ char *parsed;
+
+ if (getline (&buf, &bufsize, in) < 0)
+ break;
+
+ {
+ char *oldname = NULL;
+ char *newsuffix;
+ char *ptr;
+
+ for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
+
+ oldname = entryname;
+ parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
+ if (newsuffix)
+ {
+ suffixlen += strlen (newsuffix);
+ suffix = xrealloc (suffix, suffixlen + 1);
+ strcat (suffix, newsuffix);
+ }
+ if (oldname != entryname && oldname)
+ fprintf (out, "}\n\n");
+ if (oldname != entryname)
+ {
+ char *escaped = grub_legacy_escape (entryname, strlen (entryname));
+ fprintf (out, "menuentry \'%s\' {\n", escaped);
+ free (escaped);
+ free (oldname);
+ }
+ }
+
+ if (parsed)
+ fprintf (out, "%s%s", entryname ? " " : "", parsed);
+ free (parsed);
+ parsed = NULL;
+ }
+
+ if (entryname)
+ fprintf (out, "}\n\n");
+
+ fwrite (suffix, 1, suffixlen, out);
+
+ free (buf);
+ free (suffix);
+ free (entryname);
+
+ if (in != stdin)
+ fclose (in);
+ if (out != stdout)
+ fclose (out);
+
+ return 0;
+}
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
new file mode 100644
index 0000000..afc66f8
--- /dev/null
+++ b/util/grub-mkconfig.in
@@ -0,0 +1,308 @@
+#! /bin/sh
+set -e
+
+# Generate grub.cfg by inspecting /boot contents.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+sysconfdir=@sysconfdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+host_os=@host_os@
+datarootdir=@datarootdir@
+datadir=@datadir@
+pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`
+grub_cfg=""
+grub_mkconfig_dir=${sysconfdir}/grub.d
+
+self=`basename $0`
+
+grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed "${transform}"`
+grub_probe=${sbindir}/`echo grub-probe | sed "${transform}"`
+grub_script_check="${bindir}/`echo grub-script-check | sed "${transform}"`"
+
+GRUB_PREFIX=`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"`
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION]
+Generate a grub config file
+
+ -o, --output=FILE output generated config to FILE [default=stdout]
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+ -o | --output)
+ grub_cfg=`argument $option "$@"`; shift;;
+ --output=*)
+ grub_cfg=`echo "$option" | sed 's/--output=//'`
+ ;;
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ # Explicitly ignore non-option arguments, for compatibility.
+ esac
+done
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+if [ "x$EUID" = "x" ] ; then
+ EUID=`id -u`
+fi
+
+if [ "$EUID" != 0 ] ; then
+ root=f
+ case "`uname 2>/dev/null`" in
+ CYGWIN*)
+ # Cygwin: Assume root if member of admin group
+ for g in `id -G 2>/dev/null` ; do
+ case $g in
+ 0|544) root=t ;;
+ esac
+ done ;;
+ esac
+ if [ $root != t ] ; then
+ echo "$self: You must run this as root" >&2
+ exit 1
+ fi
+fi
+
+set $grub_mkdevicemap dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+set $grub_probe dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+mkdir -p ${GRUB_PREFIX}
+
+if test -e ${GRUB_PREFIX}/device.map ; then : ; else
+ ${grub_mkdevicemap}
+fi
+
+# Device containing our userland. Typically used for root= parameter.
+GRUB_DEVICE="`${grub_probe} --target=device /`"
+GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+
+# Device containing our /boot partition. Usually the same as GRUB_DEVICE.
+GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
+
+# Filesystem for the device containing our userland. Used for stuff like
+# choosing Hurd filesystem module.
+GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
+
+if test -f ${sysconfdir}/default/grub ; then
+ . ${sysconfdir}/default/grub
+fi
+
+# XXX: should this be deprecated at some point?
+if [ "x${GRUB_TERMINAL}" != "x" ] ; then
+ GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
+ GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
+fi
+
+termoutdefault=0
+if [ "x${GRUB_TERMINAL_OUTPUT}" = "x" ]; then
+ GRUB_TERMINAL_OUTPUT=gfxterm;
+ termoutdefault=1;
+fi
+
+for x in ${GRUB_TERMINAL_OUTPUT}; do
+ if [ "x${x}" = "xgfxterm" ]; then
+ if [ -n "$GRUB_FONT" ] ; then
+ if is_path_readable_by_grub ${GRUB_FONT} > /dev/null ; then
+ GRUB_FONT_PATH=${GRUB_FONT}
+ else
+ echo "No such font or not readable by grub: ${GRUB_FONT}" >&2
+ exit 1
+ fi
+ else
+ for dir in ${pkgdatadir} ${GRUB_PREFIX} /usr/share/grub ; do
+ for basename in unicode unifont ascii; do
+ path="${dir}/${basename}.pf2"
+ if is_path_readable_by_grub ${path} > /dev/null ; then
+ GRUB_FONT_PATH=${path}
+ else
+ continue
+ fi
+ if [ "${basename}" = "ascii" ] ; then
+ # make sure all our children behave in conformance with ascii..
+ export LANG=C
+ fi
+ break 2
+ done
+ done
+ fi
+ if [ -z "${GRUB_FONT_PATH}" ] ; then
+ if [ "x$termoutdefault" != "x1" ]; then
+ echo "No font for gfxterm found." >&2 ; exit 1
+ fi
+ GRUB_TERMINAL_OUTPUT=
+ fi
+ fi
+done
+
+for x in ${GRUB_TERMINAL_OUTPUT}; do
+ case "x${x}" in
+ xgfxterm) ;;
+ xconsole | xserial | xofconsole)
+ # make sure all our children behave in conformance with ascii..
+ export LANG=C;;
+ *) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
+ esac
+done
+
+# These are defined in this script, export them here so that user can
+# override them.
+export GRUB_DEVICE \
+ GRUB_DEVICE_UUID \
+ GRUB_DEVICE_BOOT \
+ GRUB_DEVICE_BOOT_UUID \
+ GRUB_FS \
+ GRUB_FONT_PATH \
+ GRUB_PRELOAD_MODULES \
+ GRUB_PREFIX
+
+# These are optional, user-defined variables.
+export GRUB_DEFAULT \
+ GRUB_HIDDEN_TIMEOUT \
+ GRUB_HIDDEN_TIMEOUT_QUIET \
+ GRUB_TIMEOUT \
+ GRUB_DEFAULT_BUTTON \
+ GRUB_HIDDEN_TIMEOUT_BUTTON \
+ GRUB_TIMEOUT_BUTTON \
+ GRUB_BUTTON_CMOS_ADDRESS \
+ GRUB_BUTTON_CMOS_CLEAN \
+ GRUB_DISTRIBUTOR \
+ GRUB_CMDLINE_LINUX \
+ GRUB_CMDLINE_LINUX_DEFAULT \
+ GRUB_CMDLINE_XEN \
+ GRUB_CMDLINE_XEN_DEFAULT \
+ GRUB_CMDLINE_NETBSD \
+ GRUB_CMDLINE_NETBSD_DEFAULT \
+ GRUB_TERMINAL_INPUT \
+ GRUB_TERMINAL_OUTPUT \
+ GRUB_SERIAL_COMMAND \
+ GRUB_DISABLE_LINUX_UUID \
+ GRUB_DISABLE_RECOVERY \
+ GRUB_VIDEO_BACKEND \
+ GRUB_GFXMODE \
+ GRUB_BACKGROUND \
+ GRUB_THEME \
+ GRUB_GFXPAYLOAD_LINUX \
+ GRUB_DISABLE_OS_PROBER \
+ GRUB_INIT_TUNE \
+ GRUB_SAVEDEFAULT \
+ GRUB_BADRAM
+
+if test "x${grub_cfg}" != "x"; then
+ rm -f ${grub_cfg}.new
+ exec > ${grub_cfg}.new
+
+ # Allow this to fail, since /boot/grub/ might need to be fatfs to support some
+ # firmware implementations (e.g. OFW or EFI).
+ chmod 400 ${grub_cfg}.new || grub_warn "Could not make ${grub_cfg}.new readable by only root.\
+ This means that if the generated config contains a password it is readable by everyone"
+fi
+echo "Generating grub.cfg ..." >&2
+
+cat << EOF
+#
+# DO NOT EDIT THIS FILE
+#
+# It is automatically generated by $self using templates
+# from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub
+#
+EOF
+
+for i in ${grub_mkconfig_dir}/* ; do
+ case "$i" in
+ # emacsen backup files. FIXME: support other editors
+ *~) ;;
+ # emacsen autosave files. FIXME: support other editors
+ \#*\#) ;;
+ *)
+ if grub_file_is_not_garbage "$i" && test -x "$i" ; then
+ echo
+ echo "### BEGIN $i ###"
+ "$i"
+ echo "### END $i ###"
+ fi
+ ;;
+ esac
+done
+
+if test "x${grub_cfg}" != "x" ; then
+ if ! ${grub_script_check} ${grub_cfg}.new; then
+ echo "Syntax errors are detected in generated GRUB config file." >&2
+ echo "Ensure that there are no errors in /etc/default/grub" >&2
+ echo "and /etc/grub.d/* files or please file a bug report with" >&2
+ echo "${grub_cfg}.new file attached." >&2
+ else
+ # none of the children aborted with error, install the new grub.cfg
+ mv -f ${grub_cfg}.new ${grub_cfg}
+ fi
+fi
+
+echo "done" >&2
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
new file mode 100644
index 0000000..2c5fd8c
--- /dev/null
+++ b/util/grub-mkconfig_lib.in
@@ -0,0 +1,227 @@
+# Helper library for grub-mkconfig
+# Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+transform="@program_transform_name@"
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+datadir="@datadir@"
+bindir="@bindir@"
+sbindir="@sbindir@"
+pkgdatadir="${datadir}/`echo "@PACKAGE_TARNAME@" | sed "${transform}"`"
+
+if test "x$grub_probe" = x; then
+ grub_probe="${sbindir}/`echo grub-probe | sed "${transform}"`"
+fi
+if test "x$grub_mkrelpath" = x; then
+ grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed "${transform}"`"
+fi
+
+if $(which gettext >/dev/null 2>/dev/null) ; then
+ gettext="gettext"
+else
+ gettext="echo"
+fi
+
+grub_warn ()
+{
+ echo "Warning: $@" >&2
+}
+
+make_system_path_relative_to_its_root ()
+{
+ "${grub_mkrelpath}" "$1"
+}
+
+is_path_readable_by_grub ()
+{
+ path="$1"
+
+ # abort if path doesn't exist
+ if test -e "$path" ; then : ;else
+ return 1
+ fi
+
+ # abort if file is in a filesystem we can't read
+ if "${grub_probe}" -t fs "$path" > /dev/null 2>&1 ; then : ; else
+ return 1
+ fi
+
+ # ... or if we can't figure out the abstraction module, for example if
+ # memberlist fails on an LVM volume group.
+ if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else
+ return 1
+ fi
+
+ return 0
+}
+
+convert_system_path_to_grub_path ()
+{
+ path="$1"
+
+ grub_warn "convert_system_path_to_grub_path() is deprecated. Use prepare_grub_to_access_device() instead."
+
+ # abort if GRUB can't access the path
+ if is_path_readable_by_grub "${path}" ; then : ; else
+ return 1
+ fi
+
+ if drive="`"${grub_probe}" -t drive "$path"`" ; then : ; else
+ return 1
+ fi
+
+ if relative_path="`make_system_path_relative_to_its_root "$path"`" ; then : ; else
+ return 1
+ fi
+
+ echo "${drive}${relative_path}"
+}
+
+save_default_entry ()
+{
+ if [ "x${GRUB_SAVEDEFAULT}" = "xtrue" ] ; then
+ cat << EOF
+savedefault
+EOF
+ fi
+}
+
+prepare_grub_to_access_device ()
+{
+ device="$1"
+
+ # Abstraction modules aren't auto-loaded.
+ abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
+ for module in ${abstraction} ; do
+ echo "insmod ${module}"
+ done
+
+ partmap="`"${grub_probe}" --device "${device}" --target=partmap`"
+ for module in ${partmap} ; do
+ case "${module}" in
+ netbsd | openbsd)
+ echo "insmod part_bsd";;
+ *)
+ echo "insmod part_${module}";;
+ esac
+ done
+
+ fs="`"${grub_probe}" --device "${device}" --target=fs`"
+ for module in ${fs} ; do
+ echo "insmod ${module}"
+ done
+
+ # If there's a filesystem UUID that GRUB is capable of identifying, use it;
+ # otherwise set root as per value in device.map.
+ echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'"
+ if fs_uuid="`"${grub_probe}" --device "${device}" --target=fs_uuid 2> /dev/null`" ; then
+ echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ fi
+}
+
+grub_file_is_not_garbage ()
+{
+ if test -f "$1" ; then
+ case "$1" in
+ *.dpkg-*) return 1 ;; # debian dpkg
+ README*) return 1 ;; # documentation
+ esac
+ else
+ return 1
+ fi
+ return 0
+}
+
+version_test_numeric ()
+{
+ local a="$1"
+ local cmp="$2"
+ local b="$3"
+ if [ "$a" = "$b" ] ; then
+ case "$cmp" in
+ ge|eq|le) return 0 ;;
+ gt|lt) return 1 ;;
+ esac
+ fi
+ if [ "$cmp" = "lt" ] ; then
+ c="$a"
+ a="$b"
+ b="$c"
+ fi
+ if (echo "$a" ; echo "$b") | sort -n | head -n 1 | grep -qx "$b" ; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+version_test_gt ()
+{
+ local a="`echo "$1" | sed -e "s/[^-]*-//"`"
+ local b="`echo "$2" | sed -e "s/[^-]*-//"`"
+ local cmp=gt
+ if [ "x$b" = "x" ] ; then
+ return 0
+ fi
+ case "$a:$b" in
+ *.old:*.old) ;;
+ *.old:*) a="`echo -n "$a" | sed -e 's/\.old$//'`" ; cmp=gt ;;
+ *:*.old) b="`echo -n "$b" | sed -e 's/\.old$//'`" ; cmp=ge ;;
+ esac
+ version_test_numeric "$a" "$cmp" "$b"
+ return "$?"
+}
+
+version_find_latest ()
+{
+ local a=""
+ for i in "$@" ; do
+ if version_test_gt "$i" "$a" ; then
+ a="$i"
+ fi
+ done
+ echo "$a"
+}
+
+# One layer of quotation is eaten by "", the second by sed, and the third by
+# printf; so this turns ' into \'. Note that you must use the output of
+# this function in a printf format string.
+gettext_quoted () {
+ "$gettext" "$@" | sed "s/'/'\\\\\\\\''/g"
+}
+
+# Run the first argument through gettext_quoted, and then pass that and all
+# remaining arguments to printf. This is a useful abbreviation and tends to
+# be easier to type.
+gettext_printf () {
+ local format="$1"
+ shift
+ printf "$(gettext_quoted "$format")" "$@"
+}
+
+uses_abstraction () {
+ device="$1"
+
+ abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`"
+ for module in ${abstraction}; do
+ if test "x${module}" = "x$2"; then
+ return 0
+ fi
+ done
+ return 1
+}
diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
new file mode 100644
index 0000000..bdecae4
--- /dev/null
+++ b/util/grub-mkdevicemap.c
@@ -0,0 +1,171 @@
+/* grub-mkdevicemap.c - make a device map file automatically */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/deviceiter.h>
+#include <grub/env.h>
+#include <grub/i18n.h>
+
+#define _GNU_SOURCE 1
+#include <getopt.h>
+
+#include "progname.h"
+
+static void
+make_device_map (const char *device_map, int floppy_disks)
+{
+ int num_hd = 0;
+ int num_fd = 0;
+ FILE *fp;
+
+ auto int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy);
+
+ int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy)
+ {
+ grub_util_emit_devicemap_entry (fp, (char *) name,
+ is_floppy, &num_fd, &num_hd);
+ return 0;
+ }
+
+ if (strcmp (device_map, "-") == 0)
+ fp = stdout;
+ else
+ fp = fopen (device_map, "w");
+
+ if (! fp)
+ grub_util_error ("cannot open %s", device_map);
+
+ grub_util_iterate_devices (process_device, floppy_disks);
+
+ if (fp != stdout)
+ fclose (fp);
+}
+
+static struct option options[] =
+ {
+ {"device-map", required_argument, 0, 'm'},
+ {"probe-second-floppy", no_argument, 0, 's'},
+ {"no-floppy", no_argument, 0, 'n'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr,
+ "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTION]...\n\
+\n\
+Generate a device map file automatically.\n\
+\n\
+ -n, --no-floppy do not probe any floppy drive\n\
+ -s, --probe-second-floppy probe the second floppy drive\n\
+ -m, --device-map=FILE use FILE as the device map [default=%s]\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", program_name,
+ DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *dev_map = 0;
+ int floppy_disks = 1;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'm':
+ if (dev_map)
+ free (dev_map);
+
+ dev_map = xstrdup (optarg);
+ break;
+
+ case 'n':
+ floppy_disks = 0;
+ break;
+
+ case 's':
+ floppy_disks = 2;
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (verbosity > 1)
+ grub_env_set ("debug", "all");
+
+ make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
+
+ free (dev_map);
+
+ return 0;
+}
diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
new file mode 100644
index 0000000..3108d46
--- /dev/null
+++ b/util/grub-mkfont.c
@@ -0,0 +1,1240 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/fontformat.h>
+#include <grub/font.h>
+#include <grub/unicode.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_TRUETYPE_TABLES_H
+#include <freetype/ftsynth.h>
+
+#undef __FTERRORS_H__
+#define FT_ERROR_START_LIST const char *ft_errmsgs[] = {
+#define FT_ERRORDEF(e, v, s) [e] = s,
+#define FT_ERROR_END_LIST };
+#include FT_ERRORS_H
+
+#include "progname.h"
+
+#define GRUB_FONT_DEFAULT_SIZE 16
+
+#define GRUB_FONT_RANGE_BLOCK 1024
+
+struct grub_glyph_info
+{
+ struct grub_glyph_info *next;
+ grub_uint32_t char_code;
+ int width;
+ int height;
+ int x_ofs;
+ int y_ofs;
+ int device_width;
+ int bitmap_size;
+ grub_uint8_t *bitmap;
+};
+
+enum file_formats
+{
+ PF2,
+ ASCII_BITMAPS,
+ WIDTH_SPEC
+};
+
+#define GRUB_FONT_FLAG_BOLD 1
+#define GRUB_FONT_FLAG_NOBITMAP 2
+#define GRUB_FONT_FLAG_NOHINTING 4
+#define GRUB_FONT_FLAG_FORCEHINT 8
+
+struct grub_font_info
+{
+ char* name;
+ int style;
+ int desc;
+ int asce;
+ int size;
+ int max_width;
+ int max_height;
+ int min_y;
+ int max_y;
+ int flags;
+ int num_range;
+ grub_uint32_t *ranges;
+ struct grub_glyph_info *glyphs_unsorted;
+ struct grub_glyph_info *glyphs_sorted;
+ int num_glyphs;
+};
+
+static struct option options[] =
+{
+ {"output", required_argument, 0, 'o'},
+ {"name", required_argument, 0, 'n'},
+ {"index", required_argument, 0, 'i'},
+ {"range", required_argument, 0, 'r'},
+ {"size", required_argument, 0, 's'},
+ {"desc", required_argument, 0, 'd'},
+ {"asce", required_argument, 0, 'c'},
+ {"bold", no_argument, 0, 'b'},
+ {"no-bitmap", no_argument, 0, 0x100},
+ {"no-hinting", no_argument, 0, 0x101},
+ {"force-autohint", no_argument, 0, 'a'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {"ascii-bitmaps", no_argument, 0, 0x102},
+ {"width-spec", no_argument, 0, 0x103},
+ {0, 0, 0, 0}
+};
+
+int font_verbosity;
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS] FONT_FILES\n\
+\nOptions:\n\
+ -o, --output=FILE_NAME set output file name\n\
+ --ascii-bitmaps save only the ASCII bitmaps\n\
+ --width-spec create width summary file\n\
+ -i, --index=N set face index\n\
+ -r, --range=A-B[,C-D] set font range\n\
+ -n, --name=S set font family name\n\
+ -s, --size=N set font size\n\
+ -d, --desc=N set font descent\n\
+ -c, --asce=N set font ascent\n\
+ -b, --bold convert to bold font\n\
+ -a, --force-autohint force autohint\n\
+ --no-hinting disable hinting\n\
+ --no-bitmap ignore bitmap strikes when loading\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+void
+add_pixel (grub_uint8_t **data, int *mask, int not_blank)
+{
+ if (*mask == 0)
+ {
+ (*data)++;
+ **data = 0;
+ *mask = 128;
+ }
+
+ if (not_blank)
+ **data |= *mask;
+
+ *mask >>= 1;
+}
+
+static void
+add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face,
+ grub_uint32_t char_code, int nocut)
+{
+ struct grub_glyph_info *glyph_info;
+ int width, height;
+ int cuttop, cutbottom, cutleft, cutright;
+ grub_uint8_t *data;
+ int mask, i, j, bitmap_size;
+ FT_GlyphSlot glyph;
+ int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
+ FT_Error err;
+
+ if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
+ flag |= FT_LOAD_NO_BITMAP;
+
+ if (font_info->flags & GRUB_FONT_FLAG_NOHINTING)
+ flag |= FT_LOAD_NO_HINTING;
+ else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
+ flag |= FT_LOAD_FORCE_AUTOHINT;
+
+ err = FT_Load_Glyph (face, glyph_idx, flag);
+ if (err)
+ {
+ printf ("Freetype Error %d loading glyph 0x%x for U+0x%x%s",
+ err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK,
+ char_code & GRUB_FONT_CODE_RIGHT_JOINED
+ ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (medial)":
+ " (leftmost)")
+ : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)":
+ ""));
+
+ if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
+ printf (": %s\n", ft_errmsgs[err]);
+ else
+ printf ("\n");
+ return;
+ }
+
+ glyph = face->glyph;
+
+ if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+ FT_GlyphSlot_Embolden (glyph);
+
+ if (glyph->next)
+ printf ("%x\n", char_code);
+
+ if (nocut)
+ cuttop = cutbottom = cutleft = cutright = 0;
+ else
+ {
+ for (cuttop = 0; cuttop < glyph->bitmap.rows; cuttop++)
+ {
+ for (j = 0; j < glyph->bitmap.width; j++)
+ if (glyph->bitmap.buffer[j / 8 + cuttop * glyph->bitmap.pitch]
+ & (1 << (7 - (j & 7))))
+ break;
+ if (j != glyph->bitmap.width)
+ break;
+ }
+
+ for (cutbottom = glyph->bitmap.rows - 1; cutbottom >= 0; cutbottom--)
+ {
+ for (j = 0; j < glyph->bitmap.width; j++)
+ if (glyph->bitmap.buffer[j / 8 + cutbottom * glyph->bitmap.pitch]
+ & (1 << (7 - (j & 7))))
+ break;
+ if (j != glyph->bitmap.width)
+ break;
+ }
+ cutbottom = glyph->bitmap.rows - 1 - cutbottom;
+ if (cutbottom + cuttop >= glyph->bitmap.rows)
+ cutbottom = 0;
+
+ for (cutleft = 0; cutleft < glyph->bitmap.width; cutleft++)
+ {
+ for (j = 0; j < glyph->bitmap.rows; j++)
+ if (glyph->bitmap.buffer[cutleft / 8 + j * glyph->bitmap.pitch]
+ & (1 << (7 - (cutleft & 7))))
+ break;
+ if (j != glyph->bitmap.rows)
+ break;
+ }
+ for (cutright = glyph->bitmap.width - 1; cutright >= 0; cutright--)
+ {
+ for (j = 0; j < glyph->bitmap.rows; j++)
+ if (glyph->bitmap.buffer[cutright / 8 + j * glyph->bitmap.pitch]
+ & (1 << (7 - (cutright & 7))))
+ break;
+ if (j != glyph->bitmap.rows)
+ break;
+ }
+ cutright = glyph->bitmap.width - 1 - cutright;
+ if (cutright + cutleft >= glyph->bitmap.width)
+ cutright = 0;
+ }
+
+ width = glyph->bitmap.width - cutleft - cutright;
+ height = glyph->bitmap.rows - cutbottom - cuttop;
+
+ bitmap_size = ((width * height + 7) / 8);
+ glyph_info = xmalloc (sizeof (struct grub_glyph_info));
+ glyph_info->bitmap = xmalloc (bitmap_size);
+ glyph_info->bitmap_size = bitmap_size;
+
+ glyph_info->next = font_info->glyphs_unsorted;
+ font_info->glyphs_unsorted = glyph_info;
+ font_info->num_glyphs++;
+
+ glyph_info->char_code = char_code;
+ glyph_info->width = width;
+ glyph_info->height = height;
+ glyph_info->x_ofs = glyph->bitmap_left + cutleft;
+ glyph_info->y_ofs = glyph->bitmap_top - height - cuttop;
+ glyph_info->device_width = glyph->metrics.horiAdvance / 64;
+
+ if (width > font_info->max_width)
+ font_info->max_width = width;
+
+ if (height > font_info->max_height)
+ font_info->max_height = height;
+
+ if (glyph_info->y_ofs < font_info->min_y && glyph_info->y_ofs > -font_info->size)
+ font_info->min_y = glyph_info->y_ofs;
+
+ if (glyph_info->y_ofs + height > font_info->max_y)
+ font_info->max_y = glyph_info->y_ofs + height;
+
+ mask = 0;
+ data = &glyph_info->bitmap[0] - 1;
+ for (j = cuttop; j < height + cuttop; j++)
+ for (i = cutleft; i < width + cutleft; i++)
+ add_pixel (&data, &mask,
+ glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
+ (1 << (7 - (i & 7))));
+}
+
+struct glyph_replace *subst_rightjoin, *subst_leftjoin, *subst_medijoin;
+
+struct glyph_replace
+{
+ struct glyph_replace *next;
+ grub_uint32_t from, to;
+};
+
+/* TODO: sort glyph_replace and use binary search if necessary. */
+static void
+add_char (struct grub_font_info *font_info, FT_Face face,
+ grub_uint32_t char_code, int nocut)
+{
+ FT_UInt glyph_idx;
+ struct glyph_replace *cur;
+
+ glyph_idx = FT_Get_Char_Index (face, char_code);
+ if (!glyph_idx)
+ return;
+ add_glyph (font_info, glyph_idx, face, char_code, nocut);
+ for (cur = subst_rightjoin; cur; cur = cur->next)
+ if (cur->from == glyph_idx)
+ {
+ add_glyph (font_info, cur->to, face,
+ char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
+ break;
+ }
+ if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
+ && char_code < GRUB_UNICODE_ARABIC_END)
+ {
+ int i;
+ for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
+ if (grub_unicode_arabic_shapes[i].code == char_code
+ && grub_unicode_arabic_shapes[i].right_linked)
+ {
+ FT_UInt idx2;
+ idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
+ .right_linked);
+ if (idx2)
+ add_glyph (font_info, idx2, face,
+ char_code | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
+ break;
+ }
+
+ }
+
+ for (cur = subst_leftjoin; cur; cur = cur->next)
+ if (cur->from == glyph_idx)
+ {
+ add_glyph (font_info, cur->to, face,
+ char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
+ break;
+ }
+ if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
+ && char_code < GRUB_UNICODE_ARABIC_END)
+ {
+ int i;
+ for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
+ if (grub_unicode_arabic_shapes[i].code == char_code
+ && grub_unicode_arabic_shapes[i].left_linked)
+ {
+ FT_UInt idx2;
+ idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
+ .left_linked);
+ if (idx2)
+ add_glyph (font_info, idx2, face,
+ char_code | GRUB_FONT_CODE_LEFT_JOINED, nocut);
+ break;
+ }
+
+ }
+ for (cur = subst_medijoin; cur; cur = cur->next)
+ if (cur->from == glyph_idx)
+ {
+ add_glyph (font_info, cur->to, face,
+ char_code | GRUB_FONT_CODE_LEFT_JOINED
+ | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
+ break;
+ }
+ if (!cur && char_code >= GRUB_UNICODE_ARABIC_START
+ && char_code < GRUB_UNICODE_ARABIC_END)
+ {
+ int i;
+ for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
+ if (grub_unicode_arabic_shapes[i].code == char_code
+ && grub_unicode_arabic_shapes[i].both_linked)
+ {
+ FT_UInt idx2;
+ idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i]
+ .both_linked);
+ if (idx2)
+ add_glyph (font_info, idx2, face,
+ char_code | GRUB_FONT_CODE_LEFT_JOINED
+ | GRUB_FONT_CODE_RIGHT_JOINED, nocut);
+ break;
+ }
+
+ }
+}
+
+struct gsub_header
+{
+ grub_uint32_t version;
+ grub_uint16_t scripts_off;
+ grub_uint16_t features_off;
+ grub_uint16_t lookups_off;
+} __attribute__ ((packed));
+
+struct gsub_features
+{
+ grub_uint16_t count;
+ struct
+ {
+#define FEATURE_FINA 0x66696e61
+#define FEATURE_INIT 0x696e6974
+#define FEATURE_MEDI 0x6d656469
+#define FEATURE_AALT 0x61616c74
+#define FEATURE_LIGA 0x6c696761
+#define FEATURE_RLIG 0x726c6967
+ grub_uint32_t feature_tag;
+ grub_uint16_t offset;
+ } __attribute__ ((packed)) features[0];
+} __attribute__ ((packed));
+
+struct gsub_feature
+{
+ grub_uint16_t params;
+ grub_uint16_t lookupcount;
+ grub_uint16_t lookupindices[0];
+} __attribute__ ((packed));
+
+struct gsub_lookup_list
+{
+ grub_uint16_t count;
+ grub_uint16_t offsets[0];
+} __attribute__ ((packed));
+
+struct gsub_lookup
+{
+ grub_uint16_t type;
+ grub_uint16_t flag;
+ grub_uint16_t subtablecount;
+ grub_uint16_t subtables[0];
+} __attribute__ ((packed));
+
+struct gsub_substitution
+{
+ grub_uint16_t type;
+ grub_uint16_t coverage_off;
+ union
+ {
+ grub_int16_t delta;
+ struct
+ {
+ grub_int16_t count;
+ grub_uint16_t repl[0];
+ };
+ };
+} __attribute__ ((packed));
+
+struct gsub_coverage_list
+{
+ grub_uint16_t type;
+ grub_uint16_t count;
+ grub_uint16_t glyphs[0];
+} __attribute__ ((packed));
+
+struct gsub_coverage_ranges
+{
+ grub_uint16_t type;
+ grub_uint16_t count;
+ struct
+ {
+ grub_uint16_t start;
+ grub_uint16_t end;
+ grub_uint16_t start_index;
+ } __attribute__ ((packed)) ranges[0];
+} __attribute__ ((packed));
+
+#define GSUB_SINGLE_SUBSTITUTION 1
+
+#define GSUB_SUBSTITUTION_DELTA 1
+#define GSUB_SUBSTITUTION_MAP 2
+
+#define GSUB_COVERAGE_LIST 1
+#define GSUB_COVERAGE_RANGE 2
+
+#define GSUB_RTL_CHAR 1
+
+static void
+add_subst (grub_uint32_t from, grub_uint32_t to, struct glyph_replace **target)
+{
+ struct glyph_replace *new = xmalloc (sizeof (*new));
+ new->next = *target;
+ new->from = from;
+ new->to = to;
+ *target = new;
+}
+
+static void
+process_cursive (struct gsub_feature *feature,
+ struct gsub_lookup_list *lookups,
+ grub_uint32_t feattag)
+{
+ int j, k;
+ int i;
+ struct glyph_replace **target;
+ struct gsub_substitution *sub;
+
+ auto inline void subst (grub_uint32_t glyph);
+ void subst (grub_uint32_t glyph)
+ {
+ grub_uint16_t substtype;
+ substtype = grub_be_to_cpu16 (sub->type);
+
+ if (substtype == GSUB_SUBSTITUTION_DELTA)
+ add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target);
+ else if (i >= grub_be_to_cpu16 (sub->count))
+ printf ("Out of range substitution (%d, %d)\n", i,
+ grub_be_to_cpu16 (sub->count));
+ else
+ add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target);
+ }
+
+ for (j = 0; j < grub_be_to_cpu16 (feature->lookupcount); j++)
+ {
+ int lookup_index = grub_be_to_cpu16 (feature->lookupindices[j]);
+ struct gsub_lookup *lookup;
+ if (lookup_index >= grub_be_to_cpu16 (lookups->count))
+ {
+ printf ("Out of range lookup: %d\n", lookup_index);
+ continue;
+ }
+ lookup = (struct gsub_lookup *)
+ ((grub_uint8_t *) lookups
+ + grub_be_to_cpu16 (lookups->offsets[lookup_index]));
+ if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION)
+ {
+ printf ("Unsupported substitution type: %d\n",
+ grub_be_to_cpu16 (lookup->type));
+ continue;
+ }
+ if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
+ {
+ printf ("Unsupported substitution flag: 0x%x\n",
+ grub_be_to_cpu16 (lookup->flag));
+ }
+ switch (feattag)
+ {
+ case FEATURE_INIT:
+ if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
+ target = &subst_leftjoin;
+ else
+ target = &subst_rightjoin;
+ break;
+ case FEATURE_FINA:
+ if (grub_be_to_cpu16 (lookup->flag) & GSUB_RTL_CHAR)
+ target = &subst_rightjoin;
+ else
+ target = &subst_leftjoin;
+ break;
+ case FEATURE_MEDI:
+ target = &subst_medijoin;
+ break;
+ }
+ for (k = 0; k < grub_be_to_cpu16 (lookup->subtablecount); k++)
+ {
+ sub = (struct gsub_substitution *)
+ ((grub_uint8_t *) lookup + grub_be_to_cpu16 (lookup->subtables[k]));
+ grub_uint16_t substtype;
+ substtype = grub_be_to_cpu16 (sub->type);
+ if (substtype != GSUB_SUBSTITUTION_MAP
+ && substtype != GSUB_SUBSTITUTION_DELTA)
+ {
+ printf ("Unsupported substitution specification: %d\n",
+ substtype);
+ continue;
+ }
+ void *coverage = (grub_uint8_t *) sub
+ + grub_be_to_cpu16 (sub->coverage_off);
+ grub_uint32_t covertype;
+ covertype = grub_be_to_cpu16 (*(grub_uint16_t * __attribute__ ((packed))) coverage);
+ i = 0;
+ if (covertype == GSUB_COVERAGE_LIST)
+ {
+ struct gsub_coverage_list *cover = coverage;
+ int l;
+ for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
+ subst (grub_be_to_cpu16 (cover->glyphs[l]));
+ }
+ else if (covertype == GSUB_COVERAGE_RANGE)
+ {
+ struct gsub_coverage_ranges *cover = coverage;
+ int l, m;
+ for (l = 0; l < grub_be_to_cpu16 (cover->count); l++)
+ for (m = grub_be_to_cpu16 (cover->ranges[l].start);
+ m <= grub_be_to_cpu16 (cover->ranges[l].end); m++)
+ subst (m);
+ }
+ else
+ printf ("Unsupported coverage specification: %d\n", covertype);
+ }
+ }
+}
+
+void
+add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
+{
+ struct gsub_header *gsub = NULL;
+ FT_ULong gsub_len = 0;
+
+ if (!FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, NULL, &gsub_len))
+ {
+ gsub = xmalloc (gsub_len);
+ if (FT_Load_Sfnt_Table (face, TTAG_GSUB, 0, (void *) gsub, &gsub_len))
+ {
+ free (gsub);
+ gsub = NULL;
+ gsub_len = 0;
+ }
+ }
+ if (gsub)
+ {
+ struct gsub_features *features
+ = (struct gsub_features *) (((grub_uint8_t *) gsub)
+ + grub_be_to_cpu16 (gsub->features_off));
+ struct gsub_lookup_list *lookups
+ = (struct gsub_lookup_list *) (((grub_uint8_t *) gsub)
+ + grub_be_to_cpu16 (gsub->lookups_off));
+ int i;
+ int nfeatures = grub_be_to_cpu16 (features->count);
+ for (i = 0; i < nfeatures; i++)
+ {
+ struct gsub_feature *feature = (struct gsub_feature *)
+ ((grub_uint8_t *) features
+ + grub_be_to_cpu16 (features->features[i].offset));
+ grub_uint32_t feattag
+ = grub_be_to_cpu32 (features->features[i].feature_tag);
+ if (feature->params)
+ printf ("WARNING: unsupported feature parameters: %x\n",
+ grub_be_to_cpu16 (feature->params));
+ switch (feattag)
+ {
+ /* Used for retrieving all possible variants. Useless in grub. */
+ case FEATURE_AALT:
+ break;
+
+ /* FIXME: Add ligature support. */
+ case FEATURE_LIGA:
+ case FEATURE_RLIG:
+ break;
+
+ /* Cursive form variants. */
+ case FEATURE_FINA:
+ case FEATURE_INIT:
+ case FEATURE_MEDI:
+ process_cursive (feature, lookups, feattag);
+ break;
+
+ default:
+ {
+ char str[5];
+ int j;
+ memcpy (str, &features->features[i].feature_tag,
+ sizeof (features->features[i].feature_tag));
+ str[4] = 0;
+ for (j = 0; j < 4; j++)
+ if (!grub_isgraph (str[j]))
+ str[j] = '?';
+ printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str);
+ }
+ }
+ }
+ }
+
+ if (font_info->num_range)
+ {
+ int i;
+ grub_uint32_t j;
+
+ for (i = 0; i < font_info->num_range; i++)
+ for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
+ j++)
+ add_char (font_info, face, j, nocut);
+ }
+ else
+ {
+ grub_uint32_t char_code, glyph_index;
+
+ for (char_code = FT_Get_First_Char (face, &glyph_index);
+ glyph_index;
+ char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
+ add_char (font_info, face, char_code, nocut);
+ }
+}
+
+void
+write_string_section (char *name, char *str, int* offset, FILE* file)
+{
+ grub_uint32_t leng, leng_be32;
+
+ leng = strlen (str) + 1;
+ leng_be32 = grub_cpu_to_be32 (leng);
+
+ grub_util_write_image (name, 4, file);
+ grub_util_write_image ((char *) &leng_be32, 4, file);
+ grub_util_write_image (str, leng, file);
+
+ *offset += 8 + leng;
+}
+
+void
+write_be16_section (char *name, grub_uint16_t data, int* offset, FILE* file)
+{
+ grub_uint32_t leng;
+
+ leng = grub_cpu_to_be32 (2);
+ data = grub_cpu_to_be16 (data);
+ grub_util_write_image (name, 4, file);
+ grub_util_write_image ((char *) &leng, 4, file);
+ grub_util_write_image ((char *) &data, 2, file);
+
+ *offset += 10;
+}
+
+void
+print_glyphs (struct grub_font_info *font_info)
+{
+ int num;
+ struct grub_glyph_info *glyph;
+ char line[512];
+
+ for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
+ glyph++, num++)
+ {
+ int x, y, xmax, xmin, ymax, ymin;
+ grub_uint8_t *bitmap, mask;
+
+ printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code);
+ printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
+ glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs,
+ glyph->device_width);
+
+ xmax = glyph->x_ofs + glyph->width;
+ if (xmax < glyph->device_width)
+ xmax = glyph->device_width;
+
+ xmin = glyph->x_ofs;
+ if (xmin > 0)
+ xmin = 0;
+
+ ymax = glyph->y_ofs + glyph->height;
+ if (ymax < font_info->asce)
+ ymax = font_info->asce;
+
+ ymin = glyph->y_ofs;
+ if (ymin > - font_info->desc)
+ ymin = - font_info->desc;
+
+ bitmap = glyph->bitmap;
+ mask = 0x80;
+ for (y = ymax - 1; y >= ymin; y--)
+ {
+ int line_pos;
+
+ line_pos = 0;
+ for (x = xmin; x < xmax; x++)
+ {
+ if ((x >= glyph->x_ofs) &&
+ (x < glyph->x_ofs + glyph->width) &&
+ (y >= glyph->y_ofs) &&
+ (y < glyph->y_ofs + glyph->height))
+ {
+ line[line_pos++] = (*bitmap & mask) ? '#' : '_';
+ mask >>= 1;
+ if (mask == 0)
+ {
+ mask = 0x80;
+ bitmap++;
+ }
+ }
+ else if ((x >= 0) &&
+ (x < glyph->device_width) &&
+ (y >= - font_info->desc) &&
+ (y < font_info->asce))
+ {
+ line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.';
+ }
+ else
+ line[line_pos++] = '*';
+ }
+ line[line_pos] = 0;
+ printf ("%s\n", line);
+ }
+ }
+}
+
+void
+write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file)
+{
+ FILE *file;
+ struct grub_glyph_info *glyph;
+ int num;
+
+ file = fopen (output_file, "wb");
+ if (! file)
+ grub_util_error ("Can\'t write to file %s.", output_file);
+
+ int correct_size;
+ for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs;
+ glyph++, num++)
+ {
+ correct_size = 1;
+ if (glyph->width != 8 || glyph->height != 16)
+ {
+ /* printf ("Width or height from glyph U+%04x not supported, skipping.\n", glyph->char_code); */
+ correct_size = 0;
+ }
+ int row;
+ for (row = 0; row < glyph->height; row++)
+ {
+ if (correct_size)
+ fwrite (&glyph->bitmap[row], sizeof(glyph->bitmap[row]), 1, file);
+ else
+ fwrite (&correct_size, 1, 1, file);
+ }
+ }
+ fclose (file);
+}
+
+void
+write_font_width_spec (struct grub_font_info *font_info, char *output_file)
+{
+ FILE *file;
+ struct grub_glyph_info *glyph;
+ grub_uint8_t *out;
+
+ out = xmalloc (8192);
+ memset (out, 0, 8192);
+
+ file = fopen (output_file, "wb");
+ if (! file)
+ grub_util_error ("Can\'t write to file %s.", output_file);
+
+ for (glyph = font_info->glyphs_sorted;
+ glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++)
+ if (glyph->width > 12)
+ out[glyph->char_code >> 3] |= (1 << (glyph->char_code & 7));
+
+ fwrite (out, 8192, 1, file);
+ fclose (file);
+ free (out);
+}
+
+void
+write_font_pf2 (struct grub_font_info *font_info, char *output_file)
+{
+ FILE *file;
+ grub_uint32_t leng;
+ char style_name[20], *font_name;
+ int offset;
+ struct grub_glyph_info *cur;
+
+ file = fopen (output_file, "wb");
+ if (! file)
+ grub_util_error ("can\'t write to file %s.", output_file);
+
+ offset = 0;
+
+ leng = grub_cpu_to_be32 (4);
+ grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE,
+ sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file);
+ grub_util_write_image ((char *) &leng, 4, file);
+ grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file);
+ offset += 12;
+
+ if (! font_info->name)
+ font_info->name = "Unknown";
+
+ if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+ font_info->style |= FT_STYLE_FLAG_BOLD;
+
+ style_name[0] = 0;
+ if (font_info->style & FT_STYLE_FLAG_BOLD)
+ strcpy (style_name, " Bold");
+
+ if (font_info->style & FT_STYLE_FLAG_ITALIC)
+ strcat (style_name, " Italic");
+
+ if (! style_name[0])
+ strcpy (style_name, " Regular");
+
+ font_name = xasprintf ("%s %s %d", font_info->name, &style_name[1],
+ font_info->size);
+
+ write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME,
+ font_name, &offset, file);
+ write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY,
+ font_info->name, &offset, file);
+ write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT,
+ (font_info->style & FT_STYLE_FLAG_BOLD) ?
+ "bold" : "normal",
+ &offset, file);
+ write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN,
+ (font_info->style & FT_STYLE_FLAG_ITALIC) ?
+ "italic" : "normal",
+ &offset, file);
+
+ write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
+ font_info->size, &offset, file);
+ write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
+ font_info->max_width, &offset, file);
+ write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
+ font_info->max_height, &offset, file);
+
+ if (! font_info->desc)
+ {
+ if (font_info->min_y >= 0)
+ font_info->desc = 1;
+ else
+ font_info->desc = - font_info->min_y;
+ }
+
+ if (! font_info->asce)
+ {
+ if (font_info->max_y <= 0)
+ font_info->asce = 1;
+ else
+ font_info->asce = font_info->max_y;
+ }
+
+ write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT,
+ font_info->asce, &offset, file);
+ write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT,
+ font_info->desc, &offset, file);
+
+ if (font_verbosity > 0)
+ {
+ printf ("Font name: %s\n", font_name);
+ printf ("Max width: %d\n", font_info->max_width);
+ printf ("Max height: %d\n", font_info->max_height);
+ printf ("Font ascent: %d\n", font_info->asce);
+ printf ("Font descent: %d\n", font_info->desc);
+ }
+
+ if (font_verbosity > 0)
+ printf ("Number of glyph: %d\n", font_info->num_glyphs);
+
+ leng = grub_cpu_to_be32 (font_info->num_glyphs * 9);
+ grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
+ sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1,
+ file);
+ grub_util_write_image ((char *) &leng, 4, file);
+ offset += 8 + font_info->num_glyphs * 9 + 8;
+
+ for (cur = font_info->glyphs_sorted;
+ cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
+ {
+ grub_uint32_t data32;
+ grub_uint8_t data8;
+ data32 = grub_cpu_to_be32 (cur->char_code);
+ grub_util_write_image ((char *) &data32, 4, file);
+ data8 = 0;
+ grub_util_write_image ((char *) &data8, 1, file);
+ data32 = grub_cpu_to_be32 (offset);
+ grub_util_write_image ((char *) &data32, 4, file);
+ offset += 10 + cur->bitmap_size;
+ }
+
+ leng = 0xffffffff;
+ grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA,
+ sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file);
+ grub_util_write_image ((char *) &leng, 4, file);
+
+ for (cur = font_info->glyphs_sorted;
+ cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++)
+ {
+ grub_uint16_t data;
+ data = grub_cpu_to_be16 (cur->width);
+ grub_util_write_image ((char *) &data, 2, file);
+ data = grub_cpu_to_be16 (cur->height);
+ grub_util_write_image ((char *) &data, 2, file);
+ data = grub_cpu_to_be16 (cur->x_ofs);
+ grub_util_write_image ((char *) &data, 2, file);
+ data = grub_cpu_to_be16 (cur->y_ofs);
+ grub_util_write_image ((char *) &data, 2, file);
+ data = grub_cpu_to_be16 (cur->device_width);
+ grub_util_write_image ((char *) &data, 2, file);
+ grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file);
+ }
+
+ fclose (file);
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct grub_font_info font_info;
+ FT_Library ft_lib;
+ int font_index = 0;
+ int font_size = 0;
+ char *output_file = NULL;
+ enum file_formats file_format = PF2;
+
+ memset (&font_info, 0, sizeof (font_info));
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'b':
+ font_info.flags |= GRUB_FONT_FLAG_BOLD;
+ break;
+
+ case 0x100:
+ font_info.flags |= GRUB_FONT_FLAG_NOBITMAP;
+ break;
+
+ case 0x101:
+ font_info.flags |= GRUB_FONT_FLAG_NOHINTING;
+ break;
+
+ case 'a':
+ font_info.flags |= GRUB_FONT_FLAG_FORCEHINT;
+ break;
+
+ case 'o':
+ output_file = optarg;
+ break;
+
+ case 'n':
+ font_info.name = optarg;
+ break;
+
+ case 'i':
+ font_index = strtoul (optarg, NULL, 0);
+ break;
+
+ case 's':
+ font_size = strtoul (optarg, NULL, 0);
+ break;
+
+ case 'r':
+ {
+ char *p = optarg;
+
+ while (1)
+ {
+ grub_uint32_t a, b;
+
+ a = strtoul (p, &p, 0);
+ if (*p != '-')
+ grub_util_error ("invalid font range");
+ b = strtoul (p + 1, &p, 0);
+ if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
+ font_info.ranges = xrealloc (font_info.ranges,
+ (font_info.num_range +
+ GRUB_FONT_RANGE_BLOCK) *
+ sizeof (grub_uint32_t) * 2);
+
+ font_info.ranges[font_info.num_range * 2] = a;
+ font_info.ranges[font_info.num_range * 2 + 1] = b;
+ font_info.num_range++;
+
+ if (*p)
+ {
+ if (*p != ',')
+ grub_util_error ("invalid font range");
+ else
+ p++;
+ }
+ else
+ break;
+ }
+ break;
+ }
+
+ case 'd':
+ font_info.desc = strtoul (optarg, NULL, 0);
+ break;
+
+ case 'e':
+ font_info.asce = strtoul (optarg, NULL, 0);
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ font_verbosity++;
+ break;
+
+ case 0x102:
+ file_format = ASCII_BITMAPS;
+ break;
+
+ case 0x103:
+ file_format = WIDTH_SPEC;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (file_format == ASCII_BITMAPS && font_info.num_range > 0)
+ {
+ grub_util_error ("Option --ascii-bitmaps doesn't accept ranges (use ASCII).");
+ return 1;
+ }
+
+ else if (file_format == ASCII_BITMAPS)
+ {
+ font_info.ranges = xrealloc (font_info.ranges,
+ GRUB_FONT_RANGE_BLOCK *
+ sizeof (grub_uint32_t) * 2);
+
+ font_info.ranges[0] = (grub_uint32_t) 0x00;
+ font_info.ranges[1] = (grub_uint32_t) 0x7f;
+ font_info.num_range = 1;
+ }
+
+ if (! output_file)
+ grub_util_error ("no output file is specified");
+
+ if (FT_Init_FreeType (&ft_lib))
+ grub_util_error ("FT_Init_FreeType fails");
+
+ for (; optind < argc; optind++)
+ {
+ FT_Face ft_face;
+ int size;
+ FT_Error err;
+
+ err = FT_New_Face (ft_lib, argv[optind], font_index, &ft_face);
+ if (err)
+ {
+ grub_printf ("can't open file %s, index %d: error %d", argv[optind],
+ font_index, err);
+ if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
+ printf (": %s\n", ft_errmsgs[err]);
+ else
+ printf ("\n");
+
+ continue;
+ }
+
+ if ((! font_info.name) && (ft_face->family_name))
+ font_info.name = xstrdup (ft_face->family_name);
+
+ size = font_size;
+ if (! size)
+ {
+ if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) ||
+ (! ft_face->num_fixed_sizes))
+ size = GRUB_FONT_DEFAULT_SIZE;
+ else
+ size = ft_face->available_sizes[0].height;
+ }
+
+ font_info.style = ft_face->style_flags;
+ font_info.size = size;
+
+ if (FT_Set_Pixel_Sizes (ft_face, size, size))
+ grub_util_error ("can't set %dx%d font size", size, size);
+ add_font (&font_info, ft_face, file_format != PF2);
+ FT_Done_Face (ft_face);
+ }
+
+ FT_Done_FreeType (ft_lib);
+
+ {
+ int counter[65537];
+ struct grub_glyph_info *tmp, *cur;
+ int i;
+
+ memset (counter, 0, sizeof (counter));
+
+ for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
+ counter[(cur->char_code & 0xffff) + 1]++;
+ for (i = 0; i < 0x10000; i++)
+ counter[i+1] += counter[i];
+ tmp = xmalloc (font_info.num_glyphs
+ * sizeof (tmp[0]));
+ for (cur = font_info.glyphs_unsorted; cur; cur = cur->next)
+ tmp[counter[(cur->char_code & 0xffff)]++] = *cur;
+
+ memset (counter, 0, sizeof (counter));
+
+ for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
+ counter[((cur->char_code & 0xffff0000) >> 16) + 1]++;
+ for (i = 0; i < 0x10000; i++)
+ counter[i+1] += counter[i];
+ font_info.glyphs_sorted = xmalloc (font_info.num_glyphs
+ * sizeof (font_info.glyphs_sorted[0]));
+ for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++)
+ font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) >> 16]++]
+ = *cur;
+ free (tmp);
+ }
+
+ switch (file_format)
+ {
+ case PF2:
+ write_font_pf2 (&font_info, output_file);
+ break;
+
+ case ASCII_BITMAPS:
+ write_font_ascii_bitmap (&font_info, output_file);
+ break;
+
+ case WIDTH_SPEC:
+ write_font_width_spec (&font_info, output_file);
+ break;
+ }
+
+ if (font_verbosity > 1)
+ print_glyphs (&font_info);
+
+ return 0;
+}
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
new file mode 100644
index 0000000..5e964a3
--- /dev/null
+++ b/util/grub-mkimage.c
@@ -0,0 +1,1620 @@
+/* grub-mkimage.c - make a bootable image */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/elf.h>
+#include <grub/aout.h>
+#include <grub/i18n.h>
+#include <grub/kernel.h>
+#include <grub/disk.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/misc.h>
+#include <grub/offsets.h>
+#include <grub/crypto.h>
+#include <time.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <grub/efi/pe32.h>
+
+#define _GNU_SOURCE 1
+#include <getopt.h>
+
+#include "progname.h"
+
+#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
+
+#ifdef HAVE_LIBLZMA
+#include <lzma.h>
+#endif
+
+#define TARGET_NO_FIELD 0xffffffff
+
+typedef enum {
+ COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ
+} grub_compression_t;
+
+struct image_target_desc
+{
+ const char *name;
+ grub_size_t voidp_sizeof;
+ int bigendian;
+ enum {
+ IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
+ IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275,
+ IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
+ IMAGE_I386_PC_PXE
+ } id;
+ enum
+ {
+ PLATFORM_FLAGS_NONE = 0,
+ PLATFORM_FLAGS_LZMA = 1,
+ PLATFORM_FLAGS_DECOMPRESSORS = 2
+ } flags;
+ unsigned prefix;
+ unsigned prefix_end;
+ unsigned raw_size;
+ unsigned total_module_size;
+ unsigned kernel_image_size;
+ unsigned compressed_size;
+ unsigned link_align;
+ grub_uint16_t elf_target;
+ unsigned section_align;
+ signed vaddr_offset;
+ unsigned install_dos_part, install_bsd_part;
+ grub_uint64_t link_addr;
+ unsigned mod_gap, mod_align;
+ grub_compression_t default_compression;
+};
+
+struct image_target_desc image_targets[] =
+ {
+ {
+ .name = "i386-coreboot",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_COREBOOT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_I386_COREBOOT_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_COREBOOT_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
+ .elf_target = EM_386,
+ .link_align = 4,
+ .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
+ .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
+ },
+ {
+ .name = "i386-multiboot",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_COREBOOT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_I386_MULTIBOOT_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
+ .elf_target = EM_386,
+ .link_align = 4,
+ .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
+ .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
+ },
+ {
+ .name = "i386-pc",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_PC,
+ .flags = PLATFORM_FLAGS_LZMA,
+ .prefix = GRUB_KERNEL_I386_PC_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END,
+ .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE,
+ .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE,
+ .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE,
+ .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART,
+ .install_bsd_part = GRUB_KERNEL_I386_PC_INSTALL_BSD_PART,
+ .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR
+ },
+ {
+ .name = "i386-pc-pxe",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_PC_PXE,
+ .flags = PLATFORM_FLAGS_LZMA,
+ .prefix = GRUB_KERNEL_I386_PC_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END,
+ .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE,
+ .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE,
+ .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE,
+ .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART,
+ .install_bsd_part = GRUB_KERNEL_I386_PC_INSTALL_BSD_PART,
+ .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR
+ },
+ {
+ .name = "i386-efi",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_I386_EFI_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_EFI_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
+ + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header)
+ + sizeof (struct grub_pe32_optional_header)
+ + 4 * sizeof (struct grub_pe32_section_table),
+ GRUB_PE32_SECTION_ALIGNMENT),
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ },
+ {
+ .name = "i386-ieee1275",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_IEEE1275,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_I386_IEEE1275_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_IEEE1275_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR,
+ .elf_target = EM_386,
+ .mod_gap = GRUB_KERNEL_I386_IEEE1275_MOD_GAP,
+ .mod_align = GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN,
+ .link_align = 4,
+ },
+ {
+ .name = "i386-qemu",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_QEMU,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_I386_QEMU_PREFIX,
+ .prefix_end = GRUB_KERNEL_I386_QEMU_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
+ },
+ {
+ .name = "x86_64-efi",
+ .voidp_sizeof = 8,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_X86_64_EFI_PREFIX,
+ .prefix_end = GRUB_KERNEL_X86_64_EFI_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
+ + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header)
+ + sizeof (struct grub_pe64_optional_header)
+ + 4 * sizeof (struct grub_pe32_section_table),
+ GRUB_PE32_SECTION_ALIGNMENT),
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ },
+ {
+ .name = "mipsel-yeeloong-flash",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_YEELOONG_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
+ .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .name = "mipsel-yeeloong-elf",
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_YEELOONG_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
+ .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
+ .compressed_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
+ .default_compression = COMPRESSION_NONE
+ },
+ {
+ .name = "powerpc-ieee1275",
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_PPC,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX,
+ .prefix_end = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END,
+ .raw_size = 0,
+ .total_module_size = TARGET_NO_FIELD,
+ .kernel_image_size = TARGET_NO_FIELD,
+ .compressed_size = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR,
+ .elf_target = EM_PPC,
+ .mod_gap = GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP,
+ .mod_align = GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN,
+ .link_align = 4
+ },
+ {
+ .name = "sparc64-ieee1275-raw",
+ .voidp_sizeof = 8,
+ .bigendian = 1,
+ .id = IMAGE_SPARC64_RAW,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX,
+ .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END,
+ .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE,
+ .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
+ .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE,
+ .compressed_size = GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
+ },
+ {
+ .name = "sparc64-ieee1275-aout",
+ .voidp_sizeof = 8,
+ .bigendian = 1,
+ .id = IMAGE_SPARC64_AOUT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX,
+ .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END,
+ .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE,
+ .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
+ .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE,
+ .compressed_size = GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .install_dos_part = TARGET_NO_FIELD,
+ .install_bsd_part = TARGET_NO_FIELD,
+ .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
+ },
+ };
+
+#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
+#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
+#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
+#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
+#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
+#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
+#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
+
+static inline grub_uint32_t
+grub_target_to_host32_real (struct image_target_desc *image_target, grub_uint32_t in)
+{
+ if (image_target->bigendian)
+ return grub_be_to_cpu32 (in);
+ else
+ return grub_le_to_cpu32 (in);
+}
+
+static inline grub_uint64_t
+grub_target_to_host64_real (struct image_target_desc *image_target, grub_uint64_t in)
+{
+ if (image_target->bigendian)
+ return grub_be_to_cpu64 (in);
+ else
+ return grub_le_to_cpu64 (in);
+}
+
+static inline grub_uint64_t
+grub_host_to_target64_real (struct image_target_desc *image_target, grub_uint64_t in)
+{
+ if (image_target->bigendian)
+ return grub_cpu_to_be64 (in);
+ else
+ return grub_cpu_to_le64 (in);
+}
+
+static inline grub_uint32_t
+grub_host_to_target32_real (struct image_target_desc *image_target, grub_uint32_t in)
+{
+ if (image_target->bigendian)
+ return grub_cpu_to_be32 (in);
+ else
+ return grub_cpu_to_le32 (in);
+}
+
+static inline grub_uint16_t
+grub_target_to_host16_real (struct image_target_desc *image_target, grub_uint16_t in)
+{
+ if (image_target->bigendian)
+ return grub_be_to_cpu16 (in);
+ else
+ return grub_le_to_cpu16 (in);
+}
+
+static inline grub_uint16_t
+grub_host_to_target16_real (struct image_target_desc *image_target, grub_uint16_t in)
+{
+ if (image_target->bigendian)
+ return grub_cpu_to_be16 (in);
+ else
+ return grub_cpu_to_le16 (in);
+}
+
+static inline grub_uint64_t
+grub_host_to_target_addr_real (struct image_target_desc *image_target, grub_uint64_t in)
+{
+ if (image_target->voidp_sizeof == 8)
+ return grub_host_to_target64_real (image_target, in);
+ else
+ return grub_host_to_target32_real (image_target, in);
+}
+
+static inline grub_uint64_t
+grub_target_to_host_real (struct image_target_desc *image_target, grub_uint64_t in)
+{
+ if (image_target->voidp_sizeof == 8)
+ return grub_target_to_host64_real (image_target, in);
+ else
+ return grub_target_to_host32_real (image_target, in);
+}
+
+#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
+#define GRUB_IEEE1275_NOTE_TYPE 0x1275
+
+/* These structures are defined according to the CHRP binding to IEEE1275,
+ "Client Program Format" section. */
+
+struct grub_ieee1275_note_hdr
+{
+ grub_uint32_t namesz;
+ grub_uint32_t descsz;
+ grub_uint32_t type;
+ char name[sizeof (GRUB_IEEE1275_NOTE_NAME)];
+};
+
+struct grub_ieee1275_note_desc
+{
+ grub_uint32_t real_mode;
+ grub_uint32_t real_base;
+ grub_uint32_t real_size;
+ grub_uint32_t virt_base;
+ grub_uint32_t virt_size;
+ grub_uint32_t load_base;
+};
+
+struct grub_ieee1275_note
+{
+ struct grub_ieee1275_note_hdr header;
+ struct grub_ieee1275_note_desc descriptor;
+};
+
+#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
+
+#include <grub/lib/LzmaEnc.h>
+
+static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); }
+static void SzFree(void *p, void *address) { p = p; free(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+static void
+compress_kernel_lzma (char *kernel_img, size_t kernel_size,
+ char **core_img, size_t *core_size, size_t raw_size)
+{
+ CLzmaEncProps props;
+ unsigned char out_props[5];
+ size_t out_props_size = 5;
+
+ LzmaEncProps_Init(&props);
+ props.dictSize = 1 << 16;
+ props.lc = 3;
+ props.lp = 0;
+ props.pb = 2;
+ props.numThreads = 1;
+
+ if (kernel_size < raw_size)
+ grub_util_error (_("the core image is too small"));
+
+ *core_img = xmalloc (kernel_size);
+ memcpy (*core_img, kernel_img, raw_size);
+
+ *core_size = kernel_size - raw_size;
+ if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size,
+ (unsigned char *) kernel_img + raw_size,
+ kernel_size - raw_size,
+ &props, out_props, &out_props_size,
+ 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
+ grub_util_error (_("cannot compress the kernel image"));
+
+ *core_size += raw_size;
+}
+
+#ifdef HAVE_LIBLZMA
+static void
+compress_kernel_xz (char *kernel_img, size_t kernel_size,
+ char **core_img, size_t *core_size, size_t raw_size)
+{
+ lzma_stream strm = LZMA_STREAM_INIT;
+ lzma_ret xzret;
+ lzma_options_lzma lzopts = {
+ .dict_size = 1 << 16,
+ .preset_dict = NULL,
+ .preset_dict_size = 0,
+ .lc = 3,
+ .lp = 0,
+ .pb = 2,
+ .mode = LZMA_MODE_NORMAL,
+ .nice_len = 64,
+ .mf = LZMA_MF_BT4,
+ .depth = 0,
+ };
+ lzma_filter fltrs[] = {
+ { .id = LZMA_FILTER_LZMA2, .options = &lzopts},
+ { .id = LZMA_VLI_UNKNOWN, .options = NULL}
+ };
+
+ if (kernel_size < raw_size)
+ grub_util_error (_("the core image is too small"));
+
+ xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
+ if (xzret != LZMA_OK)
+ grub_util_error (_("cannot compress the kernel image"));
+
+ *core_img = xmalloc (kernel_size);
+ memcpy (*core_img, kernel_img, raw_size);
+
+ *core_size = kernel_size - raw_size;
+ strm.next_in = (unsigned char *) kernel_img + raw_size;
+ strm.avail_in = kernel_size - raw_size;
+ strm.next_out = (unsigned char *) *core_img + raw_size;
+ strm.avail_out = *core_size;
+
+ while (1)
+ {
+ xzret = lzma_code (&strm, LZMA_FINISH);
+ if (xzret == LZMA_OK)
+ continue;
+ if (xzret == LZMA_STREAM_END)
+ break;
+ grub_util_error (_("cannot compress the kernel image"));
+ }
+
+ *core_size -= strm.avail_out;
+
+ *core_size += raw_size;
+}
+#endif
+
+static void
+compress_kernel (struct image_target_desc *image_target, char *kernel_img,
+ size_t kernel_size, char **core_img, size_t *core_size,
+ grub_compression_t comp)
+{
+ if (image_target->flags & PLATFORM_FLAGS_LZMA)
+ {
+ compress_kernel_lzma (kernel_img, kernel_size, core_img,
+ core_size, image_target->raw_size);
+ return;
+ }
+
+#ifdef HAVE_LIBLZMA
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
+ && (comp == COMPRESSION_XZ))
+ {
+ compress_kernel_xz (kernel_img, kernel_size, core_img,
+ core_size, image_target->raw_size);
+ return;
+ }
+#endif
+
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
+ && (comp != COMPRESSION_NONE))
+ grub_util_error ("unknown compression %d\n", comp);
+
+ *core_img = xmalloc (kernel_size);
+ memcpy (*core_img, kernel_img, kernel_size);
+ *core_size = kernel_size;
+}
+
+struct fixup_block_list
+{
+ struct fixup_block_list *next;
+ int state;
+ struct grub_pe32_fixup_block b;
+};
+
+#define MKIMAGE_ELF32 1
+#include "grub-mkimagexx.c"
+#undef MKIMAGE_ELF32
+
+#define MKIMAGE_ELF64 1
+#include "grub-mkimagexx.c"
+#undef MKIMAGE_ELF64
+
+static void
+generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
+ char *memdisk_path, char *config_path,
+ struct image_target_desc *image_target, int note,
+ grub_compression_t comp)
+{
+ char *kernel_img, *core_img;
+ size_t kernel_size, total_module_size, core_size, exec_size;
+ size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
+ char *kernel_path;
+ size_t offset;
+ struct grub_util_path_list *path_list, *p, *next;
+ grub_size_t bss_size;
+ grub_uint64_t start_address;
+ void *rel_section;
+ grub_size_t reloc_size, align;
+
+ if (comp == COMPRESSION_AUTO)
+ comp = image_target->default_compression;
+
+ path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+ kernel_path = grub_util_get_path (dir, "kernel.img");
+
+ if (image_target->voidp_sizeof == 8)
+ total_module_size = sizeof (struct grub_module_info64);
+ else
+ total_module_size = sizeof (struct grub_module_info32);
+
+ if (memdisk_path)
+ {
+ memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
+ grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+ total_module_size += memdisk_size + sizeof (struct grub_module_header);
+ }
+
+ if (config_path)
+ {
+ config_size_pure = grub_util_get_image_size (config_path) + 1;
+ config_size = ALIGN_ADDR (config_size_pure);
+ grub_util_info ("the size of config file is 0x%x", config_size);
+ total_module_size += config_size + sizeof (struct grub_module_header);
+ }
+
+ for (p = path_list; p; p = p->next)
+ total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
+ + sizeof (struct grub_module_header));
+
+ grub_util_info ("the total module size is 0x%x", total_module_size);
+
+ if (image_target->voidp_sizeof == 4)
+ kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
+ total_module_size, &start_address, &rel_section,
+ &reloc_size, &align, image_target);
+ else
+ kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
+ total_module_size, &start_address, &rel_section,
+ &reloc_size, &align, image_target);
+
+ if (image_target->prefix + strlen (prefix) + 1 > image_target->prefix_end)
+ grub_util_error (_("prefix is too long"));
+ strcpy (kernel_img + image_target->prefix, prefix);
+
+ if (image_target->voidp_sizeof == 8)
+ {
+ /* Fill in the grub_module_info structure. */
+ struct grub_module_info64 *modinfo;
+ modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
+ memset (modinfo, 0, sizeof (struct grub_module_info64));
+ modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
+ modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
+ modinfo->size = grub_host_to_target_addr (total_module_size);
+ offset = kernel_size + sizeof (struct grub_module_info64);
+ }
+ else
+ {
+ /* Fill in the grub_module_info structure. */
+ struct grub_module_info32 *modinfo;
+ modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
+ memset (modinfo, 0, sizeof (struct grub_module_info32));
+ modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
+ modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
+ modinfo->size = grub_host_to_target_addr (total_module_size);
+ offset = kernel_size + sizeof (struct grub_module_info32);
+ }
+
+ for (p = path_list; p; p = p->next)
+ {
+ struct grub_module_header *header;
+ size_t mod_size, orig_size;
+
+ orig_size = grub_util_get_image_size (p->name);
+ mod_size = ALIGN_ADDR (orig_size);
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
+ header->size = grub_host_to_target32 (mod_size + sizeof (*header));
+ offset += sizeof (*header);
+ memset (kernel_img + offset + orig_size, 0, mod_size - orig_size);
+
+ grub_util_load_image (p->name, kernel_img + offset);
+ offset += mod_size;
+ }
+
+ if (memdisk_path)
+ {
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK);
+ header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_util_load_image (memdisk_path, kernel_img + offset);
+ offset += memdisk_size;
+ }
+
+ if (config_path)
+ {
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG);
+ header->size = grub_host_to_target32 (config_size + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_util_load_image (config_path, kernel_img + offset);
+ *(kernel_img + offset + config_size_pure - 1) = 0;
+ offset += config_size;
+ }
+
+ if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ && (image_target->total_module_size != TARGET_NO_FIELD))
+ *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
+ = grub_host_to_target32 (total_module_size);
+
+ grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
+ compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
+ &core_img, &core_size, comp);
+
+ grub_util_info ("the core size is 0x%x", core_size);
+
+ if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ && image_target->total_module_size != TARGET_NO_FIELD)
+ *((grub_uint32_t *) (core_img + image_target->total_module_size))
+ = grub_host_to_target32 (total_module_size);
+ if (image_target->kernel_image_size != TARGET_NO_FIELD)
+ *((grub_uint32_t *) (core_img + image_target->kernel_image_size))
+ = grub_host_to_target32 (kernel_size);
+ if (image_target->compressed_size != TARGET_NO_FIELD)
+ *((grub_uint32_t *) (core_img + image_target->compressed_size))
+ = grub_host_to_target32 (core_size - image_target->raw_size);
+
+ /* If we included a drive in our prefix, let GRUB know it doesn't have to
+ prepend the drive told by BIOS. */
+ if (image_target->install_dos_part != TARGET_NO_FIELD
+ && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(')
+ {
+ *((grub_int32_t *) (core_img + image_target->install_dos_part))
+ = grub_host_to_target32 (-2);
+ *((grub_int32_t *) (core_img + image_target->install_bsd_part))
+ = grub_host_to_target32 (-2);
+ }
+
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ {
+ char *full_img;
+ size_t full_size;
+ char *decompress_path, *decompress_img;
+ size_t decompress_size;
+ const char *name;
+
+ switch (comp)
+ {
+ case COMPRESSION_XZ:
+ name = "xz_decompress.img";
+ break;
+ case COMPRESSION_NONE:
+ name = "none_decompress.img";
+ break;
+ default:
+ grub_util_error ("unknown compression %d\n", comp);
+ }
+
+ decompress_path = grub_util_get_path (dir, name);
+ decompress_size = grub_util_get_image_size (decompress_path);
+ decompress_img = grub_util_read_image (decompress_path);
+
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE))
+ = grub_host_to_target32 (core_size);
+
+ *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE))
+ = grub_host_to_target32 (kernel_size + total_module_size);
+
+ full_size = core_size + decompress_size;
+
+ full_img = xmalloc (full_size);
+ memset (full_img, 0, full_size);
+
+ memcpy (full_img, decompress_img, decompress_size);
+
+ memcpy (full_img + decompress_size, core_img, core_size);
+
+ memset (full_img + decompress_size + core_size, 0,
+ full_size - (decompress_size + core_size));
+
+ free (core_img);
+ core_img = full_img;
+ core_size = full_size;
+ }
+
+ switch (image_target->id)
+ {
+ case IMAGE_I386_PC:
+ case IMAGE_I386_PC_PXE:
+ {
+ unsigned num;
+ char *boot_path, *boot_img;
+ size_t boot_size;
+
+ if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > GRUB_MEMORY_I386_PC_UPPER)
+ grub_util_error (_("core image is too big (%p > %p)"),
+ GRUB_KERNEL_I386_PC_LINK_ADDR + core_size,
+ GRUB_MEMORY_I386_PC_UPPER);
+
+ num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+ if (num > 0xffff)
+ grub_util_error (_("the core image is too big"));
+
+ if (image_target->id == IMAGE_I386_PC_PXE)
+ {
+ char *pxeboot_path, *pxeboot_img;
+ size_t pxeboot_size;
+
+ pxeboot_path = grub_util_get_path (dir, "pxeboot.img");
+ pxeboot_size = grub_util_get_image_size (pxeboot_path);
+ pxeboot_img = grub_util_read_image (pxeboot_path);
+
+ grub_util_write_image (pxeboot_img, pxeboot_size, out);
+ free (pxeboot_img);
+ free (pxeboot_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)
+ grub_util_error (_("diskboot.img size must be %u bytes"),
+ GRUB_DISK_SECTOR_SIZE);
+
+ boot_img = grub_util_read_image (boot_path);
+
+ {
+ struct grub_pc_bios_boot_blocklist *block;
+ block = (struct grub_pc_bios_boot_blocklist *) (boot_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*block));
+ block->len = grub_host_to_target16 (num);
+
+ /* This is filled elsewhere. Verify it just in case. */
+ assert (block->segment
+ == grub_host_to_target16 (GRUB_BOOT_I386_PC_KERNEL_SEG
+ + (GRUB_DISK_SECTOR_SIZE >> 4)));
+ }
+
+ grub_util_write_image (boot_img, boot_size, out);
+ free (boot_img);
+ free (boot_path);
+ }
+ break;
+ case IMAGE_EFI:
+ {
+ void *pe_img;
+ grub_uint8_t *header;
+ void *sections;
+ size_t pe_size;
+ struct grub_pe32_coff_header *c;
+ struct grub_pe32_section_table *text_section, *data_section;
+ struct grub_pe32_section_table *mods_section, *reloc_section;
+ static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
+ int header_size;
+ int reloc_addr;
+
+ if (image_target->voidp_sizeof == 4)
+ header_size = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
+ + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header)
+ + sizeof (struct grub_pe32_optional_header)
+ + 4 * sizeof (struct grub_pe32_section_table),
+ GRUB_PE32_SECTION_ALIGNMENT);
+ else
+ header_size = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
+ + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header)
+ + sizeof (struct grub_pe64_optional_header)
+ + 4 * sizeof (struct grub_pe32_section_table),
+ GRUB_PE32_SECTION_ALIGNMENT);
+
+ reloc_addr = ALIGN_UP (header_size + core_size,
+ image_target->section_align);
+
+ pe_size = ALIGN_UP (reloc_addr + reloc_size,
+ image_target->section_align);
+ pe_img = xmalloc (reloc_addr + reloc_size);
+ memset (pe_img, 0, header_size);
+ memcpy (pe_img + header_size, core_img, core_size);
+ memcpy (pe_img + reloc_addr, rel_section, reloc_size);
+ header = pe_img;
+
+ /* The magic. */
+ memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
+ memcpy (header + GRUB_PE32_MSDOS_STUB_SIZE, "PE\0\0",
+ GRUB_PE32_SIGNATURE_SIZE);
+
+ /* The COFF file header. */
+ c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
+ + GRUB_PE32_SIGNATURE_SIZE);
+ if (image_target->voidp_sizeof == 4)
+ c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_I386);
+ else
+ c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_X86_64);
+
+ c->num_sections = grub_host_to_target16 (4);
+ c->time = grub_host_to_target32 (time (0));
+ c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
+ | GRUB_PE32_LINE_NUMS_STRIPPED
+ | ((image_target->voidp_sizeof == 4)
+ ? GRUB_PE32_32BIT_MACHINE
+ : 0)
+ | GRUB_PE32_LOCAL_SYMS_STRIPPED
+ | GRUB_PE32_DEBUG_STRIPPED);
+
+ /* The PE Optional header. */
+ if (image_target->voidp_sizeof == 4)
+ {
+ struct grub_pe32_optional_header *o;
+
+ c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
+
+ o = (struct grub_pe32_optional_header *)
+ (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header));
+ o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
+ o->code_size = grub_host_to_target32 (exec_size);
+ o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
+ - header_size);
+ o->bss_size = grub_cpu_to_le32 (bss_size);
+ o->entry_addr = grub_cpu_to_le32 (start_address);
+ o->code_base = grub_cpu_to_le32 (header_size);
+
+ o->data_base = grub_host_to_target32 (header_size + exec_size);
+
+ o->image_base = 0;
+ o->section_alignment = grub_host_to_target32 (image_target->section_align);
+ o->file_alignment = grub_host_to_target32 (image_target->section_align);
+ o->image_size = grub_host_to_target32 (pe_size);
+ o->header_size = grub_host_to_target32 (header_size);
+ o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+
+ /* Do these really matter? */
+ o->stack_reserve_size = grub_host_to_target32 (0x10000);
+ o->stack_commit_size = grub_host_to_target32 (0x10000);
+ o->heap_reserve_size = grub_host_to_target32 (0x10000);
+ o->heap_commit_size = grub_host_to_target32 (0x10000);
+
+ o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+
+ o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
+ o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
+ sections = o + 1;
+ }
+ else
+ {
+ struct grub_pe64_optional_header *o;
+
+ c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
+
+ o = (struct grub_pe64_optional_header *)
+ (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ + sizeof (struct grub_pe32_coff_header));
+ o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
+ o->code_size = grub_host_to_target32 (exec_size);
+ o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
+ - header_size);
+ o->bss_size = grub_cpu_to_le32 (bss_size);
+ o->entry_addr = grub_cpu_to_le32 (start_address);
+ o->code_base = grub_cpu_to_le32 (header_size);
+ o->image_base = 0;
+ o->section_alignment = grub_host_to_target32 (image_target->section_align);
+ o->file_alignment = grub_host_to_target32 (image_target->section_align);
+ o->image_size = grub_host_to_target32 (pe_size);
+ o->header_size = grub_host_to_target32 (header_size);
+ o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+
+ /* Do these really matter? */
+ o->stack_reserve_size = grub_host_to_target32 (0x10000);
+ o->stack_commit_size = grub_host_to_target32 (0x10000);
+ o->heap_reserve_size = grub_host_to_target32 (0x10000);
+ o->heap_commit_size = grub_host_to_target32 (0x10000);
+
+ o->num_data_directories
+ = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+
+ o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
+ o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
+ sections = o + 1;
+ }
+ /* The sections. */
+ text_section = sections;
+ strcpy (text_section->name, ".text");
+ text_section->virtual_size = grub_cpu_to_le32 (exec_size);
+ text_section->virtual_address = grub_cpu_to_le32 (header_size);
+ text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
+ text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
+ text_section->characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
+ | GRUB_PE32_SCN_MEM_EXECUTE
+ | GRUB_PE32_SCN_MEM_READ);
+
+ data_section = text_section + 1;
+ strcpy (data_section->name, ".data");
+ data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size);
+ data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size);
+ data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
+ data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
+ data_section->characteristics
+ = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ | GRUB_PE32_SCN_MEM_READ
+ | GRUB_PE32_SCN_MEM_WRITE);
+
+#if 0
+ bss_section = data_section + 1;
+ strcpy (bss_section->name, ".bss");
+ bss_section->virtual_size = grub_cpu_to_le32 (bss_size);
+ bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size);
+ bss_section->raw_data_size = 0;
+ bss_section->raw_data_offset = 0;
+ bss_section->characteristics
+ = grub_cpu_to_le32 (GRUB_PE32_SCN_MEM_READ
+ | GRUB_PE32_SCN_MEM_WRITE
+ | GRUB_PE32_SCN_ALIGN_64BYTES
+ | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ | 0x80);
+#endif
+
+ mods_section = data_section + 1;
+ strcpy (mods_section->name, "mods");
+ mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
+ mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size);
+ mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
+ mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
+ mods_section->characteristics
+ = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ | GRUB_PE32_SCN_MEM_READ
+ | GRUB_PE32_SCN_MEM_WRITE);
+
+ reloc_section = mods_section + 1;
+ strcpy (reloc_section->name, ".reloc");
+ reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size);
+ reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size);
+ reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
+ reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
+ reloc_section->characteristics
+ = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ | GRUB_PE32_SCN_MEM_DISCARDABLE
+ | GRUB_PE32_SCN_MEM_READ);
+ free (core_img);
+ core_img = pe_img;
+ core_size = pe_size;
+ }
+ break;
+ case IMAGE_QEMU:
+ {
+ char *rom_img;
+ size_t rom_size;
+ char *boot_path, *boot_img;
+ size_t boot_size;
+
+ boot_path = grub_util_get_path (dir, "boot.img");
+ boot_size = grub_util_get_image_size (boot_path);
+ boot_img = grub_util_read_image (boot_path);
+
+ /* Rom sizes must be 64k-aligned. */
+ rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024);
+
+ rom_img = xmalloc (rom_size);
+ memset (rom_img, 0, rom_size);
+
+ *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
+ = grub_host_to_target32 ((grub_uint32_t) -rom_size);
+
+ memcpy (rom_img, core_img, core_size);
+
+ *((grub_int32_t *) (boot_img + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR))
+ = grub_host_to_target32 ((grub_uint32_t) -rom_size);
+
+ memcpy (rom_img + rom_size - boot_size, boot_img, boot_size);
+
+ free (core_img);
+ core_img = rom_img;
+ core_size = rom_size;
+
+ free (boot_img);
+ free (boot_path);
+ }
+ break;
+ case IMAGE_SPARC64_AOUT:
+ {
+ void *aout_img;
+ size_t aout_size;
+ struct grub_aout32_header *aout_head;
+
+ aout_size = core_size + sizeof (*aout_head);
+ aout_img = xmalloc (aout_size);
+ aout_head = aout_img;
+ aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
+ | AOUT32_OMAGIC);
+ aout_head->a_text = grub_host_to_target32 (core_size);
+ aout_head->a_entry
+ = grub_host_to_target32 (GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS);
+ memcpy (aout_img + sizeof (*aout_head), core_img, core_size);
+
+ free (core_img);
+ core_img = aout_img;
+ core_size = aout_size;
+ }
+ break;
+ case IMAGE_SPARC64_RAW:
+ {
+ unsigned int num;
+ char *boot_path, *boot_img;
+ size_t boot_size;
+
+ num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+ num <<= GRUB_DISK_SECTOR_BITS;
+
+ 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)
+ grub_util_error ("diskboot.img is not one sector size");
+
+ boot_img = grub_util_read_image (boot_path);
+
+ *((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
+ - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE + 8))
+ = grub_host_to_target32 (num);
+
+ grub_util_write_image (boot_img, boot_size, out);
+ free (boot_img);
+ free (boot_path);
+ }
+ break;
+ case IMAGE_YEELOONG_FLASH:
+ {
+ char *rom_img;
+ size_t rom_size;
+ char *boot_path, *boot_img;
+ size_t boot_size;
+ grub_uint8_t context[GRUB_MD_SHA512->contextsize];
+ /* fwstart.img is the only part which can't be tested by using *-elf
+ target. Check it against the checksum. This checksum is obtained with
+ sha512sum utility after compiling on Gnewsense.
+ */
+ const grub_uint8_t fwstart_good_hash[] =
+ {
+ 0x44, 0xce, 0xbc, 0xe7, 0xc2, 0x5e, 0xff, 0x65,
+ 0xc5, 0xda, 0x29, 0x5a, 0xb9, 0x08, 0x89, 0x42,
+ 0x83, 0x3f, 0x2b, 0x2e, 0x06, 0xe1, 0x6f, 0x79,
+ 0x9b, 0x78, 0x6d, 0xe5, 0xd3, 0x64, 0x98, 0x35,
+ 0xc8, 0x58, 0xac, 0xb8, 0x08, 0x6d, 0x21, 0x51,
+ 0xcf, 0xe0, 0x76, 0x48, 0x81, 0x6c, 0xed, 0x65,
+ 0x4a, 0x50, 0xb4, 0x06, 0x38, 0x0b, 0x26, 0x74,
+ 0x43, 0xbf, 0xc5, 0x2e, 0x07, 0xa6, 0xb8, 0x0e,
+ };
+
+ boot_path = grub_util_get_path (dir, "fwstart.img");
+ boot_size = grub_util_get_image_size (boot_path);
+ boot_img = grub_util_read_image (boot_path);
+
+ grub_memset (context, 0, sizeof (context));
+ GRUB_MD_SHA512->init (context);
+ GRUB_MD_SHA512->write (context, boot_img, boot_size);
+ GRUB_MD_SHA512->final (context);
+ if (grub_memcmp (GRUB_MD_SHA512->read (context), fwstart_good_hash,
+ GRUB_MD_SHA512->mdlen) != 0)
+ grub_util_warn ("fwstart.img doesn't match the known good version. "
+ "Proceed at your own risk");
+
+ if (core_size + boot_size > 512 * 1024)
+ grub_util_error ("firmware image is too big");
+ rom_size = 512 * 1024;
+
+ rom_img = xmalloc (rom_size);
+ memset (rom_img, 0, rom_size);
+
+ memcpy (rom_img, boot_img, boot_size);
+
+ memcpy (rom_img + boot_size, core_img, core_size);
+
+ memset (rom_img + boot_size + core_size, 0,
+ rom_size - (boot_size + core_size));
+
+ free (core_img);
+ core_img = rom_img;
+ core_size = rom_size;
+ }
+ break;
+ case IMAGE_YEELOONG_ELF:
+ case IMAGE_PPC:
+ case IMAGE_COREBOOT:
+ case IMAGE_I386_IEEE1275:
+ {
+ char *elf_img;
+ size_t program_size;
+ Elf32_Ehdr *ehdr;
+ Elf32_Phdr *phdr;
+ grub_uint32_t target_addr;
+ int header_size, footer_size = 0;
+ int phnum = 1;
+
+ if (image_target->id != IMAGE_YEELOONG_ELF)
+ phnum += 2;
+
+ if (note)
+ {
+ phnum++;
+ footer_size += sizeof (struct grub_ieee1275_note);
+ }
+ header_size = ALIGN_ADDR (sizeof (*ehdr) + phnum * sizeof (*phdr));
+
+ program_size = ALIGN_ADDR (core_size);
+
+ elf_img = xmalloc (program_size + header_size + footer_size);
+ memset (elf_img, 0, program_size + header_size);
+ memcpy (elf_img + header_size, core_img, core_size);
+ ehdr = (void *) elf_img;
+ phdr = (void *) (elf_img + sizeof (*ehdr));
+ memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
+ ehdr->e_ident[EI_CLASS] = ELFCLASS32;
+ if (!image_target->bigendian)
+ ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+ else
+ ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
+ ehdr->e_type = grub_host_to_target16 (ET_EXEC);
+ ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
+ ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
+
+ ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
+ ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
+ ehdr->e_phnum = grub_host_to_target16 (phnum);
+
+ /* No section headers. */
+ ehdr->e_shoff = grub_host_to_target32 (0);
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ ehdr->e_shentsize = grub_host_to_target16 (0);
+ else
+ ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf32_Shdr));
+ ehdr->e_shnum = grub_host_to_target16 (0);
+ ehdr->e_shstrndx = grub_host_to_target16 (0);
+
+ ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
+
+ phdr->p_type = grub_host_to_target32 (PT_LOAD);
+ phdr->p_offset = grub_host_to_target32 (header_size);
+ phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ target_addr = ALIGN_UP (image_target->link_addr
+ + kernel_size + total_module_size, 32);
+ else
+ target_addr = image_target->link_addr;
+ ehdr->e_entry = grub_host_to_target32 (target_addr);
+ phdr->p_vaddr = grub_host_to_target32 (target_addr);
+ phdr->p_paddr = grub_host_to_target32 (target_addr);
+ phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
+ | EF_MIPS_PIC | EF_MIPS_CPIC);
+ else
+ ehdr->e_flags = 0;
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ {
+ phdr->p_filesz = grub_host_to_target32 (core_size);
+ phdr->p_memsz = grub_host_to_target32 (core_size);
+ }
+ else
+ {
+ grub_uint32_t target_addr_mods;
+ phdr->p_filesz = grub_host_to_target32 (kernel_size);
+ phdr->p_memsz = grub_host_to_target32 (kernel_size + bss_size);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
+ phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+ phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
+ phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+ phdr->p_align = grub_host_to_target32 (image_target->link_align);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_LOAD);
+ phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+ phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+ phdr->p_filesz = phdr->p_memsz
+ = grub_host_to_target32 (core_size - kernel_size);
+
+ target_addr_mods = ALIGN_UP (target_addr + kernel_size + bss_size
+ + image_target->mod_gap,
+ image_target->mod_align);
+ phdr->p_vaddr = grub_host_to_target32 (target_addr_mods);
+ phdr->p_paddr = grub_host_to_target32 (target_addr_mods);
+ phdr->p_align = grub_host_to_target32 (image_target->link_align);
+ }
+
+ if (note)
+ {
+ int note_size = sizeof (struct grub_ieee1275_note);
+ struct grub_ieee1275_note *note = (struct grub_ieee1275_note *)
+ (elf_img + program_size + header_size);
+
+ grub_util_info ("adding CHRP NOTE segment");
+
+ note->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
+ note->header.descsz = grub_host_to_target32 (note_size);
+ note->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
+ strcpy (note->header.name, GRUB_IEEE1275_NOTE_NAME);
+ note->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
+ note->descriptor.real_base = grub_host_to_target32 (0x00c00000);
+ note->descriptor.real_size = grub_host_to_target32 (0xffffffff);
+ note->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
+ note->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
+ note->descriptor.load_base = grub_host_to_target32 (0x00004000);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ }
+
+ free (core_img);
+ core_img = elf_img;
+ core_size = program_size + header_size + footer_size;
+ }
+ break;
+ }
+
+ grub_util_write_image (core_img, core_size, out);
+ free (kernel_img);
+ free (core_img);
+ free (kernel_path);
+
+ while (path_list)
+ {
+ next = path_list->next;
+ free ((void *) path_list->name);
+ free (path_list);
+ path_list = next;
+ }
+}
+
+
+
+static struct option options[] =
+ {
+ {"directory", required_argument, 0, 'd'},
+ {"prefix", required_argument, 0, 'p'},
+ {"memdisk", required_argument, 0, 'm'},
+ {"font", required_argument, 0, 'f'},
+ {"config", required_argument, 0, 'c'},
+ {"output", required_argument, 0, 'o'},
+ {"note", no_argument, 0, 'n'},
+ {"format", required_argument, 0, 'O'},
+ {"compression", required_argument, 0, 'C'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name);
+ else
+ {
+ int format_len = 0;
+ char *formats;
+ char *ptr;
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE (image_targets); i++)
+ format_len += strlen (image_targets[i].name) + 2;
+ ptr = formats = xmalloc (format_len);
+ for (i = 0; i < ARRAY_SIZE (image_targets); i++)
+ {
+ strcpy (ptr, image_targets[i].name);
+ ptr += strlen (image_targets[i].name);
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ }
+ ptr[-2] = 0;
+
+ printf (_("\
+Usage: %s [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of GRUB.\n\
+\n\
+ -d, --directory=DIR use images and modules under DIR [default=%s/@platform@]\n\
+ -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
+ -m, --memdisk=FILE embed FILE as a memdisk image\n\
+ -c, --config=FILE embed FILE as boot config\n\
+ -n, --note add NOTE segment for CHRP Open Firmware\n\
+ -o, --output=FILE output a generated image to FILE [default=stdout]\n\
+ -O, --format=FORMAT generate an image in format\n\
+ available formats: %s\n\
+ -C, --compression=(xz|none|auto) choose the compression to use\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+"),
+ program_name, GRUB_PKGLIBROOTDIR, DEFAULT_DIRECTORY,
+ formats,
+ PACKAGE_BUGREPORT);
+ free (formats);
+ }
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *output = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *memdisk = NULL;
+ char *font = NULL;
+ char *config = NULL;
+ FILE *fp = stdout;
+ int note = 0;
+ struct image_target_desc *image_target = NULL;
+ grub_compression_t comp = COMPRESSION_AUTO;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:C:hVvn", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'o':
+ if (output)
+ free (output);
+
+ output = xstrdup (optarg);
+ break;
+
+ case 'O':
+ {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE (image_targets); i++)
+ if (strcmp (optarg, image_targets[i].name) == 0)
+ image_target = &image_targets[i];
+ if (!image_target)
+ {
+ printf ("unknown target format %s\n", optarg);
+ usage (1);
+ }
+ break;
+ }
+ case 'd':
+ if (dir)
+ free (dir);
+
+ dir = xstrdup (optarg);
+ break;
+
+ case 'n':
+ note = 1;
+ break;
+
+ case 'm':
+ if (memdisk)
+ free (memdisk);
+
+ memdisk = xstrdup (optarg);
+
+ if (prefix)
+ free (prefix);
+
+ prefix = xstrdup ("(memdisk)/boot/grub");
+ break;
+
+ case 'c':
+ if (config)
+ free (config);
+
+ config = xstrdup (optarg);
+ break;
+
+ case 'C':
+ if (grub_strcmp (optarg, "xz") == 0)
+ {
+#ifdef HAVE_LIBLZMA
+ comp = COMPRESSION_XZ;
+#else
+ grub_util_error ("grub-mkimage is compiled without XZ support",
+ optarg);
+#endif
+ }
+ else if (grub_strcmp (optarg, "none") == 0)
+ comp = COMPRESSION_NONE;
+ else
+ grub_util_error ("Unknown compression format %s", optarg);
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ case 'p':
+ if (prefix)
+ free (prefix);
+
+ prefix = xstrdup (optarg);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (!image_target)
+ {
+ printf ("Target format not specified (use the -O option).\n");
+ usage (1);
+ }
+
+ if (output)
+ {
+ fp = fopen (output, "wb");
+ if (! fp)
+ grub_util_error (_("cannot open %s"), output);
+ free (output);
+ }
+
+ if (!dir)
+ {
+ const char *last;
+ last = strchr (image_target->name, '-');
+ if (last)
+ last = strchr (last + 1, '-');
+ if (!last)
+ last = image_target->name + strlen (image_target->name);
+ dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name)
+ + 1);
+ memcpy (dir, GRUB_PKGLIBROOTDIR, sizeof (GRUB_PKGLIBROOTDIR) - 1);
+ *(dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/';
+ if (strncmp (image_target->name, "mipsel-yeeloong",
+ last - image_target->name) == 0)
+ {
+ memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), "mips-yeeloong",
+ sizeof ("mips-yeeloong"));
+ }
+ else
+ {
+ memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->name,
+ last - image_target->name);
+ *(dir + sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name))
+ = 0;
+ }
+ }
+
+ generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp,
+ argv + optind, memdisk, config,
+ image_target, note, comp);
+
+ fflush (fp);
+ fsync (fileno (fp));
+ fclose (fp);
+
+ if (dir)
+ free (dir);
+
+ return 0;
+}
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
new file mode 100644
index 0000000..ce51f2f
--- /dev/null
+++ b/util/grub-mkimagexx.c
@@ -0,0 +1,756 @@
+/* grub-mkimage.c - make a bootable image */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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 <http://www.gnu.org/licenses/>.
+ */
+
+#undef ELF_R_SYM
+#undef ELF_R_TYPE
+
+#if defined(MKIMAGE_ELF32)
+# define SUFFIX(x) x ## 32
+# define ELFCLASSXX ELFCLASS32
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Phdr Elf32_Phdr
+# define Elf_Addr Elf32_Addr
+# define Elf_Sym Elf32_Sym
+# define Elf_Off Elf32_Off
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Rela Elf32_Rela
+# define Elf_Rel Elf32_Rel
+# define ELF_R_SYM(val) ELF32_R_SYM(val)
+# define ELF_R_TYPE(val) ELF32_R_TYPE(val)
+#elif defined(MKIMAGE_ELF64)
+# define SUFFIX(x) x ## 64
+# define ELFCLASSXX ELFCLASS64
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Phdr Elf64_Phdr
+# define Elf_Addr Elf64_Addr
+# define Elf_Sym Elf64_Sym
+# define Elf_Off Elf64_Off
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Rela Elf64_Rela
+# define Elf_Rel Elf64_Rel
+# define ELF_R_SYM(val) ELF64_R_SYM(val)
+# define ELF_R_TYPE(val) ELF64_R_TYPE(val)
+#else
+#error "I'm confused"
+#endif
+
+/* Relocate symbols; note that this function overwrites the symbol table.
+ Return the address of a start symbol. */
+static Elf_Addr
+SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
+ Elf_Half section_entsize, Elf_Half num_sections,
+ struct image_target_desc *image_target)
+{
+ Elf_Word symtab_size, sym_size, num_syms;
+ Elf_Off symtab_offset;
+ Elf_Addr start_address = 0;
+ Elf_Sym *sym;
+ Elf_Word i;
+ Elf_Shdr *strtab_section;
+ const char *strtab;
+
+ strtab_section
+ = (Elf_Shdr *) ((char *) sections
+ + (grub_target_to_host32 (symtab_section->sh_link)
+ * section_entsize));
+ strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);
+
+ symtab_size = grub_target_to_host (symtab_section->sh_size);
+ sym_size = grub_target_to_host (symtab_section->sh_entsize);
+ symtab_offset = grub_target_to_host (symtab_section->sh_offset);
+ num_syms = symtab_size / sym_size;
+
+ for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
+ i < num_syms;
+ i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
+ {
+ Elf_Section index;
+ const char *name;
+
+ name = strtab + grub_target_to_host32 (sym->st_name);
+
+ index = grub_target_to_host16 (sym->st_shndx);
+ if (index == STN_ABS)
+ {
+ continue;
+ }
+ else if ((index == STN_UNDEF))
+ {
+ if (sym->st_name)
+ grub_util_error ("undefined symbol %s", name);
+ else
+ continue;
+ }
+ else if (index >= num_sections)
+ grub_util_error ("section %d does not exist", index);
+
+ sym->st_value = (grub_target_to_host32 (sym->st_value)
+ + section_addresses[index]);
+ grub_util_info ("locating %s at 0x%x", name, sym->st_value);
+
+ if (! start_address)
+ if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
+ start_address = sym->st_value;
+ }
+
+ return start_address;
+}
+
+/* Return the address of a symbol at the index I in the section S. */
+static Elf_Addr
+SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
+ struct image_target_desc *image_target)
+{
+ Elf_Sym *sym;
+
+ sym = (Elf_Sym *) ((char *) e
+ + grub_target_to_host32 (s->sh_offset)
+ + i * grub_target_to_host32 (s->sh_entsize));
+ return sym->st_value;
+}
+
+/* Return the address of a modified value. */
+static Elf_Addr *
+SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
+ struct image_target_desc *image_target)
+{
+ return (Elf_Addr *) ((char *) e + grub_target_to_host32 (s->sh_offset) + offset);
+}
+
+/* Deal with relocation information. This function relocates addresses
+ within the virtual address space starting from 0. So only relative
+ addresses can be fully resolved. Absolute addresses must be relocated
+ again by a PE32 relocator when loaded. */
+static void
+SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Addr *section_addresses,
+ Elf_Half section_entsize, Elf_Half num_sections,
+ const char *strtab, struct image_target_desc *image_target)
+{
+ Elf_Half i;
+ Elf_Shdr *s;
+
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
+ (s->sh_type == grub_host_to_target32 (SHT_RELA)))
+ {
+ Elf_Rela *r;
+ Elf_Word rtab_size, r_size, num_rs;
+ Elf_Off rtab_offset;
+ Elf_Shdr *symtab_section;
+ Elf_Word target_section_index;
+ Elf_Addr target_section_addr;
+ Elf_Shdr *target_section;
+ Elf_Word j;
+
+ symtab_section = (Elf_Shdr *) ((char *) sections
+ + (grub_target_to_host32 (s->sh_link)
+ * section_entsize));
+ target_section_index = grub_target_to_host32 (s->sh_info);
+ target_section_addr = section_addresses[target_section_index];
+ target_section = (Elf_Shdr *) ((char *) sections
+ + (target_section_index
+ * section_entsize));
+
+ grub_util_info ("dealing with the relocation section %s for %s",
+ strtab + grub_target_to_host32 (s->sh_name),
+ strtab + grub_target_to_host32 (target_section->sh_name));
+
+ rtab_size = grub_target_to_host32 (s->sh_size);
+ r_size = grub_target_to_host32 (s->sh_entsize);
+ rtab_offset = grub_target_to_host32 (s->sh_offset);
+ num_rs = rtab_size / r_size;
+
+ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
+ j < num_rs;
+ j++, r = (Elf_Rela *) ((char *) r + r_size))
+ {
+ Elf_Addr info;
+ Elf_Addr offset;
+ Elf_Addr sym_addr;
+ Elf_Addr *target;
+ Elf_Addr addend;
+
+ offset = grub_target_to_host (r->r_offset);
+ target = SUFFIX (get_target_address) (e, target_section,
+ offset, image_target);
+ info = grub_target_to_host (r->r_info);
+ sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
+ ELF_R_SYM (info), image_target);
+
+ addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
+ r->r_addend : 0;
+
+ if (image_target->voidp_sizeof == 4)
+ switch (ELF_R_TYPE (info))
+ {
+ case R_386_NONE:
+ break;
+
+ case R_386_32:
+ /* This is absolute. */
+ *target = grub_host_to_target32 (grub_target_to_host32 (*target)
+ + addend + sym_addr);
+ grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
+ *target, offset);
+ break;
+
+ case R_386_PC32:
+ /* This is relative. */
+ *target = grub_host_to_target32 (grub_target_to_host32 (*target)
+ + addend + sym_addr
+ - target_section_addr - offset
+ - image_target->vaddr_offset);
+ grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
+ *target, offset);
+ break;
+ default:
+ grub_util_error ("unknown relocation type %d",
+ ELF_R_TYPE (info));
+ break;
+ }
+ else
+ switch (ELF_R_TYPE (info))
+ {
+
+ case R_X86_64_NONE:
+ break;
+
+ case R_X86_64_64:
+ *target = grub_host_to_target64 (grub_target_to_host64 (*target)
+ + addend + sym_addr);
+ grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
+ *target, offset);
+ break;
+
+ case R_X86_64_PC32:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
+ + addend + sym_addr
+ - target_section_addr - offset
+ - image_target->vaddr_offset);
+ grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
+ *t32, offset);
+ break;
+ }
+
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
+ + addend + sym_addr);
+ grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
+ *t32, offset);
+ break;
+ }
+
+ default:
+ grub_util_error ("unknown relocation type %d",
+ ELF_R_TYPE (info));
+ break;
+ }
+ }
+ }
+}
+
+/* Add a PE32's fixup entry for a relocation. Return the resulting address
+ after having written to the file OUT. */
+static Elf_Addr
+SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
+ Elf_Addr addr, int flush, Elf_Addr current_address,
+ struct image_target_desc *image_target)
+{
+ struct grub_pe32_fixup_block *b;
+
+ b = &((*cblock)->b);
+
+ /* First, check if it is necessary to write out the current block. */
+ if ((*cblock)->state)
+ {
+ if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
+ {
+ grub_uint32_t size;
+
+ if (flush)
+ {
+ /* Add as much padding as necessary to align the address
+ with a section boundary. */
+ Elf_Addr next_address;
+ unsigned padding_size;
+ size_t index;
+
+ next_address = current_address + b->block_size;
+ padding_size = ((ALIGN_UP (next_address, image_target->section_align)
+ - next_address)
+ >> 1);
+ index = ((b->block_size - sizeof (*b)) >> 1);
+ grub_util_info ("adding %d padding fixup entries", padding_size);
+ while (padding_size--)
+ {
+ b->entries[index++] = 0;
+ b->block_size += 2;
+ }
+ }
+ else if (b->block_size & (8 - 1))
+ {
+ /* If not aligned with a 32-bit boundary, add
+ a padding entry. */
+ size_t index;
+
+ grub_util_info ("adding a padding fixup entry");
+ index = ((b->block_size - sizeof (*b)) >> 1);
+ b->entries[index] = 0;
+ b->block_size += 2;
+ }
+
+ /* Flush it. */
+ grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
+ b->block_size, b->page_rva);
+ size = b->block_size;
+ current_address += size;
+ b->page_rva = grub_host_to_target32 (b->page_rva);
+ b->block_size = grub_host_to_target32 (b->block_size);
+ (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
+ memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
+ *cblock = (*cblock)->next;
+ }
+ }
+
+ b = &((*cblock)->b);
+
+ if (! flush)
+ {
+ grub_uint16_t entry;
+ size_t index;
+
+ /* If not allocated yet, allocate a block with enough entries. */
+ if (! (*cblock)->state)
+ {
+ (*cblock)->state = 1;
+
+ /* The spec does not mention the requirement of a Page RVA.
+ Here, align the address with a 4K boundary for safety. */
+ b->page_rva = (addr & ~(0x1000 - 1));
+ b->block_size = sizeof (*b);
+ }
+
+ /* Sanity check. */
+ if (b->block_size >= sizeof (*b) + 2 * 0x1000)
+ grub_util_error ("too many fixup entries");
+
+ /* Add a new entry. */
+ index = ((b->block_size - sizeof (*b)) >> 1);
+ entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
+ b->entries[index] = grub_host_to_target16 (entry);
+ b->block_size += 2;
+ }
+
+ return current_address;
+}
+
+/* Make a .reloc section. */
+static Elf_Addr
+SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
+ Elf_Addr *section_addresses, Elf_Shdr *sections,
+ Elf_Half section_entsize, Elf_Half num_sections,
+ const char *strtab, struct image_target_desc *image_target)
+{
+ Elf_Half i;
+ Elf_Shdr *s;
+ struct fixup_block_list *lst, *lst0;
+ Elf_Addr current_address = 0;
+
+ lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000);
+ memset (lst, 0, sizeof (*lst) + 2 * 0x1000);
+
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
+ (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
+ {
+ Elf_Rel *r;
+ Elf_Word rtab_size, r_size, num_rs;
+ Elf_Off rtab_offset;
+ Elf_Addr section_address;
+ Elf_Word j;
+
+ grub_util_info ("translating the relocation section %s",
+ strtab + grub_le_to_cpu32 (s->sh_name));
+
+ rtab_size = grub_le_to_cpu32 (s->sh_size);
+ r_size = grub_le_to_cpu32 (s->sh_entsize);
+ rtab_offset = grub_le_to_cpu32 (s->sh_offset);
+ num_rs = rtab_size / r_size;
+
+ section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
+
+ for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
+ j < num_rs;
+ j++, r = (Elf_Rel *) ((char *) r + r_size))
+ {
+ Elf_Addr info;
+ Elf_Addr offset;
+
+ offset = grub_le_to_cpu32 (r->r_offset);
+ info = grub_le_to_cpu32 (r->r_info);
+
+ /* Necessary to relocate only absolute addresses. */
+ if (image_target->voidp_sizeof == 4)
+ {
+ if (ELF_R_TYPE (info) == R_386_32)
+ {
+ Elf_Addr addr;
+
+ addr = section_address + offset;
+ grub_util_info ("adding a relocation entry for 0x%x", addr);
+ current_address
+ = SUFFIX (add_fixup_entry) (&lst,
+ GRUB_PE32_REL_BASED_HIGHLOW,
+ addr, 0, current_address,
+ image_target);
+ }
+ }
+ else
+ {
+ if ((ELF_R_TYPE (info) == R_X86_64_32) ||
+ (ELF_R_TYPE (info) == R_X86_64_32S))
+ {
+ grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
+ }
+ else if (ELF_R_TYPE (info) == R_X86_64_64)
+ {
+ Elf_Addr addr;
+
+ addr = section_address + offset;
+ grub_util_info ("adding a relocation entry for 0x%llx", addr);
+ current_address
+ = SUFFIX (add_fixup_entry) (&lst,
+ GRUB_PE32_REL_BASED_DIR64,
+ addr,
+ 0, current_address,
+ image_target);
+ }
+ }
+ }
+ }
+
+ current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target);
+
+ {
+ grub_uint8_t *ptr;
+ ptr = *out = xmalloc (current_address);
+ for (lst = lst0; lst; lst = lst->next)
+ if (lst->state)
+ {
+ memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size));
+ ptr += grub_target_to_host32 (lst->b.block_size);
+ }
+ if (current_address + *out != ptr)
+ {
+ grub_util_error ("Bug detected %d != %d\n", ptr - (grub_uint8_t *) *out,
+ current_address);
+ }
+ }
+
+ return current_address;
+}
+
+/* Determine if this section is a text section. Return false if this
+ section is not allocated. */
+static int
+SUFFIX (is_text_section) (Elf_Shdr *s, struct image_target_desc *image_target)
+{
+ if (image_target->id != IMAGE_EFI
+ && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
+ return 0;
+ return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
+ == (SHF_EXECINSTR | SHF_ALLOC));
+}
+
+/* Determine if this section is a data section. This assumes that
+ BSS is also a data section, since the converter initializes BSS
+ when producing PE32 to avoid a bug in EFI implementations. */
+static int
+SUFFIX (is_data_section) (Elf_Shdr *s, struct image_target_desc *image_target)
+{
+ if (image_target->id != IMAGE_EFI
+ && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
+ return 0;
+ return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
+ == SHF_ALLOC);
+}
+
+/* Return if the ELF header is valid. */
+static int
+SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, struct image_target_desc *image_target)
+{
+ if (size < sizeof (*e)
+ || e->e_ident[EI_MAG0] != ELFMAG0
+ || e->e_ident[EI_MAG1] != ELFMAG1
+ || e->e_ident[EI_MAG2] != ELFMAG2
+ || e->e_ident[EI_MAG3] != ELFMAG3
+ || e->e_ident[EI_VERSION] != EV_CURRENT
+ || e->e_ident[EI_CLASS] != ELFCLASSXX
+ || e->e_version != grub_host_to_target32 (EV_CURRENT))
+ return 0;
+
+ return 1;
+}
+
+/* Locate section addresses by merging code sections and data sections
+ into .text and .data, respectively. Return the array of section
+ addresses. */
+static Elf_Addr *
+SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize,
+ Elf_Half num_sections, const char *strtab,
+ grub_size_t *exec_size, grub_size_t *kernel_sz,
+ grub_size_t *all_align,
+ struct image_target_desc *image_target)
+{
+ int i;
+ Elf_Addr current_address;
+ Elf_Addr *section_addresses;
+ Elf_Shdr *s;
+
+ *all_align = 1;
+
+ section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
+ memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
+
+ current_address = 0;
+
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
+ && grub_host_to_target32 (s->sh_addralign) > *all_align)
+ *all_align = grub_host_to_target32 (s->sh_addralign);
+
+
+ /* .text */
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (SUFFIX (is_text_section) (s, image_target))
+ {
+ Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
+ const char *name = strtab + grub_host_to_target32 (s->sh_name);
+ if (align)
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ align) - image_target->vaddr_offset;
+ grub_util_info ("locating the section %s at 0x%x",
+ name, current_address);
+ section_addresses[i] = current_address;
+ current_address += grub_host_to_target_addr (s->sh_size);
+ }
+
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ image_target->section_align)
+ - image_target->vaddr_offset;
+ *exec_size = current_address;
+
+ /* .data */
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (SUFFIX (is_data_section) (s, image_target))
+ {
+ Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
+ const char *name = strtab + grub_host_to_target32 (s->sh_name);
+
+ if (align)
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ align)
+ - image_target->vaddr_offset;
+
+ grub_util_info ("locating the section %s at 0x%x",
+ name, current_address);
+ section_addresses[i] = current_address;
+ current_address += grub_host_to_target_addr (s->sh_size);
+ }
+
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ image_target->section_align) - image_target->vaddr_offset;
+ *kernel_sz = current_address;
+ return section_addresses;
+}
+
+static char *
+SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size,
+ grub_size_t *kernel_sz, grub_size_t *bss_size,
+ grub_size_t total_module_size, grub_uint64_t *start,
+ void **reloc_section, grub_size_t *reloc_size,
+ grub_size_t *align,
+ struct image_target_desc *image_target)
+{
+ char *kernel_img, *out_img;
+ const char *strtab;
+ Elf_Ehdr *e;
+ Elf_Shdr *sections;
+ Elf_Addr *section_addresses;
+ Elf_Addr *section_vaddresses;
+ int i;
+ Elf_Shdr *s;
+ Elf_Half num_sections;
+ Elf_Off section_offset;
+ Elf_Half section_entsize;
+ grub_size_t kernel_size;
+ Elf_Shdr *symtab_section;
+
+ *start = 0;
+
+ kernel_size = grub_util_get_image_size (kernel_path);
+ kernel_img = xmalloc (kernel_size);
+ grub_util_load_image (kernel_path, kernel_img);
+
+ e = (Elf_Ehdr *) kernel_img;
+ if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
+ grub_util_error ("invalid ELF header");
+
+ section_offset = grub_target_to_host (e->e_shoff);
+ section_entsize = grub_target_to_host16 (e->e_shentsize);
+ num_sections = grub_target_to_host16 (e->e_shnum);
+
+ if (kernel_size < section_offset + section_entsize * num_sections)
+ grub_util_error ("invalid ELF format");
+
+ sections = (Elf_Shdr *) (kernel_img + section_offset);
+
+ /* Relocate sections then symbols in the virtual address space. */
+ s = (Elf_Shdr *) ((char *) sections
+ + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
+ strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
+
+ section_addresses = SUFFIX (locate_sections) (sections, section_entsize,
+ num_sections, strtab,
+ exec_size, kernel_sz, align,
+ image_target);
+
+ section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
+
+ for (i = 0; i < num_sections; i++)
+ section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
+
+ if (image_target->id != IMAGE_EFI)
+ {
+ Elf_Addr current_address = *kernel_sz;
+
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
+ {
+ Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
+ const char *name = strtab + grub_host_to_target32 (s->sh_name);
+
+ if (align)
+ current_address = ALIGN_UP (current_address
+ + image_target->vaddr_offset, align)
+ - image_target->vaddr_offset;
+
+ grub_util_info ("locating the section %s at 0x%x",
+ name, current_address);
+ section_vaddresses[i] = current_address
+ + image_target->vaddr_offset;
+ current_address += grub_host_to_target_addr (s->sh_size);
+ }
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ image_target->section_align)
+ - image_target->vaddr_offset;
+ *bss_size = current_address - *kernel_sz;
+ }
+ else
+ *bss_size = 0;
+
+ if (image_target->id == IMAGE_EFI)
+ {
+ symtab_section = NULL;
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
+ {
+ symtab_section = s;
+ break;
+ }
+
+ if (! symtab_section)
+ grub_util_error ("no symbol table");
+
+ *start = SUFFIX (relocate_symbols) (e, sections, symtab_section,
+ section_vaddresses, section_entsize,
+ num_sections, image_target);
+ if (*start == 0)
+ grub_util_error ("start symbol is not defined");
+
+ /* Resolve addresses in the virtual address space. */
+ SUFFIX (relocate_addresses) (e, sections, section_addresses, section_entsize,
+ num_sections, strtab, image_target);
+
+ *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
+ section_vaddresses, sections,
+ section_entsize, num_sections,
+ strtab, image_target);
+ }
+ else
+ {
+ *reloc_size = 0;
+ *reloc_section = NULL;
+ }
+
+ out_img = xmalloc (*kernel_sz + total_module_size);
+
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (SUFFIX (is_data_section) (s, image_target)
+ || SUFFIX (is_text_section) (s, image_target))
+ {
+ if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
+ memset (out_img + section_addresses[i], 0,
+ grub_host_to_target_addr (s->sh_size));
+ else
+ memcpy (out_img + section_addresses[i],
+ kernel_img + grub_host_to_target_addr (s->sh_offset),
+ grub_host_to_target_addr (s->sh_size));
+ }
+ free (kernel_img);
+
+ return out_img;
+}
+
+
+#undef SUFFIX
+#undef ELFCLASSXX
+#undef Elf_Ehdr
+#undef Elf_Phdr
+#undef Elf_Shdr
+#undef Elf_Addr
+#undef Elf_Sym
+#undef Elf_Off
+#undef Elf_Rela
+#undef Elf_Rel
+#undef ELF_R_TYPE
+#undef ELF_R_SYM
diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c
new file mode 100644
index 0000000..04501cb
--- /dev/null
+++ b/util/grub-mklayout.c
@@ -0,0 +1,505 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+#include <grub/term.h>
+#include <grub/keyboard_layouts.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "progname.h"
+
+#define CKBCOMP "ckbcomp"
+
+static struct option options[] = {
+ {"output", required_argument, 0, 'o'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+struct console_grub_equivalence
+{
+ char *layout;
+ grub_uint32_t grub;
+};
+
+static struct console_grub_equivalence console_grub_equivalences_shift[] = {
+ {"KP_0", '0'},
+ {"KP_1", '1'},
+ {"KP_2", '2'},
+ {"KP_3", '3'},
+ {"KP_4", '4'},
+ {"KP_5", '5'},
+ {"KP_6", '6'},
+ {"KP_7", '7'},
+ {"KP_8", '8'},
+ {"KP_9", '9'},
+ {"KP_Period", '.'},
+
+ {NULL, '\0'}
+};
+
+static struct console_grub_equivalence console_grub_equivalences_unshift[] = {
+ {"KP_0", GRUB_TERM_KEY_INSERT},
+ {"KP_1", GRUB_TERM_KEY_END},
+ {"KP_2", GRUB_TERM_KEY_DOWN},
+ {"KP_3", GRUB_TERM_KEY_NPAGE},
+ {"KP_4", GRUB_TERM_KEY_LEFT},
+ {"KP_5", GRUB_TERM_KEY_CENTER},
+ {"KP_6", GRUB_TERM_KEY_RIGHT},
+ {"KP_7", GRUB_TERM_KEY_HOME},
+ {"KP_8", GRUB_TERM_KEY_UP},
+ {"KP_9", GRUB_TERM_KEY_PPAGE},
+ {"KP_Period", GRUB_TERM_KEY_DC},
+
+ {NULL, '\0'}
+};
+
+static struct console_grub_equivalence console_grub_equivalences_common[] = {
+ {"Escape", GRUB_TERM_ESC},
+ {"Tab", GRUB_TERM_TAB},
+ {"Delete", GRUB_TERM_BACKSPACE},
+
+ {"KP_Enter", '\n'},
+ {"Return", '\n'},
+
+ {"KP_Multiply", '*'},
+ {"KP_Subtract", '-'},
+ {"KP_Add", '+'},
+ {"KP_Divide", '/'},
+
+ {"F1", GRUB_TERM_KEY_F1},
+ {"F2", GRUB_TERM_KEY_F2},
+ {"F3", GRUB_TERM_KEY_F3},
+ {"F4", GRUB_TERM_KEY_F4},
+ {"F5", GRUB_TERM_KEY_F5},
+ {"F6", GRUB_TERM_KEY_F6},
+ {"F7", GRUB_TERM_KEY_F7},
+ {"F8", GRUB_TERM_KEY_F8},
+ {"F9", GRUB_TERM_KEY_F9},
+ {"F10", GRUB_TERM_KEY_F10},
+ {"F11", GRUB_TERM_KEY_F11},
+ {"F12", GRUB_TERM_KEY_F12},
+ {"F13", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT},
+ {"F14", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT},
+ {"F15", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT},
+ {"F16", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT},
+ {"F17", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT},
+ {"F18", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT},
+ {"F19", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT},
+ {"F20", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT},
+ {"F21", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT},
+ {"F22", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT},
+ {"F23", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT},
+ {"F24", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT},
+ {"Console_13", GRUB_TERM_KEY_F1 | GRUB_TERM_ALT},
+ {"Console_14", GRUB_TERM_KEY_F2 | GRUB_TERM_ALT},
+ {"Console_15", GRUB_TERM_KEY_F3 | GRUB_TERM_ALT},
+ {"Console_16", GRUB_TERM_KEY_F4 | GRUB_TERM_ALT},
+ {"Console_17", GRUB_TERM_KEY_F5 | GRUB_TERM_ALT},
+ {"Console_18", GRUB_TERM_KEY_F6 | GRUB_TERM_ALT},
+ {"Console_19", GRUB_TERM_KEY_F7 | GRUB_TERM_ALT},
+ {"Console_20", GRUB_TERM_KEY_F8 | GRUB_TERM_ALT},
+ {"Console_21", GRUB_TERM_KEY_F9 | GRUB_TERM_ALT},
+ {"Console_22", GRUB_TERM_KEY_F10 | GRUB_TERM_ALT},
+ {"Console_23", GRUB_TERM_KEY_F11 | GRUB_TERM_ALT},
+ {"Console_24", GRUB_TERM_KEY_F12 | GRUB_TERM_ALT},
+ {"Console_25", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_26", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_27", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_28", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_29", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_30", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_31", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_32", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_33", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_34", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_35", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+ {"Console_36", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT | GRUB_TERM_ALT},
+
+ {"Insert", GRUB_TERM_KEY_INSERT},
+ {"Down", GRUB_TERM_KEY_DOWN},
+ {"Up", GRUB_TERM_KEY_UP},
+ {"Home", GRUB_TERM_KEY_HOME},
+ {"End", GRUB_TERM_KEY_END},
+ {"Right", GRUB_TERM_KEY_RIGHT},
+ {"Left", GRUB_TERM_KEY_LEFT},
+ {"Next", GRUB_TERM_KEY_NPAGE},
+ {"Prior", GRUB_TERM_KEY_PPAGE},
+ {"Remove", GRUB_TERM_KEY_DC},
+ {"VoidSymbol", 0},
+
+ /* "Undead" keys since no dead key support in GRUB. */
+ {"dead_acute", '\''},
+ {"dead_circumflex", '^'},
+ {"dead_grave", '`'},
+ {"dead_tilde", '~'},
+ {"dead_diaeresis", '"'},
+
+ /* Following ones don't provide any useful symbols for shell. */
+ {"dead_cedilla", 0},
+ {"dead_ogonek", 0},
+ {"dead_caron", 0},
+ {"dead_breve", 0},
+ {"dead_doubleacute", 0},
+
+ /* Unused in GRUB. */
+ {"Pause", 0},
+ {"Scroll_Forward", 0},
+ {"Scroll_Backward", 0},
+ {"Hex_0", 0},
+ {"Hex_1", 0},
+ {"Hex_2", 0},
+ {"Hex_3", 0},
+ {"Hex_4", 0},
+ {"Hex_5", 0},
+ {"Hex_6", 0},
+ {"Hex_7", 0},
+ {"Hex_8", 0},
+ {"Hex_9", 0},
+ {"Hex_A", 0},
+ {"Hex_B", 0},
+ {"Hex_C", 0},
+ {"Hex_D", 0},
+ {"Hex_E", 0},
+ {"Hex_F", 0},
+ {"Scroll_Lock", 0},
+ {"Show_Memory", 0},
+ {"Show_Registers", 0},
+ {"Control_backslash", 0},
+ {"Compose", 0},
+
+ {NULL, '\0'}
+};
+
+static grub_uint8_t linux_to_usb_map[128] = {
+ /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
+ /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
+ /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
+ /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
+ /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
+ /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
+ /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
+ /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
+ /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
+ /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
+ /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
+ /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
+ /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
+ /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
+ /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
+ /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
+ /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
+ /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
+ /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
+ /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
+ /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
+ /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
+ /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
+ /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
+ /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
+ /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
+ /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
+ /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
+ /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
+ /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
+ /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
+ /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
+ /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
+ /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
+ /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
+ /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
+ /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
+ /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
+ /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
+ /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
+ /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
+ /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT,
+ /* 0x54 */ 0, 0,
+ /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
+ /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
+ /* 0x5a */ 0, 0,
+ /* 0x5c */ 0, 0,
+ /* 0x5e */ 0, 0,
+ /* 0x60 */ GRUB_KEYBOARD_KEY_NUMENTER, GRUB_KEYBOARD_KEY_RIGHT_CTRL,
+ /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0,
+ /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0,
+ /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP,
+ /* 0x68 */ GRUB_KEYBOARD_KEY_PPAGE, GRUB_KEYBOARD_KEY_LEFT,
+ /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END,
+ /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_NPAGE,
+ /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE
+};
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS]\n\
+ -i, --input set input filename. Default is STDIN\n\
+ -o, --output set output filename. Default is STDOUT\n\
+ -h, --help display this message and exit.\n\
+ -V, --version print version information and exit.\n\
+ -v, --verbose print verbose messages.\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+static void
+add_special_keys (struct grub_keyboard_layout *layout)
+{
+ (void) layout;
+}
+
+static unsigned
+lookup (char *code, int shift)
+{
+ int i;
+ struct console_grub_equivalence *pr;
+
+ if (shift)
+ pr = console_grub_equivalences_shift;
+ else
+ pr = console_grub_equivalences_unshift;
+
+ for (i = 0; pr[i].layout != NULL; i++)
+ if (strcmp (code, pr[i].layout) == 0)
+ return pr[i].grub;
+
+ for (i = 0; console_grub_equivalences_common[i].layout != NULL; i++)
+ if (strcmp (code, console_grub_equivalences_common[i].layout) == 0)
+ return console_grub_equivalences_common[i].grub;
+
+ fprintf (stderr, "Unknown key %s\n", code);
+
+ return '\0';
+}
+
+static unsigned int
+get_grub_code (char *layout_code, int shift)
+{
+ unsigned int code;
+
+ if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0)
+ sscanf (layout_code, "U+%x", &code);
+ else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0)
+ sscanf (layout_code, "+U+%x", &code);
+ else
+ code = lookup (layout_code, shift);
+ return code;
+}
+
+static void
+write_file (FILE *out, struct grub_keyboard_layout *layout)
+{
+ grub_uint32_t version;
+ unsigned i;
+
+ version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION);
+
+ for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++)
+ layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]);
+
+ for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift); i++)
+ layout->keyboard_map_shift[i]
+ = grub_cpu_to_le32(layout->keyboard_map_shift[i]);
+
+ for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_l3); i++)
+ layout->keyboard_map_l3[i]
+ = grub_cpu_to_le32(layout->keyboard_map_l3[i]);
+
+ for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift_l3); i++)
+ layout->keyboard_map_shift_l3[i]
+ = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]);
+
+ fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1,
+ GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, out);
+ fwrite (&version, sizeof (version), 1, out);
+ fwrite (layout, 1, sizeof (*layout), out);
+}
+
+static void
+write_keymaps (FILE *in, FILE *out)
+{
+ struct grub_keyboard_layout layout;
+ char line[2048];
+ int ok;
+
+ memset (&layout, 0, sizeof (layout));
+
+ /* Process the ckbcomp output and prepare the layouts. */
+ ok = 0;
+ while (fgets (line, sizeof (line), in))
+ {
+ if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0)
+ {
+ unsigned keycode_linux;
+ unsigned keycode_usb;
+ char normal[64];
+ char shift[64];
+ char normalalt[64];
+ char shiftalt[64];
+
+ sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_linux,
+ normal, shift, normalalt, shiftalt);
+
+ /* Not used. */
+ if (keycode_linux == 0x77 /* Pause */
+ /* Some obscure keys */
+ || keycode_linux == 0x63 || keycode_linux == 0x7d
+ || keycode_linux == 0x7e)
+ continue;
+
+ /* Not remappable. */
+ if (keycode_linux == 0x1d /* Left CTRL */
+ || keycode_linux == 0x61 /* Right CTRL */
+ || keycode_linux == 0x2a /* Left Shift. */
+ || keycode_linux == 0x36 /* Right Shift. */
+ || keycode_linux == 0x38 /* Left ALT. */
+ || keycode_linux == 0x64 /* Right ALT. */
+ || keycode_linux == 0x3a /* CapsLock. */
+ || keycode_linux == 0x45 /* NumLock. */
+ || keycode_linux == 0x46 /* ScrollLock. */)
+ continue;
+
+ keycode_usb = linux_to_usb_map[keycode_linux];
+ if (keycode_usb == 0
+ || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE)
+ {
+ fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux);
+ continue;
+ }
+ if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE)
+ {
+ layout.keyboard_map[keycode_usb] = get_grub_code (normal, 0);
+ layout.keyboard_map_shift[keycode_usb] = get_grub_code (shift, 1);
+ layout.keyboard_map_l3[keycode_usb]
+ = get_grub_code (normalalt, 0);
+ layout.keyboard_map_shift_l3[keycode_usb]
+ = get_grub_code (shiftalt, 1);
+ ok = 1;
+ }
+ }
+ }
+
+ if (ok == 0)
+ {
+ fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n",
+ CKBCOMP);
+ exit (1);
+ }
+
+ add_special_keys (&layout);
+
+ write_file (out, &layout);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int verbosity;
+ char *infile_name = NULL;
+ char *outfile_name = NULL;
+ FILE *in, *out;
+
+ set_program_name (argv[0]);
+
+ verbosity = 0;
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "o:i:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'i':
+ infile_name = optarg;
+ break;
+
+ case 'o':
+ outfile_name = optarg;
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME,
+ PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (infile_name)
+ in = fopen (infile_name, "r");
+ else
+ in = stdin;
+
+ if (!in)
+ grub_util_error ("Couldn't open input file: %s\n", strerror (errno));
+
+ if (outfile_name)
+ out = fopen (outfile_name, "wb");
+ else
+ out = stdout;
+
+ if (!out)
+ {
+ if (in != stdin)
+ fclose (in);
+ grub_util_error ("Couldn't open output file: %s\n", strerror (errno));
+ }
+
+ write_keymaps (in, out);
+
+ if (in != stdin)
+ fclose (in);
+
+ if (out != stdout)
+ fclose (out);
+
+ return 0;
+}
diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in
new file mode 100644
index 0000000..b353e98
--- /dev/null
+++ b/util/grub-mknetdir.in
@@ -0,0 +1,230 @@
+#! /bin/sh
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+host_os=@host_os@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+localedir=@datadir@/locale
+native_platform=@platform@
+pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst"
+
+self=`basename $0`
+
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+rootdir=/srv/tftp
+grub_prefix=`echo /boot/grub | sed ${transform}`
+modules=
+
+install_device=
+no_floppy=
+recheck=no
+debug=no
+debug_image=
+subdir=`echo /boot/grub | sed ${transform}`
+pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] install_device
+Install GRUB on your drive.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ --modules=MODULES pre-load specified modules MODULES
+ --net-directory=DIR root directory of TFTP server
+ --subdir=DIR relative subdirectory on network server
+ --grub-mkimage=FILE use FILE as grub-mkimage
+
+$self copies GRUB images into net_directory/subdir/${target_cpu}-${platform}
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --modules)
+ modules=`argument $option "$@"`; shift;;
+ --modules=*)
+ modules=`echo "$option" | sed 's/--modules=//'` ;;
+
+ --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=//'` ;;
+
+ --grub-mkimage)
+ grub_mkimage=`argument $option "$@"`; shift;;
+ --grub-mkimage=*)
+ grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+
+ # 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=//'` ;;
+
+ # Intentionally undocumented
+ --override-directory)
+ override_dir=`argument $option "$@"`
+ shift
+ PATH=${override_dir}:$PATH
+ export PATH
+ ;;
+ --override-directory=*)
+ override_dir=`echo "${option}/" | sed 's/--override-directory=//'`
+ PATH=${override_dir}:$PATH
+ export PATH
+ ;;
+
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ *)
+ if test "x$install_device" != x; then
+ echo "More than one install_devices?" 1>&2
+ usage
+ exit 1
+ fi
+ install_device="${option}" ;;
+ esac
+done
+
+set $grub_mkimage dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 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=
+ mkdir -p "$grubdir" || exit 1
+
+ for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do
+ if test -f $file && [ "`basename $file`" != menu.lst ]; then
+ rm -f $file || exit 1
+ fi
+ done
+ for file in ${input_dir}/*.mod; do
+ if test -f "$file"; then
+ cp -f "$file" "$grubdir/"
+ fi
+ done
+ for file in ${pkglib_DATA}; do
+ if test -f "${input_dir}/${file}"; then
+ cp -f "${input_dir}/${file}" "$grubdir/"
+ fi
+ done
+
+ mkdir -p "$grubdir/locale"
+ for file in ${input_dir}/po/*.mo; do
+ if test -f "$file"; then
+ cp -f "$file" "$grubdir/locale/"
+ fi
+ done
+
+ 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
+
+ case "${platform}" in
+ i386-pc) mkimage_target=i386-pc-pxe;
+ netmodules="pxe";
+ prefix="(pxe)/${subdir}/${platform}";
+ ext=0 ;;
+ *) echo Unsupported platform ${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 $netmodules || exit 1
+ echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext"
+}
+
+if [ "${override_dir}" = "" ] ; then
+ if test -e "${pc_dir}" ; then
+ process_input_dir ${pc_dir} i386-pc
+ fi
+else
+ process_input_dir ${override_dir} ${target_cpu}-${native_platform}
+fi
+
+
+# Bye.
+exit 0
diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c
new file mode 100644
index 0000000..dc2afdb
--- /dev/null
+++ b/util/grub-mkpasswd-pbkdf2.c
@@ -0,0 +1,314 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1992-1999,2001,2003,2004,2005,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/types.h>
+#include <grub/crypto.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <termios.h>
+
+#include "progname.h"
+
+static struct option options[] =
+ {
+ {"iteration_count", required_argument, 0, 'c'},
+ {"buflen", required_argument, 0, 'l'},
+ {"saltlen", required_argument, 0, 's'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS]\n\
+\nOptions:\n\
+ -c number, --iteration-count=number Number of PBKDF2 iterations\n\
+ -l number, --buflen=number Length of generated hash\n\
+ -s number, --salt=number Length of salt\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+static void
+hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
+{
+ while (n--)
+ {
+ if (((*bin & 0xf0) >> 4) < 10)
+ *hex = ((*bin & 0xf0) >> 4) + '0';
+ else
+ *hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
+ hex++;
+
+ if ((*bin & 0xf) < 10)
+ *hex = (*bin & 0xf) + '0';
+ else
+ *hex = (*bin & 0xf) + 'A' - 10;
+ hex++;
+ bin++;
+ }
+ *hex = 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ unsigned int count = 10000, buflen = 64, saltlen = 64;
+ char *pass1, *pass2;
+ char *bufhex, *salthex;
+ gcry_err_code_t gcry_err;
+ grub_uint8_t *buf, *salt;
+ ssize_t nr;
+ FILE *in, *out;
+ struct termios s, t;
+ int tty_changed;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0);
+
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'c':
+ count = strtoul (optarg, NULL, 0);
+ break;
+
+ case 'l':
+ buflen = strtoul (optarg, NULL, 0);
+ break;
+
+ case 's':
+ saltlen = strtoul (optarg, NULL, 0);
+ break;
+
+ case 'h':
+ usage (0);
+ return 0;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name,
+ PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ default:
+ usage (1);
+ return 1;
+ }
+ }
+
+ bufhex = malloc (buflen * 2 + 1);
+ if (!bufhex)
+ grub_util_error ("out of memory");
+ buf = malloc (buflen);
+ if (!buf)
+ {
+ free (bufhex);
+ grub_util_error ("out of memory");
+ }
+
+ salt = malloc (saltlen);
+ if (!salt)
+ {
+ free (bufhex);
+ free (buf);
+ grub_util_error ("out of memory");
+ }
+ salthex = malloc (saltlen * 2 + 1);
+ if (!salthex)
+ {
+ free (salt);
+ free (bufhex);
+ free (buf);
+ grub_util_error ("out of memory");
+ }
+
+ /* Disable echoing. Based on glibc. */
+ in = fopen ("/dev/tty", "w+c");
+ if (in == NULL)
+ {
+ in = stdin;
+ out = stderr;
+ }
+ else
+ out = in;
+
+ if (tcgetattr (fileno (in), &t) == 0)
+ {
+ /* Save the old one. */
+ s = t;
+ /* Tricky, tricky. */
+ t.c_lflag &= ~(ECHO|ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
+ }
+ else
+ tty_changed = 0;
+
+ printf ("Enter password: ");
+ pass1 = NULL;
+ {
+ grub_size_t n;
+ nr = getline (&pass1, &n, stdin);
+ }
+ if (nr < 0 || !pass1)
+ {
+ free (buf);
+ free (bufhex);
+ free (salthex);
+ free (salt);
+ /* Restore the original setting. */
+ if (tty_changed)
+ (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
+ grub_util_error ("failure to read password");
+ }
+ if (nr >= 1 && pass1[nr-1] == '\n')
+ pass1[nr-1] = 0;
+
+ printf ("\nReenter password: ");
+ pass2 = NULL;
+ {
+ grub_size_t n;
+ nr = getline (&pass2, &n, stdin);
+ }
+ /* Restore the original setting. */
+ if (tty_changed)
+ (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
+ printf ("\n");
+
+ if (nr < 0 || !pass2)
+ {
+ memset (pass1, 0, strlen (pass1));
+ free (pass1);
+ free (buf);
+ free (bufhex);
+ free (salthex);
+ free (salt);
+ grub_util_error ("failure to read password");
+ }
+ if (nr >= 1 && pass2[nr-1] == '\n')
+ pass2[nr-1] = 0;
+
+ if (strcmp (pass1, pass2) != 0)
+ {
+ memset (pass1, 0, strlen (pass1));
+ memset (pass2, 0, strlen (pass2));
+ free (pass1);
+ free (pass2);
+ free (buf);
+ free (bufhex);
+ free (salthex);
+ free (salt);
+ grub_util_error ("passwords don't match");
+ }
+ memset (pass2, 0, strlen (pass2));
+ free (pass2);
+
+#if ! defined (__linux__) && ! defined (__FreeBSD__)
+ printf ("WARNING: your random generator isn't known to be secure\n");
+#endif
+
+ {
+ FILE *f;
+ size_t rd;
+ f = fopen ("/dev/urandom", "rb");
+ if (!f)
+ {
+ memset (pass1, 0, strlen (pass1));
+ free (pass1);
+ free (buf);
+ free (bufhex);
+ free (salthex);
+ free (salt);
+ fclose (f);
+ grub_util_error ("couldn't retrieve random data for salt");
+ }
+ rd = fread (salt, 1, saltlen, f);
+ if (rd != saltlen)
+ {
+ fclose (f);
+ memset (pass1, 0, strlen (pass1));
+ free (pass1);
+ free (buf);
+ free (bufhex);
+ free (salthex);
+ free (salt);
+ fclose (f);
+ grub_util_error ("couldn't retrieve random data for salt");
+ }
+ fclose (f);
+ }
+
+ gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
+ (grub_uint8_t *) pass1, strlen (pass1),
+ salt, saltlen,
+ count, buf, buflen);
+ memset (pass1, 0, strlen (pass1));
+ free (pass1);
+
+ if (gcry_err)
+ {
+ memset (buf, 0, buflen);
+ memset (bufhex, 0, 2 * buflen);
+ free (buf);
+ free (bufhex);
+ memset (salt, 0, saltlen);
+ memset (salthex, 0, 2 * saltlen);
+ free (salt);
+ free (salthex);
+ grub_util_error ("cryptographic error number %d", gcry_err);
+ }
+
+ hexify (bufhex, buf, buflen);
+ hexify (salthex, salt, saltlen);
+
+ printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n",
+ count, salthex, bufhex);
+ memset (buf, 0, buflen);
+ memset (bufhex, 0, 2 * buflen);
+ free (buf);
+ free (bufhex);
+ memset (salt, 0, saltlen);
+ memset (salthex, 0, 2 * saltlen);
+ free (salt);
+ free (salthex);
+
+ return 0;
+}
diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c
new file mode 100644
index 0000000..3fe3fe6
--- /dev/null
+++ b/util/grub-mkrelpath.c
@@ -0,0 +1,109 @@
+/* grub-mkrelpath.c - make a system path relative to its root */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <grub/util/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/i18n.h>
+#include <getopt.h>
+
+#include "progname.h"
+
+static struct option options[] =
+ {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS] PATH\n\
+\n\
+Make a system path relative to its root.\n\
+\n\
+Options:\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *argument, *relpath;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "hV", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (optind >= argc)
+ {
+ fprintf (stderr, "No path is specified.\n");
+ usage (1);
+ }
+
+ if (optind + 1 != argc)
+ {
+ fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+ usage (1);
+ }
+
+ argument = argv[optind];
+
+ relpath = grub_make_system_path_relative_to_its_root (argument);
+ printf ("%s\n", relpath);
+ free (relpath);
+
+ return 0;
+}
diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in
new file mode 100644
index 0000000..f7f7517
--- /dev/null
+++ b/util/grub-mkrescue.in
@@ -0,0 +1,315 @@
+#! /bin/sh
+set -e
+
+# 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 <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+native_platform=@platform@
+pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst"
+
+self=`basename $0`
+
+multiboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot
+coreboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot
+qemu_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu
+pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc
+efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi
+efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi
+rom_directory=
+override_dir=
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+
+xorriso=xorriso
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] SOURCE...
+Make GRUB rescue image.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ -o, --output=FILE save output in FILE [required]
+ --modules=MODULES pre-load specified modules MODULES
+ --rom-directory=DIR save rom images in DIR [optional]
+ --xorriso=FILE use FILE as xorriso [optional]
+ --grub-mkimage=FILE use FILE as grub-mkimage
+
+$self generates a bootable rescue image with specified source files, source
+directories, or mkisofs options listed by: xorriso -as mkisofs -help
+
+Option -- switches to native xorriso command mode.
+
+Report bugs to <bug-grub@gnu.org>.
+Mail xorriso support requests to <bug-xorriso@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --modules)
+ modules=`argument $option "$@"`; shift ;;
+ --modules=*)
+ modules=`echo "$option" | sed 's/--modules=//'` ;;
+
+ -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
+ --override-directory)
+ override_dir=`argument $option "$@"`
+ shift
+ PATH=${override_dir}:$PATH
+ export PATH
+ ;;
+ --override-directory=*)
+ override_dir=`echo "${option}/" | sed 's/--override-directory=//'`
+ PATH=${override_dir}:$PATH
+ export PATH
+ ;;
+
+ --grub-mkimage)
+ grub_mkimage=`argument $option "$@"`; shift ;;
+ --grub-mkimage=*)
+ grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+
+ --xorriso)
+ xorriso=`argument $option "$@"`; shift ;;
+ --xorriso=*)
+ xorriso=`echo "${option}/" | sed 's/--xorriso=//'` ;;
+
+ *)
+ source="${source} ${option} $@"; break ;;
+ esac
+done
+
+if [ "x${output_image}" = x ] ; then
+ echo "output file must be given" >&2
+ usage
+ exit 1
+fi
+
+set $grub_mkimage dummy
+if test -f "$1"; then
+ :
+else
+ echo "$1: Not found." 1>&2
+ exit 1
+fi
+
+iso9660_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+mkdir -p ${iso9660_dir}/boot/grub
+
+process_input_dir ()
+{
+ input_dir="$1"
+ platform="$2"
+ mkdir -p ${iso9660_dir}/boot/grub/${platform}
+ for file in "${input_dir}/"*.mod "${input_dir}/"efiemu32.o "${input_dir}/"efiemu64.o; do
+ if test -f "$file"; then
+ cp -f "$file" ${iso9660_dir}/boot/grub/${platform}/
+ fi
+ done
+ for file in ${pkglib_DATA}; do
+ if test -f "${input_dir}/${file}"; then
+ cp -f "${input_dir}/${file}" ${iso9660_dir}/boot/grub/${platform}/
+ fi
+ done
+
+ mkdir -p ${iso9660_dir}/boot/grub/locale
+ for file in ${input_dir}/po/*.mo; do
+ if test -f "$file"; then
+ cp -f "$file" ${iso9660_dir}/boot/grub/locale/
+ fi
+ done
+}
+
+make_image ()
+{
+ source_directory="$1"
+ platform=$2
+ if ! test -e "${source_directory}"; then
+ return;
+ fi
+
+ echo "Enabling $2 support ..."
+
+ memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+ memdisk_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+ mkdir -p ${memdisk_dir}/boot/grub
+
+ cat << EOF > ${memdisk_dir}/boot/grub/grub.cfg
+search --fs-uuid --set=root ${iso_uuid}
+set prefix=(\${root})/boot/grub/${platform}
+source \$prefix/grub.cfg
+EOF
+ (for i in $(cat ${source_directory}/partmap.lst) ${modules} ; do
+ echo "insmod $i"
+ done ; \
+ echo "source /boot/grub/grub.cfg") \
+ > ${iso9660_dir}/boot/grub/${platform}/grub.cfg
+
+ (cd "${memdisk_dir}"; tar -cf - boot) > "${memdisk_img}"
+ rm -rf ${memdisk_dir}
+ $grub_mkimage -O ${platform} -d "${source_directory}" -m "${memdisk_img}" -o "$3" --prefix='(memdisk)/boot/grub' \
+ search iso9660 configfile normal memdisk tar $4
+ rm -rf ${memdisk_img}
+}
+
+if [ "${override_dir}" = "" ] ; then
+ 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 "${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
+else
+ process_input_dir ${override_dir} ${target_cpu}-${native_platform}
+ multiboot_dir=
+ pc_dir=
+ efi32_dir=
+ efi64_dir=
+ coreboot_dir=
+ qemu_dir=
+ case "${target_cpu}-${native_platform}" in
+ i386-multiboot) multiboot_dir=${override_dir} ;;
+ i386-coreboot) coreboot_dir=${override_dir} ;;
+ i386-qemu) qemu_dir=${override_dir} ;;
+ i386-pc) pc_dir=${override_dir} ;;
+ i386-efi) efi32_dir=${override_dir} ;;
+ x86_64-efi) efi64_dir=${override_dir} ;;
+ 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
+ echo "Enabling BIOS support ..."
+ core_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+ $grub_mkimage -O i386-pc -d ${pc_dir}/ -o ${core_img} --prefix=/boot/grub/i386-pc \
+ iso9660 biosdisk
+ cat ${pc_dir}/cdboot.img ${core_img} > ${iso9660_dir}/boot/grub/i386-pc/eltorito.img
+
+ embed_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+ cat ${pc_dir}/boot.img ${core_img} > ${embed_img}
+
+ rm -f ${core_img}
+
+ (for i in $(cat ${pc_dir}/partmap.lst) ${modules} ; do
+ echo "insmod $i"
+ done ; \
+ echo "source /boot/grub/grub.cfg") \
+ > ${iso9660_dir}/boot/grub/i386-pc/grub.cfg
+
+ grub_mkisofs_arguments="${grub_mkisofs_arguments} -b boot/grub/i386-pc/eltorito.img -no-emul-boot -boot-info-table \
+ --embedded-boot ${embed_img}"
+fi
+
+# build multiboot core.img
+make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "ata at_keyboard"
+
+if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then
+ efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+ mkdir -p "${efi_dir}/efi/boot"
+
+ # build bootx64.efi
+ make_image "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi ""
+ # build bootia32.efi
+ make_image "${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
+
+ 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"
+fi
+
+make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "ata at_keyboard"
+if [ -e "${iso9660_dir}/boot/qemu.img" ] && [ -d "${rom_directory}" ]; then
+ cp "${iso9660_dir}/boot/qemu.img" "${rom_directory}/qemu.img"
+fi
+make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "ata at_keyboard"
+if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then
+ cp "${iso9660_dir}/boot/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 ${embed_img}
+
+exit 0
diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c
new file mode 100644
index 0000000..4b93faa
--- /dev/null
+++ b/util/grub-pe2elf.c
@@ -0,0 +1,537 @@
+/* grub-pe2elf.c - tool to convert pe image to elf. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/elf.h>
+#include <grub/efi/pe32.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include "progname.h"
+
+static struct option options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+};
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTIONS] input [output]\n\
+\n\
+Tool to convert pe image to elf.\n\
+\nOptions:\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+/*
+ * Section layout
+ *
+ * null
+ * .text
+ * .rdata
+ * .data
+ * .bss
+ * .modname
+ * .moddeps
+ * .symtab
+ * .strtab
+ * relocation sections
+ */
+
+#define TEXT_SECTION 1
+#define RDATA_SECTION 2
+#define DATA_SECTION 3
+#define BSS_SECTION 4
+#define MODNAME_SECTION 5
+#define MODDEPS_SECTION 6
+#define MODLICENSE_SECTION 7
+#define SYMTAB_SECTION 8
+#define STRTAB_SECTION 9
+
+#define REL_SECTION 10
+#define MAX_SECTIONS 16
+
+#define STRTAB_BLOCK 256
+
+static char *strtab;
+static int strtab_max, strtab_len;
+
+Elf32_Ehdr ehdr;
+Elf32_Shdr shdr[MAX_SECTIONS];
+int num_sections;
+grub_uint32_t offset;
+
+static int
+insert_string (const char *name)
+{
+ int len, result;
+
+ if (*name == '_')
+ name++;
+
+ len = strlen (name);
+ if (strtab_len + len >= strtab_max)
+ {
+ strtab_max += STRTAB_BLOCK;
+ strtab = xrealloc (strtab, strtab_max);
+ }
+
+ strcpy (strtab + strtab_len, name);
+ result = strtab_len;
+ strtab_len += len + 1;
+
+ return result;
+}
+
+static int *
+write_section_data (FILE* fp, char *image,
+ struct grub_pe32_coff_header *pe_chdr,
+ struct grub_pe32_section_table *pe_shdr)
+{
+ int *section_map;
+ int i;
+ char *pe_strtab = (image + pe_chdr->symtab_offset
+ + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
+
+ section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int));
+ section_map[0] = 0;
+
+ for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++)
+ {
+ grub_uint32_t idx;
+ const char *name = pe_shdr->name;
+
+ if (name[0] == '/' && isdigit (name[1]))
+ {
+ char t[sizeof (pe_shdr->name) + 1];
+ memcpy (t, name, sizeof (pe_shdr->name));
+ t[sizeof (pe_shdr->name)] = 0;
+ name = pe_strtab + atoi (t + 1);
+ }
+
+ if (! strcmp (name, ".text"))
+ {
+ idx = TEXT_SECTION;
+ shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+ }
+ else if (! strcmp (name, ".rdata"))
+ {
+ idx = RDATA_SECTION;
+ shdr[idx].sh_flags = SHF_ALLOC;
+ }
+ else if (! strcmp (name, ".data"))
+ {
+ idx = DATA_SECTION;
+ shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
+ }
+ else if (! strcmp (name, ".bss"))
+ {
+ idx = BSS_SECTION;
+ shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
+ }
+ else if (! strcmp (name, ".modname"))
+ idx = MODNAME_SECTION;
+ else if (! strcmp (name, ".moddeps"))
+ idx = MODDEPS_SECTION;
+ else if (strcmp (name, ".module_license") == 0)
+ idx = MODLICENSE_SECTION;
+ else
+ {
+ section_map[i + 1] = -1;
+ continue;
+ }
+
+ section_map[i + 1] = idx;
+
+ shdr[idx].sh_type = (idx == BSS_SECTION) ? SHT_NOBITS : SHT_PROGBITS;
+ shdr[idx].sh_size = pe_shdr->raw_data_size;
+ shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
+ GRUB_PE32_SCN_ALIGN_SHIFT) &
+ GRUB_PE32_SCN_ALIGN_MASK) - 1);
+
+ if (idx != BSS_SECTION)
+ {
+ shdr[idx].sh_offset = offset;
+ grub_util_write_image_at (image + pe_shdr->raw_data_offset,
+ pe_shdr->raw_data_size, offset, fp);
+
+ offset += pe_shdr->raw_data_size;
+ }
+
+ if (pe_shdr->relocations_offset)
+ {
+ char relname[5 + strlen (name)];
+
+ if (num_sections >= MAX_SECTIONS)
+ grub_util_error ("too many sections");
+
+ sprintf (relname, ".rel%s", name);
+
+ shdr[num_sections].sh_name = insert_string (relname);
+ shdr[num_sections].sh_link = i;
+ shdr[num_sections].sh_info = idx;
+
+ shdr[idx].sh_name = shdr[num_sections].sh_name + 4;
+
+ num_sections++;
+ }
+ else
+ shdr[idx].sh_name = insert_string (name);
+ }
+
+ return section_map;
+}
+
+static void
+write_reloc_section (FILE* fp, char *image,
+ struct grub_pe32_coff_header *pe_chdr,
+ struct grub_pe32_section_table *pe_shdr,
+ Elf32_Sym *symtab,
+ int *symtab_map)
+{
+ int i;
+
+ for (i = REL_SECTION; i < num_sections; i++)
+ {
+ struct grub_pe32_section_table *pe_sec;
+ struct grub_pe32_reloc *pe_rel;
+ Elf32_Rel *rel;
+ int num_rels, j, modified;
+
+ pe_sec = pe_shdr + shdr[i].sh_link;
+ pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
+ rel = (Elf32_Rel *) xmalloc (pe_sec->num_relocations * sizeof (Elf32_Rel));
+ num_rels = 0;
+ modified = 0;
+
+ for (j = 0; j < pe_sec->num_relocations; j++, pe_rel++)
+ {
+ int type;
+ grub_uint32_t ofs, *addr;
+
+ if ((pe_rel->symtab_index >= pe_chdr->num_symbols) ||
+ (symtab_map[pe_rel->symtab_index] == -1))
+ grub_util_error ("invalid symbol");
+
+ if (pe_rel->type == GRUB_PE32_REL_I386_DIR32)
+ type = R_386_32;
+ else if (pe_rel->type == GRUB_PE32_REL_I386_REL32)
+ type = R_386_PC32;
+ else
+ grub_util_error ("unknown pe relocation type %d\n", pe_rel->type);
+
+ ofs = pe_rel->offset - pe_sec->virtual_address;
+ addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs);
+ if (type == R_386_PC32)
+ {
+ unsigned char code;
+
+ code = image[pe_sec->raw_data_offset + ofs - 1];
+
+ if (((code != 0xe8) && (code != 0xe9)) || (*addr))
+ grub_util_error ("invalid relocation (%x %x)", code, *addr);
+
+ modified = 1;
+ if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx)
+ {
+ if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
+ != shdr[i].sh_info)
+ grub_util_error ("cross section call is not allowed");
+
+ *addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value
+ - ofs - 4);
+
+ continue;
+ }
+ else
+ *addr = -4;
+ }
+
+ rel[num_rels].r_offset = ofs;
+ rel[num_rels].r_info = ELF32_R_INFO (symtab_map[pe_rel->symtab_index],
+ type);
+ num_rels++;
+ }
+
+ if (modified)
+ grub_util_write_image_at (image + pe_sec->raw_data_offset,
+ shdr[shdr[i].sh_info].sh_size,
+ shdr[shdr[i].sh_info].sh_offset,
+ fp);
+
+ shdr[i].sh_type = SHT_REL;
+ shdr[i].sh_offset = offset;
+ shdr[i].sh_link = SYMTAB_SECTION;
+ shdr[i].sh_addralign = 4;
+ shdr[i].sh_entsize = sizeof (Elf32_Rel);
+ shdr[i].sh_size = num_rels * sizeof (Elf32_Rel);
+
+ grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp);
+ offset += shdr[i].sh_size;
+ free (rel);
+ }
+}
+
+static void
+write_symbol_table (FILE* fp, char *image,
+ struct grub_pe32_coff_header *pe_chdr,
+ struct grub_pe32_section_table *pe_shdr,
+ int *section_map)
+{
+ struct grub_pe32_symbol *pe_symtab;
+ char *pe_strtab;
+ Elf32_Sym *symtab;
+ int *symtab_map, num_syms;
+ int i;
+
+ pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
+ pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
+
+ symtab = (Elf32_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
+ sizeof (Elf32_Sym));
+ memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf32_Sym));
+ num_syms = 1;
+
+ symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
+
+ for (i = 0; i < (int) pe_chdr->num_symbols;
+ i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1)
+ {
+ int bind, type;
+
+ symtab_map[i] = -1;
+ if ((pe_symtab->section > pe_chdr->num_sections) ||
+ (section_map[pe_symtab->section] == -1))
+ continue;
+
+ if (! pe_symtab->section)
+ type = STT_NOTYPE;
+ else if (pe_symtab->type == GRUB_PE32_DT_FUNCTION)
+ type = STT_FUNC;
+ else
+ type = STT_OBJECT;
+
+ if (pe_symtab->storage_class == GRUB_PE32_SYM_CLASS_EXTERNAL)
+ bind = STB_GLOBAL;
+ else
+ bind = STB_LOCAL;
+
+ if ((pe_symtab->type != GRUB_PE32_DT_FUNCTION) && (pe_symtab->num_aux))
+ {
+ if (! pe_symtab->value)
+ type = STT_SECTION;
+
+ symtab[num_syms].st_name = shdr[section_map[pe_symtab->section]].sh_name;
+ }
+ else
+ {
+ char short_name[9];
+ char *name;
+
+ if (pe_symtab->long_name[0])
+ {
+ strncpy (short_name, pe_symtab->short_name, 8);
+ short_name[8] = 0;
+ name = short_name;
+ }
+ else
+ name = pe_strtab + pe_symtab->long_name[1];
+
+ if ((strcmp (name, "_grub_mod_init")) &&
+ (strcmp (name, "_grub_mod_fini")) &&
+ (bind == STB_LOCAL))
+ continue;
+
+ symtab[num_syms].st_name = insert_string (name);
+ }
+
+ symtab[num_syms].st_shndx = section_map[pe_symtab->section];
+ symtab[num_syms].st_value = pe_symtab->value;
+ symtab[num_syms].st_info = ELF32_ST_INFO (bind, type);
+
+ symtab_map[i] = num_syms;
+ num_syms++;
+ }
+
+ write_reloc_section (fp, image, pe_chdr, pe_shdr, symtab, symtab_map);
+
+ shdr[SYMTAB_SECTION].sh_name = insert_string (".symtab");
+ shdr[SYMTAB_SECTION].sh_type = SHT_SYMTAB;
+ shdr[SYMTAB_SECTION].sh_offset = offset;
+ shdr[SYMTAB_SECTION].sh_size = num_syms * sizeof (Elf32_Sym);
+ shdr[SYMTAB_SECTION].sh_entsize = sizeof (Elf32_Sym);
+ shdr[SYMTAB_SECTION].sh_link = STRTAB_SECTION;
+ shdr[SYMTAB_SECTION].sh_addralign = 4;
+
+ grub_util_write_image_at (symtab, shdr[SYMTAB_SECTION].sh_size,
+ offset, fp);
+ offset += shdr[SYMTAB_SECTION].sh_size;
+
+ free (symtab);
+ free (symtab_map);
+}
+
+static void
+write_string_table (FILE* fp)
+{
+ shdr[STRTAB_SECTION].sh_name = insert_string (".strtab");
+ shdr[STRTAB_SECTION].sh_type = SHT_STRTAB;
+ shdr[STRTAB_SECTION].sh_offset = offset;
+ shdr[STRTAB_SECTION].sh_size = strtab_len;
+ shdr[STRTAB_SECTION].sh_addralign = 1;
+ grub_util_write_image_at (strtab, strtab_len, offset, fp);
+ offset += strtab_len;
+
+ free (strtab);
+}
+
+static void
+write_section_header (FILE* fp)
+{
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_type = ET_REL;
+
+ ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr.e_machine = EM_386;
+
+ ehdr.e_ehsize = sizeof (ehdr);
+ ehdr.e_shentsize = sizeof (Elf32_Shdr);
+ ehdr.e_shstrndx = STRTAB_SECTION;
+
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = num_sections;
+ grub_util_write_image_at (&shdr, sizeof (Elf32_Shdr) * num_sections,
+ offset, fp);
+
+ grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp);
+}
+
+static void
+convert_pe (FILE* fp, char *image)
+{
+ struct grub_pe32_coff_header *pe_chdr;
+ struct grub_pe32_section_table *pe_shdr;
+ int *section_map;
+
+ pe_chdr = (struct grub_pe32_coff_header *) image;
+ if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386)
+ grub_util_error ("invalid coff image");
+
+ strtab = xmalloc (STRTAB_BLOCK);
+ strtab_max = STRTAB_BLOCK;
+ strtab[0] = 0;
+ strtab_len = 1;
+
+ offset = sizeof (ehdr);
+ pe_shdr = (struct grub_pe32_section_table *) (pe_chdr + 1);
+ num_sections = REL_SECTION;
+
+ section_map = write_section_data (fp, image, pe_chdr, pe_shdr);
+
+ write_symbol_table (fp, image, pe_chdr, pe_shdr, section_map);
+ free (section_map);
+
+ write_string_table (fp);
+
+ write_section_header (fp);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *image;
+ FILE* fp;
+
+ set_program_name (argv[0]);
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ /* Obtain PATH. */
+ if (optind >= argc)
+ {
+ fprintf (stderr, "Filename not specified.\n");
+ usage (1);
+ }
+
+ image = grub_util_read_image (argv[optind]);
+
+ if (optind + 1 < argc)
+ optind++;
+
+ fp = fopen (argv[optind], "wb");
+ if (! fp)
+ grub_util_error ("cannot open %s", argv[optind]);
+
+ convert_pe (fp, image);
+
+ fclose (fp);
+
+ return 0;
+}
diff --git a/util/grub-probe.c b/util/grub-probe.c
new file mode 100644
index 0000000..0d5dac9
--- /dev/null
+++ b/util/grub-probe.c
@@ -0,0 +1,419 @@
+/* grub-probe.c - probe device information for a given path */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/partition.h>
+#include <grub/msdos_partition.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+#include <grub/term.h>
+#include <grub/env.h>
+#include <grub/raid.h>
+#include <grub/i18n.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define _GNU_SOURCE 1
+#include <getopt.h>
+
+#include "progname.h"
+
+enum {
+ PRINT_FS,
+ PRINT_FS_UUID,
+ PRINT_FS_LABEL,
+ PRINT_DRIVE,
+ PRINT_DEVICE,
+ PRINT_PARTMAP,
+ PRINT_ABSTRACTION,
+};
+
+int print = PRINT_FS;
+static unsigned int argument_is_device = 0;
+
+static void
+probe_partmap (grub_disk_t disk)
+{
+ grub_partition_t part;
+
+ if (disk->partition == NULL)
+ {
+ grub_util_info ("no partition map found for %s", disk->name);
+ return;
+ }
+
+ for (part = disk->partition; part; part = part->parent)
+ printf ("%s\n", part->partmap->name);
+}
+
+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_RAID_ID)
+ return -1;
+
+ return ((struct grub_raid_array *) disk->data)->level;
+}
+
+static void
+probe (const char *path, char *device_name)
+{
+ char *drive_name = NULL;
+ char *grub_path = NULL;
+ char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
+ grub_device_t dev = NULL;
+ grub_fs_t fs;
+
+ if (path == NULL)
+ {
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+ if (! grub_util_check_char_device (device_name))
+ grub_util_error ("%s is not a character device", device_name);
+#else
+ if (! grub_util_check_block_device (device_name))
+ grub_util_error ("%s is not a block device", device_name);
+#endif
+ }
+ else
+ device_name = grub_guess_root_device (path);
+
+ if (! device_name)
+ grub_util_error ("cannot find a device for %s (is /dev mounted?)", path);
+
+ if (print == PRINT_DEVICE)
+ {
+ printf ("%s\n", device_name);
+ goto end;
+ }
+
+ drive_name = grub_util_get_grub_dev (device_name);
+ if (! drive_name)
+ grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name);
+
+ if (print == PRINT_DRIVE)
+ {
+ printf ("(%s)\n", drive_name);
+ goto end;
+ }
+
+ grub_util_info ("opening %s", drive_name);
+ dev = grub_device_open (drive_name);
+ if (! dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (print == PRINT_ABSTRACTION)
+ {
+ grub_disk_memberlist_t list = NULL, tmp;
+ const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
+ int is_raid = 0;
+ int is_raid5 = 0;
+ int is_raid6 = 0;
+ int raid_level;
+ grub_disk_t raid_disk;
+
+ raid_level = probe_raid_level (dev->disk);
+ if (raid_level >= 0)
+ {
+ is_raid = 1;
+ is_raid5 |= (raid_level == 5);
+ is_raid6 |= (raid_level == 6);
+ raid_disk = dev->disk;
+ }
+
+ if ((is_lvm) && (dev->disk->dev->memberlist))
+ list = dev->disk->dev->memberlist (dev->disk);
+ while (list)
+ {
+ raid_level = probe_raid_level (list->disk);
+ if (raid_level >= 0)
+ {
+ is_raid = 1;
+ is_raid5 |= (raid_level == 5);
+ is_raid6 |= (raid_level == 6);
+ raid_disk = list->disk;
+ }
+
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+
+ if (is_raid)
+ {
+ printf ("raid ");
+ if (is_raid5)
+ printf ("raid5rec ");
+ if (is_raid6)
+ printf ("raid6rec ");
+ if (raid_disk->dev->raidname)
+ printf ("%s ", raid_disk->dev->raidname (raid_disk));
+ }
+
+ if (is_lvm)
+ printf ("lvm ");
+
+ printf ("\n");
+
+ goto end;
+ }
+
+ if (print == PRINT_PARTMAP)
+ {
+ grub_disk_memberlist_t list = NULL, tmp;
+
+ /* Check if dev->disk itself is contained in a partmap. */
+ probe_partmap (dev->disk);
+
+ /* In case of LVM/RAID, check the member devices as well. */
+ if (dev->disk->dev->memberlist)
+ list = dev->disk->dev->memberlist (dev->disk);
+ while (list)
+ {
+ probe_partmap (list->disk);
+ /* LVM on RAID */
+ if (list->disk->dev->memberlist)
+ {
+ grub_disk_memberlist_t sub_list;
+
+ sub_list = list->disk->dev->memberlist (list->disk);
+ while (sub_list)
+ {
+ probe_partmap (sub_list->disk);
+ tmp = sub_list->next;
+ free (sub_list);
+ sub_list = tmp;
+ }
+ }
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+ goto end;
+ }
+
+ fs = grub_fs_probe (dev);
+ if (! fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (print == PRINT_FS)
+ {
+ printf ("%s\n", fs->name);
+ }
+ else if (print == PRINT_FS_UUID)
+ {
+ char *uuid;
+ if (! fs->uuid)
+ grub_util_error ("%s does not support UUIDs", fs->name);
+
+ if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE)
+ grub_util_error ("%s", grub_errmsg);
+
+ printf ("%s\n", uuid);
+ }
+ else if (print == PRINT_FS_LABEL)
+ {
+ char *label;
+ if (! fs->label)
+ grub_util_error ("%s does not support labels", fs->name);
+
+ if (fs->label (dev, &label) != GRUB_ERR_NONE)
+ grub_util_error ("%s", grub_errmsg);
+
+ printf ("%s\n", label);
+ }
+
+ end:
+ if (dev)
+ grub_device_close (dev);
+ free (grub_path);
+ free (filebuf_via_grub);
+ free (filebuf_via_sys);
+ free (drive_name);
+}
+
+static struct option options[] =
+ {
+ {"device", no_argument, 0, 'd'},
+ {"device-map", required_argument, 0, 'm'},
+ {"target", required_argument, 0, 't'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr,
+ "Try `%s --help' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [OPTION]... [PATH|DEVICE]\n\
+\n\
+Probe device information for a given path (or device, if the -d option is given).\n\
+\n\
+ -d, --device given argument is a system device, not a path\n\
+ -m, --device-map=FILE use FILE as the device map [default=%s]\n\
+ -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\
+ print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", program_name,
+ DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *dev_map = 0;
+ char *argument;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'd':
+ argument_is_device = 1;
+ break;
+
+ case 'm':
+ if (dev_map)
+ free (dev_map);
+
+ dev_map = xstrdup (optarg);
+ break;
+
+ case 't':
+ if (!strcmp (optarg, "fs"))
+ print = PRINT_FS;
+ else if (!strcmp (optarg, "fs_uuid"))
+ print = PRINT_FS_UUID;
+ else if (!strcmp (optarg, "fs_label"))
+ print = PRINT_FS_LABEL;
+ else if (!strcmp (optarg, "drive"))
+ print = PRINT_DRIVE;
+ else if (!strcmp (optarg, "device"))
+ print = PRINT_DEVICE;
+ else if (!strcmp (optarg, "partmap"))
+ print = PRINT_PARTMAP;
+ else if (!strcmp (optarg, "abstraction"))
+ print = PRINT_ABSTRACTION;
+ else
+ usage (1);
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ if (verbosity > 1)
+ grub_env_set ("debug", "all");
+
+ /* Obtain ARGUMENT. */
+ if (optind >= argc)
+ {
+ fprintf (stderr, "No path or device is specified.\n");
+ usage (1);
+ }
+
+ if (optind + 1 != argc)
+ {
+ fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+ usage (1);
+ }
+
+ argument = argv[optind];
+
+ /* Initialize the emulated biosdisk driver. */
+ grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
+
+ /* Initialize all modules. */
+ grub_init_all ();
+
+ grub_lvm_fini ();
+ grub_mdraid09_fini ();
+ grub_mdraid1x_fini ();
+ grub_raid_fini ();
+ grub_raid_init ();
+ grub_mdraid09_init ();
+ grub_mdraid1x_init ();
+ grub_lvm_init ();
+
+ /* Do it. */
+ if (argument_is_device)
+ probe (NULL, argument);
+ else
+ probe (argument, NULL);
+
+ /* Free resources. */
+ grub_fini_all ();
+ grub_util_biosdisk_fini ();
+
+ free (dev_map);
+
+ return 0;
+}
diff --git a/util/grub-reboot.in b/util/grub-reboot.in
new file mode 100644
index 0000000..929cf52
--- /dev/null
+++ b/util/grub-reboot.in
@@ -0,0 +1,135 @@
+#! /bin/sh
+#
+# Set a default boot entry for GRUB, for the next boot only.
+# Copyright (C) 2004,2009 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+
+self=`basename $0`
+
+grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
+rootdir=
+bootdir=
+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] entry
+Set the default boot entry for GRUB, for the next boot only.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@
+ instead of the $grubdir directory
+
+ENTRY is a number or a menu item title.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+# 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=//'` ;;
+
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ *)
+ if test "x$entry" != x; then
+ echo "More than one entry?" 1>&2
+ usage
+ exit 1
+ fi
+ entry="${option}" ;;
+ esac
+done
+
+if test "x$entry" = x; then
+ echo "entry not specified." 1>&2
+ usage
+ exit 1
+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'`
+
+prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'`
+if [ "$prev_saved_entry" ]; then
+ $grub_editenv ${grubdir}/grubenv set prev_saved_entry="$prev_saved_entry"
+else
+ # We need some non-empty value for prev_saved_entry so that GRUB will
+ # recognise that grub-reboot has been used and restore the previous
+ # saved entry. "0" is the same as an empty value, i.e. the first menu
+ # entry.
+ $grub_editenv ${grubdir}/grubenv set prev_saved_entry=0
+fi
+$grub_editenv ${grubdir}/grubenv set saved_entry="$entry"
+
+# Bye.
+exit 0
diff --git a/util/grub-script-check.c b/util/grub-script-check.c
new file mode 100644
index 0000000..2d1b31c
--- /dev/null
+++ b/util/grub-script-check.c
@@ -0,0 +1,201 @@
+/* grub-script-check.c - check grub script file for syntax errors */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+#include <grub/parser.h>
+#include <grub/script_sh.h>
+
+#define _GNU_SOURCE 1
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "progname.h"
+
+static struct option options[] =
+ {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+static void
+usage (int status)
+{
+ if (status)
+ fprintf (stderr,
+ "Try ``%s --help'' for more information.\n", program_name);
+ else
+ printf ("\
+Usage: %s [PATH]\n\
+\n\
+Checks GRUB script configuration file for syntax errors.\n\
+\n\
+ -h, --help display this message and exit\n\
+ -V, --version print version information and exit\n\
+ -v, --verbose print the script as it is being processed\n\
+\n\
+Report bugs to <%s>.\n\
+", program_name,
+ PACKAGE_BUGREPORT);
+ exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *argument;
+ char *input;
+ int lineno = 0;
+ FILE *file = 0;
+ int verbose = 0;
+ int found_input = 0;
+ struct grub_script *script = NULL;
+
+ auto grub_err_t get_config_line (char **line, int cont);
+ grub_err_t get_config_line (char **line, int cont __attribute__ ((unused)))
+ {
+ int i;
+ char *cmdline = 0;
+ size_t len = 0;
+ ssize_t read;
+
+ read = getline(&cmdline, &len, (file ?: stdin));
+ if (read == -1)
+ {
+ *line = 0;
+ grub_errno = GRUB_ERR_READ_ERROR;
+
+ if (cmdline)
+ free (cmdline);
+ return grub_errno;
+ }
+
+ if (verbose)
+ grub_printf("%s", cmdline);
+
+ for (i = 0; cmdline[i] != '\0'; i++)
+ {
+ /* Replace tabs and carriage returns with spaces. */
+ if (cmdline[i] == '\t' || cmdline[i] == '\r')
+ cmdline[i] = ' ';
+
+ /* Replace '\n' with '\0'. */
+ if (cmdline[i] == '\n')
+ cmdline[i] = '\0';
+ }
+
+ lineno++;
+ *line = grub_strdup (cmdline);
+
+ free (cmdline);
+ return 0;
+ }
+
+ set_program_name (argv[0]);
+ grub_util_init_nls ();
+
+ /* Check for options. */
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "hvV", options, 0);
+
+ if (c == -1)
+ break;
+ else
+ switch (c)
+ {
+ case 'h':
+ usage (0);
+ break;
+
+ case 'V':
+ printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+ return 0;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ default:
+ usage (1);
+ break;
+ }
+ }
+
+ /* Obtain ARGUMENT. */
+ if (optind >= argc)
+ {
+ file = 0; /* read from stdin */
+ }
+ else if (optind + 1 != argc)
+ {
+ fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+ usage (1);
+ }
+ else
+ {
+ argument = argv[optind];
+ file = fopen (argument, "r");
+ if (! file)
+ {
+ fprintf (stderr, "%s: %s: %s\n", program_name, argument, strerror(errno));
+ usage (1);
+ }
+ }
+
+ do
+ {
+ input = 0;
+ get_config_line(&input, 0);
+ if (! input)
+ break;
+ found_input = 1;
+
+ script = grub_script_parse (input, get_config_line);
+ if (script)
+ {
+ grub_script_execute (script);
+ grub_script_free (script);
+ }
+
+ grub_free (input);
+ } while (script != 0);
+
+ if (file) fclose (file);
+
+ if (found_input && script == 0)
+ {
+ fprintf (stderr, "error: line no: %u\n", lineno);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/util/grub-set-default.in b/util/grub-set-default.in
new file mode 100644
index 0000000..b09727d
--- /dev/null
+++ b/util/grub-set-default.in
@@ -0,0 +1,126 @@
+#! /bin/sh
+#
+# Set a default boot entry for GRUB.
+# Copyright (C) 2004,2009 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+
+self=`basename $0`
+
+grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
+rootdir=
+bootdir=
+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] entry
+Set the default boot entry for GRUB.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@
+ instead of the $grubdir directory
+
+ENTRY is a number or a menu item title.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+# 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=//'` ;;
+
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ *)
+ if test "x$entry" != x; then
+ echo "More than one entry?" 1>&2
+ usage
+ exit 1
+ fi
+ entry="${option}" ;;
+ esac
+done
+
+if test "x$entry" = x; then
+ echo "entry not specified." 1>&2
+ usage
+ exit 1
+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'`
+
+$grub_editenv ${grubdir}/grubenv unset prev_saved_entry
+$grub_editenv ${grubdir}/grubenv set saved_entry="$entry"
+
+# Bye.
+exit 0
diff --git a/util/grub-setup.c b/util/grub-setup.c
new file mode 100644
index 0000000..7d47fa6
--- /dev/null
+++ b/util/grub-setup.c
@@ -0,0 +1,1017 @@
+/* grub-setup.c - make GRUB usable */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/partition.h>
+#include <grub/env.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.h>
+#include <grub/term.h>
+#include <grub/i18n.h>
+#include <grub/util/raid.h>
+#include <grub/util/lvm.h>
+#ifdef GRUB_MACHINE_IEEE1275
+#include <grub/util/ofpath.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <assert.h>
+#include <grub/emu/getroot.h>
+#include "progname.h"
+#include <grub/reed_solomon.h>
+#include <grub/msdos_partition.h>
+
+#define _GNU_SOURCE 1
+#include <argp.h>
+
+/* On SPARC this program fills in various fields inside of the 'boot' and 'core'
+ * image files.
+ *
+ * The 'boot' image needs to know the OBP path name of the root
+ * device. It also needs to know the initial block number of
+ * 'core' (which is 'diskboot' concatenated with 'kernel' and
+ * all the modules, this is created by grub-mkimage). This resulting
+ * 'boot' image is 512 bytes in size and is placed in the second block
+ * of a partition.
+ *
+ * The initial 'diskboot' block acts as a loader for the actual GRUB
+ * kernel. It contains the loading code and then a block list.
+ *
+ * The block list of 'core' starts at the end of the 'diskboot' image
+ * and works it's way backwards towards the end of the code of 'diskboot'.
+ *
+ * We patch up the images with the necessary values and write out the
+ * result.
+ */
+
+#define DEFAULT_BOOT_FILE "boot.img"
+#define DEFAULT_CORE_FILE "core.img"
+
+#ifdef GRUB_MACHINE_SPARC64
+#define grub_target_to_host16(x) grub_be_to_cpu16(x)
+#define grub_target_to_host32(x) grub_be_to_cpu32(x)
+#define grub_target_to_host64(x) grub_be_to_cpu64(x)
+#define grub_host_to_target16(x) grub_cpu_to_be16(x)
+#define grub_host_to_target32(x) grub_cpu_to_be32(x)
+#define grub_host_to_target64(x) grub_cpu_to_be64(x)
+#elif defined (GRUB_MACHINE_PCBIOS)
+#define grub_target_to_host16(x) grub_le_to_cpu16(x)
+#define grub_target_to_host32(x) grub_le_to_cpu32(x)
+#define grub_target_to_host64(x) grub_le_to_cpu64(x)
+#define grub_host_to_target16(x) grub_cpu_to_le16(x)
+#define grub_host_to_target32(x) grub_cpu_to_le32(x)
+#define grub_host_to_target64(x) grub_cpu_to_le64(x)
+#else
+#error Complete this
+#endif
+
+static void
+write_rootdev (char *core_img, grub_device_t root_dev,
+ char *boot_img, grub_uint64_t first_sector)
+{
+#ifdef GRUB_MACHINE_PCBIOS
+ {
+ grub_int32_t *install_dos_part, *install_bsd_part;
+ grub_int32_t dos_part, bsd_part;
+ grub_uint8_t *boot_drive;
+ grub_disk_addr_t *kernel_sector;
+ boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE);
+ kernel_sector = (grub_disk_addr_t *) (boot_img
+ + GRUB_BOOT_MACHINE_KERNEL_SECTOR);
+
+
+ install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+ + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART);
+ install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+ + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART);
+
+ /* If we hardcoded drive as part of prefix, we don't want to
+ override the current setting. */
+ if (*install_dos_part != -2)
+ {
+ /* Embed information about the installed location. */
+ if (root_dev->disk->partition)
+ {
+ if (root_dev->disk->partition->parent)
+ {
+ if (root_dev->disk->partition->parent->parent)
+ grub_util_error ("Installing on doubly nested partitions is "
+ "not supported");
+ dos_part = root_dev->disk->partition->parent->number;
+ bsd_part = root_dev->disk->partition->number;
+ }
+ else
+ {
+ dos_part = root_dev->disk->partition->number;
+ bsd_part = -1;
+ }
+ }
+ else
+ dos_part = bsd_part = -1;
+ }
+ else
+ {
+ dos_part = grub_le_to_cpu32 (*install_dos_part);
+ bsd_part = grub_le_to_cpu32 (*install_bsd_part);
+ }
+
+ grub_util_info ("dos partition is %d, bsd partition is %d",
+ dos_part, bsd_part);
+
+ *install_dos_part = grub_cpu_to_le32 (dos_part);
+ *install_bsd_part = grub_cpu_to_le32 (bsd_part);
+
+ /* FIXME: can this be skipped? */
+ *boot_drive = 0xFF;
+
+ *kernel_sector = grub_cpu_to_le64 (first_sector);
+ }
+#endif
+#ifdef GRUB_MACHINE_IEEE1275
+ {
+ grub_disk_addr_t *kernel_byte;
+ kernel_byte = (grub_disk_addr_t *) (boot_img
+ + GRUB_BOOT_AOUT_HEADER_SIZE
+ + GRUB_BOOT_MACHINE_KERNEL_BYTE);
+ *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS);
+ }
+#endif
+}
+
+#ifdef GRUB_MACHINE_IEEE1275
+#define BOOT_SECTOR 1
+#else
+#define BOOT_SECTOR 0
+#endif
+
+static void
+setup (const char *dir,
+ const char *boot_file, const char *core_file,
+ const char *root, const char *dest, int must_embed, int force,
+ int fs_probe, int allow_floppy)
+{
+ char *boot_path, *core_path, *core_path_dev, *core_path_dev_full;
+ char *boot_img, *core_img;
+ size_t boot_size, core_size;
+ grub_uint16_t core_sectors;
+ grub_device_t root_dev, dest_dev;
+ struct grub_boot_blocklist *first_block, *block;
+ char *tmp_img;
+ int i;
+ grub_disk_addr_t first_sector;
+#ifdef GRUB_MACHINE_PCBIOS
+ grub_uint16_t current_segment
+ = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
+#endif
+ grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
+ grub_file_t file;
+ FILE *fp;
+
+ auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length);
+ auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length);
+
+ void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length)
+ {
+ grub_util_info ("the first sector is <%llu,%u,%u>",
+ sector, offset, length);
+
+ if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("the first sector of the core file is not sector-aligned"));
+
+ first_sector = sector;
+ }
+
+ void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
+ unsigned offset,
+ unsigned length)
+ {
+ struct grub_boot_blocklist *prev = block + 1;
+
+ grub_util_info ("saving <%llu,%u,%u>", sector, offset, length);
+
+ if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("non-sector-aligned data is found in the core file"));
+
+ if (block != first_block
+ && (grub_target_to_host64 (prev->start)
+ + grub_target_to_host16 (prev->len)) == sector)
+ prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1);
+ else
+ {
+ block->start = grub_host_to_target64 (sector);
+ block->len = grub_host_to_target16 (1);
+#ifdef GRUB_MACHINE_PCBIOS
+ block->segment = grub_host_to_target16 (current_segment);
+#endif
+
+ block--;
+ if (block->len)
+ grub_util_error (_("the sectors of the core file are too fragmented"));
+ }
+
+ last_length = length;
+#ifdef GRUB_MACHINE_PCBIOS
+ current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+#endif
+ }
+
+ /* Read the boot image by the OS service. */
+ boot_path = grub_util_get_path (dir, boot_file);
+ boot_size = grub_util_get_image_size (boot_path);
+ if (boot_size != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("the size of `%s' is not %u"),
+ boot_path, GRUB_DISK_SECTOR_SIZE);
+ boot_img = grub_util_read_image (boot_path);
+ free (boot_path);
+
+ core_path = grub_util_get_path (dir, core_file);
+ core_size = grub_util_get_image_size (core_path);
+ core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS);
+ if (core_size < GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("the size of `%s' is too small"), core_path);
+#ifdef GRUB_MACHINE_PCBIOS
+ if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("the size of `%s' is too large"), core_path);
+#endif
+
+ core_img = grub_util_read_image (core_path);
+
+ /* Have FIRST_BLOCK to point to the first blocklist. */
+ first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*block));
+ grub_util_info ("root is `%s', dest is `%s'", root, dest);
+
+ /* Open the root device and the destination device. */
+ grub_util_info ("Opening root");
+ root_dev = grub_device_open (root);
+ if (! root_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ grub_util_info ("Opening dest");
+ dest_dev = grub_device_open (dest);
+ if (! dest_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ grub_util_info ("setting the root device to `%s'", root);
+ if (grub_env_set ("root", root) != GRUB_ERR_NONE)
+ grub_util_error ("%s", grub_errmsg);
+
+#ifdef GRUB_MACHINE_PCBIOS
+ /* Read the original sector from the disk. */
+ tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE);
+ if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img))
+ grub_util_error ("%s", grub_errmsg);
+#endif
+
+#ifdef GRUB_MACHINE_PCBIOS
+ {
+ grub_uint16_t *boot_drive_check;
+ boot_drive_check = (grub_uint16_t *) (boot_img
+ + GRUB_BOOT_MACHINE_DRIVE_CHECK);
+ /* Copy the possible DOS BPB. */
+ memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START,
+ tmp_img + GRUB_BOOT_MACHINE_BPB_START,
+ GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START);
+
+ /* If DEST_DRIVE is a hard disk, enable the workaround, which is
+ for buggy BIOSes which don't pass boot drive correctly. Instead,
+ they pass 0x00 or 0x01 even when booted from 0x80. */
+ if (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk))
+ /* Replace the jmp (2 bytes) with double nop's. */
+ *boot_drive_check = 0x9090;
+ }
+#endif
+
+#ifdef GRUB_MACHINE_PCBIOS
+ {
+ grub_partition_map_t dest_partmap = NULL;
+ grub_partition_t container = dest_dev->disk->partition;
+ int multiple_partmaps = 0;
+ grub_err_t err;
+ grub_disk_addr_t *sectors;
+ int i;
+ grub_fs_t fs;
+ unsigned int nsec;
+
+ /* Unlike root_dev, with dest_dev we're interested in the partition map even
+ if dest_dev itself is a whole disk. */
+ auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk,
+ const grub_partition_t p);
+ int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)),
+ const grub_partition_t p)
+ {
+ if (p->parent != container)
+ return 0;
+ /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
+ so they are safe to ignore.
+ */
+ if (grub_strcmp (p->partmap->name, "netbsd") == 0
+ || grub_strcmp (p->partmap->name, "openbsd") == 0)
+ return 0;
+ if (dest_partmap == NULL)
+ {
+ dest_partmap = p->partmap;
+ return 0;
+ }
+ if (dest_partmap == p->partmap)
+ return 0;
+ multiple_partmaps = 1;
+ return 1;
+ }
+
+ grub_partition_iterate (dest_dev->disk, identify_partmap);
+
+ if (container && grub_strcmp (container->partmap->name, "msdos") == 0
+ && dest_partmap
+ && (container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
+ || container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
+ {
+ grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
+ goto unable_to_embed;
+ }
+
+ fs = grub_fs_probe (dest_dev);
+ if (!fs)
+ grub_errno = GRUB_ERR_NONE;
+
+#ifdef GRUB_MACHINE_PCBIOS
+ if (fs_probe)
+ {
+ if (!fs && !dest_partmap)
+ grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
+ dest_dev->disk->name);
+ if (fs && !fs->reserved_first_sector)
+ grub_util_error (_("%s appears to contain a %s filesystem which isn't known to "
+ "reserve space for DOS-style boot. Installing GRUB there could "
+ "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
+ "by grub-setup (--skip-fs-probe disables this "
+ "check, use at your own risk)"), dest_dev->disk->name, fs->name);
+
+ if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0
+ && strcmp (dest_partmap->name, "gpt") != 0
+ && strcmp (dest_partmap->name, "bsd") != 0
+ && strcmp (dest_partmap->name, "netbsd") != 0
+ && strcmp (dest_partmap->name, "openbsd") != 0
+ && strcmp (dest_partmap->name, "sunpc") != 0)
+ grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
+ "reserve space for DOS-style boot. Installing GRUB there could "
+ "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
+ "by grub-setup (--skip-fs-probe disables this "
+ "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name);
+ }
+#endif
+
+ /* Copy the partition table. */
+ if (dest_partmap ||
+ (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)))
+ memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
+ tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
+ GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
+
+ free (tmp_img);
+
+ if (! dest_partmap)
+ {
+ grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
+ goto unable_to_embed;
+ }
+ if (multiple_partmaps || fs)
+ {
+ grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet."));
+ goto unable_to_embed;
+ }
+
+ if (!dest_partmap->embed)
+ {
+ grub_util_warn ("Partition style '%s' doesn't support embeding",
+ dest_partmap->name);
+ goto unable_to_embed;
+ }
+
+ nsec = core_sectors;
+ err = dest_partmap->embed (dest_dev->disk, &nsec,
+ GRUB_EMBED_PCBIOS, &sectors);
+ if (nsec > 2 * core_sectors)
+ nsec = 2 * core_sectors;
+
+ if (err)
+ {
+ grub_util_warn ("%s", grub_errmsg);
+ grub_errno = GRUB_ERR_NONE;
+ goto unable_to_embed;
+ }
+
+ /* Clean out the blocklists. */
+ block = first_block;
+ while (block->len)
+ {
+ grub_memset (block, 0, sizeof (block));
+
+ block--;
+
+ if ((char *) block <= core_img)
+ grub_util_error ("No terminator in the core image");
+ }
+
+ save_first_sector (sectors[0] + grub_partition_get_start (container),
+ 0, GRUB_DISK_SECTOR_SIZE);
+
+ block = first_block;
+ for (i = 1; i < nsec; i++)
+ save_blocklists (sectors[i] + grub_partition_get_start (container),
+ 0, GRUB_DISK_SECTOR_SIZE);
+
+ write_rootdev (core_img, root_dev, boot_img, first_sector);
+
+ core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
+ first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*block));
+
+ *(grub_uint32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+ + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY)
+ = grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size);
+
+ grub_reed_solomon_add_redundancy (core_img + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + GRUB_DISK_SECTOR_SIZE,
+ core_size - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - GRUB_DISK_SECTOR_SIZE,
+ nsec * GRUB_DISK_SECTOR_SIZE
+ - core_size);
+
+ /* Make sure that the second blocklist is a terminator. */
+ block = first_block - 1;
+ block->start = 0;
+ block->len = 0;
+ block->segment = 0;
+
+ /* Write the core image onto the disk. */
+ for (i = 0; i < nsec; i++)
+ grub_disk_write (dest_dev->disk, sectors[i], 0,
+ GRUB_DISK_SECTOR_SIZE,
+ core_img + i * GRUB_DISK_SECTOR_SIZE);
+
+ grub_free (sectors);
+
+ goto finish;
+ }
+#endif
+
+unable_to_embed:
+
+ if (must_embed)
+ grub_util_error (_("embedding is not possible, but this is required when "
+ "the root device is on a RAID array or LVM volume"));
+
+#ifdef GRUB_MACHINE_PCBIOS
+ if (dest_dev->disk->id != root_dev->disk->id)
+ grub_util_error (_("embedding is not possible, but this is required for "
+ "cross-disk install"));
+#endif
+
+ grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this "
+ "setup by using blocklists. However, blocklists are UNRELIABLE and "
+ "their use is discouraged."));
+ if (! force)
+ grub_util_error (_("will not proceed with blocklists"));
+
+ /* The core image must be put on a filesystem unfortunately. */
+ grub_util_info ("will leave the core image on the filesystem");
+
+ /* Make sure that GRUB reads the identical image as the OS. */
+ tmp_img = xmalloc (core_size);
+ core_path_dev_full = grub_util_get_path (dir, core_file);
+ core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full);
+ free (core_path_dev_full);
+
+ grub_util_biosdisk_flush (root_dev->disk);
+
+#define MAX_TRIES 5
+
+ for (i = 0; i < MAX_TRIES; i++)
+ {
+ grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB")
+ : _("attempting to read the core image `%s' from GRUB again"),
+ core_path_dev);
+
+ grub_disk_cache_invalidate_all ();
+
+ grub_file_filter_disable_compression ();
+ file = grub_file_open (core_path_dev);
+ if (file)
+ {
+ if (grub_file_size (file) != core_size)
+ grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
+ (int) grub_file_size (file), (int) core_size);
+ else if (grub_file_read (file, tmp_img, core_size)
+ != (grub_ssize_t) core_size)
+ grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
+ (int) core_size);
+ else if (memcmp (core_img, tmp_img, core_size) != 0)
+ {
+#if 0
+ FILE *dump;
+ FILE *dump2;
+
+ dump = fopen ("dump.img", "wb");
+ if (dump)
+ {
+ fwrite (tmp_img, 1, core_size, dump);
+ fclose (dump);
+ }
+
+ dump2 = fopen ("dump2.img", "wb");
+ if (dump2)
+ {
+ fwrite (core_img, 1, core_size, dump2);
+ fclose (dump2);
+ }
+
+#endif
+ grub_util_info ("succeeded in opening the core image but the data is different");
+ }
+ else
+ {
+ grub_file_close (file);
+ break;
+ }
+
+ grub_file_close (file);
+ }
+ else
+ grub_util_info ("couldn't open the core image");
+
+ if (grub_errno)
+ grub_util_info ("error message = %s", grub_errmsg);
+
+ grub_errno = GRUB_ERR_NONE;
+ grub_util_biosdisk_flush (root_dev->disk);
+ sleep (1);
+ }
+
+ if (i == MAX_TRIES)
+ grub_util_error (_("cannot read `%s' correctly"), core_path_dev);
+
+ /* Clean out the blocklists. */
+ block = first_block;
+ while (block->len)
+ {
+ block->start = 0;
+ block->len = 0;
+#ifdef GRUB_MACHINE_PCBIOS
+ block->segment = 0;
+#endif
+
+ block--;
+
+ if ((char *) block <= core_img)
+ grub_util_error (_("no terminator in the core image"));
+ }
+
+ /* Now read the core image to determine where the sectors are. */
+ grub_file_filter_disable_compression ();
+ file = grub_file_open (core_path_dev);
+ if (! file)
+ grub_util_error ("%s", grub_errmsg);
+
+ file->read_hook = save_first_sector;
+ if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
+ != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("failed to read the first sector of the core image"));
+
+ block = first_block;
+ file->read_hook = save_blocklists;
+ if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
+ != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("failed to read the rest sectors of the core image"));
+
+#ifdef GRUB_MACHINE_IEEE1275
+ {
+ char *boot_devpath;
+ boot_devpath = (char *) (boot_img
+ + GRUB_BOOT_AOUT_HEADER_SIZE
+ + GRUB_BOOT_MACHINE_BOOT_DEVPATH);
+ if (file->device->disk->id != dest_dev->disk->id)
+ {
+ const char *dest_ofpath;
+ dest_ofpath
+ = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk));
+ grub_util_info ("dest_ofpath is `%s'", dest_ofpath);
+ strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
+ - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1);
+ boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
+ - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0;
+ }
+ else
+ {
+ grub_util_info ("non cross-disk install");
+ memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
+ - GRUB_BOOT_MACHINE_BOOT_DEVPATH);
+ }
+ grub_util_info ("boot device path %s", boot_devpath);
+ }
+#endif
+
+ grub_file_close (file);
+
+ free (core_path_dev);
+ free (tmp_img);
+
+ write_rootdev (core_img, root_dev, boot_img, first_sector);
+
+ /* Write the first two sectors of the core image onto the disk. */
+ grub_util_info ("opening the core image `%s'", core_path);
+ fp = fopen (core_path, "r+b");
+ if (! fp)
+ grub_util_error (_("cannot open `%s'"), core_path);
+
+ grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp);
+ fclose (fp);
+
+ finish:
+
+ /* Write the boot image onto the disk. */
+ if (grub_disk_write (dest_dev->disk, BOOT_SECTOR,
+ 0, GRUB_DISK_SECTOR_SIZE, boot_img))
+ grub_util_error ("%s", grub_errmsg);
+
+
+ grub_util_biosdisk_flush (root_dev->disk);
+ grub_util_biosdisk_flush (dest_dev->disk);
+
+ free (core_path);
+ free (core_img);
+ free (boot_img);
+ grub_device_close (dest_dev);
+ grub_device_close (root_dev);
+}
+
+static struct argp_option options[] = {
+ {"boot-image", 'b', N_("FILE"), 0,
+ N_("Use FILE as the boot image [default=%s]"), 0},
+ {"core-image", 'c', N_("FILE"), 0,
+ N_("Use FILE as the core image [default=%s]"), 0},
+ {"directory", 'd', N_("DIR"), 0,
+ N_("Use GRUB files in the directory DIR [default=%s]"), 0},
+ {"device-map", 'm', N_("FILE"), 0,
+ N_("Use FILE as the device map [default=%s]"), 0},
+ {"root-device", 'r', N_("DEV"), 0,
+ N_("Use DEV as the root device [default=guessed]"), 0},
+ {"force", 'f', 0, 0,
+ N_("Install even if problems are detected"), 0},
+ {"skip-fs-probe",'s',0, 0,
+ N_("Do not probe for filesystems in DEVICE"), 0},
+ {"verbose", 'v', 0, 0,
+ N_("Print verbose messages."), 0},
+ {"allow-floppy", 'a', 0, 0,
+ N_("Make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0},
+
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+ switch (key)
+ {
+ case 'b':
+ return xasprintf (text, DEFAULT_BOOT_FILE);
+
+ case 'c':
+ return xasprintf (text, DEFAULT_CORE_FILE);
+
+ case 'd':
+ return xasprintf (text, DEFAULT_DIRECTORY);
+
+ case 'm':
+ return xasprintf (text, DEFAULT_DEVICE_MAP);
+
+ default:
+ return (char *) text;
+ }
+}
+
+struct arguments
+{
+ char *boot_file;
+ char *core_file;
+ char *dir;
+ char *dev_map;
+ char *root_dev;
+ int force;
+ int fs_probe;
+ int allow_floppy;
+ char *device;
+};
+
+/* Print the version information. */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+ fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
+}
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Set the bug report address */
+const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">";
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ /* Get the input argument from argp_parse, which we
+ know is a pointer to our arguments structure. */
+ struct arguments *arguments = state->input;
+
+ char *p;
+
+ switch (key)
+ {
+ case 'a':
+ arguments->allow_floppy = 1;
+ break;
+
+ case 'b':
+ if (arguments->boot_file)
+ free (arguments->boot_file);
+
+ arguments->boot_file = xstrdup (arg);
+ break;
+
+ case 'c':
+ if (arguments->core_file)
+ free (arguments->core_file);
+
+ arguments->core_file = xstrdup (arg);
+ break;
+
+ case 'd':
+ if (arguments->dir)
+ free (arguments->dir);
+
+ arguments->dir = xstrdup (arg);
+ break;
+
+ case 'm':
+ if (arguments->dev_map)
+ free (arguments->dev_map);
+
+ arguments->dev_map = xstrdup (arg);
+ break;
+
+ case 'r':
+ if (arguments->root_dev)
+ free (arguments->root_dev);
+
+ arguments->root_dev = xstrdup (arg);
+ break;
+
+ case 'f':
+ arguments->force = 1;
+ break;
+
+ case 's':
+ arguments->fs_probe = 0;
+ break;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ case ARGP_KEY_ARG:
+ if (state->arg_num == 0)
+ arguments->device = xstrdup(arg);
+ else
+ {
+ /* Too many arguments. */
+ fprintf (stderr, _("Unknown extra argument `%s'.\n"), arg);
+ argp_usage (state);
+ }
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ fprintf (stderr, "%s", _("No device is specified.\n"));
+ argp_usage (state);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static struct argp argp = {
+ options, argp_parser, N_("DEVICE"),
+ "\n"N_("\
+Set up images to boot from DEVICE.\n\
+\n\
+You should not normally run this program directly. Use grub-install instead.")
+"\v"N_("\
+DEVICE must be an OS device (e.g. /dev/sda)."),
+ NULL, help_filter, NULL
+};
+
+static char *
+get_device_name (char *dev)
+{
+ size_t len = strlen (dev);
+
+ if (dev[0] != '(' || dev[len - 1] != ')')
+ return 0;
+
+ dev[len - 1] = '\0';
+ return dev + 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *root_dev = NULL;
+ char *dest_dev = NULL;
+ int must_embed = 0;
+ struct arguments arguments;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ /* Default option values. */
+ memset (&arguments, 0, sizeof (struct arguments));
+ arguments.fs_probe = 1;
+
+ /* Parse our arguments */
+ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
+ {
+ fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
+ exit(1);
+ }
+
+#ifdef GRUB_MACHINE_IEEE1275
+ arguments.force = 1;
+#endif
+
+ if (verbosity > 1)
+ grub_env_set ("debug", "all");
+
+ /* Initialize the emulated biosdisk driver. */
+ grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP);
+
+ /* Initialize all modules. */
+ grub_init_all ();
+
+ grub_lvm_fini ();
+ grub_mdraid09_fini ();
+ grub_mdraid1x_fini ();
+ grub_raid_fini ();
+ grub_raid_init ();
+ grub_mdraid09_init ();
+ grub_mdraid1x_init ();
+ grub_lvm_init ();
+
+ dest_dev = get_device_name (arguments.device);
+ if (! dest_dev)
+ {
+ /* Possibly, the user specified an OS device file. */
+ dest_dev = grub_util_get_grub_dev (arguments.device);
+ if (! dest_dev)
+ {
+ char *program = xstrdup(program_name);
+ fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device);
+ argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
+ free(program);
+ exit(1);
+ }
+ grub_util_info ("transformed OS device `%s' into GRUB device `%s'",
+ arguments.device, dest_dev);
+ }
+ else
+ {
+ /* For simplicity. */
+ dest_dev = xstrdup (dest_dev);
+ grub_util_info ("Using `%s' as GRUB device", dest_dev);
+ }
+
+ if (arguments.root_dev)
+ {
+ root_dev = get_device_name (arguments.root_dev);
+
+ if (! root_dev)
+ grub_util_error (_("invalid root device `%s'"), arguments.root_dev);
+
+ root_dev = xstrdup (root_dev);
+ }
+ else
+ {
+ char *root_device =
+ grub_guess_root_device (arguments.dir ? : DEFAULT_DIRECTORY);
+
+ root_dev = grub_util_get_grub_dev (root_device);
+ if (! root_dev)
+ {
+ grub_util_info ("guessing the root device failed, because of `%s'",
+ grub_errmsg);
+ grub_util_error (_("cannot guess the root device. Specify the option "
+ "`--root-device'"));
+ }
+ grub_util_info ("guessed root device `%s' and root_dev `%s' from "
+ "dir `%s'", root_device, root_dev,
+ arguments.dir ? : DEFAULT_DIRECTORY);
+ }
+
+#ifdef __linux__
+ if (grub_util_lvm_isvolume (root_dev))
+ must_embed = 1;
+
+ if (root_dev[0] == 'm' && root_dev[1] == 'd'
+ && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/'))
+ {
+ /* FIXME: we can avoid this on RAID1. */
+ must_embed = 1;
+ }
+
+ if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
+ && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/'))
+ {
+ char **devicelist;
+ int i;
+
+ if (arguments.device[0] == '/')
+ devicelist = grub_util_raid_getmembers (arguments.device);
+ else
+ {
+ char *devname;
+ devname = xasprintf ("/dev/%s", dest_dev);
+ devicelist = grub_util_raid_getmembers (dest_dev);
+ free (devname);
+ }
+
+ for (i = 0; devicelist[i]; i++)
+ {
+ setup (arguments.dir ? : DEFAULT_DIRECTORY,
+ arguments.boot_file ? : DEFAULT_BOOT_FILE,
+ arguments.core_file ? : DEFAULT_CORE_FILE,
+ root_dev, grub_util_get_grub_dev (devicelist[i]), 1,
+ arguments.force, arguments.fs_probe,
+ arguments.allow_floppy);
+ }
+ }
+ else
+#endif
+ /* Do the real work. */
+ setup (arguments.dir ? : DEFAULT_DIRECTORY,
+ arguments.boot_file ? : DEFAULT_BOOT_FILE,
+ arguments.core_file ? : DEFAULT_CORE_FILE,
+ root_dev, dest_dev, must_embed, arguments.force,
+ arguments.fs_probe, arguments.allow_floppy);
+
+ /* Free resources. */
+ grub_fini_all ();
+ grub_util_biosdisk_fini ();
+
+ free (arguments.boot_file);
+ free (arguments.core_file);
+ free (arguments.dir);
+ free (arguments.root_dev);
+ free (arguments.dev_map);
+ free (arguments.device);
+ free (root_dev);
+ free (dest_dev);
+
+ return 0;
+}
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
new file mode 100644
index 0000000..9da1511
--- /dev/null
+++ b/util/grub.d/00_header.in
@@ -0,0 +1,271 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}`
+grub_lang=`echo $LANG | cut -d . -f 1`
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+# Do this as early as possible, since other commands might depend on it.
+# (e.g. the `loadfont' command might need lvm or raid modules)
+for i in ${GRUB_PRELOAD_MODULES} ; do
+ echo "insmod $i"
+done
+
+if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi
+if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi
+if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi
+if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi
+
+if [ "x${GRUB_DEFAULT_BUTTON}" = "x" ] ; then GRUB_DEFAULT_BUTTON="$GRUB_DEFAULT" ; fi
+if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_entry}' ; fi
+if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi
+
+cat << EOF
+if [ -s \$prefix/grubenv ]; then
+ load_env
+fi
+EOF
+if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
+ cat <<EOF
+if cmostest $GRUB_BUTTON_CMOS_ADDRESS ; then
+ set default="${GRUB_DEFAULT_BUTTON}"
+else
+ set default="${GRUB_DEFAULT}"
+fi
+EOF
+else
+ cat <<EOF
+set default="${GRUB_DEFAULT}"
+EOF
+fi
+cat <<EOF
+if [ "\${prev_saved_entry}" ]; then
+ set saved_entry="\${prev_saved_entry}"
+ save_env saved_entry
+ set prev_saved_entry=
+ save_env prev_saved_entry
+ set boot_once=true
+fi
+
+function savedefault {
+ if [ -z "\${boot_once}" ]; then
+ saved_entry="\${chosen}"
+ save_env saved_entry
+ fi
+}
+
+function load_video {
+EOF
+if [ -n "${GRUB_VIDEO_BACKEND}" ]; then
+ cat <<EOF
+ insmod ${GRUB_VIDEO_BACKEND}
+EOF
+else
+ # Insert all available backends; GRUB will use the most appropriate.
+ have_video=0;
+ for backend in $(cat "${GRUB_PREFIX}/video.lst"); do
+ have_video=1;
+ cat <<EOF
+ insmod ${backend}
+EOF
+ done
+ if [ x$have_video = x0 ]; then
+ echo "true"
+ fi
+fi
+cat <<EOF
+}
+
+EOF
+
+serial=0;
+gfxterm=0;
+for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do
+ if [ xserial = "x$x" ]; then
+ serial=1;
+ fi
+ if [ xgfxterm = "x$x" ]; then
+ gfxterm=1;
+ fi
+done
+
+if [ "x$serial" = x1 ]; then
+ if ! test -e ${GRUB_PREFIX}/serial.mod ; then
+ echo "Serial terminal not available on this platform." >&2 ; exit 1
+ fi
+
+ if [ "x${GRUB_SERIAL_COMMAND}" = "x" ] ; then
+ grub_warn "Requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used."
+ GRUB_SERIAL_COMMAND=serial
+ fi
+ echo "${GRUB_SERIAL_COMMAND}"
+fi
+
+if [ "x$gfxterm" = x1 ]; then
+ # Make the font accessible
+ prepare_grub_to_access_device `${grub_probe} --target=device "${GRUB_FONT_PATH}"`
+
+ cat << EOF
+if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT_PATH}"` ; then
+ set gfxmode=${GRUB_GFXMODE}
+ load_video
+ insmod gfxterm
+EOF
+
+# Gettext variables and module
+if [ "x${LANG}" != "xC" ] && [ -d "${locale_dir}" ] ; then
+ prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir}) | sed -e "s/^/ /"
+ cat << EOF
+ set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir})
+ set lang=${grub_lang}
+ insmod gettext
+EOF
+fi
+
+cat <<EOF
+fi
+EOF
+fi
+
+case x${GRUB_TERMINAL_INPUT} in
+ x)
+ # Just use the native terminal
+ ;;
+ x*)
+ cat << EOF
+terminal_input ${GRUB_TERMINAL_INPUT}
+EOF
+ ;;
+esac
+
+case x${GRUB_TERMINAL_OUTPUT} in
+ x)
+ # Just use the native terminal
+ ;;
+ x*)
+ cat << EOF
+terminal_output ${GRUB_TERMINAL_OUTPUT}
+EOF
+ ;;
+esac
+
+if [ "x$gfxterm" = x1 ]; then
+ if [ "x$GRUB_THEME" != x ] && [ -f "$GRUB_THEME" ] \
+ && is_path_readable_by_grub "$GRUB_THEME"; then
+ echo "Found theme: $GRUB_THEME" >&2
+ prepare_grub_to_access_device `${grub_probe} --target=device "$GRUB_THEME"`
+ cat << EOF
+insmod gfxmenu
+EOF
+ themedir="`dirname "$GRUB_THEME"`"
+ for x in "$themedir"/*.pf2 "$themedir"/f/*.pf2; do
+ if [ -f "$x" ]; then
+ cat << EOF
+loadfont (\$root)`make_system_path_relative_to_its_root $x`
+EOF
+ fi
+ done
+ if [ x"`echo "$themedir"/*.jpg`" != x"$themedir/*.jpg" ] || [ x"`echo "$themedir"/*.jpeg`" != x"$themedir/*.jpeg" ]; then
+ cat << EOF
+insmod jpeg
+EOF
+ fi
+ if [ x"`echo "$themedir"/*.png`" != x"$themedir/*.png" ]; then
+ cat << EOF
+insmod png
+EOF
+ fi
+ if [ x"`echo "$themedir"/*.tga`" != x"$themedir/*.tga" ]; then
+ cat << EOF
+insmod tga
+EOF
+ fi
+
+ cat << EOF
+set theme=(\$root)`make_system_path_relative_to_its_root $GRUB_THEME`
+EOF
+ elif [ "x$GRUB_BACKGROUND" != x ] && [ -f "$GRUB_BACKGROUND" ] \
+ && is_path_readable_by_grub "$GRUB_BACKGROUND"; then
+ echo "Found background: $GRUB_BACKGROUND" >&2
+ case "$GRUB_BACKGROUND" in
+ *.png) reader=png ;;
+ *.tga) reader=tga ;;
+ *.jpg|*.jpeg) reader=jpeg ;;
+ *) echo "Unsupported image format" >&2; exit 1 ;;
+ esac
+ prepare_grub_to_access_device `${grub_probe} --target=device "$GRUB_BACKGROUND"`
+ cat << EOF
+insmod $reader
+background_image -m stretch `make_system_path_relative_to_its_root "$GRUB_BACKGROUND"`
+EOF
+ fi
+fi
+
+make_timeout ()
+{
+ if [ "x${1}" != "x" ] ; then
+ if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then
+ verbose=
+ else
+ verbose=" --verbose"
+ fi
+ cat << EOF
+if sleep$verbose --interruptible ${1} ; then
+ set timeout=${2}
+fi
+EOF
+ else
+ cat << EOF
+set timeout=${2}
+EOF
+ fi
+}
+
+if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
+ cat <<EOF
+if cmostest $GRUB_BUTTON_CMOS_ADDRESS ; then
+EOF
+make_timeout "${GRUB_HIDDEN_TIMEOUT_BUTTON}" "${GRUB_TIMEOUT_BUTTON}"
+echo else
+make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}"
+echo fi
+else
+make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}"
+fi
+
+if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ] && [ "x$GRUB_BUTTON_CMOS_CLEAN" = "xyes" ]; then
+ cat <<EOF
+cmosclean $GRUB_BUTTON_CMOS_ADDRESS
+EOF
+fi
+
+# Play an initial tune
+if [ "x${GRUB_INIT_TUNE}" != "x" ] ; then
+ echo "play ${GRUB_INIT_TUNE}"
+fi
+
+if [ "x${GRUB_BADRAM}" != "x" ] ; then
+ echo "badram ${GRUB_BADRAM}"
+fi
diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
new file mode 100644
index 0000000..8c54eab
--- /dev/null
+++ b/util/grub.d/10_hurd.in
@@ -0,0 +1,127 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+CLASS="--class gnu --class os"
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU
+else
+ OS="${GRUB_DISTRIBUTOR} GNU/Hurd"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
+fi
+
+at_least_one=false
+all_of_them=true
+
+# FIXME: add l4 here?
+kernel=
+for i in /boot/gnumach* ; do
+ if test -e $i ; then
+ basename=`basename $i`
+ dirname=`dirname $i`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+ echo "Found GNU Mach: $i" >&2
+ kernels="${kernels} ${rel_dirname}/${basename}"
+ at_least_one=true
+ fi
+done
+
+# FIXME: This works for ext2. For other filesystems we might need special-casing
+case "${GRUB_FS}" in
+ *fs) hurd_fs="${GRUB_FS}" ;;
+ *) hurd_fs="${GRUB_FS}fs" ;;
+esac
+
+for i in /hurd/${hurd_fs}.static /hurd/exec ; do
+ if test -e "$i" ; then
+ echo "Found Hurd module: $i" >&2
+ at_least_one=true
+ else
+ all_of_them=false
+ fi
+done
+
+if ${at_least_one} ; then : ; else
+ # no hurd here, aborting silently
+ exit 0
+fi
+
+if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else
+ echo "Some Hurd stuff found, but not enough to boot." >&2
+ exit 1
+fi
+
+for kernel in ${kernels}
+do
+ kernel_base="`basename "${kernel}"`"
+ KERNEL="using ${kernel_base}"
+
+ cat << EOF
+menuentry "${OS} ${KERNEL}" ${CLASS} {
+EOF
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+ message="$(gettext_printf "Loading GNU Mach ...")"
+ cat << EOF
+ echo '$message'
+ multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/}
+EOF
+ save_default_entry | sed -e "s/^/\t/"
+ prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/"
+ message="$(gettext_printf "Loading the Hurd ...")"
+ cat << EOF
+ echo '$message'
+ module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\
+ --multiboot-command-line='\${kernel-command-line}' \\
+ --host-priv-port='\${host-port}' \\
+ --device-master-port='\${device-port}' \\
+ --exec-server-task='\${exec-task}' -T typed '\${root}' \\
+ '\$(task-create)' '\$(task-resume)'
+ module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
+}
+EOF
+
+ cat << EOF
+menuentry "${OS} ${KERNEL} (recovery mode)" ${CLASS} {
+EOF
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+ message="$(gettext_printf "Loading GNU Mach ...")"
+ cat << EOF
+ echo '$message'
+ multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} -s
+EOF
+ prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/"
+ message="$(gettext_printf "Loading the Hurd ...")"
+ cat << EOF
+ echo '$message'
+ module /hurd/${hurd_fs}.static ${hurd_fs} \\
+ --multiboot-command-line='\${kernel-command-line}' \\
+ --host-priv-port='\${host-port}' \\
+ --device-master-port='\${device-port}' \\
+ --exec-server-task='\${exec-task}' -T typed '\${root}' \\
+ '\$(task-create)' '\$(task-resume)'
+ module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
+}
+EOF
+
+done
diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
new file mode 100644
index 0000000..3600c74
--- /dev/null
+++ b/util/grub.d/10_kfreebsd.in
@@ -0,0 +1,192 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR=@localedir@
+
+CLASS="--class os"
+
+case "${GRUB_DISTRIBUTOR}" in
+ Debian)
+ OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) --class gnu-kfreebsd --class gnu ${CLASS}"
+ ;;
+ *)
+ OS="FreeBSD"
+ CLASS="--class freebsd --class bsd ${CLASS}"
+ ;;
+esac
+
+load_kfreebsd_module ()
+{
+ mod="$1"
+ allow_fail="$2"
+
+ if ! test -e "${module_dir}/${mod}.ko" ; then
+ if [ "${allow_fail}" = "true" ] ; then
+ # Return silently
+ return
+ else
+ # Print an error and fail.
+ ls "${module_dir}/${mod}.ko" > /dev/null
+ fi
+ fi
+
+ if [ -z "${prepare_module_dir_cache}" ]; then
+ prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")"
+ fi
+
+ printf '%s\n' "${prepare_module_dir_cache}"
+ cat << EOF
+ kfreebsd_module_elf ${module_dir_rel}/${mod}.ko
+EOF
+}
+
+kfreebsd_entry ()
+{
+ os="$1"
+ version="$2"
+ recovery="$3"
+ args="$4"
+ if ${recovery} ; then
+ title="$(gettext_quoted "%s, with kFreeBSD %s (recovery mode)")"
+ else
+ title="$(gettext_quoted "%s, with kFreeBSD %s")"
+ fi
+ printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}"
+ if ! ${recovery} ; then
+ save_default_entry | sed -e "s/^/\t/"
+ fi
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
+ fi
+
+ printf '%s\n' "${prepare_boot_cache}"
+ message="$(gettext_printf "Loading kernel of FreeBSD %s ..." ${version})"
+ cat << EOF
+ echo '$message'
+ kfreebsd ${rel_dirname}/${basename} ${args}
+EOF
+
+ if test -n "${devices}" ; then
+ cat << EOF
+ kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename}
+EOF
+ fi
+
+ load_kfreebsd_module acpi true
+
+ case "${kfreebsd_fs}" in
+ zfs)
+ load_kfreebsd_module opensolaris false
+
+ ls "${dirname}/zfs/zpool.cache" > /dev/null
+ printf '%s\n' "${prepare_boot_cache}"
+ cat << EOF
+ kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache
+EOF
+ ;;
+ esac
+
+ if [ x${kfreebsd_fs} = xufs ]; then
+ load_kfreebsd_module ${kfreebsd_fs} true
+ else
+ load_kfreebsd_module ${kfreebsd_fs} false
+ fi
+
+ cat << EOF
+ set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${kfreebsd_device}
+ set kFreeBSD.vfs.root.mountfrom.options=rw
+}
+EOF
+}
+
+list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do
+ if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+ done`
+prepare_boot_cache=
+
+while [ "x$list" != "x" ] ; do
+ kfreebsd=`version_find_latest $list`
+ echo "Found kernel of FreeBSD: $kfreebsd" >&2
+ basename=`basename $kfreebsd`
+ dirname=`dirname $kfreebsd`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+
+ if [ -f /boot/device.hints ] ; then
+ devices=/boot/device.hints
+ devices_basename=`basename $devices`
+ devices_dirname=`dirname $devices`
+ devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname`
+ fi
+
+ case ${GRUB_FS} in
+ ufs1 | ufs2) kfreebsd_fs=ufs ;;
+ ext2) kfreebsd_fs=ext2fs ;;
+ *) kfreebsd_fs=${GRUB_FS} ;;
+ esac
+
+ case ${GRUB_FS} in
+ zfs)
+ # zpool name
+ kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE})
+ # filesystem name (empty string for the main filesystem)
+ kfreebsd_device="${kfreebsd_device}$(grub-mkrelpath / | sed -e "s,/*@$,,")"
+ ;;
+ *)
+ kfreebsd_device=${kfreebsd_fs}id/${GRUB_DEVICE_UUID}
+ # Debian GNU/kFreeBSD can't remount root if it's supplied as UUID but
+ # as an UUID
+ if [ "x${GRUB_DISTRIBUTOR}" = "xDebian" ] \
+ && ! (cat /etc/fstab | awk '!/^[[:space:]]*#/ && $2=="/" { print $1; }' \
+ | grep "${kfreebsd_fs}id/${GRUB_DEVICE_UUID}" > /dev/null); then
+ kfreebsd_device=${GRUB_DEVICE}
+ fi
+ ;;
+ esac
+
+ version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"`
+ alt_version=`echo $version | sed -e "s,\.old$,,g"`
+
+ module_dir=
+ for i in "/lib/modules/${version}" "/lib/modules/${alt_version}" \
+ "/boot/kernel"; do
+ if test -e "$i" ; then
+ module_dir="$i"
+ break
+ fi
+ done
+ if test -n "${module_dir}" ; then
+ echo "Found kernel module directory: ${module_dir}" >&2
+ module_dir_rel=$(make_system_path_relative_to_its_root $module_dir)
+ fi
+
+ kfreebsd_entry "${OS}" "${version}" false
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ kfreebsd_entry "${OS}" "${version}" true "-s"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | grep -vx $kfreebsd | tr '\n' ' '`
+done
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
new file mode 100644
index 0000000..1d1eb40
--- /dev/null
+++ b/util/grub.d/10_linux.in
@@ -0,0 +1,199 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR=@localedir@
+
+CLASS="--class gnu-linux --class gnu --class os"
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU/Linux
+else
+ OS="${GRUB_DISTRIBUTOR} GNU/Linux"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
+fi
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
+ ;;
+esac
+
+if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+ || uses_abstraction "${GRUB_DEVICE}" lvm; then
+ LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+else
+ LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+fi
+
+linux_entry ()
+{
+ os="$1"
+ version="$2"
+ recovery="$3"
+ args="$4"
+ if ${recovery} ; then
+ title="$(gettext_quoted "%s, with Linux %s (recovery mode)")"
+ else
+ title="$(gettext_quoted "%s, with Linux %s")"
+ fi
+ printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}"
+ if ! ${recovery} ; then
+ save_default_entry | sed -e "s/^/\t/"
+ fi
+
+ # Use ELILO's generic "efifb" when it's known to be available.
+ # FIXME: We need an interface to select vesafb in case efifb can't be used.
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
+ cat << EOF
+ load_video
+EOF
+ if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+ && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
+ cat << EOF
+ set gfxpayload=keep
+EOF
+ fi
+ else
+ if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
+ cat << EOF
+ load_video
+EOF
+ fi
+ cat << EOF
+ set gfxpayload=$GRUB_GFXPAYLOAD_LINUX
+EOF
+ fi
+
+ cat << EOF
+ insmod gzio
+EOF
+
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_root_cache}"
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_boot_cache}"
+ fi
+ message="$(gettext_printf "Loading Linux %s ..." ${version})"
+ cat << EOF
+ echo '$message'
+ linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+EOF
+ if test -n "${initrd}" ; then
+ message="$(gettext_printf "Loading initial ramdisk ...")"
+ cat << EOF
+ echo '$message'
+ initrd ${rel_dirname}/${initrd}
+EOF
+ fi
+ cat << EOF
+}
+EOF
+}
+
+case x`uname -m` in
+ xi?86 | xx86_64)
+ list=`for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+ done` ;;
+ *)
+ list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
+ if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+ done` ;;
+esac
+
+prepare_boot_cache=
+prepare_root_cache=
+
+while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
+ echo "Found linux image: $linux" >&2
+ basename=`basename $linux`
+ dirname=`dirname $linux`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+ version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
+ alt_version=`echo $version | sed -e "s,\.old$,,g"`
+ linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
+
+ initrd=
+ for i in "initrd.img-${version}" "initrd-${version}.img" \
+ "initrd-${version}" "initramfs-${version}.img" \
+ "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
+ "initrd-${alt_version}" "initramfs-${alt_version}.img" \
+ "initramfs-genkernel-${version}" \
+ "initramfs-genkernel-${alt_version}"; do
+ if test -e "${dirname}/${i}" ; then
+ initrd="$i"
+ break
+ fi
+ done
+
+ config=
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ if test -e "${i}" ; then
+ config="${i}"
+ break
+ fi
+ done
+
+ initramfs=
+ if test -n "${config}" ; then
+ initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
+ fi
+
+ if test -n "${initrd}" ; then
+ echo "Found initrd image: ${dirname}/${initrd}" >&2
+ elif test -z "${initramfs}" ; then
+ # "UUID=" magic is parsed by initrd or initramfs. Since there's
+ # no initrd or builtin initramfs, it can't work here.
+ linux_root_device_thisversion=${GRUB_DEVICE}
+ fi
+
+ linux_entry "${OS}" "${version}" false \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" true \
+ "single ${GRUB_CMDLINE_LINUX}"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
+done
diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
new file mode 100644
index 0000000..ffd31ad
--- /dev/null
+++ b/util/grub.d/10_netbsd.in
@@ -0,0 +1,143 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR=@localedir@
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS="NetBSD"
+else
+ OS="${GRUB_DISTRIBUTOR} NetBSD"
+fi
+
+netbsd_load_fs_module ()
+{
+ loader="$1" # "knetbsd" or "multiboot"
+ kernel="$2" # absolute path to the kernel file
+
+ case $(zcat -f "${kernel}" | file -bL - | cut -d , -f 2 | tr -d ' ') in
+ Intel80386)
+ karch="i386"
+ ;;
+ x86-64)
+ karch="amd64"
+ ;;
+ *)
+ return
+ ;;
+ esac
+
+ case $(${grub_probe} --target=fs -d ${GRUB_DEVICE}) in
+ ext2)
+ kmod="ext2fs"
+ ;;
+ fat)
+ kmod="msdosfs"
+ ;;
+ ntfs)
+ kmod="ntfs"
+ ;;
+ ufs*)
+ kmod="ffs"
+ ;;
+ *)
+ return
+ ;;
+ esac
+
+ kversion=$(zcat -f "${kernel}" | strings | sed -n -e '/^@(#)NetBSD/ { s/^@(#)NetBSD \([0-9\.]*\) .*$/\1/g ; p ; q ; }')
+ kmodule="/stand/${karch}/${kversion}/modules/${kmod}/${kmod}.kmod"
+
+ if test -z "$karch" -o -z "$kversion" -o ! -f "${kmodule}"; then
+ return
+ fi
+
+ kmodule_rel=$(make_system_path_relative_to_its_root "$kmodule") || return
+ prepare_grub_to_access_device $(${grub_probe} -t device "${kmodule}") | sed -e 's,^, ,'
+ case "${loader}" in
+ knetbsd)
+ printf "\tknetbsd_module_elf %s\n" "${kmodule_rel}"
+ ;;
+ multiboot)
+ printf "\tmodule %s\n" "${kmodule_rel}"
+ ;;
+ esac
+}
+
+netbsd_entry ()
+{
+ loader="$1" # "knetbsd" or "multiboot"
+ kernel="$2" # absolute path to the kernel file
+ recovery="$3" # is this is a recovery entry?
+ args="$4" # extra arguments appended to loader command
+
+ kroot_device="$(echo ${GRUB_DEVICE} | sed -e 's,^/dev/r,,')"
+ if ${recovery} ; then
+ title="$(gettext_quoted "%s, with kernel %s (via %s, recovery mode)")"
+ else
+ title="$(gettext_quoted "%s, with kernel %s (via %s)")"
+ fi
+
+ printf "menuentry \"${title}\" {\n" \
+ "${OS}" "$(echo ${kernel} | sed -e 's,^.*/,,')" "${loader}"
+ printf "%s\n" "${prepare_boot_cache}"
+ case "${loader}" in
+ knetbsd)
+ printf "\tknetbsd %s -r %s %s\n" \
+ "${kernel}" "${kroot_device}" "${GRUB_CMDLINE_NETBSD} ${args}"
+ ;;
+ multiboot)
+ printf "\tmultiboot %s %s root=%s %s\n" \
+ "${kernel}" "${kernel}" "${kroot_device}" "${GRUB_CMDLINE_NETBSD} ${args}"
+ ;;
+ esac
+
+ netbsd_load_fs_module "${loader}" "${kernel}"
+
+ printf "}\n"
+}
+
+prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e 's,^, ,')"
+
+# We look for NetBSD kernels in / but not in subdirectories. We simply
+# pick all statically linked ELF executable files (or links) in / with a
+# name that starts with `netbsd'.
+pattern="^ELF[^,]*executable.*statically linked"
+for k in $(ls -t /netbsd*) ; do
+ if ! grub_file_is_not_garbage "$k" ; then
+ continue
+ fi
+ if ! (zcat -f "$k" | file -bL - | grep -q "${pattern}") 2>/dev/null ; then
+ continue
+ fi
+
+ echo "Found NetBSD kernel: $k" >&2
+ netbsd_entry "knetbsd" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}"
+ netbsd_entry "multiboot" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}"
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ netbsd_entry "knetbsd" "$k" true "-s"
+ netbsd_entry "multiboot" "$k" true "-s"
+ fi
+done
diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in
new file mode 100644
index 0000000..fd068dd
--- /dev/null
+++ b/util/grub.d/10_windows.in
@@ -0,0 +1,94 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+case "`uname 2>/dev/null`" in
+ CYGWIN*) ;;
+ *) exit 0 ;;
+esac
+
+# Try C: even if current system is on other partition.
+case "$SYSTEMDRIVE" in
+ [Cc]:) drives="C:" ;;
+ [D-Zd-z]:) drives="C: $SYSTEMDRIVE" ;;
+ *) exit 0 ;;
+esac
+
+get_os_name_from_boot_ini ()
+{
+ # Fail if no or more than one partition.
+ test "`sed -n 's,^\(\(multi\|scsi\)[^=]*\)=.*$,\1,p' "$1" 2>/dev/null | \
+ sort | uniq | wc -l`" = 1 || return 1
+
+ # Search 'default=PARTITION'
+ local part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'`
+ test -n "$part" || return 1
+
+ # Search 'PARTITION="NAME" ...'
+ local name=`sed -n 's,\\\\,/,g;s,^'"$part"'="\([^"]*\)".*$,\1,p' "$1" | sed 1q`
+ test -n "$name" || return 1
+
+ echo "$name"
+}
+
+
+for drv in $drives ; do
+
+ # Convert to Cygwin path.
+ dir=`cygpath "$drv"`
+ test -n "$dir" || continue
+
+ needmap=
+
+ # Check for Vista bootmgr.
+ if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then
+ OS="Windows Vista bootmgr"
+
+ # Check for NTLDR.
+ elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then
+ OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="Windows NT/2000/XP loader"
+ needmap=t
+
+ else
+ continue
+ fi
+
+ # Get boot /dev/ice.
+ dev=`${grub_probe} -t device "$dir" 2>/dev/null` || continue
+
+ echo "Found $OS on $drv ($dev)" >&2
+ cat << EOF
+menuentry "$OS" {
+EOF
+
+ save_default_entry | sed -e 's,^,\t,'
+ prepare_grub_to_access_device "$dev" | sed 's,^,\t,'
+ test -z "$needmap" || cat <<EOF
+ drivemap -s (hd0) \$root
+EOF
+ cat << EOF
+ chainloader +1
+}
+EOF
+done
+
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
new file mode 100644
index 0000000..a900760
--- /dev/null
+++ b/util/grub.d/20_linux_xen.in
@@ -0,0 +1,174 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR=@localedir@
+
+CLASS="--class gnu-linux --class gnu --class os --class xen"
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+ OS=GNU/Linux
+else
+ OS="${GRUB_DISTRIBUTOR} GNU/Linux"
+ CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
+fi
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
+ ;;
+esac
+
+if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+ || uses_abstraction "${GRUB_DEVICE}" lvm; then
+ LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+else
+ LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+fi
+
+linux_entry ()
+{
+ os="$1"
+ version="$2"
+ xen_version="$3"
+ recovery="$4"
+ args="$5"
+ xen_args="$6"
+ if ${recovery} ; then
+ title="$(gettext_quoted "%s, with Xen %s and Linux %s (recovery mode)")"
+ else
+ title="$(gettext_quoted "%s, with Xen %s and Linux %s")"
+ fi
+ printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${xen_version}" "${version}"
+ if ! ${recovery} ; then
+ save_default_entry | sed -e "s/^/\t/"
+ fi
+
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_boot_cache}"
+ xmessage="$(gettext_printf "Loading Xen %s ..." ${xen_version})"
+ lmessage="$(gettext_printf "Loading Linux %s ..." ${version})"
+ cat << EOF
+ echo '$xmessage'
+ multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args}
+ echo '$lmessage'
+ module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
+EOF
+ if test -n "${initrd}" ; then
+ message="$(gettext_printf "Loading initial ramdisk ...")"
+ cat << EOF
+ echo '$message'
+ module ${rel_dirname}/${initrd}
+EOF
+ fi
+ cat << EOF
+}
+EOF
+}
+
+linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* /boot/kernel-*; do
+ if grub_file_is_not_garbage "$i"; then
+ basename=$(basename $i)
+ version=$(echo $basename | sed -e "s,^[^0-9]*-,,g")
+ dirname=$(dirname $i)
+ config=
+ for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ if test -e "${j}" ; then
+ config="${j}"
+ break
+ fi
+ done
+ if (grep -qx "CONFIG_XEN_DOM0=y" "${config}" 2> /dev/null || grep -qx "CONFIG_XEN_PRIVILEGED_GUEST=y" "${config}" 2> /dev/null); then echo -n "$i " ; fi
+ fi
+ done`
+if [ "x${linux_list}" = "x" ] ; then
+ exit 0
+fi
+xen_list=`for i in /boot/xen*; do
+ if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+ done`
+prepare_boot_cache=
+
+while [ "x${xen_list}" != "x" ] ; do
+ list="${linux_list}"
+ current_xen=`version_find_latest $xen_list`
+ xen_basename=`basename ${current_xen}`
+ xen_dirname=`dirname ${current_xen}`
+ rel_xen_dirname=`make_system_path_relative_to_its_root $xen_dirname`
+ xen_version=`echo $xen_basename | sed -e "s,.gz$,,g;s,^xen-,,g"`
+ echo "submenu \"Xen ${xen_version}\" {"
+ while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
+ echo "Found linux image: $linux" >&2
+ basename=`basename $linux`
+ dirname=`dirname $linux`
+ rel_dirname=`make_system_path_relative_to_its_root $dirname`
+ version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
+ alt_version=`echo $version | sed -e "s,\.old$,,g"`
+ linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
+
+ initrd=
+ for i in "initrd.img-${version}" "initrd-${version}.img" \
+ "initrd-${version}" "initrd.img-${alt_version}" \
+ "initrd-${alt_version}.img" "initrd-${alt_version}" \
+ "initramfs-genkernel-${version}" \
+ "initramfs-genkernel-${alt_version}" ; do
+ if test -e "${dirname}/${i}" ; then
+ initrd="$i"
+ break
+ fi
+ done
+ if test -n "${initrd}" ; then
+ echo "Found initrd image: ${dirname}/${initrd}" >&2
+ else
+ # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here.
+ linux_root_device_thisversion=${GRUB_DEVICE}
+ fi
+
+ linux_entry "${OS}" "${version}" "${xen_version}" false \
+ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}"
+ if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+ linux_entry "${OS}" "${version}" "${xen_version}" true \
+ "single ${GRUB_CMDLINE_LINUX}" "${GRUB_CMDLINE_XEN}"
+ fi
+
+ list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
+ done
+ echo "}"
+ xen_list=`echo $xen_list | tr ' ' '\n' | grep -vx $current_xen | tr '\n' ' '`
+done
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
new file mode 100644
index 0000000..d9d4b0a
--- /dev/null
+++ b/util/grub.d/30_os-prober.in
@@ -0,0 +1,204 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+ exit 0
+fi
+
+if [ -z "`which os-prober 2> /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then
+ # missing os-prober and/or linux-boot-prober
+ exit 0
+fi
+
+OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
+if [ -z "${OSPROBED}" ] ; then
+ # empty os-prober output, nothing doing
+ exit 0
+fi
+
+osx_entry() {
+ cat << EOF
+menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" --class osx --class darwin --class os {
+EOF
+ save_default_entry | sed -e "s/^/\t/"
+ prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
+ cat << EOF
+ load_video
+ set do_resume=0
+ if [ /var/vm/sleepimage -nt10 / ]; then
+ if xnu_resume /var/vm/sleepimage; then
+ set do_resume=1
+ fi
+ fi
+ if [ \$do_resume = 0 ]; then
+ xnu_uuid ${OSXUUID} uuid
+ if [ -f /Extra/DSDT.aml ]; then
+ acpi -e /Extra/DSDT.aml
+ fi
+ $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid
+ if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then
+ xnu_mkext /System/Library/Extensions.mkext
+ else
+ xnu_kextdir /System/Library/Extensions
+ fi
+ if [ -f /Extra/Extensions.mkext ]; then
+ xnu_mkext /Extra/Extensions.mkext
+ fi
+ if [ -d /Extra/Extensions ]; then
+ xnu_kextdir /Extra/Extensions
+ fi
+ if [ -f /Extra/devprop.bin ]; then
+ xnu_devprop_load /Extra/devprop.bin
+ fi
+ if [ -f /Extra/splash.jpg ]; then
+ insmod jpeg
+ xnu_splash /Extra/splash.jpg
+ fi
+ if [ -f /Extra/splash.png ]; then
+ insmod png
+ xnu_splash /Extra/splash.png
+ fi
+ if [ -f /Extra/splash.tga ]; then
+ insmod tga
+ xnu_splash /Extra/splash.tga
+ fi
+ fi
+}
+EOF
+}
+
+for OS in ${OSPROBED} ; do
+ DEVICE="`echo ${OS} | cut -d ':' -f 1`"
+ LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
+ LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
+ BOOT="`echo ${OS} | cut -d ':' -f 4`"
+
+ if [ -z "${LONGNAME}" ] ; then
+ LONGNAME="${LABEL}"
+ fi
+
+ echo "Found ${LONGNAME} on ${DEVICE}" >&2
+
+ case ${BOOT} in
+ chain)
+
+ cat << EOF
+menuentry "${LONGNAME} (on ${DEVICE})" --class windows --class os {
+EOF
+ save_default_entry | sed -e "s/^/\t/"
+ prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
+
+ case ${LONGNAME} in
+ Windows\ Vista*|Windows\ 7*|Windows\ Server\ 2008*)
+ ;;
+ *)
+ cat << EOF
+ drivemap -s (hd0) \${root}
+EOF
+ ;;
+ esac
+
+ cat <<EOF
+ chainloader +1
+}
+EOF
+ ;;
+ linux)
+ LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
+ prepare_boot_cache=
+
+ for LINUX in ${LINUXPROBED} ; do
+ LROOT="`echo ${LINUX} | cut -d ':' -f 1`"
+ LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"
+ LLABEL="`echo ${LINUX} | cut -d ':' -f 3 | tr '^' ' '`"
+ LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
+ LINITRD="`echo ${LINUX} | cut -d ':' -f 5`"
+ LPARAMS="`echo ${LINUX} | cut -d ':' -f 6- | tr '^' ' '`"
+
+ if [ -z "${LLABEL}" ] ; then
+ LLABEL="${LONGNAME}"
+ fi
+
+ if [ "${LROOT}" != "${LBOOT}" ]; then
+ LKERNEL="${LKERNEL#/boot}"
+ LINITRD="${LINITRD#/boot}"
+ fi
+
+ cat << EOF
+menuentry "${LLABEL} (on ${DEVICE})" --class gnu-linux --class gnu --class os {
+EOF
+ save_default_entry | sed -e "s/^/\t/"
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")"
+ fi
+ printf '%s\n' "${prepare_boot_cache}"
+ cat << EOF
+ linux ${LKERNEL} ${LPARAMS}
+EOF
+ if [ -n "${LINITRD}" ] ; then
+ cat << EOF
+ initrd ${LINITRD}
+EOF
+ fi
+ cat << EOF
+}
+EOF
+ done
+ ;;
+ macosx)
+ OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`"
+ osx_entry xnu_kernel 32
+ osx_entry xnu_kernel64 64
+ ;;
+ hurd)
+ cat << EOF
+menuentry "${LONGNAME} (on ${DEVICE})" --class hurd --class gnu --class os {
+EOF
+ save_default_entry | sed -e "s/^/\t/"
+ prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
+ grub_device="`${grub_probe} --device ${DEVICE} --target=drive`"
+ mach_device="`echo "${grub_device}" | sed -e 's/(\(hd.*\),msdos\(.*\))/\1s\2/'`"
+ grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`"
+ case "${grub_fs}" in
+ *fs) hurd_fs="${grub_fs}" ;;
+ *) hurd_fs="${grub_fs}fs" ;;
+ esac
+ cat << EOF
+ multiboot /boot/gnumach.gz root=device:${mach_device}
+ module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\
+ --multiboot-command-line='\${kernel-command-line}' \\
+ --host-priv-port='\${host-port}' \\
+ --device-master-port='\${device-port}' \\
+ --exec-server-task='\${exec-task}' -T typed '\${root}' \\
+ '\$(task-create)' '\$(task-resume)'
+ module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)'
+}
+EOF
+ ;;
+ *)
+ echo " ${LONGNAME} is not yet supported by grub-mkconfig." >&2
+ ;;
+ esac
+done
diff --git a/util/grub.d/40_custom.in b/util/grub.d/40_custom.in
new file mode 100644
index 0000000..48068de
--- /dev/null
+++ b/util/grub.d/40_custom.in
@@ -0,0 +1,5 @@
+#!/bin/sh
+exec tail -n +3 $0
+# This file provides an easy way to add custom menu entries. Simply type the
+# menu entries you want to add after this comment. Be careful not to change
+# the 'exec tail' line above.
diff --git a/util/grub.d/41_custom.in b/util/grub.d/41_custom.in
new file mode 100644
index 0000000..64d691c
--- /dev/null
+++ b/util/grub.d/41_custom.in
@@ -0,0 +1,7 @@
+#!/bin/sh
+cat <<EOF
+if [ -f \$prefix/custom.cfg ]; then
+ source \$prefix/custom.cfg;
+fi
+EOF
+
diff --git a/util/grub.d/README b/util/grub.d/README
new file mode 100644
index 0000000..3ea109d
--- /dev/null
+++ b/util/grub.d/README
@@ -0,0 +1,11 @@
+
+All executable files in this directory are processed in shell expansion order.
+
+ 00_*: Reserved for 00_header.
+ 10_*: Native boot entries.
+ 20_*: Third party apps (e.g. memtest86+).
+
+The number namespace in-between is configurable by system installer and/or
+administrator. For example, you can add an entry to boot another OS as
+01_otheros, 11_otheros, etc, depending on the position you want it to occupy in
+the menu; and then adjust the default setting via /etc/default/grub.
diff --git a/util/i386/efi/grub-dumpdevtree b/util/i386/efi/grub-dumpdevtree
new file mode 100644
index 0000000..51004cc
--- /dev/null
+++ b/util/i386/efi/grub-dumpdevtree
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) 2009 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+if [ "x$1" = "x" ]; then
+ echo "Filename required".
+fi
+
+ioreg -lw0 -p IODeviceTree -n efi -r -x |grep device-properties | sed 's/.*<//;s/>.*//;' | xxd -r -p > $1
diff --git a/util/ieee1275/devicemap.c b/util/ieee1275/devicemap.c
new file mode 100644
index 0000000..19ab746
--- /dev/null
+++ b/util/ieee1275/devicemap.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <string.h>
+#include <grub/types.h>
+#include <grub/util/deviceiter.h>
+#include <grub/util/ofpath.h>
+#include <grub/util/misc.h>
+
+/* 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 *) orig_path;
+
+ new_path = xmalloc (strlen (orig_path) * 2);
+
+ p = orig_path;
+ d = new_path;
+ while ((c = *p++) != '\0')
+ {
+ if (c == ',')
+ *d++ = '\\';
+ *d++ = c;
+ }
+
+ free ((char *) orig_path);
+
+ return new_path;
+}
+
+void
+grub_util_emit_devicemap_entry (FILE *fp, char *name,
+ int is_floppy __attribute__((unused)),
+ int *num_fd __attribute__((unused)),
+ int *num_hd __attribute__((unused)))
+{
+ const char *orig_path = grub_util_devname_to_ofpath (name);
+ char *ofpath = escape_of_path (orig_path);
+
+ fprintf(fp, "(%s)\t%s\n", ofpath, name);
+
+ free (ofpath);
+}
diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c
new file mode 100644
index 0000000..3ac6fce
--- /dev/null
+++ b/util/ieee1275/grub-ofpathname.c
@@ -0,0 +1,47 @@
+/* grub-ofpathname.c - Find OpenBOOT path for a given device */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/util/misc.h>
+#include <grub/util/ofpath.h>
+
+#include <grub/i18n.h>
+
+#include "progname.h"
+
+int main(int argc, char **argv)
+{
+ char *of_path;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ if (argc != 2)
+ {
+ printf("Usage: %s DEVICE\n", program_name);
+ return 1;
+ }
+
+ of_path = grub_util_devname_to_ofpath (argv[1]);
+ printf("%s\n", of_path);
+
+ free (of_path);
+
+ return 0;
+}
diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c
new file mode 100644
index 0000000..1a43334
--- /dev/null
+++ b/util/ieee1275/ofpath.c
@@ -0,0 +1,425 @@
+/* ofpath.c - calculate OpenFirmware path names given an OS device */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#undef OFPATH_STANDALONE
+
+#ifndef OFPATH_STANDALONE
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/util/ofpath.h>
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef OFPATH_STANDALONE
+#define xmalloc malloc
+void
+grub_util_error (const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, "ofpath: error: ");
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ exit (1);
+}
+
+#endif
+
+static void
+kill_trailing_dir(char *path)
+{
+ char *end = path + strlen(path) - 1;
+
+ while (end >= path)
+ {
+ if (*end != '/')
+ {
+ end--;
+ continue;
+ }
+ *end = '\0';
+ break;
+ }
+}
+
+static void
+trim_newline (char *path)
+{
+ char *end = path + strlen(path) - 1;
+
+ while (*end == '\n')
+ *end-- = '\0';
+}
+
+#define OF_PATH_MAX 256
+
+static void
+find_obppath(char *of_path, const char *sysfs_path_orig)
+{
+ char *sysfs_path, *path;
+
+ sysfs_path = xmalloc (PATH_MAX);
+ path = xmalloc (PATH_MAX);
+
+ strcpy(sysfs_path, sysfs_path_orig);
+ while (1)
+ {
+ int fd;
+
+ snprintf(path, PATH_MAX, "%s/obppath", sysfs_path);
+#if 0
+ printf("Trying %s\n", path);
+#endif
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ {
+ kill_trailing_dir(sysfs_path);
+ if (!strcmp(sysfs_path, "/sys"))
+ grub_util_error("'obppath' not found in parent dirs of %s",
+ sysfs_path_orig);
+ continue;
+ }
+ memset(of_path, 0, OF_PATH_MAX);
+ read(fd, of_path, OF_PATH_MAX);
+ close(fd);
+
+ trim_newline(of_path);
+ break;
+ }
+
+ free (path);
+ free (sysfs_path);
+}
+
+static void
+block_device_get_sysfs_path_and_link(const char *devicenode,
+ char *sysfs_path, int sysfs_path_len)
+{
+ char *rpath = xmalloc (PATH_MAX);
+
+ snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode);
+
+ if (!realpath (sysfs_path, rpath))
+ grub_util_error ("cannot get the real path of `%s'", sysfs_path);
+
+ strcat(rpath, "/device");
+
+ if (!realpath (rpath, sysfs_path))
+ grub_util_error ("cannot get the real path of `%s'", rpath);
+
+ free (rpath);
+}
+
+static const char *
+trailing_digits (const char *p)
+{
+ const char *end;
+
+ end = p + strlen(p) - 1;
+ while (end >= p)
+ {
+ if (! isdigit(*end))
+ break;
+ end--;
+ }
+
+ return end + 1;
+}
+
+static void
+__of_path_common(char *of_path, char *sysfs_path,
+ const char *device, int devno)
+{
+ const char *digit_string;
+ char disk[64];
+
+ find_obppath(of_path, sysfs_path);
+
+ digit_string = trailing_digits (device);
+ if (*digit_string == '\0')
+ {
+ sprintf(disk, "/disk@%d", devno);
+ }
+ else
+ {
+ int part;
+
+ sscanf(digit_string, "%d", &part);
+ sprintf(disk, "/disk@%d:%c", devno, 'a' + (part - 1));
+ }
+ strcat(of_path, disk);
+}
+
+static char *
+get_basename(char *p)
+{
+ char *ret = p;
+
+ while (*p)
+ {
+ if (*p == '/')
+ ret = p + 1;
+ p++;
+ }
+
+ return ret;
+}
+
+static void
+of_path_of_vdisk(char *of_path,
+ const char *devname __attribute__((unused)),
+ const char *device,
+ const char *devnode __attribute__((unused)),
+ const char *devicenode)
+{
+ char *sysfs_path, *p;
+ int devno, junk;
+
+ sysfs_path = xmalloc (PATH_MAX);
+ block_device_get_sysfs_path_and_link(devicenode,
+ sysfs_path, PATH_MAX);
+ p = get_basename (sysfs_path);
+ sscanf(p, "vdc-port-%d-%d", &devno, &junk);
+ __of_path_common(of_path, sysfs_path, device, devno);
+
+ free (sysfs_path);
+}
+
+static void
+of_path_of_ide(char *of_path,
+ const char *devname __attribute__((unused)), const char *device,
+ const char *devnode __attribute__((unused)),
+ const char *devicenode)
+{
+ char *sysfs_path, *p;
+ int chan, devno;
+
+ sysfs_path = xmalloc (PATH_MAX);
+ block_device_get_sysfs_path_and_link(devicenode,
+ sysfs_path, PATH_MAX);
+ p = get_basename (sysfs_path);
+ sscanf(p, "%d.%d", &chan, &devno);
+
+ __of_path_common(of_path, sysfs_path, device, devno);
+
+ free (sysfs_path);
+}
+
+static int
+vendor_is_ATA(const char *path)
+{
+ int fd, err;
+ char *buf;
+
+ buf = xmalloc (PATH_MAX);
+
+ snprintf(buf, PATH_MAX, "%s/vendor", path);
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ grub_util_error ("cannot open 'vendor' node of `%s'", path);
+
+ memset(buf, 0, PATH_MAX);
+ err = read(fd, buf, PATH_MAX);
+ if (err < 0)
+ grub_util_error ("cannot read 'vendor' node of `%s'", path);
+
+ close(fd);
+
+ free (buf);
+
+ if (!strncmp(buf, "ATA", 3))
+ return 1;
+ return 0;
+}
+
+static void
+check_sas (char *sysfs_path, int *tgt)
+{
+ char *ed = strstr (sysfs_path, "end_device");
+ char *p, *q, *path;
+ char phy[16];
+ int fd;
+
+ if (!ed)
+ return;
+
+ /* SAS devices are identified using disk@$PHY_ID */
+ p = strdup (sysfs_path);
+ ed = strstr(p, "end_device");
+
+ q = ed;
+ while (*q && *q != '/')
+ q++;
+ *q = '\0';
+
+ path = xmalloc (PATH_MAX);
+ sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed);
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ grub_util_error("cannot open SAS PHY ID `%s'\n", path);
+
+ memset (phy, 0, sizeof (phy));
+ read (fd, phy, sizeof (phy));
+
+ sscanf (phy, "%d", tgt);
+
+ free (path);
+ free (p);
+}
+
+static void
+of_path_of_scsi(char *of_path,
+ const char *devname __attribute__((unused)), const char *device,
+ const char *devnode __attribute__((unused)),
+ const char *devicenode)
+{
+ const char *p, *digit_string, *disk_name;
+ int host, bus, tgt, lun;
+ char *sysfs_path, disk[64];
+
+ sysfs_path = xmalloc (PATH_MAX);
+
+ block_device_get_sysfs_path_and_link(devicenode,
+ sysfs_path, PATH_MAX);
+ p = get_basename (sysfs_path);
+ sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun);
+ check_sas (sysfs_path, &tgt);
+
+ if (vendor_is_ATA(sysfs_path))
+ {
+ __of_path_common(of_path, sysfs_path, device, tgt);
+ free (sysfs_path);
+ return;
+ }
+
+ find_obppath(of_path, sysfs_path);
+ free (sysfs_path);
+
+ if (strstr (of_path, "qlc"))
+ strcat (of_path, "/fp@0,0");
+
+ if (strstr (of_path, "sbus"))
+ disk_name = "sd";
+ else
+ disk_name = "disk";
+
+ digit_string = trailing_digits (device);
+ if (*digit_string == '\0')
+ {
+ sprintf(disk, "/%s@%x,%d", disk_name, tgt, lun);
+ }
+ else
+ {
+ int part;
+
+ sscanf(digit_string, "%d", &part);
+ sprintf(disk, "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1));
+ }
+ strcat(of_path, disk);
+}
+
+static char *
+strip_trailing_digits (const char *p)
+{
+ char *new, *end;
+
+ new = strdup (p);
+ end = new + strlen(new) - 1;
+ while (end >= new)
+ {
+ if (! isdigit(*end))
+ break;
+ *end-- = '\0';
+ }
+
+ return new;
+}
+
+char *
+grub_util_devname_to_ofpath (const char *devname)
+{
+ char *name_buf, *device, *devnode, *devicenode, *ofpath;
+
+ name_buf = xmalloc (PATH_MAX);
+ name_buf = realpath (devname, name_buf);
+ if (! name_buf)
+ grub_util_error ("cannot get the real path of `%s'", devname);
+
+ device = get_basename (name_buf);
+ devnode = strip_trailing_digits (name_buf);
+ devicenode = strip_trailing_digits (device);
+
+ ofpath = xmalloc (OF_PATH_MAX);
+
+ if (device[0] == 'h' && device[1] == 'd')
+ of_path_of_ide(ofpath, name_buf, device, devnode, devicenode);
+ else if (device[0] == 's'
+ && (device[1] == 'd' || device[1] == 'r'))
+ of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode);
+ else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i'
+ && device[3] == 's' && device[4] == 'k')
+ of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode);
+ else if (device[0] == 'f' && device[1] == 'd'
+ && device[2] == '0' && device[3] == '\0')
+ /* All the models I've seen have a devalias "floppy".
+ New models have no floppy at all. */
+ strcpy (ofpath, "floppy");
+ else
+ grub_util_error ("unknown device type %s\n", device);
+
+ free (devnode);
+ free (devicenode);
+ free (name_buf);
+
+ return ofpath;
+}
+
+#ifdef OFPATH_STANDALONE
+int main(int argc, char **argv)
+{
+ char *of_path;
+
+ if (argc != 2)
+ {
+ printf("Usage: grub-ofpathname DEVICE\n");
+ return 1;
+ }
+
+ of_path = grub_util_devname_to_ofpath (argv[1]);
+ printf("%s\n", of_path);
+
+ return 0;
+}
+#endif
diff --git a/util/import_gcry.py b/util/import_gcry.py
new file mode 100644
index 0000000..b2a0a54
--- /dev/null
+++ b/util/import_gcry.py
@@ -0,0 +1,346 @@
+#*
+#* GRUB -- GRand Unified Bootloader
+#* Copyright (C) 2009 Free Software Foundation, Inc.
+#*
+#* GRUB is free software: you can redistribute it and/or modify
+#* it under the terms of the GNU General Public License as published by
+#* the Free Software Foundation, either version 3 of the License, or
+#* (at your option) any later version.
+#*
+#* GRUB is distributed in the hope that it will be useful,
+#* but WITHOUT ANY WARRANTY; without even the implied warranty of
+#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#* GNU General Public License for more details.
+#*
+#* You should have received a copy of the GNU General Public License
+#* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+#*
+
+import re
+import sys
+import os
+import datetime
+
+if len (sys.argv) < 3:
+ print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
+ exit (0)
+indir = sys.argv[1]
+outdir = sys.argv[2]
+
+basedir = os.path.join (outdir, "lib/libgcrypt-grub")
+try:
+ os.makedirs (basedir)
+except:
+ print ("WARNING: %s already exists" % basedir)
+cipher_dir_in = os.path.join (indir, "cipher")
+cipher_dir_out = os.path.join (basedir, "cipher")
+try:
+ os.makedirs (cipher_dir_out)
+except:
+ print ("WARNING: %s already exists" % cipher_dir_out)
+
+cipher_files = os.listdir (cipher_dir_in)
+conf = open (os.path.join ("grub-core", "Makefile.gcry.def"), "w")
+conf.write ("AutoGen definitions Makefile.tpl;\n\n")
+chlog = ""
+
+# Strictly speaking CRC32/CRC24 work on bytes so this value should be 1
+# But libgcrypt uses 64. Let's keep the value for compatibility. Since
+# noone uses CRC24/CRC32 for HMAC this is no problem
+mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
+ "_gcry_digest_spec_crc32_rfc1510" : 64,
+ "_gcry_digest_spec_crc24_rfc2440" : 64,
+ "_gcry_digest_spec_md4" : 64,
+ "_gcry_digest_spec_md5" : 64,
+ "_gcry_digest_spec_rmd160" : 64,
+ "_gcry_digest_spec_sha1" : 64,
+ "_gcry_digest_spec_sha224" : 64,
+ "_gcry_digest_spec_sha256" : 64,
+ "_gcry_digest_spec_sha384" : 128,
+ "_gcry_digest_spec_sha512" : 128,
+ "_gcry_digest_spec_tiger" : 64,
+ "_gcry_digest_spec_whirlpool" : 64}
+
+cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w")
+
+# rijndael is the only cipher using aliases. So no need for mangling, just
+# hardcode it
+cryptolist.write ("RIJNDAEL: gcry_rijndael\n");
+cryptolist.write ("RIJNDAEL192: gcry_rijndael\n");
+cryptolist.write ("RIJNDAEL256: gcry_rijndael\n");
+cryptolist.write ("AES128: gcry_rijndael\n");
+cryptolist.write ("AES-128: gcry_rijndael\n");
+cryptolist.write ("AES-192: gcry_rijndael\n");
+cryptolist.write ("AES-256: gcry_rijndael\n");
+
+for cipher_file in cipher_files:
+ infile = os.path.join (cipher_dir_in, cipher_file)
+ outfile = os.path.join (cipher_dir_out, cipher_file)
+ if cipher_file == "ChangeLog":
+ continue
+ chlognew = " * %s" % cipher_file
+ if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file):
+ chlog = "%s%s: Removed\n" % (chlog, chlognew)
+ continue
+ # Autogenerated files. Not even worth mentionning in ChangeLog
+ if re.match ("Makefile\.in$", cipher_file):
+ continue
+ nch = False
+ if re.match (".*\.[ch]$", cipher_file):
+ isc = re.match (".*\.c$", cipher_file)
+ f = open (infile, "r")
+ fw = open (outfile, "w")
+ fw.write ("/* This file was automatically imported with \n")
+ fw.write (" import_gcry.py. Please don't modify it */\n")
+ fw.write ("#include <grub/dl.h>\n")
+ # Whole libgcrypt is distributed under GPLv3+ or compatible
+ if isc:
+ fw.write ("GRUB_MOD_LICENSE (\"GPLv3+\");\n")
+
+ ciphernames = []
+ mdnames = []
+ hold = False
+ skip = False
+ skip2 = False
+ ismd = False
+ iscryptostart = False
+ iscomma = False
+ isglue = False
+ skip_statement = False
+ if isc:
+ modname = cipher_file [0:len(cipher_file) - 2]
+ if re.match (".*-glue$", modname):
+ modname = modname.replace ("-glue", "")
+ isglue = True
+ modname = "gcry_%s" % modname
+ for line in f:
+ if skip_statement:
+ if not re.search (";", line) is None:
+ skip_statement = False
+ continue
+ if skip:
+ if line[0] == "}":
+ skip = False
+ continue
+ if skip2:
+ if not re.search (" *};", line) is None:
+ skip2 = False
+ continue
+ if iscryptostart:
+ s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
+ if not s is None:
+ sg = s.groups()[0]
+ cryptolist.write (("%s: %s\n") % (sg, modname))
+ iscryptostart = False
+ if ismd:
+ if not re.search (" *};", line) is None:
+ if not mdblocksizes.has_key (mdname):
+ print ("ERROR: Unknown digest blocksize: %s\n" % mdname)
+ exit (1)
+ if not iscomma:
+ fw.write (" ,\n")
+ fw.write (" .blocksize = %s\n" % mdblocksizes [mdname])
+ ismd = False
+ iscomma = not re.search (",$", line) is None
+ # Used only for selftests.
+ m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line)
+ if not m is None:
+ skip = True
+ fname = m.groups ()[1]
+ chmsg = "(%s): Removed." % fname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ if hold:
+ hold = False
+ # We're optimising for size.
+ if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info)", line) is None:
+ skip = True
+ fname = re.match ("[a-zA-Z0-9_]*", line).group ()
+ chmsg = "(%s): Removed." % fname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ else:
+ fw.write (holdline)
+ m = re.match ("#include <.*>", line)
+ if not m is None:
+ chmsg = "Removed including of %s" % \
+ m.group () [len ("#include <"):len (m.group ()) - 1]
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s: %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ m = re.match ("gcry_cipher_spec_t", line)
+ if isc and not m is None:
+ assert (not iscryptostart)
+ ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
+ ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
+ ciphernames.append (ciphername)
+ iscryptostart = True
+ m = re.match ("gcry_md_spec_t", line)
+ if isc and not m is None:
+ assert (not ismd)
+ assert (not iscryptostart)
+ mdname = line [len ("gcry_md_spec_t"):].strip ()
+ mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
+ mdnames.append (mdname)
+ ismd = True
+ iscryptostart = True
+ m = re.match ("static const char \*selftest.*;$", line)
+ if not m is None:
+ fname = line[len ("static const char \*"):]
+ fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+ chmsg = "(%s): Removed declaration." % fname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t)$", line)
+ if not m is None:
+ hold = True
+ holdline = line
+ continue
+ m = re.match ("static int tripledes_set2keys \(.*\);", line)
+ if not m is None:
+ continue
+ m = re.match ("static int tripledes_set2keys \(", line)
+ if not m is None:
+ skip_statement = True
+ continue
+ m = re.match ("cipher_extra_spec_t", line)
+ if isc and not m is None:
+ skip2 = True
+ fname = line[len ("cipher_extra_spec_t "):]
+ fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+ chmsg = "(%s): Removed." % fname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ m = re.match ("md_extra_spec_t", line)
+ if isc and not m is None:
+ skip2 = True
+ fname = line[len ("md_extra_spec_t "):]
+ fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+ chmsg = "(%s): Removed." % fname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s %s" % (chlognew, chmsg)
+ nch = True
+ continue
+ fw.write (line)
+ if len (ciphernames) > 0 or len (mdnames) > 0:
+ if isglue:
+ modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
+ % (cipher_file, cipher_file.replace ("-glue.c", ".c"))
+ else:
+ modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
+ chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
+ if nch:
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ else:
+ chlognew = "%s%s" % (chlognew, chmsg)
+ nch = True
+ fw.write ("\n\nGRUB_MOD_INIT(%s)\n" % modname)
+ fw.write ("{\n")
+ for ciphername in ciphernames:
+ chmsg = "Register cipher %s" % ciphername
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ fw.write (" grub_cipher_register (&%s);\n" % ciphername)
+ for mdname in mdnames:
+ chmsg = "Register digest %s" % mdname
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ fw.write (" grub_md_register (&%s);\n" % mdname)
+ fw.write ("}")
+ chmsg = "(GRUB_MOD_FINI(%s)): New function\n" % modname
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ fw.write ("\n\nGRUB_MOD_FINI(%s)\n" % modname)
+ fw.write ("{\n")
+ for ciphername in ciphernames:
+ chmsg = "Unregister cipher %s" % ciphername
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ fw.write (" grub_cipher_unregister (&%s);\n" % ciphername)
+ for mdname in mdnames:
+ chmsg = "Unregister MD %s" % mdname
+ chlognew = "%s\n %s" % (chlognew, chmsg)
+ fw.write (" grub_md_unregister (&%s);\n" % mdname)
+ fw.write ("}\n")
+ conf.write ("module = {\n")
+ conf.write (" name = %s;\n" % modname)
+ for src in modfiles.split():
+ conf.write (" common = %s;\n" % src)
+ conf.write (" cflags = '$(CFLAGS_GCRY)';\n");
+ conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n");
+ conf.write ("};\n\n")
+ elif isc and cipher_file != "camellia.c":
+ print ("WARNING: C file isn't a module: %s" % cipher_file)
+ f.close ()
+ fw.close ()
+ if nch:
+ chlog = "%s%s\n" % (chlog, chlognew)
+ continue
+ chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
+ print ("WARNING: unknown file %s" % cipher_file)
+
+cryptolist.close ()
+chlog = "%s * crypto.lst: New file.\n" % chlog
+
+outfile = os.path.join (cipher_dir_out, "types.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/types.h>\n")
+fw.write ("#include <cipher_wrap.h>\n")
+chlog = "%s * types.h: New file.\n" % chlog
+fw.close ()
+
+outfile = os.path.join (cipher_dir_out, "memory.h")
+fw=open (outfile, "w")
+fw.write ("#include <cipher_wrap.h>\n")
+chlog = "%s * memory.h: New file.\n" % chlog
+fw.close ()
+
+
+outfile = os.path.join (cipher_dir_out, "cipher.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/crypto.h>\n")
+fw.write ("#include <cipher_wrap.h>\n")
+chlog = "%s * cipher.h: Likewise.\n" % chlog
+fw.close ()
+
+outfile = os.path.join (cipher_dir_out, "g10lib.h")
+fw=open (outfile, "w")
+fw.write ("#include <cipher_wrap.h>\n")
+chlog = "%s * g10lib.h: Likewise.\n" % chlog
+fw.close ()
+
+infile = os.path.join (cipher_dir_in, "ChangeLog")
+outfile = os.path.join (cipher_dir_out, "ChangeLog")
+
+
+f=open (infile, "r")
+fw=open (outfile, "w")
+dt = datetime.date.today ()
+fw.write ("%04d-%02d-%02d Automatic import tool\n" % \
+ (dt.year,dt.month, dt.day))
+fw.write ("\n")
+fw.write (" Imported ciphers to GRUB\n")
+fw.write ("\n")
+fw.write (chlog)
+fw.write ("\n")
+for line in f:
+ fw.write (line)
+f.close ()
+fw.close ()
diff --git a/util/import_unicode.py b/util/import_unicode.py
new file mode 100644
index 0000000..8d17e7e
--- /dev/null
+++ b/util/import_unicode.py
@@ -0,0 +1,189 @@
+#*
+#* GRUB -- GRand Unified Bootloader
+#* Copyright (C) 2010 Free Software Foundation, Inc.
+#*
+#* GRUB is free software: you can redistribute it and/or modify
+#* it under the terms of the GNU General Public License as published by
+#* the Free Software Foundation, either version 3 of the License, or
+#* (at your option) any later version.
+#*
+#* GRUB is distributed in the hope that it will be useful,
+#* but WITHOUT ANY WARRANTY; without even the implied warranty of
+#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#* GNU General Public License for more details.
+#*
+#* You should have received a copy of the GNU General Public License
+#* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+#*
+
+import re
+import sys
+
+if len (sys.argv) < 3:
+ print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
+ exit (0)
+infile = open (sys.argv[3], "r")
+joining = {}
+for line in infile:
+ line = re.sub ("#.*$", "", line)
+ line = line.replace ("\n", "")
+ line = line.replace (" ", "")
+ if len (line) == 0 or line[0] == '\n':
+ continue
+ sp = line.split (";")
+ curcode = int (sp[0], 16)
+ if sp[2] == "U":
+ joining[curcode] = "NONJOINING"
+ elif sp[2] == "L":
+ joining[curcode] = "LEFT"
+ elif sp[2] == "R":
+ joining[curcode] = "RIGHT"
+ elif sp[2] == "D":
+ joining[curcode] = "DUAL"
+ elif sp[2] == "C":
+ joining[curcode] = "CAUSING"
+ else:
+ print ("Unknown joining type '%s'" % sp[2])
+ exit (1)
+infile.close ()
+
+infile = open (sys.argv[1], "r")
+outfile = open (sys.argv[4], "w")
+outfile.write ("#include <grub/unicode.h>\n")
+outfile.write ("\n")
+outfile.write ("struct grub_unicode_compact_range grub_unicode_compact[] = {\n")
+
+begincode = -2
+lastcode = -2
+lastbiditype = "X"
+lastmirrortype = False
+lastcombtype = -1
+arabicsubst = {}
+for line in infile:
+ sp = line.split (";")
+ curcode = int (sp[0], 16)
+ curcombtype = int (sp[3], 10)
+ curbiditype = sp[4]
+ curmirrortype = (sp[9] == "Y")
+ if curcombtype <= 255 and curcombtype >= 253:
+ print ("UnicodeData.txt uses combination type %d. Conflict." \
+ % curcombtype)
+ raise
+ if sp[2] != "Lu" and sp[2] != "Ll" and sp[2] != "Lt" and sp[2] != "Lm" \
+ and sp[2] != "Lo"\
+ and sp[2] != "Me" and sp[2] != "Mc" and sp[2] != "Mn" \
+ and sp[2] != "Nd" and sp[2] != "Nl" and sp[2] != "No" \
+ and sp[2] != "Pc" and sp[2] != "Pd" and sp[2] != "Ps" \
+ and sp[2] != "Pe" and sp[2] != "Pi" and sp[2] != "Pf" \
+ and sp[2] != "Po" \
+ and sp[2] != "Sm" and sp[2] != "Sc" and sp[2] != "Sk" \
+ and sp[2] != "So"\
+ and sp[2] != "Zs" and sp[2] != "Zl" and sp[2] != "Zp" \
+ and sp[2] != "Cc" and sp[2] != "Cf" and sp[2] != "Cs" \
+ and sp[2] != "Co":
+ print ("WARNING: Unknown type %s" % sp[2])
+ if curcombtype == 0 and sp[2] == "Me":
+ curcombtype = 253
+ if curcombtype == 0 and sp[2] == "Mc":
+ curcombtype = 254
+ if curcombtype == 0 and sp[2] == "Mn":
+ curcombtype = 255
+ if (curcombtype >= 2 and curcombtype <= 6) \
+ or (curcombtype >= 37 and curcombtype != 84 and curcombtype != 91 and curcombtype != 103 and curcombtype != 107 and curcombtype != 118 and curcombtype != 122 and curcombtype != 129 and curcombtype != 130 and curcombtype != 132 and curcombtype != 202 and \
+ curcombtype != 214 and curcombtype != 216 and \
+ curcombtype != 218 and curcombtype != 220 and \
+ curcombtype != 222 and curcombtype != 224 and curcombtype != 226 and curcombtype != 228 and \
+ curcombtype != 230 and curcombtype != 232 and curcombtype != 233 and \
+ curcombtype != 234 and \
+ curcombtype != 240 and curcombtype != 253 and \
+ curcombtype != 254 and curcombtype != 255):
+ print ("WARNING: Unknown combining type %d" % curcombtype)
+ if curcode in joining:
+ curjoin = joining[curcode]
+ elif sp[2] == "Me" or sp[2] == "Mn" or sp[2] == "Cf":
+ curjoin = "TRANSPARENT"
+ else:
+ curjoin = "NONJOINING"
+ if sp[1].startswith ("ARABIC LETTER "):
+ arabname = sp[1][len ("ARABIC LETTER "):]
+ form = 0
+ if arabname.endswith (" ISOLATED FORM"):
+ arabname = arabname[0:len (arabname) - len (" ISOLATED FORM")]
+ form = 1
+ if arabname.endswith (" FINAL FORM"):
+ arabname = arabname[0:len (arabname) - len (" FINAL FORM")]
+ form = 2
+ if arabname.endswith (" MEDIAL FORM"):
+ arabname = arabname[0:len (arabname) - len (" MEDIAL FORM")]
+ form = 3
+ if arabname.endswith (" INITIAL FORM"):
+ arabname = arabname[0:len (arabname) - len (" INITIAL FORM")]
+ form = 4
+ if arabname not in arabicsubst:
+ arabicsubst[arabname]={}
+ arabicsubst[arabname][form] = curcode;
+ if form == 0:
+ arabicsubst[arabname]['join'] = curjoin
+ if lastcode + 1 != curcode or curbiditype != lastbiditype \
+ or curcombtype != lastcombtype or curmirrortype != lastmirrortype \
+ or curjoin != lastjoin:
+ if begincode != -2 and (lastbiditype != "L" or lastcombtype != 0 or \
+ lastmirrortype):
+ outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, GRUB_JOIN_TYPE_%s},\n" \
+ % (begincode, lastcode, lastbiditype, \
+ lastcombtype, lastmirrortype, \
+ lastjoin)))
+ begincode = curcode
+ lastcode = curcode
+ lastjoin = curjoin
+ lastbiditype = curbiditype
+ lastcombtype = curcombtype
+ lastmirrortype = curmirrortype
+if lastbiditype != "L" or lastcombtype != 0 or lastmirrortype:
+ outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, GRUB_JOIN_TYPE_%s},\n" \
+ % (begincode, lastcode, lastbiditype, lastcombtype, \
+ lastmirrortype, lastjoin)))
+outfile.write ("{0, 0, 0, 0, 0, 0},\n")
+
+outfile.write ("};\n")
+
+infile.close ()
+
+infile = open (sys.argv[2], "r")
+
+outfile.write ("struct grub_unicode_bidi_pair grub_unicode_bidi_pairs[] = {\n")
+
+for line in infile:
+ line = re.sub ("#.*$", "", line)
+ line = line.replace ("\n", "")
+ line = line.replace (" ", "")
+ if len (line) == 0 or line[0] == '\n':
+ continue
+ sp = line.split (";")
+ code1 = int (sp[0], 16)
+ code2 = int (sp[1], 16)
+ outfile.write ("{0x%x, 0x%x},\n" % (code1, code2))
+outfile.write ("{0, 0},\n")
+outfile.write ("};\n")
+
+infile.close ()
+
+outfile.write ("struct grub_unicode_arabic_shape grub_unicode_arabic_shapes[] = {\n ")
+
+for x in arabicsubst:
+ try:
+ if arabicsubst[x]['join'] == "DUAL":
+ outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], arabicsubst[x][2], arabicsubst[x][3], arabicsubst[x][4]))
+ elif arabicsubst[x]['join'] == "RIGHT":
+ outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], arabicsubst[x][2], 0, 0))
+ elif arabicsubst[x]['join'] == "LEFT":
+ outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], 0, 0, arabicsubst[x][4]))
+ except:
+ pass
+
+outfile.write ("{0, 0, 0, 0, 0},\n")
+outfile.write ("};\n")
+
+
+outfile.close ()
+
diff --git a/util/lvm.c b/util/lvm.c
new file mode 100644
index 0000000..bb2c19f
--- /dev/null
+++ b/util/lvm.c
@@ -0,0 +1,52 @@
+/* lvm.c - LVM support for GRUB utils. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We only support LVM on Linux. */
+#ifdef __linux__
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/lvm.h>
+
+#include <string.h>
+#include <sys/stat.h>
+
+#define LVM_DEV_MAPPER_STRING "/dev/mapper/"
+
+int
+grub_util_lvm_isvolume (char *name)
+{
+ char *devname;
+ struct stat st;
+ int err;
+
+ devname = xmalloc (strlen (name) + sizeof (LVM_DEV_MAPPER_STRING));
+
+ strcpy (devname, LVM_DEV_MAPPER_STRING);
+ strcpy (devname + sizeof(LVM_DEV_MAPPER_STRING) - 1, name);
+
+ err = stat (devname, &st);
+ free (devname);
+
+ if (err)
+ return 0;
+ else
+ return 1;
+}
+
+#endif /* ! __linux__ */
diff --git a/util/misc.c b/util/misc.c
new file mode 100644
index 0000000..cfbae60
--- /dev/null
+++ b/util/misc.c
@@ -0,0 +1,379 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <grub/kernel.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/cache.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/i18n.h>
+#include <grub/script_sh.h>
+
+#define ENABLE_RELOCATABLE 0
+#include "progname.h"
+
+/* Include malloc.h, only if memalign is available. It is known that
+ memalign is declared in malloc.h in all systems, if present. */
+#ifdef HAVE_MEMALIGN
+# include <malloc.h>
+#endif
+
+#ifdef __MINGW32__
+#include <windows.h>
+#include <winioctl.h>
+#endif
+
+#ifdef GRUB_UTIL
+int
+grub_err_printf (const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start (ap, fmt);
+ ret = vfprintf (stderr, fmt, ap);
+ va_end (ap);
+
+ return ret;
+}
+#endif
+
+char *
+grub_util_get_path (const char *dir, const char *file)
+{
+ char *path;
+
+ path = (char *) xmalloc (strlen (dir) + 1 + strlen (file) + 1);
+ sprintf (path, "%s/%s", dir, file);
+ return path;
+}
+
+size_t
+grub_util_get_fp_size (FILE *fp)
+{
+ struct stat st;
+
+ if (fflush (fp) == EOF)
+ grub_util_error ("fflush failed");
+
+ if (fstat (fileno (fp), &st) == -1)
+ grub_util_error ("fstat failed");
+
+ return st.st_size;
+}
+
+size_t
+grub_util_get_image_size (const char *path)
+{
+ struct stat st;
+
+ grub_util_info ("getting the size of %s", path);
+
+ if (stat (path, &st) == -1)
+ grub_util_error ("cannot stat %s", path);
+
+ return st.st_size;
+}
+
+void
+grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp)
+{
+ if (fseeko (fp, offset, SEEK_SET) == -1)
+ grub_util_error ("seek failed");
+
+ if (fread (img, 1, size, fp) != size)
+ grub_util_error ("read failed");
+}
+
+char *
+grub_util_read_image (const char *path)
+{
+ char *img;
+ FILE *fp;
+ size_t size;
+
+ grub_util_info ("reading %s", path);
+
+ size = grub_util_get_image_size (path);
+ img = (char *) xmalloc (size);
+
+ fp = fopen (path, "rb");
+ if (! fp)
+ grub_util_error ("cannot open %s", path);
+
+ grub_util_read_at (img, size, 0, fp);
+
+ fclose (fp);
+
+ return img;
+}
+
+void
+grub_util_load_image (const char *path, char *buf)
+{
+ FILE *fp;
+ size_t size;
+
+ grub_util_info ("reading %s", path);
+
+ size = grub_util_get_image_size (path);
+
+ fp = fopen (path, "rb");
+ if (! fp)
+ grub_util_error ("cannot open %s", path);
+
+ if (fread (buf, 1, size, fp) != size)
+ grub_util_error ("cannot read %s", path);
+
+ fclose (fp);
+}
+
+void
+grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
+{
+ grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
+ if (fseeko (out, offset, SEEK_SET) == -1)
+ grub_util_error ("seek failed");
+ if (fwrite (img, 1, size, out) != size)
+ grub_util_error ("write failed");
+}
+
+void
+grub_util_write_image (const char *img, size_t size, FILE *out)
+{
+ grub_util_info ("writing 0x%x bytes", size);
+ if (fwrite (img, 1, size, out) != size)
+ grub_util_error ("write failed");
+}
+
+char *
+grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_cmdlist (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_cmdwhile (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused)))
+{
+ return 0;
+}
+
+grub_err_t
+grub_script_execute (struct grub_script *script)
+{
+ if (script == 0 || script->cmd == 0)
+ return 0;
+
+ return script->cmd->exec (script->cmd);
+}
+
+void
+grub_putchar (int c)
+{
+ putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+ return -1;
+}
+
+void
+grub_refresh (void)
+{
+ fflush (stdout);
+}
+
+static void
+grub_xputs_real (const char *str)
+{
+ fputs (str, stdout);
+}
+
+void (*grub_xputs) (const char *str) = grub_xputs_real;
+
+int
+grub_dl_ref (grub_dl_t mod)
+{
+ (void) mod;
+ return 0;
+}
+
+int
+grub_dl_unref (grub_dl_t mod)
+{
+ (void) mod;
+ return 0;
+}
+
+/* Some functions that we don't use. */
+void
+grub_mm_init_region (void *addr __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
+
+void
+grub_register_exported_symbols (void)
+{
+}
+
+#ifdef __MINGW32__
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+ Sleep (ms);
+}
+
+#else
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+ struct timespec ts;
+
+ ts.tv_sec = ms / 1000;
+ ts.tv_nsec = (ms % 1000) * 1000000;
+ nanosleep (&ts, NULL);
+}
+
+#endif
+
+#ifdef __MINGW32__
+
+void sync (void)
+{
+}
+
+int fsync (int fno __attribute__ ((unused)))
+{
+ return 0;
+}
+
+void sleep (int s)
+{
+ Sleep (s * 1000);
+}
+
+grub_int64_t
+grub_util_get_disk_size (char *name)
+{
+ HANDLE hd;
+ grub_int64_t size = -1LL;
+
+ hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, 0, 0);
+
+ if (hd == INVALID_HANDLE_VALUE)
+ return size;
+
+ if (((name[0] == '/') || (name[0] == '\\')) &&
+ ((name[1] == '/') || (name[1] == '\\')) &&
+ (name[2] == '.') &&
+ ((name[3] == '/') || (name[3] == '\\')) &&
+ (! strncasecmp (name + 4, "PHYSICALDRIVE", 13)))
+ {
+ DWORD nr;
+ DISK_GEOMETRY g;
+
+ if (! DeviceIoControl (hd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ 0, 0, &g, sizeof (g), &nr, 0))
+ goto fail;
+
+ size = g.Cylinders.QuadPart;
+ size *= g.TracksPerCylinder * g.SectorsPerTrack * g.BytesPerSector;
+ }
+ else
+ {
+ LARGE_INTEGER s;
+
+ s.LowPart = GetFileSize (hd, &s.HighPart);
+ size = s.QuadPart;
+ }
+
+fail:
+
+ CloseHandle (hd);
+
+ return size;
+}
+
+#endif /* __MINGW32__ */
+
+#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/powerpc/ieee1275/grub-mkrescue.in b/util/powerpc/ieee1275/grub-mkrescue.in
new file mode 100644
index 0000000..d688431
--- /dev/null
+++ b/util/powerpc/ieee1275/grub-mkrescue.in
@@ -0,0 +1,143 @@
+#! /bin/sh
+set -e
+
+# Make GRUB rescue image
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+self=`basename $0`
+
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+
+# Usage: usage
+# Print the usage.
+usage () {
+ cat <<EOF
+Usage: $self [OPTION] output_image
+Make GRUB rescue image.
+
+ -h, --help print this message and exit
+ -v, --version print the version information and exit
+ --modules=MODULES pre-load specified modules MODULES
+ --pkglibdir=DIR use images from directory DIR
+ default: ${pkglibdir}
+ --grub-mkimage=FILE use FILE as grub-mkimage
+
+$self generates a bootable rescue CD image for PowerMac and CHRP.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ echo "$0: option requires an argument -- '$opt'" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+input_dir=${pkglibdir}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -v | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --modules)
+ modules=`argument $option "$@"`; shift ;;
+ --modules=*)
+ modules=`echo "$option" | sed 's/--modules=//'` ;;
+
+ --pkglibdir)
+ input_dir=`argument $option "$@"`; shift ;;
+ --pkglibdir=*)
+ input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;;
+
+ --grub-mkimage)
+ grub_mkimage=`argument $option "$@"`; shift ;;
+ --grub-mkimage=*)
+ grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+
+ -*)
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ ;;
+ *)
+ if test "x$output_image" != x; then
+ echo "Unrecognized option \`$option'" 1>&2
+ usage
+ exit 1
+ fi
+ output_image="${option}" ;;
+ esac
+done
+
+if test "x$output_image" = x; then
+ usage
+ exit 1
+fi
+
+if [ "x${modules}" = "x" ] ; then
+ modules=`cd ${input_dir}/ && ls *.mod`
+fi
+
+map_file=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+cat >${map_file} <<EOF
+# EXTN XLate CREATOR TYPE Comment
+grub.img Raw 'UNIX' 'tbxi' "bootstrap"
+EOF
+
+iso_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
+boot_dir=${iso_dir}/boot/grub
+mkdir ${iso_dir}/boot
+mkdir ${boot_dir}
+core_img=${boot_dir}/grub.img
+${grub_mkimage} -O powerpc-ieee1275 -n -d ${input_dir}/ -o ${core_img} ${modules}
+genisoimage -hfs -part -no-desktop -r -J -o ${output_image} \
+ -map ${map_file} -hfs-bless ${boot_dir} -chrp-boot -sysid PPC \
+ ${iso_dir}
+
+rm -rf ${iso_dir}
+rm -f ${map_file}
+
+exit 0
diff --git a/util/raid.c b/util/raid.c
new file mode 100644
index 0000000..a6aa5f9
--- /dev/null
+++ b/util/raid.c
@@ -0,0 +1,86 @@
+/* raid.c - RAID support for GRUB utils. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We only support RAID on Linux. */
+#ifdef __linux__
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/raid.h>
+#include <grub/emu/getroot.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/raid/md_p.h>
+#include <linux/raid/md_u.h>
+
+char **
+grub_util_raid_getmembers (const char *name)
+{
+ int fd, ret, i, j;
+ char **devicelist;
+ mdu_version_t version;
+ mdu_array_info_t info;
+ mdu_disk_info_t disk;
+
+ fd = open (name, O_RDONLY);
+
+ if (fd == -1)
+ grub_util_error ("can't open %s: %s", name, strerror (errno));
+
+ ret = ioctl (fd, RAID_VERSION, &version);
+ if (ret != 0)
+ grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
+
+ if (version.major != 0 || version.minor != 90)
+ grub_util_error ("unsupported RAID version: %d.%d",
+ version.major, version.minor);
+
+ ret = ioctl (fd, GET_ARRAY_INFO, &info);
+ if (ret != 0)
+ grub_util_error ("ioctl GET_ARRAY_INFO error: %s", strerror (errno));
+
+ devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *));
+
+ for (i = 0, j = 0; i <info.nr_disks; i++)
+ {
+ disk.number = i;
+ ret = ioctl (fd, GET_DISK_INFO, &disk);
+ if (ret != 0)
+ grub_util_error ("ioctl GET_DISK_INFO error: %s", strerror (errno));
+
+ if (disk.state & (1 << MD_DISK_ACTIVE))
+ {
+ devicelist[j] = grub_find_device (NULL,
+ makedev (disk.major, disk.minor));
+ j++;
+ }
+ }
+
+ devicelist[j] = NULL;
+
+ return devicelist;
+}
+
+#endif /* ! __linux__ */
diff --git a/util/resolve.c b/util/resolve.c
new file mode 100644
index 0000000..63bd7cc
--- /dev/null
+++ b/util/resolve.c
@@ -0,0 +1,270 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+
+/* Module. */
+struct mod_list
+{
+ const char *name;
+ struct mod_list *next;
+};
+
+/* Dependency. */
+struct dep_list
+{
+ const char *name;
+ struct mod_list *list;
+ struct dep_list *next;
+};
+
+static char buf[1024];
+
+static void
+free_mod_list (struct mod_list *head)
+{
+ while (head)
+ {
+ struct mod_list *next;
+
+ next = head->next;
+ free ((void *) head->name);
+ free (head);
+ head = next;
+ }
+}
+
+static void
+free_dep_list (struct dep_list *head)
+{
+ while (head)
+ {
+ struct dep_list *next;
+
+ next = head->next;
+ free ((void *) head->name);
+ free_mod_list (head->list);
+ free (head);
+ head = next;
+ }
+}
+
+/* Read the list of dependencies. */
+static struct dep_list *
+read_dep_list (FILE *fp)
+{
+ struct dep_list *dep_list = 0;
+
+ while (fgets (buf, sizeof (buf), fp))
+ {
+ char *p;
+ struct dep_list *dep;
+
+ /* Get the target name. */
+ p = strchr (buf, ':');
+ if (! p)
+ grub_util_error ("invalid line format: %s", buf);
+
+ *p++ = '\0';
+
+ dep = xmalloc (sizeof (*dep));
+ dep->name = xstrdup (buf);
+ dep->list = 0;
+
+ dep->next = dep_list;
+ dep_list = dep;
+
+ /* Add dependencies. */
+ while (*p)
+ {
+ struct mod_list *mod;
+ char *name;
+
+ /* Skip whitespace. */
+ while (*p && isspace (*p))
+ p++;
+
+ if (! *p)
+ break;
+
+ name = p;
+
+ /* Skip non-whitespace. */
+ while (*p && ! isspace (*p))
+ p++;
+
+ *p++ = '\0';
+
+ mod = (struct mod_list *) xmalloc (sizeof (*mod));
+ mod->name = xstrdup (name);
+ mod->next = dep->list;
+ dep->list = mod;
+ }
+ }
+
+ return dep_list;
+}
+
+static char *
+get_module_name (const char *str)
+{
+ char *base;
+ char *ext;
+
+ base = strrchr (str, '/');
+ if (! base)
+ base = (char *) str;
+ else
+ base++;
+
+ ext = strrchr (base, '.');
+ if (ext && strcmp (ext, ".mod") == 0)
+ {
+ char *name;
+
+ name = xmalloc (ext - base + 1);
+ memcpy (name, base, ext - base);
+ name[ext - base] = '\0';
+ return name;
+ }
+
+ return xstrdup (base);
+}
+
+static char *
+get_module_path (const char *prefix, const char *str)
+{
+ char *dir;
+ char *base;
+ char *ext;
+ char *ret;
+
+ ext = strrchr (str, '.');
+ if (ext && strcmp (ext, ".mod") == 0)
+ base = xstrdup (str);
+ else
+ {
+ base = xmalloc (strlen (str) + 4 + 1);
+ sprintf (base, "%s.mod", str);
+ }
+
+ dir = strchr (str, '/');
+ if (dir)
+ return base;
+
+ ret = grub_util_get_path (prefix, base);
+ free (base);
+ return ret;
+}
+
+static void
+add_module (const char *dir,
+ struct dep_list *dep_list,
+ struct mod_list **mod_head,
+ struct grub_util_path_list **path_head,
+ const char *name)
+{
+ char *mod_name;
+ struct grub_util_path_list *path;
+ struct mod_list *mod;
+ struct dep_list *dep;
+
+ mod_name = get_module_name (name);
+
+ /* Check if the module has already been added. */
+ for (mod = *mod_head; mod; mod = mod->next)
+ if (strcmp (mod->name, mod_name) == 0)
+ {
+ free (mod_name);
+ return;
+ }
+
+ /* Resolve dependencies. */
+ for (dep = dep_list; dep; dep = dep->next)
+ if (strcmp (dep->name, mod_name) == 0)
+ {
+ for (mod = dep->list; mod; mod = mod->next)
+ add_module (dir, dep_list, mod_head, path_head, mod->name);
+
+ break;
+ }
+
+ /* Add this module. */
+ mod = (struct mod_list *) xmalloc (sizeof (*mod));
+ mod->name = mod_name;
+ mod->next = *mod_head;
+ *mod_head = mod;
+
+ /* Add this path. */
+ path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
+ path->name = get_module_path (dir, name);
+ path->next = *path_head;
+ *path_head = path;
+}
+
+struct grub_util_path_list *
+grub_util_resolve_dependencies (const char *prefix,
+ const char *dep_list_file,
+ char *modules[])
+{
+ char *path;
+ FILE *fp;
+ struct dep_list *dep_list;
+ struct mod_list *mod_list = 0;
+ struct grub_util_path_list *path_list = 0;
+
+ path = grub_util_get_path (prefix, dep_list_file);
+ fp = fopen (path, "r");
+ if (! fp)
+ grub_util_error ("cannot open %s", path);
+
+ free (path);
+ dep_list = read_dep_list (fp);
+ fclose (fp);
+
+ while (*modules)
+ {
+ add_module (prefix, dep_list, &mod_list, &path_list, *modules);
+ modules++;
+ }
+
+ free_dep_list (dep_list);
+ free_mod_list (mod_list);
+
+ { /* Reverse the path_list */
+ struct grub_util_path_list *p, *prev, *next;
+
+ for (p = path_list, prev = NULL; p; p = next)
+ {
+ next = p->next;
+ p->next = prev;
+ prev = p;
+ }
+
+ return prev;
+ }
+}
diff --git a/util/update-grub_lib.in b/util/update-grub_lib.in
new file mode 100644
index 0000000..998452e
--- /dev/null
+++ b/util/update-grub_lib.in
@@ -0,0 +1,23 @@
+# stub for new grub-mkconfig_lib
+# Copyright (C) 2007,2008 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead"