From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [RFC] grub-install C rewrite
Date: Sun, 06 Oct 2013 16:54:08 +0200 [thread overview]
Message-ID: <52517990.1020505@gmail.com> (raw)
In-Reply-To: <524431E6.60807@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 1470 bytes --]
On 26.09.2013 15:08, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> Hello, all. Recently I made some order in hostdisk.c and getroot.c
> involving splitting in OS-specific parts.
> In the same time I added WinAPI version of getroot/hostdisk allowing
> grub-probe to work on windows natively
> Also on-going is AROS-specific parts.
> Windows and AROS are not friendly with bash.
> The attempt to make both multiple files of same type work and handling
> whitespaces/newlines/... in filenames would result in very ugly code
> with loads of evals.
> Current code may have subtle assumptions on behaviour of common tools
> like sed and on locale (E.g. "[a-z]" doesn't cover u if locale is Estonian).
> So to check viability I rewrote grub-install in C. This is mostly proof
> of concept with loads of FIXMEs but I could boot i386-pc install made
> with it. In many aspects (static variables, some tests, general
> structure) it's reminiscent of sh version of grub-install it's based on.
> Some functionality is likely to stay OS-specific, e.g. executing
> compressors or determining firmware.
Attached is the second iteration of this patch. Now the biggest problem
is in reading /etc/default/grub and getting GRUB_DISTRIBUTOR and
GRUB_ENABLE_CRYPTODISK. Trouble is that now this file is simply included
in bash script and e.g. Debian uses it to determine GRUB_DISTRIBUTOR
based on lsb_release output. Does anyone have an elegant solution for this?
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: install_c.diff --]
[-- Type: text/x-diff; name="install_c.diff", Size: 295156 bytes --]
=== modified file 'Makefile.util.def'
--- Makefile.util.def 2013-10-03 23:29:10 +0000
+++ Makefile.util.def 2013-10-04 13:50:03 +0000
@@ -159,6 +159,7 @@
mansection = 1;
common = util/grub-mkimage.c;
+ common = util/mkimage.c;
common = util/resolve.c;
common = grub-core/kern/emu/argp_common.c;
@@ -208,6 +209,7 @@
mansection = 1;
common = util/grub-editenv.c;
+ common = util/editenv.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
@@ -308,6 +310,7 @@
installdir = sbin;
mansection = 8;
common = util/grub-setup.c;
+ common = util/setup_bios.c;
common = grub-core/kern/emu/argp_common.c;
common = grub-core/lib/reed_solomon.c;
@@ -316,7 +319,7 @@
ldadd = libgrubgcry.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
- cppflags = '-DGRUB_SETUP_BIOS=1';
+ cppflags = '-DGRUB_SETUP_FUNC=grub_bios_setup';
};
program = {
@@ -324,6 +327,7 @@
installdir = sbin;
mansection = 8;
common = util/grub-setup.c;
+ common = util/setup_sparc.c;
common = grub-core/kern/emu/argp_common.c;
common = grub-core/lib/reed_solomon.c;
common = util/ieee1275/ofpath.c;
@@ -333,7 +337,7 @@
ldadd = libgrubgcry.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
- cppflags = '-DGRUB_SETUP_SPARC64=1';
+ cppflags = '-DGRUB_SETUP_FUNC=grub_sparc_setup';
};
program = {
@@ -464,14 +468,33 @@
common = util/grub-mkstandalone.in;
};
-script = {
+program = {
mansection = 8;
installdir = sbin;
name = grub-install;
- common = util/grub-install_header;
- common = util/grub-install.in;
+ common = util/mkimage.c;
+ common = util/grub-install.c;
+ common = util/grub-install-common.c;
+ common = util/setup_bios.c;
+ common = util/setup_sparc.c;
+ common = grub-core/lib/reed_solomon.c;
+ common = util/random.c;
+ common = util/ieee1275/ofpath.c;
+ common = util/editenv.c;
+
+ common = grub-core/kern/arm/dl_helper.c;
+
+ common = util/resolve.c;
enable = noemu;
+ common = grub-core/kern/emu/argp_common.c;
+
+ ldadd = '$(LIBLZMA)';
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
script = {
=== modified file 'configure.ac'
--- configure.ac 2013-09-23 11:48:10 +0000
+++ configure.ac 2013-10-04 10:59:26 +0000
@@ -73,14 +73,10 @@
TARGET_CFLAGS="$TARGET_CFLAGS -Os"
fi
-BUILD_CPPFLAGS="$BUILD_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\""
-
# Default HOST_CPPFLAGS
HOST_CPPFLAGS="$HOST_CPPFLAGS -Wall -W"
HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include"
HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_UTIL=1"
-HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_LIBDIR=\\\"\$(pkglibdir)\\\""
-HOST_CPPFLAGS="$HOST_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\""
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -Wall -W"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include"
@@ -1344,6 +1340,19 @@
AM_CONDITIONAL([COND_CYGWIN], [test x$target_os = xcygwin])
AM_CONDITIONAL([COND_STARFIELD], [test "x$starfield_excuse" = x])
+test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
+datarootdir="$(eval echo "$datarootdir")"
+grub_libdir="$(eval echo "$libdir")"
+grub_localedir="$(eval echo "$localedir")"
+grub_datadir="$(eval echo "$datadir")"
+grub_sysconfdir="$(eval echo "$sysconfdir")"
+AC_DEFINE_UNQUOTED(LOCALEDIR, "$grub_localedir", [Locale dir])
+AC_DEFINE_UNQUOTED(GRUB_LIBDIR, "$grub_libdir", [Library dir])
+AC_DEFINE_UNQUOTED(GRUB_DATADIR, "$grub_datadir", [Data dir])
+AC_DEFINE_UNQUOTED(GRUB_SYSCONFDIR, "$sysconfdir", [Configuration dir])
+
+
# Output files.
cpudir="${target_cpu}"
if test x${cpudir} = xmipsel; then
=== added file 'include/grub/util/install.h'
--- include/grub/util/install.h 1970-01-01 00:00:00 +0000
+++ include/grub/util/install.h 2013-10-05 16:58:59 +0000
@@ -0,0 +1,189 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_UTIL_INSTALL_HEADER
+#define GRUB_UTIL_INSTALL_HEADER 1
+
+#define GRUB_INSTALL_OPTIONS \
+ { "modules", GRUB_INSTALL_OPTIONS_MODULES, N_("MODULES"), \
+ 0, N_("pre-load specified modules MODULES"), 1 }, \
+ { "install-modules", GRUB_INSTALL_OPTIONS_INSTALL_MODULES, \
+ N_("MODULES"), 0, \
+ N_("install only MODULES and their dependencies [default=all]"), 1 }, \
+ { "themes", GRUB_INSTALL_OPTIONS_INSTALL_THEMES, N_("THEMES"), \
+ 0, N_("install THEMES [default=%s]"), 1 }, \
+ { "fonts", GRUB_INSTALL_OPTIONS_INSTALL_FONTS, N_("FONTS"), \
+ 0, N_("install FONTS [default=%s]"), 1 }, \
+ { "locales", GRUB_INSTALL_OPTIONS_INSTALL_LOCALES, N_("LOCALES"),\
+ 0, N_("install only LOCALES [default=all]"), 1 }, \
+ { "compress", GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS, \
+ "no,xz,gz,lzo", OPTION_ARG_OPTIONAL, \
+ N_("compress GRUB files [optional]"), 1 }, \
+ /* TRANSLATORS: platform here isn't identifier. It can be translated. */ \
+ { "directory", 'd', N_("DIR"), 0, \
+ N_("use images and modules under DIR [default=%s/<platform>]"), 1 }, \
+ { "override-directory", GRUB_INSTALL_OPTIONS_DIRECTORY2, \
+ N_("DIR"), OPTION_HIDDEN, \
+ N_("use images and modules under DIR [default=%s/<platform>]"), 1 }, \
+ { "grub-mkimage", GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE, \
+ "FILE", OPTION_HIDDEN, 0, 1 }, \
+ /* TRANSLATORS: "embed" is a verb (command description). "*/ \
+ { "pubkey", 'k', N_("FILE"), 0, \
+ N_("embed FILE as public key for signature checking"), 0}
+
+int
+grub_install_parse (int key, char *arg);
+
+void
+grub_install_push_module (const char *val);
+
+char *
+grub_install_help_filter (int key, const char *text,
+ void *input __attribute__ ((unused)));
+
+enum grub_install_plat
+ {
+ GRUB_INSTALL_PLATFORM_I386_PC,
+ GRUB_INSTALL_PLATFORM_I386_EFI,
+ GRUB_INSTALL_PLATFORM_I386_QEMU,
+ GRUB_INSTALL_PLATFORM_I386_COREBOOT,
+ GRUB_INSTALL_PLATFORM_I386_MULTIBOOT,
+ GRUB_INSTALL_PLATFORM_I386_IEEE1275,
+ GRUB_INSTALL_PLATFORM_X86_64_EFI,
+ GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON,
+ GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275,
+ GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275,
+ GRUB_INSTALL_PLATFORM_MIPSEL_ARC,
+ GRUB_INSTALL_PLATFORM_MIPS_ARC,
+ GRUB_INSTALL_PLATFORM_IA64_EFI,
+ GRUB_INSTALL_PLATFORM_ARM_UBOOT,
+ GRUB_INSTALL_PLATFORM_ARM_EFI,
+ GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS,
+ GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS,
+ };
+
+enum grub_install_options {
+ GRUB_INSTALL_OPTIONS_DIRECTORY = 'd',
+ GRUB_INSTALL_OPTIONS_MODULES = 0x201,
+ GRUB_INSTALL_OPTIONS_INSTALL_MODULES,
+ GRUB_INSTALL_OPTIONS_INSTALL_THEMES,
+ GRUB_INSTALL_OPTIONS_INSTALL_FONTS,
+ GRUB_INSTALL_OPTIONS_INSTALL_LOCALES,
+ GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS,
+ GRUB_INSTALL_OPTIONS_DIRECTORY2,
+ GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE
+};
+
+void
+grub_install_args_finish (void);
+
+extern char *grub_install_source_directory;
+
+char *
+grub_install_concat_ext (size_t n, ...);
+char *
+grub_install_concat (size_t n, ...);
+
+enum grub_install_plat
+grub_install_get_target (const char *src);
+void
+grub_install_mkdir_p (const char *dst);
+
+void
+grub_install_copy_files (const char *src,
+ const char *dst,
+ enum grub_install_plat platid);
+char *
+grub_install_get_platform_name (enum grub_install_plat platid);
+
+const char *
+grub_install_get_platform_cpu (enum grub_install_plat platid);
+
+const char *
+grub_install_get_platform_platform (enum grub_install_plat platid);
+
+
+typedef enum {
+ GRUB_COMPRESSION_AUTO,
+ GRUB_COMPRESSION_NONE,
+ GRUB_COMPRESSION_XZ,
+ GRUB_COMPRESSION_LZMA
+} grub_compression_t;
+
+void
+grub_install_make_image_wrap (const char *dir, const char *prefix,
+ const char *outname, char *memdisk_path,
+ char *config_path,
+ const char *format, int note,
+ grub_compression_t comp);
+
+void
+grub_install_copy_file (const char *src,
+ const char *dst);
+
+struct grub_install_image_target_desc;
+
+void
+grub_install_generate_image (const char *dir, const char *prefix,
+ FILE *out, const char *outname, char *mods[],
+ char *memdisk_path, char **pubkey_paths,
+ size_t npubkeys,
+ char *config_path,
+ struct grub_install_image_target_desc *image_target, int note,
+ grub_compression_t comp);
+
+struct grub_install_image_target_desc *
+grub_install_get_image_target (const char *arg);
+void
+grub_bios_setup (const char *dir,
+ const char *boot_file, const char *core_file,
+ const char *dest, int force,
+ int fs_probe, int allow_floppy);
+void
+grub_sparc_setup (const char *dir,
+ const char *boot_file, const char *core_file,
+ const char *dest, int force,
+ int fs_probe, int allow_floppy);
+
+char *
+grub_install_get_image_targets_string (void);
+
+const char *
+grub_util_get_target_dirname (struct grub_install_image_target_desc *t);
+
+#if !defined (__MINGW32__) && !defined (__CYGWIN__)
+
+int
+grub_util_exec (char **argv);
+int
+grub_util_check_executable (const char *fn);
+void
+grub_util_exec_redirect (char **argv, const char *stdin_file,
+ const char *stdout_file);
+int
+grub_util_exec_redirect_null (char **argv);
+
+#endif
+
+int
+grub_install_is_regular_file (const char *dir);
+
+void
+grub_install_create_envblk_file (const char *name);
+
+#endif
=== added file 'util/editenv.c'
--- util/editenv.c 1970-01-01 00:00:00 +0000
+++ util/editenv.c 2013-10-04 13:49:28 +0000
@@ -0,0 +1,66 @@
+/* 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 <grub/util/install.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <argp.h>
+
+#define DEFAULT_ENVBLK_SIZE 1024
+
+void
+grub_install_create_envblk_file (const char *name)
+{
+ FILE *fp;
+ char *buf;
+ char *namenew;
+
+ buf = xmalloc (DEFAULT_ENVBLK_SIZE);
+
+ namenew = xasprintf ("%s.new", name);
+ fp = fopen (namenew, "wb");
+ if (! fp)
+ grub_util_error (_("cannot open `%s': %s"), namenew,
+ strerror (errno));
+
+ 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 `%s': %s"), namenew,
+ strerror (errno));
+
+ 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);
+}
=== modified file 'util/getroot_unix.c'
--- util/getroot_unix.c 2013-09-24 17:19:31 +0000
+++ util/getroot_unix.c 2013-10-04 14:29:13 +0000
@@ -143,6 +143,77 @@
return path;
}
+int
+grub_util_exec (char **argv)
+{
+ pid_t pid;
+ int status = -1;
+
+ pid = fork ();
+ if (pid < 0)
+ grub_util_error (_("Unable to fork: %s"), strerror (errno));
+ else if (pid == 0)
+ {
+ /* Child. */
+
+ /* Close fd's. */
+ grub_util_devmapper_cleanup ();
+ grub_diskfilter_fini ();
+
+ /* Ensure child is not localised. */
+ setenv ("LC_ALL", "C", 1);
+
+ execvp (argv[0], argv);
+ exit (127);
+ }
+
+ waitpid (pid, &status, 0);
+ if (!WIFEXITED (status))
+ return -1;
+ return WEXITSTATUS (status);
+}
+
+void
+grub_util_exec_redirect (char **argv, const char *stdin_file,
+ const char *stdout_file)
+{
+ pid_t mdadm_pid;
+
+ mdadm_pid = fork ();
+ if (mdadm_pid < 0)
+ grub_util_error (_("Unable to fork: %s"), strerror (errno));
+ else if (mdadm_pid == 0)
+ {
+ int in, out;
+ /* Child. */
+
+ /* Close fd's. */
+ grub_util_devmapper_cleanup ();
+ grub_diskfilter_fini ();
+
+ in = open (stdin_file, O_RDONLY);
+ dup2 (in, STDIN_FILENO);
+ close (in);
+
+ out = open (stdout_file, O_WRONLY | O_CREAT, 0700);
+ dup2 (out, STDOUT_FILENO);
+ close (out);
+
+ /* Ensure child is not localised. */
+ setenv ("LC_ALL", "C", 1);
+
+ execvp (argv[0], argv);
+ exit (127);
+ }
+}
+
+void
+grub_util_exec_redirect_null (char **argv, const char *stdin_file,
+ const char *stdout_file)
+{
+ grub_util_exec_redirect (argv, "/dev/null", "/dev/null");
+}
+
pid_t
grub_util_exec_pipe (char **argv, int *fd)
{
@@ -518,11 +589,15 @@
}
char **
-grub_guess_root_devices (const char *dir)
+grub_guess_root_devices (const char *dir_in)
{
char **os_dev = NULL;
struct stat st;
dev_t dev;
+ char *dir = canonicalize_file_name (dir_in);
+
+ if (!dir)
+ grub_util_error (_("failed to get canonical path of `%s'"), dir_in);
#ifdef __linux__
if (!os_dev)
=== modified file 'util/grub-editenv.c'
--- util/grub-editenv.c 2013-09-27 00:08:32 +0000
+++ util/grub-editenv.c 2013-10-05 16:57:05 +0000
@@ -23,6 +23,7 @@
#include <grub/util/misc.h>
#include <grub/lib/envblk.h>
#include <grub/i18n.h>
+#include <grub/util/install.h>
#include <stdio.h>
#include <unistd.h>
@@ -32,7 +33,6 @@
#include "progname.h"
-#define DEFAULT_ENVBLK_SIZE 1024
#define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG
static struct argp_option options[] = {
@@ -108,38 +108,6 @@
NULL, help_filter, NULL
};
-static void
-create_envblk_file (const char *name)
-{
- FILE *fp;
- char *buf;
- char *namenew;
-
- buf = xmalloc (DEFAULT_ENVBLK_SIZE);
-
- namenew = xasprintf ("%s.new", name);
- fp = fopen (namenew, "wb");
- if (! fp)
- grub_util_error (_("cannot open `%s': %s"), namenew,
- strerror (errno));
-
- 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 `%s': %s"), namenew,
- strerror (errno));
-
- 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)
{
@@ -152,7 +120,7 @@
if (! fp)
{
/* Create the file implicitly. */
- create_envblk_file (name);
+ grub_install_create_envblk_file (name);
fp = fopen (name, "rb");
if (! fp)
grub_util_error (_("cannot open `%s': %s"), name,
@@ -300,7 +268,7 @@
}
if (strcmp (command, "create") == 0)
- create_envblk_file (filename);
+ grub_install_create_envblk_file (filename);
else if (strcmp (command, "list") == 0)
list_variables (filename);
else if (strcmp (command, "set") == 0)
=== added file 'util/grub-install-common.c'
--- util/grub-install-common.c 1970-01-01 00:00:00 +0000
+++ util/grub-install-common.c 2013-10-05 16:59:27 +0000
@@ -0,0 +1,810 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <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 <grub/zfs/zfs.h>
+#include <grub/util/install.h>
+#include <grub/util/resolve.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+char *
+grub_install_help_filter (int key, const char *text,
+ void *input __attribute__ ((unused)))
+{
+ switch (key)
+ {
+ case GRUB_INSTALL_OPTIONS_INSTALL_THEMES:
+ return xasprintf(text, "starfield");
+ case GRUB_INSTALL_OPTIONS_INSTALL_FONTS:
+ return xasprintf(text, "unicode");
+ case GRUB_INSTALL_OPTIONS_DIRECTORY:
+ case GRUB_INSTALL_OPTIONS_DIRECTORY2:
+ return xasprintf(text, GRUB_LIBDIR PACKAGE);
+ default:
+ return (char *) text;
+ }
+}
+
+static char **compress_argv;
+static char *copy_buf;
+
+#define COPY_BUF_SIZE 1048576
+
+static char *
+grub_install_concat_real (size_t n, int ext, va_list ap)
+{
+ size_t totlen = 0;
+ char **l = xmalloc ((n + ext) * sizeof (l[0]));
+ char *r, *p, *pi;
+ size_t i;
+ int first = 1;
+
+ for (i = 0; i < n + ext; i++)
+ {
+ l[i] = va_arg (ap, char *);
+ if (l[i])
+ totlen += strlen (l[i]) + 1;
+ }
+
+ r = xmalloc (totlen + 10);
+
+ p = r;
+ for (i = 0; i < n; i++)
+ {
+ pi = l[i];
+ if (!pi)
+ continue;
+ while (*pi == '/')
+ pi++;
+ if ((p != r || (pi != l[i] && first)) && (p == r || *(p - 1) != '/'))
+ *p++ = '/';
+ first = 0;
+ p = stpcpy (p, l[i]);
+ while (p != r && p != r + 1 && *(p - 1) == '/')
+ p--;
+ }
+
+ if (ext && l[i])
+ p = stpcpy (p, l[i]);
+
+ *p = '\0';
+
+ free (l);
+
+ return r;
+}
+
+char *
+grub_install_concat (size_t n, ...)
+{
+ va_list ap;
+ char *r;
+
+ va_start (ap, n);
+
+ r = grub_install_concat_real (n, 0, ap);
+
+ va_end (ap);
+
+ return r;
+}
+
+char *
+grub_install_concat_ext (size_t n, ...)
+{
+ va_list ap;
+ char *r;
+
+ va_start (ap, n);
+
+ r = grub_install_concat_real (n, 1, ap);
+
+ va_end (ap);
+
+ return r;
+}
+
+void
+grub_install_copy_file (const char *src,
+ const char *dst)
+{
+ FILE *in, *out;
+ in = fopen (src, "rb");
+ if (!in)
+ {
+ grub_util_warn (_("cannot open `%s': %s"), src, strerror (errno));
+ return;
+ }
+ out = fopen (dst, "wb");
+ if (!out)
+ {
+ grub_util_warn (_("cannot open `%s': %s"), dst, strerror (errno));
+ fclose (in);
+ return;
+ }
+
+ if (!copy_buf)
+ copy_buf = xmalloc (COPY_BUF_SIZE);
+
+ while (1)
+ {
+ size_t r;
+ r = fread (copy_buf, 1, COPY_BUF_SIZE, in);
+ if (r == 0)
+ break;
+ fwrite (copy_buf, 1, r, out);
+ }
+ fclose (in);
+ fclose (out);
+
+ return;
+}
+
+int
+grub_install_compress_file (const char *in_name,
+ const char *out_name,
+ int is_needed)
+{
+ FILE *in, *out;
+ in = fopen (in_name, "rb");
+ if (!in && !is_needed && errno == ENOENT)
+ return 0;
+ if (!in)
+ {
+ grub_util_warn (_("cannot open `%s': %s"), in_name, strerror (errno));
+ return 0;
+ }
+ out = fopen (out_name, "wb");
+ if (!out)
+ {
+ grub_util_warn (_("cannot open `%s': %s"), out_name, strerror (errno));
+ fclose (in);
+ return 0;
+ }
+
+ if (!copy_buf)
+ copy_buf = xmalloc (COPY_BUF_SIZE);
+
+ if (compress_argv)
+ {
+ fclose (in);
+ fclose (out);
+ grub_util_exec_redirect (compress_argv, in_name,
+ out_name);
+ return 1;
+ }
+
+ while (1)
+ {
+ size_t r;
+ r = fread (copy_buf, 1, COPY_BUF_SIZE, in);
+ if (r == 0)
+ break;
+ fwrite (copy_buf, 1, r, out);
+ }
+ fclose (in);
+ fclose (out);
+
+ return 1;
+}
+
+static int
+is_path_separator (char c)
+{
+#if defined (__MINGW32__) || defined (__CYGWIN__)
+ if (c == '\\')
+ return 1;
+#endif
+ if (c == '/')
+ return 1;
+ return 0;
+}
+
+void
+grub_install_mkdir_p (const char *dst)
+{
+ char *t = xstrdup (dst);
+ char *p;
+ for (p = t; *p; p++)
+ {
+ if (is_path_separator (*p))
+ {
+ char s = *p;
+ *p = '\0';
+ mkdir (t, 0700);
+ *p = s;
+ }
+ }
+ mkdir (t, 0700);
+}
+
+static void
+clean_grub_dir (const char *di)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir (di);
+ if (!d)
+ grub_util_error (_("cannot open directory `%s': %s"),
+ di, strerror (errno));
+
+ while ((de = readdir (d)))
+ {
+ const char *ext = strrchr (de->d_name, '.');
+ if ((ext && (strcmp (ext, ".mod") == 0
+ || strcmp (ext, ".lst") == 0
+ || strcmp (ext, ".img") == 0
+ || strcmp (ext, ".mo") == 0)
+ && strcmp (de->d_name, "menu.lst") != 0)
+ || strcmp (de->d_name, "efiemu32.o") == 0
+ || strcmp (de->d_name, "efiemu64.o") == 0)
+ {
+ char *x = grub_install_concat (2, di, de->d_name);
+ if (unlink (x) < 0)
+ grub_util_error ("cannont delete `%s': %s", x, strerror (errno));
+ free (x);
+ }
+ }
+ closedir (d);
+}
+
+struct install_list
+{
+ int is_default;
+ char **entries;
+ size_t n_entries;
+ size_t n_alloc;
+};
+
+struct install_list install_modules = { 1, 0, 0, 0 };
+struct install_list modules = { 1, 0, 0, 0 };
+struct install_list install_locales = { 1, 0, 0, 0 };
+struct install_list install_fonts = { 1, 0, 0, 0 };
+struct install_list install_themes = { 1, 0, 0, 0 };
+char *grub_install_source_directory = NULL;
+
+void
+grub_install_push_module (const char *val)
+{
+ modules.is_default = 0;
+ if (modules.n_entries + 1 >= modules.n_alloc)
+ {
+ modules.n_alloc <<= 1;
+ if (modules.n_alloc < 16)
+ modules.n_alloc = 16;
+ modules.entries = xrealloc (modules.entries,
+ modules.n_alloc * sizeof (modules.entries));
+ }
+ modules.entries[modules.n_entries++] = xstrdup (val);
+ modules.entries[modules.n_entries] = NULL;
+}
+
+static void
+handle_install_list (struct install_list *il, const char *val,
+ int default_all)
+{
+ const char *ptr;
+ char **ce;
+ il->is_default = 0;
+ free (il->entries);
+ il->entries = NULL;
+ il->n_entries = 0;
+ if (strcmp (val, "all") == 0 && default_all)
+ {
+ il->is_default = 1;
+ return;
+ }
+ ptr = val;
+ while (1)
+ {
+ while (*ptr && grub_isspace (*ptr))
+ ptr++;
+ if (!*ptr)
+ break;
+ while (*ptr && !grub_isspace (*ptr))
+ ptr++;
+ il->n_entries++;
+ }
+ il->n_alloc = il->n_entries + 1;
+ il->entries = xmalloc (il->n_alloc * sizeof (il->entries[0]));
+ for (ce = il->entries; ; ce++)
+ {
+ const char *bptr;
+ while (*ptr && grub_isspace (*ptr))
+ ptr++;
+ if (!*ptr)
+ break;
+ bptr = ptr;
+ while (*ptr && !grub_isspace (*ptr))
+ ptr++;
+ *ce = xmalloc (ptr - bptr + 1);
+ memcpy (*ce, bptr, ptr - bptr);
+ (*ce)[ptr - bptr] = '\0';
+ ce++;
+ }
+ *ce = NULL;
+}
+
+static char *compress_gzip[] = { (char *) "gzip", (char *) "--best",
+ (char *) "--stdout", NULL };
+static char *compress_xz[] = { (char *) "xz",
+ (char *) "--lzma2=dict=128KiB",
+ (char *) "--check=none",
+ (char *) "--stdout", NULL };
+static char *compress_lzo[] = {(char *) "lzop",
+ (char *) "-9",
+ (char *) "-c", NULL };
+static char **pubkeys;
+static size_t npubkeys;
+
+int
+grub_install_parse (int key, char *arg)
+{
+ switch (key)
+ {
+ case 'k':
+ pubkeys = xrealloc (pubkeys,
+ sizeof (pubkeys[0])
+ * (npubkeys + 1));
+ pubkeys[npubkeys++] = xstrdup (arg);
+ return 1;
+
+ case GRUB_INSTALL_OPTIONS_DIRECTORY:
+ case GRUB_INSTALL_OPTIONS_DIRECTORY2:
+ free (grub_install_source_directory);
+ grub_install_source_directory = xstrdup (arg);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_INSTALL_MODULES:
+ handle_install_list (&install_modules, arg, 0);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_MODULES:
+ handle_install_list (&modules, arg, 0);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_INSTALL_LOCALES:
+ handle_install_list (&install_locales, arg, 0);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_INSTALL_THEMES:
+ handle_install_list (&install_themes, arg, 0);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_INSTALL_FONTS:
+ handle_install_list (&install_fonts, arg, 0);
+ return 1;
+ case GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS:
+ if (strcmp (arg, "no") == 0)
+ {
+ compress_argv = NULL;
+ return 1;
+ }
+ if (strcmp (arg, "gz") == 0)
+ {
+ compress_argv = compress_gzip;
+ return 1;
+ }
+ if (strcmp (arg, "xz") == 0)
+ {
+ compress_argv = compress_xz;
+ return 1;
+ }
+ if (strcmp (arg, "lzo") == 0)
+ {
+ compress_argv = compress_lzo;
+ return 1;
+ }
+ grub_util_error (_("Unrecognized compression `%s'"), arg);
+ case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void
+grub_install_args_finish (void)
+{
+ if (compress_argv == compress_gzip)
+ grub_install_push_module ("gzio");
+ if (compress_argv == compress_xz)
+ {
+ grub_install_push_module ("xzio");
+ grub_install_push_module ("gcry_crc");
+ }
+ if (compress_argv == compress_lzo)
+ {
+ grub_install_push_module ("lzopio");
+ grub_install_push_module ("adler32");
+ grub_install_push_module ("gcry_crc");
+ }
+}
+
+void
+grub_install_make_image_wrap (const char *dir, const char *prefix,
+ const char *outname, char *memdisk_path,
+ char *config_path,
+ const char *mkimage_target, int note,
+ grub_compression_t comp)
+{
+ FILE *fp = stdout;
+ struct grub_install_image_target_desc *tgt;
+ fp = fopen (outname, "wb");
+ if (! fp)
+ grub_util_error (_("cannot open `%s': %s"), outname,
+ strerror (errno));
+ tgt = grub_install_get_image_target (mkimage_target);
+ if (!tgt)
+ grub_util_error (_("unknown target format %s\n"), mkimage_target);
+
+
+
+ grub_install_generate_image (dir, prefix, fp, outname,
+ modules.entries, memdisk_path,
+ pubkeys, npubkeys, config_path, tgt,
+ note, comp);
+ fflush (fp);
+ fsync (fileno (fp));
+ fclose (fp);
+}
+
+static void
+copy_by_ext (const char *srcd,
+ const char *dstd,
+ const char *extf,
+ int req)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir (srcd);
+ if (!d && !req)
+ return;
+ if (!d)
+ grub_util_error (_("cannot open directory `%s': %s"),
+ srcd, strerror (errno));
+
+ while ((de = readdir (d)))
+ {
+ const char *ext = strrchr (de->d_name, '.');
+ if (ext && strcmp (ext, extf) == 0)
+ {
+ char *srcf = grub_install_concat (2, srcd, de->d_name);
+ char *dstf = grub_install_concat (2, dstd, de->d_name);
+ grub_install_compress_file (srcf, dstf, 1);
+ free (srcf);
+ free (dstf);
+ }
+ }
+ closedir (d);
+}
+
+static void
+copy_all (const char *srcd,
+ const char *dstd)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir (srcd);
+ if (!d)
+ grub_util_error (_("cannot open directory `%s': %s"),
+ srcd, strerror (errno));
+
+ while ((de = readdir (d)))
+ {
+ char *srcf;
+ char *dstf;
+ if (strcmp (de->d_name, ".") == 0
+ || strcmp (de->d_name, "..") == 0)
+ continue;
+ srcf = grub_install_concat (2, srcd, de->d_name);
+ dstf = grub_install_concat (2, dstd, de->d_name);
+ grub_install_compress_file (srcf, dstf, 1);
+ free (srcf);
+ free (dstf);
+ }
+ closedir (d);
+}
+
+static void
+copy_locales (const char *dstd)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir (LOCALEDIR);
+ if (!d)
+ grub_util_error (_("cannot open directory `%s': %s"),
+ LOCALEDIR, strerror (errno));
+
+ while ((de = readdir (d)))
+ {
+ char *srcf = grub_install_concat_ext (3, LOCALEDIR, de->d_name,
+ PACKAGE, ".mo");
+ char *dstf = grub_install_concat_ext (2, dstd, de->d_name, ".mo");
+ grub_install_compress_file (srcf, dstf, 0);
+ free (srcf);
+ free (dstf);
+ }
+ closedir (d);
+}
+
+static struct
+{
+ enum grub_install_plat val;
+ const char *cpu;
+ const char *platform;
+} platforms[] =
+ {
+ { GRUB_INSTALL_PLATFORM_I386_PC, "i386", "pc" },
+ { GRUB_INSTALL_PLATFORM_I386_EFI, "i386", "efi" },
+ { GRUB_INSTALL_PLATFORM_I386_QEMU, "i386", "qemu" },
+ { GRUB_INSTALL_PLATFORM_I386_COREBOOT, "i386", "coreboot" },
+ { GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, "i386", "multiboot" },
+ { GRUB_INSTALL_PLATFORM_I386_IEEE1275, "i386", "ieee1275" },
+ { GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64", "efi" },
+ { GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel", "loongson" },
+ { GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "mipsel", "qemu_mips" },
+ { GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "mips", "qemu_mips" },
+ { GRUB_INSTALL_PLATFORM_MIPSEL_ARC, "mipsel", "arc" },
+ { GRUB_INSTALL_PLATFORM_MIPS_ARC, "mips", "arc" },
+ { GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275, "sparc64", "ieee1275" },
+ { GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc", "ieee1275" },
+ { GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64", "efi" },
+ { GRUB_INSTALL_PLATFORM_ARM_EFI, "arm", "efi" },
+ { GRUB_INSTALL_PLATFORM_ARM_UBOOT, "arm", "uboot" },
+ };
+
+char *
+grub_install_get_platform_name (enum grub_install_plat platid)
+{
+ return xasprintf ("%s-%s", platforms[platid].cpu,
+ platforms[platid].platform);
+}
+
+const char *
+grub_install_get_platform_cpu (enum grub_install_plat platid)
+{
+ return platforms[platid].cpu;
+}
+
+const char *
+grub_install_get_platform_platform (enum grub_install_plat platid)
+{
+ return platforms[platid].platform;
+}
+
+int
+grub_install_is_regular_file (const char *dir)
+{
+ struct stat st;
+ if (stat (dir, &st) < 0)
+ return 0;
+ return S_ISREG (st.st_mode);
+}
+
+void
+grub_install_copy_files (const char *src,
+ const char *dst,
+ enum grub_install_plat platid)
+{
+ char *dst_platform, *dst_locale, *dst_fonts;
+ char *platform = xasprintf ("%s-%s", platforms[platid].cpu,
+ platforms[platid].platform);
+ const char *pkgdatadir = secure_getenv ("pkgdatadir");
+ if (!pkgdatadir)
+ pkgdatadir = GRUB_DATADIR "/" PACKAGE;
+
+ dst_platform = grub_install_concat (2, dst, platform);
+ dst_locale = grub_install_concat (2, dst, "locale");
+ dst_fonts = grub_install_concat (2, dst, "fonts");
+ grub_install_mkdir_p (dst_platform);
+ grub_install_mkdir_p (dst_locale);
+ clean_grub_dir (dst);
+ clean_grub_dir (dst_platform);
+ clean_grub_dir (dst_locale);
+
+ if (install_modules.is_default)
+ copy_by_ext (src, dst_platform, ".mod", 1);
+ else
+ {
+ struct grub_util_path_list *path_list, *p;
+
+ path_list = grub_util_resolve_dependencies (src, "moddep.lst",
+ install_modules.entries);
+ for (p = path_list; p; p = p->next)
+ {
+ char *srcf = grub_install_concat_ext (2, src, p->name, ".mo");
+ char *dstf = grub_install_concat_ext (2, dst, p->name, ".mo");
+ grub_install_compress_file (srcf, dstf, 1);
+ free (srcf);
+ free (dstf);
+ }
+ }
+
+ const char *pkglib_DATA[] = {"efiemu32.o", "efiemu64.o",
+ "moddep.lst", "command.lst",
+ "fs.lst", "partmap.lst",
+ "parttool.lst",
+ "video.lst", "crypto.lst",
+ "terminal.lst" };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (pkglib_DATA); i++)
+ {
+ char *srcf = grub_install_concat (2, src, pkglib_DATA[i]);
+ char *dstf = grub_install_concat (2, dst_platform, pkglib_DATA[i]);
+ if (i == 0 || i == 1)
+ grub_install_compress_file (srcf, dstf, 0);
+ else
+ grub_install_compress_file (srcf, dstf, 1);
+ free (srcf);
+ free (dstf);
+ }
+
+ if (install_locales.is_default)
+ {
+ char *srcd = grub_install_concat (2, src, "po");
+ copy_by_ext (srcd, dst_locale, ".mo", 0);
+ copy_locales (dst_locale);
+ free (srcd);
+ }
+ else
+ {
+ for (i = 0; i < install_locales.n_entries; i++)
+ {
+ char *srcf = grub_install_concat_ext (3, src,
+ "po",
+ install_locales.entries[i],
+ ".mo");
+ char *dstf = grub_install_concat_ext (2, dst_locale,
+ install_locales.entries[i],
+ ".mo");
+ if (grub_install_compress_file (srcf, dstf, 0))
+ {
+ free (srcf);
+ free (dstf);
+ continue;
+ }
+ free (srcf);
+ srcf = grub_install_concat_ext (4,
+ LOCALEDIR,
+ install_locales.entries[i],
+ "LC_MESSAGES",
+ PACKAGE,
+ ".mo");
+ if (grub_install_compress_file (srcf, dstf, 0))
+ {
+ free (srcf);
+ free (dstf);
+ continue;
+ }
+ grub_util_error (_("cannot find locale `%s'"),
+ install_locales.entries[i]);
+ }
+ }
+
+ if (install_themes.is_default)
+ {
+ install_themes.is_default = 0;
+ install_themes.n_entries = 1;
+ install_themes.entries = xmalloc (2 * sizeof (install_themes.entries[0]));
+ install_themes.entries[0] = xstrdup ("starfield");
+ install_themes.entries[1] = NULL;
+ }
+
+ for (i = 0; i < install_themes.n_entries; i++)
+ {
+ char *srcf = grub_install_concat (4, pkgdatadir, "themes",
+ install_themes.entries[i],
+ "theme.txt");
+ if (grub_install_is_regular_file (srcf))
+ {
+ char *srcd = grub_install_concat (3, pkgdatadir, "themes",
+ install_themes.entries[i]);
+ char *dstd = grub_install_concat (3, dst, "themes",
+ install_themes.entries[i]);
+ copy_all (srcd, dstd);
+ free (srcd);
+ free (dstd);
+ }
+ }
+
+ if (install_fonts.is_default)
+ {
+ install_fonts.is_default = 0;
+ install_fonts.n_entries = 1;
+ install_fonts.entries = xmalloc (2 * sizeof (install_fonts.entries[0]));
+ install_fonts.entries[0] = xstrdup ("unicode");
+ install_fonts.entries[1] = NULL;
+ }
+
+ for (i = 0; i < install_fonts.n_entries; i++)
+ {
+ char *srcf = grub_install_concat_ext (2, pkgdatadir,
+ install_fonts.entries[i],
+ ".pf2");
+ char *dstf = grub_install_concat_ext (2, dst_fonts,
+ install_fonts.entries[i],
+ ".pf2");
+
+ grub_install_compress_file (srcf, dstf, 0);
+ free (srcf);
+ free (dstf);
+ }
+}
+
+enum grub_install_plat
+grub_install_get_target (const char *src)
+{
+ char *fn;
+ FILE *f;
+ char buf[2048];
+ size_t r;
+ char *c, *pl, *p;
+ size_t i;
+ fn = grub_install_concat (2, src, "modinfo.sh");
+ f = fopen (fn, "r");
+ if (!f)
+ grub_util_error (_("%s doesn't exist. Please specify --target or --directory"),
+ fn);
+ r = fread (buf, 1, sizeof (buf) - 1, f);
+ buf[r] = '\0';
+ c = strstr (buf, "grub_modinfo_target_cpu=");
+ if (!c || (c != buf && !grub_isspace (*(c-1))))
+ grub_util_error (_("invalid modinfo file `%s'"), fn);
+ pl = strstr (buf, "grub_modinfo_platform=");
+ if (!pl || (pl != buf && !grub_isspace (*(pl-1))))
+ grub_util_error (_("invalid modinfo file `%s'"), fn);
+ c += sizeof ("grub_modinfo_target_cpu=") - 1;
+ pl += sizeof ("grub_modinfo_platform=") - 1;
+ for (p = c; *p && !grub_isspace (*p); p++);
+ *p = '\0';
+ for (p = pl; *p && !grub_isspace (*p); p++);
+ *p = '\0';
+
+ for (i = 0; i < ARRAY_SIZE (platforms); i++)
+ if (strcmp (platforms[i].cpu, c) == 0
+ && strcmp (platforms[i].platform, pl) == 0)
+ return platforms[i].val;
+ grub_util_error (_("Unknown platform `%s-%s'"), c, pl);
+}
=== added file 'util/grub-install.c'
--- util/grub-install.c 1970-01-01 00:00:00 +0000
+++ util/grub-install.c 2013-10-04 14:37:48 +0000
@@ -0,0 +1,1684 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <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 <grub/zfs/zfs.h>
+#include <grub/util/install.h>
+#include <grub/emu/getroot.h>
+#include <grub/diskfilter.h>
+#include <grub/cryptodisk.h>
+#include <grub/legacy_parse.h>
+#include <grub/gpt_partition.h>
+
+#include <string.h>
+#include <dirent.h>
+
+#include "argp.h"
+
+#include "progname.h"
+
+static char *target;
+static int removable = 0;
+static int recheck = 0;
+static int update_nvram = 1;
+static char *install_device = NULL;
+static char *debug_image = NULL;
+static char *rootdir = NULL;
+static char *bootdir = NULL;
+static int efi_quiet = 0;
+static int allow_floppy = 0;
+static int force_file_id = 0;
+static char *disk_module = NULL;
+static char *efidir = NULL;
+static int force = 0;
+static int have_abstractions = 0;
+static int have_cryptodisk = 0;
+static char * bootloader_id;
+static int have_load_cfg = 0;
+static FILE * load_cfg_f = NULL;
+static char *load_cfg;
+
+enum
+ {
+ OPTION_BOOT_DIRECTORY = 0x301,
+ OPTION_ROOT_DIRECTORY,
+ OPTION_TARGET,
+ OPTION_SETUP,
+ OPTION_MKRELPATH,
+ OPTION_MKDEVICEMAP,
+ OPTION_PROBE,
+ OPTION_EDITENV,
+ OPTION_ALLOW_FLOPPY,
+ OPTION_RECHECK,
+ OPTION_FORCE,
+ OPTION_FORCE_FILE_ID,
+ OPTION_MODULE,
+ OPTION_NO_NVRAM,
+ OPTION_REMOVABLE,
+ OPTION_BOOTLOADER_ID,
+ OPTION_EFI_DIRECTORY,
+ OPTION_FONT,
+ OPTION_DEBUG,
+ OPTION_DEBUG_IMAGE,
+ OPTION_NO_FLOPPY,
+ OPTION_DISK_MODULE
+ };
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ if (grub_install_parse (key, arg))
+ return 0;
+ switch (key)
+ {
+ case OPTION_FORCE_FILE_ID:
+ force_file_id = 1;
+ return 0;
+ /* Accept and ignore for compatibility. */
+ case OPTION_FONT:
+ case OPTION_SETUP:
+ case OPTION_MKRELPATH:
+ case OPTION_PROBE:
+ case OPTION_EDITENV:
+ case OPTION_MKDEVICEMAP:
+ case OPTION_NO_FLOPPY:
+ return 0;
+ case OPTION_ROOT_DIRECTORY:
+ /* Accept for compatibility. */
+ free (rootdir);
+ rootdir = xstrdup (arg);
+ return 0;
+
+ case OPTION_BOOT_DIRECTORY:
+ free (bootdir);
+ bootdir = xstrdup (arg);
+ return 0;
+
+ case OPTION_EFI_DIRECTORY:
+ free (efidir);
+ efidir = xstrdup (arg);
+ return 0;
+
+ case OPTION_DISK_MODULE:
+ free (disk_module);
+ disk_module = xstrdup (arg);
+ return 0;
+
+ case OPTION_TARGET:
+ free (target);
+ target = xstrdup (arg);
+ return 0;
+
+ case OPTION_DEBUG_IMAGE:
+ free (debug_image);
+ debug_image = xstrdup (arg);
+ return 0;
+
+ case OPTION_NO_NVRAM:
+ update_nvram = 0;
+ return 0;
+
+ case OPTION_FORCE:
+ force = 1;
+ return 0;
+
+ case OPTION_RECHECK:
+ recheck = 1;
+ return 0;
+
+ case OPTION_REMOVABLE:
+ removable = 1;
+ return 0;
+
+ case OPTION_ALLOW_FLOPPY:
+ allow_floppy = 1;
+ return 0;
+
+ case OPTION_DEBUG:
+ verbosity++;
+ return 0;
+
+ case OPTION_BOOTLOADER_ID:
+ free (bootloader_id);
+ bootloader_id = xstrdup (arg);
+ return 0;
+
+ case ARGP_KEY_ARG:
+ if (install_device)
+ grub_util_error ("%s", _("More than one install device?"));
+ install_device = xstrdup (arg);
+ return 0;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+}
+
+
+static struct argp_option options[] = {
+ GRUB_INSTALL_OPTIONS,
+ {"boot-directory", OPTION_BOOT_DIRECTORY, N_("DIR"),
+ 0, N_("install GRUB images under the directory DIR/%s instead of the %s directory"), 2},
+ {"root-directory", OPTION_ROOT_DIRECTORY, N_("DIR"),
+ OPTION_HIDDEN, 0, 2},
+ {"font", OPTION_FONT, N_("FILE"),
+ OPTION_HIDDEN, 0, 2},
+ {"target", OPTION_TARGET, N_("TARGET"),
+ /* TRANSLATORS: "TARGET" as in "target platform". */
+ 0, N_("install GRUB for TARGET platform [default=%s]"), 2},
+ {"grub-setup", OPTION_SETUP, "FILE", OPTION_HIDDEN, 0, 2},
+ {"grub-mkrelpath", OPTION_MKRELPATH, "FILE", OPTION_HIDDEN, 0, 2},
+ {"grub-mkdevicemap", OPTION_MKDEVICEMAP, "FILE", OPTION_HIDDEN, 0, 2},
+ {"grub-probe", OPTION_PROBE, "FILE", OPTION_HIDDEN, 0, 2},
+ {"grub-editenv", OPTION_EDITENV, "FILE", OPTION_HIDDEN, 0, 2},
+ {"allow-floppy", OPTION_ALLOW_FLOPPY, 0, 0,
+ /* TRANSLATORS: "may break" doesn't just mean that option wouldn't have any
+ effect but that it will make the resulting install unbootable from HDD. */
+ N_("make the drive also bootable as floppy (default for fdX devices)."
+ " May break on some BIOSes."), 2},
+ {"recheck", OPTION_RECHECK, 0, 0,
+ N_("delete device map if it already exists"), 2},
+ {"force", OPTION_FORCE, 0, 0,
+ N_("install even if problems are detected"), 2},
+ {"force-file-id", OPTION_FORCE_FILE_ID, 0, 0,
+ N_("use identifier file even if UUID is available"), 2},
+ {"disk-module", OPTION_MODULE, N_("MODULE"), 0,
+ N_("disk module to use (biosdisk or native). "
+ "This option is only available on BIOS target."), 2},
+ {"no-nvram", OPTION_NO_NVRAM, 0, 0,
+ N_("don't update the `boot-device' NVRAM variable. "
+ "This option is only available on IEEE1275 targets."), 2},
+
+ {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
+ {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2},
+ {"debug-image", OPTION_DEBUG_IMAGE, "STR", OPTION_HIDDEN, 0, 2},
+ {"removable", OPTION_REMOVABLE, 0, 0,
+ N_("the installation device is removable. "
+ "This option is only available on EFI."), 2},
+ {"bootloader-id", OPTION_BOOTLOADER_ID, N_("ID"), 0,
+ N_("the ID of bootloader. This option is only available on EFI."), 2},
+ {"efi-directory", OPTION_EFI_DIRECTORY, N_("DIR"), 0,
+ N_("use DIR as the EFI System Partition root."), 2},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static int
+is_directory (const char *dir)
+{
+ struct stat st;
+ if (stat (dir, &st) < 0)
+ return 0;
+ return S_ISDIR (st.st_mode);
+}
+
+#ifdef __linux__
+static int
+is_not_empty_directory (const char *dir)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir (dir);
+ if (!d)
+ return 0;
+ while ((de = readdir (d)))
+ {
+ if (strcmp (de->d_name, ".") == 0
+ || strcmp (de->d_name, "..") == 0)
+ continue;
+ closedir (d);
+ return 1;
+ }
+
+ closedir (d);
+ return 0;
+}
+
+
+#include <sys/utsname.h>
+
+static int
+is_64_kernel (void)
+{
+ struct utsname un;
+
+ if (uname (&un) < 0)
+ return 0;
+
+ return strcmp (un.machine, "x86_64") == 0;
+}
+
+#endif
+
+static const char *
+get_default_platform (void)
+{
+#ifdef __powerpc__
+ return "powerpc-ieee1275";
+#elif defined (__sparc__) || defined (__sparc64__)
+ return "sparc64-ieee1275";
+#elif defined (__MIPSEL__)
+ return "mipsel-loongson";
+#elif defined (__MIPSEB__)
+ return "mips-arc";
+#elif defined (__ia64__)
+ return "ia64-efi";
+#elif defined (__arm__)
+ return "arm-uboot";
+#elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__)
+ /*
+ On Linux, we need the efivars kernel modules.
+ If no EFI is available this module just does nothing
+ besides a small hello and if we detect efi we'll load it
+ anyway later. So it should be safe to
+ try to load it here.
+ */
+#ifdef __linux__
+ grub_util_exec ((char * []){ (char *) "modprobe", (char *) "-q",
+ (char *) "efivars", NULL });
+#endif
+ if (is_not_empty_directory ("/sys/firmware/efi"))
+ {
+ if (is_64_kernel ())
+ return "x86_64-efi";
+ else
+ return "i386-efi";
+ }
+ else if (is_not_empty_directory ("/proc/device-tree"))
+ return "i386-ieee1275";
+ else
+ return "i386-pc";
+#else
+ return NULL;
+#endif
+}
+
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+ switch (key)
+ {
+ case OPTION_BOOT_DIRECTORY:
+ return xasprintf (text, GRUB_DIR_NAME, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
+ case OPTION_TARGET:
+ return xasprintf (text, get_default_platform ());
+ case ARGP_KEY_HELP_POST_DOC:
+ return xasprintf (text, program_name, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
+ default:
+ return grub_install_help_filter (key, text, input);
+ }
+}
+
+/* TRANSLATORS: INSTALL_DEVICE isn't an identifier and is the DEVICE you
+ install to. */
+struct argp argp = {
+ options, argp_parser, N_("[OPTION] [INSTALL_DEVICE]"),
+ N_("Install GRUB on your drive.")"\v"
+ N_("INSTALL_DEVICE must be system device filename.\n"
+ "%s copies GRUB images into %s. On some platforms, it"
+ " may also install GRUB into the boot sector."),
+ NULL, help_filter, NULL
+};
+
+static int
+probe_raid_level (grub_disk_t disk)
+{
+ /* disk might be NULL in the case of a LVM physical volume with no LVM
+ signature. Ignore such cases here. */
+ if (!disk)
+ return -1;
+
+ if (disk->dev->id != GRUB_DISK_DEVICE_DISKFILTER_ID)
+ return -1;
+
+ if (disk->name[0] != 'm' || disk->name[1] != 'd')
+ return -1;
+
+ if (!((struct grub_diskfilter_lv *) disk->data)->segments)
+ return -1;
+ return ((struct grub_diskfilter_lv *) disk->data)->segments->type;
+}
+
+static void
+probe_mods (grub_disk_t disk)
+{
+ grub_partition_t part;
+ grub_disk_memberlist_t list = NULL, tmp;
+ int raid_level;
+
+ if (disk->partition == NULL)
+ grub_util_info ("no partition map found for %s", disk->name);
+
+ for (part = disk->partition; part; part = part->parent)
+ {
+ char buf[50];
+ if (strcmp (part->partmap->name, "openbsd") == 0
+ || strcmp (part->partmap->name, "netbsd") == 0)
+ {
+ grub_install_push_module ("part_bsd");
+ continue;
+ }
+ snprintf (buf, sizeof (buf), "part_%s", part->partmap->name);
+ grub_install_push_module (buf);
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
+ {
+ grub_diskfilter_get_partmap (disk, grub_install_push_module);
+ have_abstractions = 1;
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
+ && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 ||
+ grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0))
+ grub_install_push_module ("lvm");
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
+ && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0)
+ grub_install_push_module ("ldm");
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ {
+ grub_util_cryptodisk_get_abstraction (disk,
+ grub_install_push_module);
+ have_abstractions = 1;
+ have_cryptodisk = 1;
+ }
+
+ raid_level = probe_raid_level (disk);
+ if (raid_level >= 0)
+ {
+ grub_install_push_module ("diskfilter");
+ if (disk->dev->raidname)
+ grub_install_push_module (disk->dev->raidname (disk));
+ }
+ if (raid_level == 5)
+ grub_install_push_module ("raid5rec");
+ if (raid_level == 6)
+ grub_install_push_module ("raid6rec");
+
+ /* In case of LVM/RAID, check the member devices as well. */
+ if (disk->dev->memberlist)
+ list = disk->dev->memberlist (disk);
+ while (list)
+ {
+ probe_mods (list->disk);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+}
+
+static int
+have_bootdev (enum grub_install_plat pl)
+{
+ switch (pl)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ return 1;
+
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ return 0;
+ }
+ return 0;
+}
+
+static void
+probe_cryptodisk_uuid (grub_disk_t disk)
+{
+ grub_disk_memberlist_t list = NULL, tmp;
+
+ /* In case of LVM/RAID, check the member devices as well. */
+ if (disk->dev->memberlist)
+ {
+ list = disk->dev->memberlist (disk);
+ }
+ while (list)
+ {
+ probe_cryptodisk_uuid (list->disk);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ {
+ const char *uuid = grub_util_cryptodisk_get_uuid (disk);
+ if (!load_cfg_f)
+ load_cfg_f = fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+
+ fprintf (load_cfg_f, "cryptomount -u %s\n",
+ uuid);
+ }
+}
+
+static int
+is_same_disk (const char *a, const char *b)
+{
+ while (1)
+ {
+ if ((*a == ',' || *a == '\0') && (*b == ',' || *b == '\0'))
+ return 1;
+ if (*a != *b)
+ return 0;
+ if (*a == '\\')
+ {
+ if (a[1] != b[1])
+ return 0;
+ a += 2;
+ b += 2;
+ continue;
+ }
+ a++;
+ b++;
+ }
+}
+
+char *
+get_rndstr (void)
+{
+ grub_uint8_t rnd[15];
+ const size_t sz = sizeof (rnd) * GRUB_CHAR_BIT / 5;
+ char * ret = xmalloc (sz + 1);
+ size_t i;
+ if (grub_get_random (rnd, sizeof (rnd)))
+ grub_util_error ("%s", _("couldn't retrieve random data"));
+ for (i = 0; i < sz; i++)
+ {
+ grub_size_t b = i * 5;
+ grub_uint8_t r;
+ grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT;
+ grub_size_t f2;
+ if (f1 > 5)
+ f1 = 5;
+ f2 = 5 - f1;
+ r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1);
+ if (f2)
+ r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1;
+ if (r < 10)
+ ret[i] = '0' + r;
+ else
+ ret[i] = 'a' + (r - 10);
+ }
+ ret[sz] = '\0';
+ return ret;
+}
+
+static char *
+escape (const char *in)
+{
+ char *ptr;
+ char *ret;
+ int overhead = 0;
+
+ for (ptr = (char*)in; *ptr; ptr++)
+ if (*ptr == '\'')
+ overhead += 3;
+ ret = grub_malloc (ptr - in + overhead + 1);
+ if (!ret)
+ return NULL;
+
+ grub_strchrsub (ret, in, '\'', "'\\''");
+ return ret;
+}
+
+static int is_cryptodisk_enabled = 0;
+static char *grub_distributor = 0;
+
+static int
+load_config (void)
+{
+ char *fn = grub_install_concat (3, GRUB_SYSCONFDIR,
+ "default", "grub");
+ FILE *f = fopen (fn, "r");
+ const char *v;
+ v = secure_getenv ("GRUB_ENABLE_CRYPTODISK");
+ if (v && v[0] == 'y' && v[1] == '\0')
+ is_cryptodisk_enabled = 1;
+
+ v = secure_getenv ("GRUB_DISTRIBUTOR");
+ if (v)
+ grub_distributor = xstrdup (v);
+
+ if (f)
+ {
+ /* FIXME: GRUB_DISTRIBUTOR, GRUB_ENABLE_CRYPTODISK. */
+ fclose (f);
+ }
+ return 0;
+}
+
+static void
+device_map_check_duplicates (const char *dev_map)
+{
+ FILE *fp;
+ char buf[1024]; /* XXX */
+ size_t alloced = 8;
+ size_t filled = 0;
+ char **d;
+ size_t i;
+
+ d = xmalloc (alloced * sizeof (d[0]));
+
+ if (dev_map[0] == '\0')
+ return;
+
+ fp = fopen (dev_map, "r");
+ if (! fp)
+ return;
+
+ while (fgets (buf, sizeof (buf), fp))
+ {
+ char *p = buf;
+ char *e;
+
+ /* Skip leading spaces. */
+ while (*p && grub_isspace (*p))
+ p++;
+
+ /* If the first character is `#' or NUL, skip this line. */
+ if (*p == '\0' || *p == '#')
+ continue;
+
+ if (*p != '(')
+ continue;
+
+ p++;
+
+ e = p;
+ p = strchr (p, ')');
+ if (! p)
+ continue;
+
+ if (filled >= alloced)
+ {
+ alloced *= 2;
+ d = xrealloc (d, alloced * sizeof (d[0]));
+ }
+
+ *p = '\0';
+
+ d[filled++] = xstrdup (e);
+ }
+
+ fclose (fp);
+
+ qsort (d, sizeof (d[0]), filled, (int (*) (const void *, const void *))strcmp);
+
+ for (i = 0; i + 1 < filled; i++)
+ if (strcmp (d[i], d[i+1]) == 0)
+ {
+ grub_util_error ("the drive %s is defined multiple times in the device map %s",
+ d[i], dev_map);
+ }
+
+ for (i = 0; i < filled; i++)
+ free (d[i]);
+
+ free (d);
+}
+
+static grub_err_t
+write_to_disk (grub_device_t dev, const char *fn)
+{
+ char *core_img;
+ size_t core_size;
+ grub_err_t err;
+
+ core_size = grub_util_get_image_size (fn);
+
+ core_img = grub_util_read_image (fn);
+
+ err = grub_disk_write (dev->disk, 0, 0,
+ core_size, core_img);
+ free (core_img);
+ return err;
+}
+
+static int
+is_prep_partition (grub_device_t dev)
+{
+ if (!dev->disk)
+ return 0;
+ if (!dev->disk->partition)
+ return 0;
+ if (strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
+ return (dev->disk->partition->msdostype == 0x41);
+
+ if (strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
+ {
+ struct grub_gpt_partentry gptdata;
+ grub_partition_t p = dev->disk->partition;
+ int ret = 0;
+ dev->disk->partition = dev->disk->partition->parent;
+
+ if (grub_disk_read (dev->disk, p->offset, p->index,
+ sizeof (gptdata), &gptdata) == 0)
+ {
+ const grub_gpt_part_type_t template = {
+ grub_cpu_to_le32_compile_time (0x9e1a2d38),
+ grub_cpu_to_le16_compile_time (0xc612),
+ grub_cpu_to_le16_compile_time (0x4316),
+ { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b }
+ };
+
+ ret = grub_memcmp (&template, &gptdata.type,
+ sizeof (template)) == 0;
+ }
+ dev->disk->partition = p;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+is_prep_empty (grub_device_t dev)
+{
+ grub_disk_addr_t dsize, addr;
+ grub_uint32_t buffer[32768];
+
+ dsize = grub_disk_get_size (dev->disk);
+ for (addr = 0; addr < dsize;
+ addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
+ {
+ grub_size_t sz = sizeof (buffer);
+ grub_uint32_t *ptr;
+
+ if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr)
+ sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE;
+ grub_disk_read (dev->disk, addr, 0, sz, buffer);
+
+ if (addr == 0 && grub_memcmp (buffer, ELFMAG, SELFMAG) == 0)
+ return 1;
+
+ for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++)
+ if (*ptr)
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+remove_old_efi_entries (const char *efi_distributor)
+{
+ int fd;
+ pid_t pid = grub_util_exec_pipe ((char * []){ (char *) "efibootmgr", NULL }, &fd);
+ char *line = NULL;
+ size_t len = 0;
+
+ if (!pid)
+ {
+ grub_util_warn (_("Unable to open stream from %s: %s"),
+ "efibootmgr", strerror (errno));
+ return;
+ }
+
+ FILE *fp = fdopen (fd, "r");
+ if (!fp)
+ {
+ grub_util_warn (_("Unable to open stream from %s: %s"),
+ "efibootmgr", strerror (errno));
+ return;
+ }
+
+ line = xmalloc (80);
+ len = 80;
+ while (1)
+ {
+ int ret;
+ char *bootnum;
+ ret = getline (&line, &len, fp);
+ if (ret == -1)
+ break;
+ if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0
+ || line[sizeof ("Boot") - 1] < '0'
+ || line[sizeof ("Boot") - 1] > '9')
+ continue;
+ if (!strcasestr (line, efi_distributor))
+ continue;
+ bootnum = line + sizeof ("Boot") - 1;
+ bootnum[4] = '\0';
+ if (efi_quiet)
+ grub_util_exec ((char * []){ (char *) "efibootmgr", (char *) "--quiet",
+ (char *) "-b", bootnum, (char *) "-B", NULL });
+ else
+ grub_util_exec ((char * []){ (char *) "efibootmgr",
+ (char *) "-b", bootnum, (char *) "-B", NULL });
+ }
+
+ free (line);
+}
+
+static char *
+get_ofpathname (const char *dev)
+{
+ char *ret = xmalloc (2 * PATH_MAX);
+ char *end = ret + 2 * PATH_MAX - 1;
+ int fd;
+ pid_t pid;
+ char *ptr = ret;
+
+ pid = grub_util_exec_pipe ((char * []){ (char *) "ofpathname",
+ (char *) dev, NULL }, &fd);
+ if (!pid)
+ goto fail;
+
+ FILE *fp = fdopen (fd, "r");
+ if (!fp)
+ goto fail;
+
+ while (!feof (fp) && ptr < end)
+ {
+ size_t r;
+ r = fread (ptr, 1, end - ptr, fp);
+ ptr += r;
+ }
+
+ fclose (fp);
+
+ return ret;
+
+ fail:
+ grub_util_error (_("couldn't find IEEE1275 device tree path for %s.\nYou will have to set `boot-device' variable manually"),
+ dev);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int is_efi = 0;
+ const char *efi_distributor;
+ const char *efi_file = NULL;
+ char **grub_devices;
+ grub_fs_t grub_fs;
+ grub_device_t grub_dev = NULL;
+ enum grub_install_plat platform;
+ char *grubdir, *device_map;
+ char **curdev, **curdrive;
+ char **grub_drives;
+ char *relative_grubdir;
+ char **efidir_device_names;
+ grub_device_t efidir_grub_dev;
+ char *efidir_grub_devname;
+
+ set_program_name (argv[0]);
+
+ grub_util_init_nls ();
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ grub_install_args_finish ();
+
+ if (verbosity > 1)
+ grub_env_set ("debug", "all");
+
+ load_config ();
+
+ if (!bootloader_id && grub_distributor)
+ {
+ char *ptr;
+ bootloader_id = xstrdup (grub_distributor);
+ for (ptr = bootloader_id; *ptr && *ptr != ' '; ptr++)
+ if (*ptr >= 'A' && *ptr <= 'Z')
+ *ptr = *ptr - 'A' + 'a';
+ *ptr = '\0';
+ }
+ if (!bootloader_id || bootloader_id[0] == '\0')
+ {
+ free (bootloader_id);
+ bootloader_id = xstrdup ("grub");
+ }
+
+ if (!grub_install_source_directory)
+ {
+ if (!target)
+ {
+ const char * t;
+ t = get_default_platform ();
+ if (!t)
+ grub_util_error ("%s",
+ _("Unable to determine your platform."
+ " Use --target.")
+ );
+ target = xstrdup (t);
+ }
+ grub_install_source_directory
+ = grub_install_concat (3, GRUB_LIBDIR, PACKAGE, target);
+ }
+
+ platform = grub_install_get_target (grub_install_source_directory);
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ if (!disk_module)
+ disk_module = xstrdup ("biosdisk");
+ break;
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ break;
+
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ disk_module = xstrdup ("native");
+ break;
+ }
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ if (!install_device)
+ grub_util_error ("%s", _("install device isn't specified"));
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ break;
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ free (install_device);
+ install_device = NULL;
+ break;
+ }
+
+ if (!bootdir)
+ bootdir = grub_install_concat (3, "/", rootdir, GRUB_BOOT_DIR_NAME);
+
+ {
+ char * t = grub_install_concat (2, bootdir, GRUB_DIR_NAME);
+ grub_install_mkdir_p (t);
+ grubdir = canonicalize_file_name (t);
+ if (!grubdir)
+ grub_util_error (_("failed to get canonical path of `%s'"), t);
+ free (t);
+ }
+ device_map = grub_install_concat (2, grubdir, "device.map");
+
+ if (recheck)
+ unlink (device_map);
+
+
+ device_map_check_duplicates (device_map);
+ grub_util_biosdisk_init (device_map);
+
+ /* Initialize all modules. */
+ grub_init_all ();
+ grub_gcry_init_all ();
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ is_efi = 1;
+ break;
+ default:
+ is_efi = 0;
+ break;
+ }
+
+ /* Find the EFI System Partition. */
+
+ if (is_efi)
+ {
+ grub_fs_t fs;
+ free (install_device);
+ install_device = NULL;
+ if (!efidir)
+ {
+ char *d = grub_install_concat (2, bootdir, "efi");
+ char *dr = NULL;
+ if (!is_directory (d))
+ {
+ free (d);
+ d = grub_install_concat (2, bootdir, "EFI");
+ }
+ /*
+ The EFI System Partition may have been given directly using
+ --root-directory.
+ */
+ if (!is_directory (d)
+ && rootdir && grub_strcmp (rootdir, "/") != 0)
+ {
+ free (d);
+ d = xstrdup (rootdir);
+ }
+ if (is_directory (d))
+ dr = grub_make_system_path_relative_to_its_root (d);
+ /* Is it a mount point? */
+ if (dr && dr[0] == '\0')
+ efidir = d;
+ else
+ free (d);
+ free (dr);
+ }
+ if (!efidir)
+ grub_util_error ("%s", _("cannot find EFI directory"));
+ efidir_device_names = grub_guess_root_devices (efidir);
+ if (!efidir_device_names || !efidir_device_names[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ efidir);
+ install_device = efidir_device_names[0];
+
+ for (curdev = efidir_device_names; *curdev; curdev++)
+ grub_util_pull_device (*curdev);
+
+ efidir_grub_devname = grub_util_get_grub_dev (efidir_device_names[0]);
+ if (!efidir_grub_devname)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ efidir_device_names[0]);
+
+ efidir_grub_dev = grub_device_open (efidir_grub_devname);
+ if (! efidir_grub_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ fs = grub_fs_probe (efidir_grub_dev);
+ if (! fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (grub_strcmp (fs->name, "fat") != 0)
+ grub_util_error (_("%s doesn't look like an EFI partition.\n"), efidir);
+
+ /* The EFI specification requires that an EFI System Partition must
+ contain an "EFI" subdirectory, and that OS loaders are stored in
+ subdirectories below EFI. Vendors are expected to pick names that do
+ not collide with other vendors. To minimise collisions, we use the
+ name of our distributor if possible.
+ */
+ char *t;
+ efi_distributor = bootloader_id;
+ if (removable)
+ {
+ /* The specification makes stricter requirements of removable
+ devices, in order that only one image can be automatically loaded
+ from them. The image must always reside under /EFI/BOOT, and it
+ must have a specific file name depending on the architecture.
+ */
+ efi_distributor = "BOOT";
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ efi_file = "BOOTIA32.EFI";
+ break;
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ efi_file = "BOOTX64.EFI";
+ break;
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ efi_file = "BOOTIA64.EFI";
+ break;
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ efi_file = "BOOTARM.EFI";
+ break;
+ default:
+ grub_util_error ("%s", _("You've found a bug"));
+ break;
+ }
+ }
+ else
+ {
+ /* It is convenient for each architecture to have a different
+ efi_file, so that different versions can be installed in parallel.
+ */
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ efi_file = "grubia32.efi";
+ break;
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ efi_file = "grubx64.efi";
+ break;
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ efi_file = "grubia64.efi";
+ break;
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ efi_file = "grubarm.efi";
+ break;
+ default:
+ efi_file = "grub.efi";
+ break;
+ }
+ }
+ t = grub_install_concat (3, efidir, "EFI", efi_distributor);
+ free (efidir);
+ efidir = t;
+ grub_install_mkdir_p (efidir);
+ }
+
+ grub_install_copy_files (grub_install_source_directory,
+ grubdir, platform);
+
+ char *envfile = grub_install_concat (2, grubdir, "grubenv");
+ if (!grub_install_is_regular_file (envfile))
+ grub_install_create_envblk_file (envfile);
+
+ size_t ndev = 0;
+
+ /* Write device to a variable so we don't have to traverse /dev every time. */
+ grub_devices = grub_guess_root_devices (grubdir);
+ if (!grub_devices || !grub_devices[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ grubdir);
+
+ for (curdev = grub_devices; *curdev; curdev++)
+ {
+ grub_util_pull_device (*curdev);
+ ndev++;
+ }
+
+ grub_drives = xmalloc (sizeof (grub_drives[0]) * (ndev + 1));
+
+ for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++,
+ curdrive++)
+ {
+ *curdrive = grub_util_get_grub_dev (*curdev);
+ if (! *curdrive)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ *curdev);
+ }
+ *curdrive = 0;
+
+ grub_dev = grub_device_open (grub_drives[0]);
+ if (! grub_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ grub_fs = grub_fs_probe (grub_dev);
+ if (! grub_fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ grub_install_push_module (grub_fs->name);
+
+ if (grub_dev->disk)
+ probe_mods (grub_dev->disk);
+
+ for (curdrive = grub_drives + 1; *curdrive; curdrive++)
+ {
+ grub_device_t dev = grub_device_open (*curdrive);
+ if (!dev)
+ continue;
+ if (dev->disk)
+ probe_mods (dev->disk);
+ grub_device_close (dev);
+ }
+
+ if (!is_cryptodisk_enabled && have_cryptodisk)
+ grub_util_error (_("attempt to install to cryptodisk without cryptodisk enabled. "
+ "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=1", GRUB_SYSCONFDIR "/default/grub");
+
+ if (disk_module && grub_strcmp (disk_module, "ata") == 0)
+ grub_install_push_module ("pata");
+ else if (disk_module && grub_strcmp (disk_module, "native") == 0)
+ {
+ grub_install_push_module ("pata");
+ grub_install_push_module ("ahci");
+ grub_install_push_module ("ohci");
+ grub_install_push_module ("uhci");
+ grub_install_push_module ("usbms");
+ }
+ else if (disk_module && disk_module[0])
+ grub_install_push_module (disk_module);
+
+ relative_grubdir = grub_make_system_path_relative_to_its_root (grubdir);
+ if (relative_grubdir[0] == '\0')
+ {
+ free (relative_grubdir);
+ relative_grubdir = xstrdup ("/");
+ }
+
+ char *platname = grub_install_get_platform_name (platform);
+ char *platdir;
+ {
+ char *t = grub_install_concat (2, grubdir,
+ platname);
+ platdir = canonicalize_file_name (t);
+ if (!platdir)
+ grub_util_error (_("failed to get canonical path of `%s'"),
+ t);
+ free (t);
+ }
+ load_cfg = grub_install_concat (2, platdir,
+ "load.cfg");
+
+ unlink (load_cfg);
+
+ if (debug_image && debug_image[0])
+ {
+ load_cfg_f = fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ fprintf (load_cfg_f, "set debug='%s'\n",
+ debug_image);
+ }
+ char *prefix_drive = NULL;
+ char *install_drive = NULL;
+
+ if (install_device)
+ {
+ if (install_device[0] == '('
+ && install_device[grub_strlen (install_device) - 1] == ')')
+ install_drive = xstrdup (install_device);
+ else
+ {
+ grub_util_pull_device (install_device);
+ install_drive = grub_util_get_grub_dev (install_device);
+ if (!install_drive)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ install_device);
+ }
+ }
+
+ if (!have_abstractions)
+ {
+ if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
+ || grub_drives[1]
+ || (!install_drive
+ && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+ || (install_drive && !is_same_disk (grub_drives[0], install_drive))
+ || !have_bootdev (platform))
+ {
+ char *uuid = NULL;
+ /* generic method (used on coreboot and ata mod). */
+ if (!force_file_id && grub_fs->uuid && grub_fs->uuid (grub_dev,
+ &uuid))
+ {
+ grub_print_error ();
+ grub_errno = 0;
+ uuid = NULL;
+ }
+
+ if (!load_cfg_f)
+ load_cfg_f = fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ if (uuid)
+ {
+ fprintf (load_cfg_f, "search.fs_uuid %s root ",
+ uuid);
+ grub_install_push_module ("search_fs_uuid");
+ }
+ else
+ {
+ char *rndstr = get_rndstr ();
+ char *fl = grub_install_concat (3, grubdir,
+ "uuid", rndstr);
+ char *fldir = grub_install_concat (2, grubdir,
+ "uuid");
+ char *relfl;
+ FILE *flf;
+ grub_install_mkdir_p (fldir);
+ flf = fopen (fl, "w");
+ if (!flf)
+ grub_util_error ("Can't create file: %s", strerror (errno));
+ fclose (flf);
+ relfl = grub_make_system_path_relative_to_its_root (fl);
+ fprintf (load_cfg_f, "search.file %s root ",
+ relfl);
+ grub_install_push_module ("search_fs_file");
+ }
+ if (disk_module && disk_module[0] && grub_strcmp (disk_module, "biosdisk") != 0)
+ {
+ /* FIXME: hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`"
+ */
+ }
+ else
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ /* FIXME: hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=bios_hints --device`"*/
+ break;
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ /* FIXME: hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=efi_hints --device`"*/
+ break;
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ /* FIXME: hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=ieee1275_hints --device`"*/
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ /* FIXME: hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`"*(*/
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ grub_util_warn ("%s", _("no hints available for your platform. Expect reduced performance"));
+ break;
+ }
+ fprintf (load_cfg_f, "\n");
+ char *escaped_relpath = escape (relative_grubdir);
+ fprintf (load_cfg_f, "set prefix=($root)'%s'\n",
+ escaped_relpath);
+ }
+ else
+ {
+ /* We need to hardcode the partition number in the core image's prefix. */
+ char *p;
+ for (p = grub_drives[0]; *p; )
+ {
+ if (*p == '\\' && p[1])
+ {
+ p += 2;
+ continue;
+ }
+ if (*p == ',' || *p == '\0')
+ break;
+ p++;
+ }
+ prefix_drive = xasprintf ("(%s)", p);
+ }
+ }
+ else
+ {
+ if (is_cryptodisk_enabled)
+ {
+ if (grub_dev->disk)
+ probe_cryptodisk_uuid (grub_dev->disk);
+
+ for (curdrive = grub_drives + 1; *curdrive; curdrive++)
+ {
+ grub_device_t dev = grub_device_open (*curdrive);
+ if (!dev)
+ continue;
+ if (dev->disk)
+ probe_cryptodisk_uuid (dev->disk);
+ grub_device_close (dev);
+ }
+ }
+ prefix_drive = xasprintf ("(%s)", grub_drives[0]);
+ }
+
+ char mkimage_target[200];
+ const char *core_name = NULL;
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ core_name = "core.efi";
+ snprintf (mkimage_target, sizeof (mkimage_target),
+ "%s-%s",
+ grub_install_get_platform_cpu (platform),
+ grub_install_get_platform_platform (platform));
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ core_name = "core.elf";
+ snprintf (mkimage_target, sizeof (mkimage_target),
+ "%s-%s-elf",
+ grub_install_get_platform_cpu (platform),
+ grub_install_get_platform_platform (platform));
+ break;
+
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ core_name = "core.elf";
+ snprintf (mkimage_target, sizeof (mkimage_target),
+ "%s-%s",
+ grub_install_get_platform_cpu (platform),
+ grub_install_get_platform_platform (platform));
+ break;
+
+
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ snprintf (mkimage_target, sizeof (mkimage_target),
+ "%s-%s",
+ grub_install_get_platform_cpu (platform),
+ grub_install_get_platform_platform (platform));
+ core_name = "core.img";
+ break;
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ strcpy (mkimage_target, "sparc64-ieee1275-raw");
+ core_name = "core.img";
+ break;
+ }
+
+ if (!core_name)
+ grub_util_error ("%s", _("You've found a bug"));
+
+ if (load_cfg_f)
+ fclose (load_cfg_f);
+
+ char *imgfile = grub_install_concat (2, platdir,
+ core_name);
+ char *prefix = xasprintf ("%s%s", prefix_drive ? : "",
+ relative_grubdir);
+ grub_install_make_image_wrap (/* source dir */ grub_install_source_directory,
+ /*prefix */ prefix,
+ /* output */ imgfile,
+ /* memdisk */ NULL,
+ have_load_cfg ? load_cfg : NULL,
+ /* image target */ mkimage_target,
+ 0, GRUB_COMPRESSION_AUTO);
+ /* Backward-compatibility kludges. */
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ {
+ char *dst = grub_install_concat (2, bootdir, "grub.elf");
+ grub_install_copy_file (imgfile, dst);
+ free (dst);
+ }
+ break;
+
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ {
+ char *dst = grub_install_concat (2, grubdir, "grub");
+ grub_install_copy_file (imgfile, dst);
+ free (dst);
+ }
+ break;
+
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ {
+ char *dst = grub_install_concat (2, platdir, "grub.efi");
+ grub_install_make_image_wrap (/* source dir */ grub_install_source_directory,
+ /* prefix */ "",
+ /* output */ dst,
+ /* memdisk */ NULL,
+ have_load_cfg ? load_cfg : NULL,
+ /* image target */ mkimage_target,
+ 0, GRUB_COMPRESSION_AUTO);
+ }
+ break;
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ break;
+ }
+
+ /* Perform the platform-dependent install */
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_PC:
+ {
+ char *boot_img_src = grub_install_concat (2,
+ grub_install_source_directory,
+ "boot.img");
+ char *boot_img = grub_install_concat (2, platdir,
+ "boot.img");
+ grub_install_copy_file (boot_img_src, boot_img);
+
+ grub_util_info ("grub_bios_setup %s %s %s --directory='%s' --device-map='%s' '%s'",
+ allow_floppy ? "--allow-floppy " : "",
+ verbosity ? "--verbose " : "",
+ force ? "--force " : "",
+ platdir,
+ device_map,
+ install_device);
+
+ /* Now perform the installation. */
+ grub_bios_setup (platdir, NULL, NULL,
+ install_drive, force,
+ 1, allow_floppy);
+ break;
+ }
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ {
+ char *boot_img_src = grub_install_concat (2,
+ grub_install_source_directory,
+ "boot.img");
+ char *boot_img = grub_install_concat (2, platdir,
+ "boot.img");
+ grub_install_copy_file (boot_img_src, boot_img);
+
+ grub_util_info ("grub_sparc_setup %s %s %s --directory='%s' --device-map='%s' '%s'",
+ allow_floppy ? "--allow-floppy " : "",
+ verbosity ? "--verbose " : "",
+ force ? "--force " : "",
+ platdir,
+ device_map,
+ install_drive);
+
+ /* Now perform the installation. */
+ grub_sparc_setup (platdir, NULL, NULL,
+ install_device, force,
+ 1, allow_floppy);
+ break;
+ }
+
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ /* If a install device is defined, copy the core.elf to PReP partition. */
+ if (install_device && install_device[0])
+ {
+ grub_device_t ins_dev;
+ ins_dev = grub_device_open (install_drive);
+ if (!ins_dev || !is_prep_partition (ins_dev))
+ {
+ grub_util_error ("%s", _("the chosen partition is not a PReP partition"));
+ }
+ if (is_prep_empty (ins_dev))
+ {
+ if (write_to_disk (ins_dev, imgfile))
+ grub_util_error ("%s", _("failed to copy Grub to the PReP partition"));
+ }
+ else
+ {
+ char *s = xasprintf ("dd if=/dev/zero of=%s", install_device);
+ grub_util_error ("the PReP partition is not empty. If you are sure you want to use it, run dd to clear it: `%s'",
+ s);
+ }
+ grub_device_close (ins_dev);
+ }
+ /* fallthrough. */
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ if (update_nvram)
+ {
+ char *boot_device;
+
+ if (grub_util_exec_redirect_null ((char * []){ (char *) "ofpathname", (char *) "--version", NULL }))
+ {
+ /* TRANSLATORS: This message is shown when required executable `%s'
+ isn't found. */
+ grub_util_error (_("%s: not found"), "ofpathname");
+ }
+
+ /* Get the Open Firmware device tree path translation. */
+ if (platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275 || !install_device
+ || install_device[0] == '\0')
+ {
+ char *relpath = grub_make_system_path_relative_to_its_root (imgfile);
+ char *ptr;
+ char *dev = grub_util_get_os_disk (grub_devices[0]);
+ char *ofpath;
+ int partno = grub_dev->disk->partition ? grub_dev->disk->partition->number + 1 : 0;
+
+ for (ptr = relpath; *ptr; ptr++)
+ if (*ptr == '/')
+ *ptr = '\\';
+ ofpath = get_ofpathname (dev);
+ boot_device = xasprintf ("%s:%d,%s",
+ ofpath, partno, relpath);
+ }
+ else
+ {
+ char *dev = grub_util_get_os_disk (install_device);
+ boot_device = get_ofpathname (dev);
+ }
+ if (grub_util_exec ((char * []){ (char *) "nvsetenv", (char *) "boot-device",
+ boot_device, NULL }))
+ {
+ char *cmd = xasprintf ("setenv boot-device %s", boot_device);
+ grub_util_error ("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n",
+ cmd);
+ }
+ }
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ grub_util_exec ((char * []){ (char *) "dvhtool", (char *) "-d",
+ install_device, (char *) "--unix-to-vh",
+ imgfile,
+ (char *) "grub", NULL });
+ grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually."));
+
+ break;
+
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ {
+ char *dst = grub_install_concat (2, efidir, "grub.efi");
+ /* For old macs. Suggested by Peter Jones. */
+ grub_install_copy_file (imgfile, dst);
+ free (dst);
+ }
+
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ {
+ char *dst = grub_install_concat (2, efidir, efi_file);
+ grub_install_copy_file (imgfile, dst);
+ free (dst);
+ }
+ if (!removable)
+ {
+ /* Try to make this image bootable using the EFI Boot Manager, if available. */
+
+ if (grub_util_exec_redirect_null ((char * []){ (char *) "efibootmgr", (char *) "--version", NULL }))
+ {
+ /* TRANSLATORS: This message is shown when required executable `%s'
+ isn't found. */
+ grub_util_error (_("%s: not found"), "efibootmgr");
+ }
+ if (!efi_distributor || efi_distributor[0] == '\0')
+ grub_util_error ("%s", "EFI distributor id isn't specified.");
+
+ /* On Linux, we need the efivars kernel modules. */
+#ifdef __linux__
+ grub_util_exec ((char * []){ (char *) "modprobe", (char *) "-q",
+ (char *) "efivars", NULL });
+#endif
+ /* Delete old entries from the same distributor. */
+ remove_old_efi_entries (efi_distributor);
+
+ char * efidir_disk = grub_util_get_os_disk (efidir_device_names[0]);
+ int efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+ char * efifile_path = xasprintf ("\\EFI\\%s\\%s",
+ efi_distributor,
+ efi_file);
+ char *efidir_part_str = xasprintf ("%d", efidir_part);
+
+ grub_util_exec ((char * []){ (char *) "efibootmgr", (char *) "--quiet",
+ (char *) "-c", (char *) "-d", efidir_disk,
+ (char *) "-p", efidir_part_str, (char *) "-w",
+ (char *) "-L", bootloader_id, (char *) "-l",
+ efifile_path, NULL });
+ free (efidir_part_str);
+ }
+ break;
+
+ case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
+ case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
+ case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
+ case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
+ case GRUB_INSTALL_PLATFORM_I386_QEMU:
+ grub_util_warn ("%s",
+ _("WARNING: no platform-specific install was performed"));
+ break;
+ }
+
+ fprintf (stderr, "%s\n", _("Installation finished. No error reported."));
+
+ /* Free resources. */
+ grub_gcry_fini_all ();
+ grub_fini_all ();
+
+ return 0;
+}
=== modified file 'util/grub-mkimage.c'
--- util/grub-mkimage.c 2013-08-23 07:01:11 +0000
+++ util/grub-mkimage.c 2013-10-04 00:39:55 +0000
@@ -43,1786 +43,14 @@
#include <grub/uboot/image.h>
#include <grub/arm/reloc.h>
#include <grub/ia64/reloc.h>
+#include <grub/util/install.h>
+#include <grub/misc.h>
#define _GNU_SOURCE 1
#include <argp.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, COMPRESSION_LZMA
-} grub_compression_t;
-
-struct image_target_desc
-{
- const char *dirname;
- const char *names[6];
- grub_size_t voidp_sizeof;
- int bigendian;
- enum {
- IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
- IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
- IMAGE_I386_IEEE1275,
- IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
- IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
- IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT
- } id;
- enum
- {
- PLATFORM_FLAGS_NONE = 0,
- PLATFORM_FLAGS_DECOMPRESSORS = 2,
- PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
- } flags;
- unsigned total_module_size;
- unsigned decompressor_compressed_size;
- unsigned decompressor_uncompressed_size;
- unsigned decompressor_uncompressed_addr;
- unsigned link_align;
- grub_uint16_t elf_target;
- unsigned section_align;
- signed vaddr_offset;
- grub_uint64_t link_addr;
- unsigned mod_gap, mod_align;
- grub_compression_t default_compression;
- grub_uint16_t pe_target;
-};
-
-#define EFI32_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)
-
-#define EFI64_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)
-
-struct image_target_desc image_targets[] =
- {
- {
- .dirname = "i386-coreboot",
- .names = { "i386-coreboot", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_COREBOOT,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .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
- },
- {
- .dirname = "i386-multiboot",
- .names = { "i386-multiboot", NULL},
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_COREBOOT,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .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
- },
- {
- .dirname = "i386-pc",
- .names = { "i386-pc", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_I386_PC,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
- .default_compression = COMPRESSION_LZMA
- },
- {
- .dirname = "i386-pc",
- .names = { "i386-pc-pxe", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_I386_PC_PXE,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
- .default_compression = COMPRESSION_LZMA
- },
- {
- .dirname = "i386-efi",
- .names = { "i386-efi", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_EFI,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = GRUB_PE32_SECTION_ALIGNMENT,
- .vaddr_offset = EFI32_HEADER_SIZE,
- .pe_target = GRUB_PE32_MACHINE_I386,
- .elf_target = EM_386,
- },
- {
- .dirname = "i386-ieee1275",
- .names = { "i386-ieee1275", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_I386_IEEE1275,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .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,
- },
- {
- .dirname = "i386-qemu",
- .names = { "i386-qemu", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_QEMU,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
- },
- {
- .dirname = "x86_64-efi",
- .names = { "x86_64-efi", NULL },
- .voidp_sizeof = 8,
- .bigendian = 0,
- .id = IMAGE_EFI,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = GRUB_PE32_SECTION_ALIGNMENT,
- .vaddr_offset = EFI64_HEADER_SIZE,
- .pe_target = GRUB_PE32_MACHINE_X86_64,
- .elf_target = EM_X86_64,
- },
- {
- .dirname = "mipsel-loongson",
- .names = { "mipsel-yeeloong-flash", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_YEELOONG_FLASH,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mipsel-loongson",
- .names = { "mipsel-fuloong2f-flash", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_FULOONG2F_FLASH,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mipsel-loongson",
- .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
- "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
- "mipsel-fuloong-elf", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_LOONGSON_ELF,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "powerpc-ieee1275",
- .names = { "powerpc-ieee1275", NULL },
- .voidp_sizeof = 4,
- .bigendian = 1,
- .id = IMAGE_PPC,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .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
- },
- {
- .dirname = "sparc64-ieee1275",
- .names = { "sparc64-ieee1275-raw", NULL },
- .voidp_sizeof = 8,
- .bigendian = 1,
- .id = IMAGE_SPARC64_RAW,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
- },
- {
- .dirname = "sparc64-ieee1275",
- .names = { "sparc64-ieee1275-cdcore", NULL },
- .voidp_sizeof = 8,
- .bigendian = 1,
- .id = IMAGE_SPARC64_CDCORE,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
- },
- {
- .dirname = "sparc64-ieee1275",
- .names = { "sparc64-ieee1275-aout", NULL },
- .voidp_sizeof = 8,
- .bigendian = 1,
- .id = IMAGE_SPARC64_AOUT,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
- },
- {
- .dirname = "ia64-efi",
- .names = {"ia64-efi", NULL},
- .voidp_sizeof = 8,
- .bigendian = 0,
- .id = IMAGE_EFI,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = GRUB_PE32_SECTION_ALIGNMENT,
- .vaddr_offset = EFI64_HEADER_SIZE,
- .pe_target = GRUB_PE32_MACHINE_IA64,
- .elf_target = EM_IA_64,
- },
- {
- .dirname = "mips-arc",
- .names = {"mips-arc", NULL},
- .voidp_sizeof = 4,
- .bigendian = 1,
- .id = IMAGE_MIPS_ARC,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mipsel-arc",
- .names = {"mipsel-arc", NULL},
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_MIPS_ARC,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPSEL_ARC_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mipsel-qemu_mips",
- .names = { "mipsel-qemu_mips-elf", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_LOONGSON_ELF,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mips-qemu_mips",
- .names = { "mips-qemu_mips-flash", NULL },
- .voidp_sizeof = 4,
- .bigendian = 1,
- .id = IMAGE_QEMU_MIPS_FLASH,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mipsel-qemu_mips",
- .names = { "mipsel-qemu_mips-flash", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_QEMU_MIPS_FLASH,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "mips-qemu_mips",
- .names = { "mips-qemu_mips-elf", NULL },
- .voidp_sizeof = 4,
- .bigendian = 1,
- .id = IMAGE_LOONGSON_ELF,
- .flags = PLATFORM_FLAGS_DECOMPRESSORS,
- .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
- .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
- .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
- .section_align = 1,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
- .elf_target = EM_MIPS,
- .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
- .default_compression = COMPRESSION_NONE
- },
- {
- .dirname = "arm-uboot",
- .names = { "arm-uboot", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_UBOOT,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = TARGET_NO_FIELD,
- .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
- .vaddr_offset = 0,
- .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
- .elf_target = EM_ARM,
- .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
- .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
- .link_align = 4
- },
- {
- .dirname = "arm-efi",
- .names = { "arm-efi", NULL },
- .voidp_sizeof = 4,
- .bigendian = 0,
- .id = IMAGE_EFI,
- .flags = PLATFORM_FLAGS_NONE,
- .total_module_size = TARGET_NO_FIELD,
- .decompressor_compressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_size = TARGET_NO_FIELD,
- .decompressor_uncompressed_addr = 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),
- .pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
- .elf_target = EM_ARM,
- },
- };
-
-#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)
-{
- 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;
-
- *core_img = xmalloc (kernel_size);
-
- *core_size = kernel_size;
- if (LzmaEncode ((unsigned char *) *core_img, core_size,
- (unsigned char *) kernel_img,
- kernel_size,
- &props, out_props, &out_props_size,
- 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
- grub_util_error ("%s", _("cannot compress the kernel image"));
-}
-
-#ifdef HAVE_LIBLZMA
-static void
-compress_kernel_xz (char *kernel_img, size_t kernel_size,
- char **core_img, size_t *core_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}
- };
-
- xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
- if (xzret != LZMA_OK)
- grub_util_error ("%s", _("cannot compress the kernel image"));
-
- *core_img = xmalloc (kernel_size);
-
- *core_size = kernel_size;
- strm.next_in = (unsigned char *) kernel_img;
- strm.avail_in = kernel_size;
- strm.next_out = (unsigned char *) *core_img;
- 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 ("%s", _("cannot compress the kernel image"));
- }
-
- *core_size -= strm.avail_out;
-}
-#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_DECOMPRESSORS
- && (comp == COMPRESSION_LZMA))
- {
- compress_kernel_lzma (kernel_img, kernel_size, core_img,
- core_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);
- 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;
-};
-
-#pragma GCC diagnostic ignored "-Wcast-align"
-
-#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, const char *prefix,
- FILE *out, const char *outname, char *mods[],
- char *memdisk_path, char **pubkey_paths, size_t npubkeys,
- 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;
- size_t prefix_size = 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 = 0;
- grub_size_t reloc_size = 0, align;
- size_t decompress_size = 0;
-
- if (comp == COMPRESSION_AUTO)
- comp = image_target->default_compression;
-
- if (image_target->id == IMAGE_I386_PC
- || image_target->id == IMAGE_I386_PC_PXE)
- comp = COMPRESSION_LZMA;
-
- 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);
-
- {
- size_t i;
- for (i = 0; i < npubkeys; i++)
- {
- size_t curs;
- curs = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[i]));
- grub_util_info ("the size of public key %zd is 0x%llx",
- i, (unsigned long long) curs);
- total_module_size += curs + sizeof (struct grub_module_header);
- }
- }
-
- 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%llx",
- (unsigned long long) 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%llx",
- (unsigned long long) config_size);
- total_module_size += config_size + sizeof (struct grub_module_header);
- }
-
- if (prefix)
- {
- prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
- total_module_size += prefix_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%llx",
- (unsigned long long) 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->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);
-
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- memmove (kernel_img + total_module_size, kernel_img, kernel_size);
-
- if (image_target->voidp_sizeof == 8)
- {
- /* Fill in the grub_module_info structure. */
- struct grub_module_info64 *modinfo;
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- modinfo = (struct grub_module_info64 *) kernel_img;
- else
- 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);
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- offset = sizeof (struct grub_module_info64);
- else
- offset = kernel_size + sizeof (struct grub_module_info64);
- }
- else
- {
- /* Fill in the grub_module_info structure. */
- struct grub_module_info32 *modinfo;
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- modinfo = (struct grub_module_info32 *) kernel_img;
- else
- 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);
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- offset = sizeof (struct grub_module_info32);
- else
- 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;
- }
-
- {
- size_t i;
- for (i = 0; i < npubkeys; i++)
- {
- size_t curs;
- struct grub_module_header *header;
-
- curs = grub_util_get_image_size (pubkey_paths[i]);
-
- header = (struct grub_module_header *) (kernel_img + offset);
- memset (header, 0, sizeof (struct grub_module_header));
- header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
- header->size = grub_host_to_target32 (curs + sizeof (*header));
- offset += sizeof (*header);
-
- grub_util_load_image (pubkey_paths[i], kernel_img + offset);
- offset += ALIGN_ADDR (curs);
- }
- }
-
- 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 (prefix)
- {
- 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_PREFIX);
- header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
- offset += sizeof (*header);
-
- grub_memset (kernel_img + offset, 0, prefix_size);
- grub_strcpy (kernel_img + offset, prefix);
- offset += prefix_size;
- }
-
- grub_util_info ("kernel_img=%p, kernel_size=0x%llx", kernel_img,
- (unsigned long long) kernel_size);
- compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
- &core_img, &core_size, comp);
- free (kernel_img);
-
- grub_util_info ("the core size is 0x%llx", (unsigned long long) 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->flags & PLATFORM_FLAGS_DECOMPRESSORS)
- {
- char *full_img;
- size_t full_size;
- char *decompress_path, *decompress_img;
- const char *name;
-
- switch (comp)
- {
- case COMPRESSION_XZ:
- name = "xz_decompress.img";
- break;
- case COMPRESSION_LZMA:
- name = "lzma_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);
-
- if ((image_target->id == IMAGE_I386_PC
- || image_target->id == IMAGE_I386_PC_PXE)
- && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200)
- grub_util_error ("%s", _("Decompressor is too big"));
-
- if (image_target->decompressor_compressed_size != TARGET_NO_FIELD)
- *((grub_uint32_t *) (decompress_img
- + image_target->decompressor_compressed_size))
- = grub_host_to_target32 (core_size);
-
- if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
- *((grub_uint32_t *) (decompress_img
- + image_target->decompressor_uncompressed_size))
- = grub_host_to_target32 (kernel_size + total_module_size);
-
- if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
- {
- if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
- *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
- = grub_host_to_target_addr (image_target->link_addr - total_module_size);
- else
- *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
- = grub_host_to_target_addr (image_target->link_addr);
- }
- 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:
- if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
- || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
- || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
- grub_util_error (_("core image is too big (0x%x > 0x%x)"),
- GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
- 0x78000);
- /* fallthrough */
- case IMAGE_COREBOOT:
- case IMAGE_QEMU:
- if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
- grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
- (unsigned) kernel_size + (unsigned) bss_size
- + GRUB_KERNEL_I386_PC_LINK_ADDR,
- 0x68000);
- break;
- case IMAGE_LOONGSON_ELF:
- case IMAGE_YEELOONG_FLASH:
- case IMAGE_FULOONG2F_FLASH:
- case IMAGE_EFI:
- case IMAGE_MIPS_ARC:
- case IMAGE_QEMU_MIPS_FLASH:
- break;
- case IMAGE_SPARC64_AOUT:
- case IMAGE_SPARC64_RAW:
- case IMAGE_SPARC64_CDCORE:
- case IMAGE_I386_IEEE1275:
- case IMAGE_PPC:
- case IMAGE_UBOOT:
- break;
- }
-
- switch (image_target->id)
- {
- case IMAGE_I386_PC:
- case IMAGE_I386_PC_PXE:
- {
- unsigned num;
- char *boot_path, *boot_img;
- size_t boot_size;
-
- num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
- if (image_target->id == IMAGE_I386_PC_PXE)
- {
- char *pxeboot_path, *pxeboot_img;
- size_t pxeboot_size;
- grub_uint32_t *ptr;
-
- 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,
- outname);
- free (pxeboot_img);
- free (pxeboot_path);
-
- /* Remove Multiboot header to avoid confusing ipxe. */
- for (ptr = (grub_uint32_t *) core_img;
- ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++)
- if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC)
- && grub_target_to_host32 (ptr[0])
- + grub_target_to_host32 (ptr[1])
- + grub_target_to_host32 (ptr[2]) == 0)
- {
- *ptr = 0;
- break;
- }
- }
-
- 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, outname);
- 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 = EFI32_HEADER_SIZE;
- else
- header_size = EFI64_HEADER_SIZE;
-
- 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 ((char *) pe_img + header_size, core_img, core_size);
- memcpy ((char *) 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);
- c->machine = grub_host_to_target16 (image_target->pe_target);
-
- 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_target64 (0x10000);
- o->stack_commit_size = grub_host_to_target64 (0x10000);
- o->heap_reserve_size = grub_host_to_target64 (0x10000);
- o->heap_commit_size = grub_host_to_target64 (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;
- grub_memset (aout_head, 0, sizeof (*aout_head));
- 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 ((char *) 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 size must be %u bytes"),
- GRUB_DISK_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, outname);
- free (boot_img);
- free (boot_path);
- }
- break;
- case IMAGE_SPARC64_CDCORE:
- break;
- case IMAGE_YEELOONG_FLASH:
- case IMAGE_FULOONG2F_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. */
- const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
- {
- 0x5f, 0x67, 0x46, 0x57, 0x31, 0x30, 0xc5, 0x0a,
- 0xe9, 0x98, 0x18, 0xc9, 0xf3, 0xca, 0x45, 0xa5,
- 0x75, 0x64, 0x6b, 0xbb, 0x24, 0xcd, 0xb4, 0xbc,
- 0xf2, 0x3e, 0x23, 0xf9, 0xc2, 0x6a, 0x8c, 0xde,
- 0x3b, 0x94, 0x9c, 0xcc, 0xa5, 0xa7, 0x58, 0xb1,
- 0xbe, 0x8b, 0x3d, 0x73, 0x98, 0x18, 0x7e, 0x68,
- 0x5e, 0x5f, 0x23, 0x7d, 0x7a, 0xe8, 0x51, 0xf7,
- 0x1a, 0xaf, 0x2f, 0x54, 0x11, 0x2e, 0x5c, 0x25
- };
- const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
- {
- 0x76, 0x9b, 0xad, 0x6e, 0xa2, 0x39, 0x47, 0x62,
- 0x1f, 0xc9, 0x3a, 0x6d, 0x05, 0x5c, 0x43, 0x5c,
- 0x29, 0x4a, 0x7e, 0x08, 0x2a, 0x31, 0x8f, 0x5d,
- 0x02, 0x84, 0xa0, 0x85, 0xf2, 0xd1, 0xb9, 0x53,
- 0xa2, 0xbc, 0xf2, 0xe1, 0x39, 0x1e, 0x51, 0xb5,
- 0xaf, 0xec, 0x9e, 0xf2, 0xf1, 0xf3, 0x0a, 0x2f,
- 0xe6, 0xf1, 0x08, 0x89, 0xbe, 0xbc, 0x73, 0xab,
- 0x46, 0x50, 0xd6, 0x21, 0xce, 0x8e, 0x24, 0xa7
- };
- const grub_uint8_t *fwstart_good_hash;
-
- if (image_target->id == IMAGE_FULOONG2F_FLASH)
- {
- fwstart_good_hash = fuloong2f_fwstart_good_hash;
- boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
- }
- else
- {
- fwstart_good_hash = yeeloong_fwstart_good_hash;
- 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)
- /* TRANSLATORS: fwstart.img may still be good, just it wasn't checked. */
- grub_util_warn ("%s",
- _("fwstart.img doesn't match the known good version. "
- "proceed at your own risk"));
-
- if (core_size + boot_size > 512 * 1024)
- grub_util_error ("%s", _("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_QEMU_MIPS_FLASH:
- {
- char *rom_img;
- size_t rom_size;
-
- if (core_size > 512 * 1024)
- grub_util_error ("%s", _("firmware image is too big"));
- rom_size = 512 * 1024;
-
- rom_img = xmalloc (rom_size);
- memset (rom_img, 0, rom_size);
-
- memcpy (rom_img, core_img, core_size);
-
- memset (rom_img + core_size, 0,
- rom_size - core_size);
-
- free (core_img);
- core_img = rom_img;
- core_size = rom_size;
- }
- break;
-
- case IMAGE_UBOOT:
- {
- struct grub_uboot_image_header *hdr;
- GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize);
-
- hdr = xmalloc (core_size + sizeof (struct grub_uboot_image_header));
- memcpy (hdr + 1, core_img, core_size);
-
- memset (hdr, 0, sizeof (*hdr));
- hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
- hdr->ih_time = grub_cpu_to_be32 (time (0));
- hdr->ih_size = grub_cpu_to_be32 (core_size);
- hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
- hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
- hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
- hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
- hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
- hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
-
- GRUB_MD_CRC32->init(crc32_context);
- GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size);
- GRUB_MD_CRC32->final(crc32_context);
- hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
-
- GRUB_MD_CRC32->init(crc32_context);
- GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr));
- GRUB_MD_CRC32->final(crc32_context);
- hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
-
- free (core_img);
- core_img = (char *) hdr;
- core_size += sizeof (struct grub_uboot_image_header);
- }
- break;
-
- case IMAGE_MIPS_ARC:
- {
- char *ecoff_img;
- struct ecoff_header {
- grub_uint16_t magic;
- grub_uint16_t nsec;
- grub_uint32_t time;
- grub_uint32_t syms;
- grub_uint32_t nsyms;
- grub_uint16_t opt;
- grub_uint16_t flags;
- grub_uint16_t magic2;
- grub_uint16_t version;
- grub_uint32_t textsize;
- grub_uint32_t datasize;
- grub_uint32_t bsssize;
- grub_uint32_t entry;
- grub_uint32_t text_start;
- grub_uint32_t data_start;
- grub_uint32_t bss_start;
- grub_uint32_t gprmask;
- grub_uint32_t cprmask[4];
- grub_uint32_t gp_value;
- };
- struct ecoff_section
- {
- char name[8];
- grub_uint32_t paddr;
- grub_uint32_t vaddr;
- grub_uint32_t size;
- grub_uint32_t file_offset;
- grub_uint32_t reloc;
- grub_uint32_t gp;
- grub_uint16_t nreloc;
- grub_uint16_t ngp;
- grub_uint32_t flags;
- };
- struct ecoff_header *head;
- struct ecoff_section *section;
- grub_uint32_t target_addr;
- size_t program_size;
-
- program_size = ALIGN_ADDR (core_size);
- if (comp == COMPRESSION_NONE)
- target_addr = (image_target->link_addr - decompress_size);
- else
- target_addr = ALIGN_UP (image_target->link_addr
- + kernel_size + total_module_size, 32);
-
- ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
- grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
- head = (void *) ecoff_img;
- section = (void *) (head + 1);
- head->magic = image_target->bigendian ? grub_host_to_target16 (0x160)
- : grub_host_to_target16 (0x166);
- head->nsec = grub_host_to_target16 (1);
- head->time = grub_host_to_target32 (0);
- head->opt = grub_host_to_target16 (0x38);
- head->flags = image_target->bigendian
- ? grub_host_to_target16 (0x207)
- : grub_host_to_target16 (0x103);
- head->magic2 = grub_host_to_target16 (0x107);
- head->textsize = grub_host_to_target32 (program_size);
- head->entry = grub_host_to_target32 (target_addr);
- head->text_start = grub_host_to_target32 (target_addr);
- head->data_start = grub_host_to_target32 (target_addr + program_size);
- grub_memcpy (section->name, ".text", sizeof (".text") - 1);
- section->vaddr = grub_host_to_target32 (target_addr);
- section->size = grub_host_to_target32 (program_size);
- section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
- if (!image_target->bigendian)
- {
- section->paddr = grub_host_to_target32 (0xaa60);
- section->flags = grub_host_to_target32 (0x20);
- }
- memcpy (section + 1, core_img, core_size);
- free (core_img);
- core_img = ecoff_img;
- core_size = program_size + sizeof (*head) + sizeof (*section);
- }
- break;
- case IMAGE_LOONGSON_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_LOONGSON_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_LOONGSON_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_LOONGSON_ELF)
- {
- if (comp == COMPRESSION_NONE)
- target_addr = (image_target->link_addr - decompress_size);
- else
- 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_LOONGSON_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_LOONGSON_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);
-
- if (image_target->id == IMAGE_COREBOOT)
- target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
- else
- 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_ptr = (struct grub_ieee1275_note *)
- (elf_img + program_size + header_size);
-
- grub_util_info ("adding CHRP NOTE segment");
-
- note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
- note_ptr->header.descsz = grub_host_to_target32 (note_size);
- note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
- strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME);
- note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
- note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
- note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
- note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
- note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
- note_ptr->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, outname);
- free (core_img);
- free (kernel_path);
-
- while (path_list)
- {
- next = path_list->next;
- free ((void *) path_list->name);
- free (path_list);
- path_list = next;
- }
-}
-
\f
static struct argp_option options[] = {
@@ -1860,22 +88,7 @@
return xasprintf (text, DEFAULT_DIRECTORY);
case 'O':
{
- int format_len = 0;
- char *formats;
- char *ptr;
- char *ret;
- unsigned i;
- for (i = 0; i < ARRAY_SIZE (image_targets); i++)
- format_len += strlen (image_targets[i].names[0]) + 2;
- ptr = formats = xmalloc (format_len);
- for (i = 0; i < ARRAY_SIZE (image_targets); i++)
- {
- strcpy (ptr, image_targets[i].names[0]);
- ptr += strlen (image_targets[i].names[0]);
- *ptr++ = ',';
- *ptr++ = ' ';
- }
- ptr[-2] = 0;
+ char *formats = grub_install_get_image_targets_string (), *ret;
ret = xasprintf ("%s\n%s %s", _("generate an image in FORMAT"),
_("available formats:"), formats);
free (formats);
@@ -1900,10 +113,11 @@
char *font;
char *config;
int note;
- struct image_target_desc *image_target;
+ struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
};
+
static error_t
argp_parser (int key, char *arg, struct argp_state *state)
{
@@ -1922,12 +136,7 @@
case 'O':
{
- unsigned i, j;
- for (i = 0; i < ARRAY_SIZE (image_targets); i++)
- for (j = 0; image_targets[i].names[j]
- && j < ARRAY_SIZE (image_targets[i].names); j++)
- if (strcmp (arg, image_targets[i].names[j]) == 0)
- arguments->image_target = &image_targets[i];
+ arguments->image_target = grub_install_get_image_target (arg);
if (!arguments->image_target)
{
printf (_("unknown target format %s\n"), arg);
@@ -1977,16 +186,16 @@
if (grub_strcmp (arg, "xz") == 0)
{
#ifdef HAVE_LIBLZMA
- arguments->comp = COMPRESSION_XZ;
+ arguments->comp = GRUB_COMPRESSION_XZ;
#else
grub_util_error ("%s",
_("grub-mkimage is compiled without XZ support"));
#endif
}
else if (grub_strcmp (arg, "none") == 0)
- arguments->comp = COMPRESSION_NONE;
+ arguments->comp = GRUB_COMPRESSION_NONE;
else if (grub_strcmp (arg, "auto") == 0)
- arguments->comp = COMPRESSION_AUTO;
+ arguments->comp = GRUB_COMPRESSION_AUTO;
else
grub_util_error (_("Unknown compression format %s"), arg);
break;
@@ -2029,7 +238,7 @@
grub_util_init_nls ();
memset (&arguments, 0, sizeof (struct arguments));
- arguments.comp = COMPRESSION_AUTO;
+ arguments.comp = GRUB_COMPRESSION_AUTO;
arguments.modules_max = argc + 1;
arguments.modules = xmalloc ((arguments.modules_max + 1)
* sizeof (arguments.modules[0]));
@@ -2061,21 +270,24 @@
if (!arguments.dir)
{
+ const char *dn = grub_util_get_target_dirname (arguments.image_target);
arguments.dir = xmalloc (sizeof (GRUB_PKGLIBDIR)
- + grub_strlen (arguments.image_target->dirname)
+ + grub_strlen (dn)
+ 1);
memcpy (arguments.dir, GRUB_PKGLIBDIR,
sizeof (GRUB_PKGLIBDIR) - 1);
*(arguments.dir + sizeof (GRUB_PKGLIBDIR) - 1) = '/';
- strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR),
- arguments.image_target->dirname);
+ strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR), dn);
}
- generate_image (arguments.dir, arguments.prefix ? : DEFAULT_DIRECTORY, fp,
- arguments.output,
- arguments.modules, arguments.memdisk, arguments.pubkeys,
- arguments.npubkeys, arguments.config,
- arguments.image_target, arguments.note, arguments.comp);
+ grub_install_generate_image (arguments.dir,
+ arguments.prefix ? : DEFAULT_DIRECTORY, fp,
+ arguments.output,
+ arguments.modules, arguments.memdisk,
+ arguments.pubkeys,
+ arguments.npubkeys, arguments.config,
+ arguments.image_target, arguments.note,
+ arguments.comp);
fflush (fp);
fsync (fileno (fp));
=== modified file 'util/grub-mkimagexx.c'
--- util/grub-mkimagexx.c 2013-08-23 07:01:11 +0000
+++ util/grub-mkimagexx.c 2013-10-04 00:39:55 +0000
@@ -67,7 +67,7 @@
Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
void *jumpers, Elf_Addr jumpers_addr,
- struct image_target_desc *image_target)
+ struct grub_install_image_target_desc *image_target)
{
Elf_Word symtab_size, sym_size, num_syms;
Elf_Off symtab_offset;
@@ -140,7 +140,7 @@
/* 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)
+ struct grub_install_image_target_desc *image_target)
{
Elf_Sym *sym;
@@ -153,7 +153,7 @@
/* 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)
+ struct grub_install_image_target_desc *image_target)
{
return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
}
@@ -161,7 +161,7 @@
#ifdef MKIMAGE_ELF64
static Elf_Addr
SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
- struct image_target_desc *image_target)
+ struct grub_install_image_target_desc *image_target)
{
Elf_Word symtab_size, sym_size, num_syms;
Elf_Off symtab_offset;
@@ -195,7 +195,7 @@
const char *strtab,
char *pe_target, Elf_Addr tramp_off,
Elf_Addr got_off,
- struct image_target_desc *image_target)
+ struct grub_install_image_target_desc *image_target)
{
Elf_Half i;
Elf_Shdr *s;
@@ -472,7 +472,7 @@
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_install_image_target_desc *image_target)
{
struct grub_pe32_fixup_block *b;
@@ -569,7 +569,7 @@
Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab,
Elf_Addr jumpers, grub_size_t njumpers,
- struct image_target_desc *image_target)
+ struct grub_install_image_target_desc *image_target)
{
unsigned i;
Elf_Shdr *s;
@@ -755,7 +755,7 @@
/* 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)
+SUFFIX (is_text_section) (Elf_Shdr *s, struct grub_install_image_target_desc *image_target)
{
if (image_target->id != IMAGE_EFI
&& grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
@@ -768,7 +768,7 @@
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)
+SUFFIX (is_data_section) (Elf_Shdr *s, struct grub_install_image_target_desc *image_target)
{
if (image_target->id != IMAGE_EFI
&& grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
@@ -779,7 +779,7 @@
/* 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)
+SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, struct grub_install_image_target_desc *image_target)
{
if (size < sizeof (*e)
|| e->e_ident[EI_MAG0] != ELFMAG0
@@ -802,7 +802,7 @@
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)
+ struct grub_install_image_target_desc *image_target)
{
int i;
Elf_Addr current_address;
@@ -884,7 +884,7 @@
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)
+ struct grub_install_image_target_desc *image_target)
{
char *kernel_img, *out_img;
const char *strtab;
=== modified file 'util/grub-setup.c'
--- util/grub-setup.c 2013-04-04 06:55:06 +0000
+++ util/grub-setup.c 2013-10-04 00:39:55 +0000
@@ -31,14 +31,6 @@
#include <grub/term.h>
#include <grub/i18n.h>
#include <grub/util/lvm.h>
-#ifdef GRUB_SETUP_SPARC64
-#include <grub/util/ofpath.h>
-#include <grub/sparc64/ieee1275/boot.h>
-#include <grub/sparc64/ieee1275/kernel.h>
-#else
-#include <grub/i386/pc/boot.h>
-#include <grub/i386/pc/kernel.h>
-#endif
#include <stdio.h>
#include <unistd.h>
@@ -53,6 +45,7 @@
#include <grub/reed_solomon.h>
#include <grub/msdos_partition.h>
#include <include/grub/crypto.h>
+#include <grub/util/install.h>
#ifdef __linux__
#include <sys/ioctl.h>
@@ -63,917 +56,6 @@
#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_SETUP_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_SETUP_BIOS)
-#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 (grub_device_t root_dev,
- char *boot_img, grub_uint64_t first_sector)
-{
-#ifdef GRUB_SETUP_BIOS
- {
- grub_uint8_t *boot_drive;
- void *kernel_sector;
- boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE);
- kernel_sector = (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR);
-
- /* FIXME: can this be skipped? */
- *boot_drive = 0xFF;
-
- grub_set_unaligned64 (kernel_sector, grub_cpu_to_le64 (first_sector));
- }
-#endif
-#ifdef GRUB_SETUP_SPARC64
- {
- void *kernel_byte;
- kernel_byte = (boot_img + GRUB_BOOT_AOUT_HEADER_SIZE
- + GRUB_BOOT_MACHINE_KERNEL_BYTE);
- grub_set_unaligned64 (kernel_byte,
- grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS));
- }
-#endif
-}
-
-#ifdef GRUB_SETUP_SPARC64
-#define BOOT_SECTOR 1
-#else
-#define BOOT_SECTOR 0
-#endif
-
-/* Helper for setup. */
-static void
-save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length,
- void *data)
-{
- grub_disk_addr_t *first_sector = data;
- grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
- sector, offset, length);
-
- if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
- grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
-
- *first_sector = sector;
-}
-
-struct blocklists
-{
- struct grub_boot_blocklist *first_block, *block;
-#ifdef GRUB_SETUP_BIOS
- grub_uint16_t current_segment;
-#endif
- grub_uint16_t last_length;
-};
-
-/* Helper for setup. */
-static void
-save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
- void *data)
-{
- struct blocklists *bl = data;
- struct grub_boot_blocklist *prev = bl->block + 1;
-
- grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
- sector, offset, length);
-
- if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
- grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
-
- if (bl->block != bl->first_block
- && (grub_target_to_host64 (prev->start)
- + grub_target_to_host16 (prev->len)) == sector)
- {
- grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
- prev->len = grub_host_to_target16 (t);
- }
- else
- {
- bl->block->start = grub_host_to_target64 (sector);
- bl->block->len = grub_host_to_target16 (1);
-#ifdef GRUB_SETUP_BIOS
- bl->block->segment = grub_host_to_target16 (bl->current_segment);
-#endif
-
- bl->block--;
- if (bl->block->len)
- grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
- }
-
- bl->last_length = length;
-#ifdef GRUB_SETUP_BIOS
- bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
-#endif
-}
-
-#ifdef GRUB_SETUP_BIOS
-/* Context for setup/identify_partmap. */
-struct identify_partmap_ctx
-{
- grub_partition_map_t dest_partmap;
- grub_partition_t container;
- int multiple_partmaps;
-};
-
-/* Helper for setup.
- Unlike root_dev, with dest_dev we're interested in the partition map even
- if dest_dev itself is a whole disk. */
-static int
-identify_partmap (grub_disk_t disk __attribute__ ((unused)),
- const grub_partition_t p, void *data)
-{
- struct identify_partmap_ctx *ctx = data;
-
- if (p->parent != ctx->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 (ctx->dest_partmap == NULL)
- {
- ctx->dest_partmap = p->partmap;
- return 0;
- }
- if (ctx->dest_partmap == p->partmap)
- return 0;
- ctx->multiple_partmaps = 1;
- return 1;
-}
-#endif
-
-static void
-setup (const char *dir,
- const char *boot_file, const char *core_file,
- const char *dest, 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;
- char *root = 0;
- size_t boot_size, core_size;
-#ifdef GRUB_SETUP_BIOS
- grub_uint16_t core_sectors;
-#endif
- grub_device_t root_dev = 0, dest_dev, core_dev;
- struct blocklists bl;
- char *tmp_img;
- grub_disk_addr_t first_sector = (grub_disk_addr_t)-1;
- FILE *fp;
-
-#ifdef GRUB_SETUP_BIOS
- bl.current_segment =
- GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
-#endif
- bl.last_length = GRUB_DISK_SECTOR_SIZE;
-
- /* 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);
-#ifdef GRUB_SETUP_BIOS
- core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
-#endif
- if (core_size < GRUB_DISK_SECTOR_SIZE)
- grub_util_error (_("the size of `%s' is too small"), core_path);
-#ifdef GRUB_SETUP_BIOS
- 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. */
- bl.first_block = (struct grub_boot_blocklist *) (core_img
- + GRUB_DISK_SECTOR_SIZE
- - sizeof (*bl.block));
- grub_util_info ("root is `%s', dest is `%s'", root, dest);
-
- grub_util_info ("Opening dest");
- dest_dev = grub_device_open (dest);
- if (! dest_dev)
- grub_util_error ("%s", grub_errmsg);
-
- core_dev = dest_dev;
-
- {
- char **root_devices = grub_guess_root_devices (dir);
- char **cur;
- int found = 0;
-
- for (cur = root_devices; *cur; cur++)
- {
- char *drive;
- grub_device_t try_dev;
-
- drive = grub_util_get_grub_dev (*cur);
- if (!drive)
- continue;
- try_dev = grub_device_open (drive);
- if (! try_dev)
- continue;
- if (!found && try_dev->disk->id == dest_dev->disk->id
- && try_dev->disk->dev->id == dest_dev->disk->dev->id)
- {
- if (root_dev)
- grub_device_close (root_dev);
- free (root);
- root_dev = try_dev;
- root = drive;
- found = 1;
- continue;
- }
- if (!root_dev)
- {
- root_dev = try_dev;
- root = drive;
- continue;
- }
- grub_device_close (try_dev);
- free (drive);
- }
- if (!root_dev)
- {
- grub_util_error ("guessing the root device failed, because of `%s'",
- grub_errmsg);
- }
- grub_util_info ("guessed root_dev `%s' from "
- "dir `%s'", root_dev->disk->name, dir);
- }
-
- 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_SETUP_BIOS
- /* 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_SETUP_BIOS
- {
- grub_uint8_t *boot_drive_check;
- boot_drive_check = (grub_uint8_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[0] = 0x90;
- boot_drive_check[1] = 0x90;
- }
- }
-#endif
-
-#ifdef GRUB_SETUP_BIOS
- {
- struct identify_partmap_ctx ctx = {
- .dest_partmap = NULL,
- .container = dest_dev->disk->partition,
- .multiple_partmaps = 0
- };
- int is_ldm;
- grub_err_t err;
- grub_disk_addr_t *sectors;
- int i;
- grub_fs_t fs;
- unsigned int nsec, maxsec;
-
- grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
-
- if (ctx.container
- && grub_strcmp (ctx.container->partmap->name, "msdos") == 0
- && ctx.dest_partmap
- && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
- || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
- {
- grub_util_warn ("%s", _("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;
-
- is_ldm = grub_util_is_ldm (dest_dev->disk);
-
- if (fs_probe)
- {
- if (!fs && !ctx.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)
- /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */
- 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 (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
- && strcmp (ctx.dest_partmap->name, "gpt") != 0
- && strcmp (ctx.dest_partmap->name, "bsd") != 0
- && strcmp (ctx.dest_partmap->name, "netbsd") != 0
- && strcmp (ctx.dest_partmap->name, "openbsd") != 0
- && strcmp (ctx.dest_partmap->name, "sunpc") != 0)
- /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
- 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, ctx.dest_partmap->name);
- if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
- && strcmp (ctx.dest_partmap->name, "gpt") != 0)
- grub_util_error (_("%s appears to contain a %s partition map and "
- "LDM which isn't known to be a safe combination."
- " 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, ctx.dest_partmap->name);
-
- }
-
- /* Copy the partition table. */
- if (ctx.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 (! ctx.dest_partmap && ! fs && !is_ldm)
- {
- grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
- goto unable_to_embed;
- }
- if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs))
- {
- grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
- goto unable_to_embed;
- }
-
- if (ctx.dest_partmap && !ctx.dest_partmap->embed)
- {
- grub_util_warn (_("Partition style `%s' doesn't support embedding"),
- ctx.dest_partmap->name);
- goto unable_to_embed;
- }
-
- if (fs && !fs->embed)
- {
- grub_util_warn (_("File system `%s' doesn't support embedding"),
- fs->name);
- goto unable_to_embed;
- }
-
- nsec = core_sectors;
-
- maxsec = 2 * core_sectors;
- if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
- >> GRUB_DISK_SECTOR_BITS))
- maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
- >> GRUB_DISK_SECTOR_BITS);
-
- if (is_ldm)
- err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
- GRUB_EMBED_PCBIOS, §ors);
- else if (ctx.dest_partmap)
- err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
- GRUB_EMBED_PCBIOS, §ors);
- else
- err = fs->embed (dest_dev, &nsec, maxsec,
- GRUB_EMBED_PCBIOS, §ors);
- if (!err && nsec < core_sectors)
- {
- err = grub_error (GRUB_ERR_OUT_OF_RANGE,
- N_("Your embedding area is unusually small. "
- "core.img won't fit in it."));
- }
-
- if (err)
- {
- grub_util_warn ("%s", grub_errmsg);
- grub_errno = GRUB_ERR_NONE;
- goto unable_to_embed;
- }
-
- assert (nsec <= maxsec);
-
- /* Clean out the blocklists. */
- bl.block = bl.first_block;
- while (bl.block->len)
- {
- grub_memset (bl.block, 0, sizeof (bl.block));
-
- bl.block--;
-
- if ((char *) bl.block <= core_img)
- grub_util_error ("%s", _("no terminator in the core image"));
- }
-
- save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
- 0, GRUB_DISK_SECTOR_SIZE, &first_sector);
-
- bl.block = bl.first_block;
- for (i = 1; i < nsec; i++)
- save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
- 0, GRUB_DISK_SECTOR_SIZE, &bl);
-
- /* Make sure that the last blocklist is a terminator. */
- if (bl.block == bl.first_block)
- bl.block--;
- bl.block->start = 0;
- bl.block->len = 0;
- bl.block->segment = 0;
-
- write_rootdev (root_dev, boot_img, first_sector);
-
- core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
- bl.first_block = (struct grub_boot_blocklist *) (core_img
- + GRUB_DISK_SECTOR_SIZE
- - sizeof (*bl.block));
-
- grub_size_t no_rs_length;
- grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE
- + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY),
- grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size));
- no_rs_length = grub_target_to_host16
- (grub_get_unaligned16 (core_img
- + GRUB_DISK_SECTOR_SIZE
- + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH));
-
- if (no_rs_length == 0xffff)
- grub_util_error ("%s", _("core.img version mismatch"));
-
- void *tmp = xmalloc (core_size);
- grub_memcpy (tmp, core_img, core_size);
- grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE,
- core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE,
- nsec * GRUB_DISK_SECTOR_SIZE
- - core_size);
- assert (grub_memcmp (tmp, core_img, core_size) == 0);
- free (tmp);
-
- /* 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;
- }
-
-unable_to_embed:
-#endif
-
- if (dest_dev->disk->dev->id != root_dev->disk->dev->id)
- grub_util_error ("%s", _("embedding is not possible, but this is required for "
- "RAID and LVM install"));
-
- {
- grub_fs_t fs;
- fs = grub_fs_probe (root_dev);
- if (!fs)
- grub_util_error (_("can't determine filesystem on %s"), root);
-
- if (!fs->blocklist_install)
- grub_util_error (_("filesystem `%s' doesn't support blocklists"),
- fs->name);
- }
-
-#ifdef GRUB_SETUP_BIOS
- if (dest_dev->disk->id != root_dev->disk->id
- || dest_dev->disk->dev->id != root_dev->disk->dev->id)
- /* TRANSLATORS: cross-disk refers to /boot being on one disk
- but MBR on another. */
- grub_util_error ("%s", _("embedding is not possible, but this is required for "
- "cross-disk install"));
-#else
- core_dev = root_dev;
-#endif
-
- grub_util_warn ("%s", _("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)
- /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */
- grub_util_error ("%s", _("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);
-
-#ifndef __linux__
-
-#define MAX_TRIES 5
- {
- int i;
- for (i = 0; i < MAX_TRIES; i++)
- {
- grub_file_t file;
-
- 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);
- }
-
-#endif
-
- /* Clean out the blocklists. */
- bl.block = bl.first_block;
- while (bl.block->len)
- {
- bl.block->start = 0;
- bl.block->len = 0;
-#ifdef GRUB_SETUP_BIOS
- bl.block->segment = 0;
-#endif
-
- bl.block--;
-
- if ((char *) bl.block <= core_img)
- grub_util_error ("%s", _("no terminator in the core image"));
- }
-
- bl.block = bl.first_block;
-
-#ifdef __linux__
- {
- grub_partition_t container = root_dev->disk->partition;
- grub_uint64_t container_start = grub_partition_get_start (container);
- struct fiemap fie1;
- int fd;
-
- /* 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, "rb");
- if (! fp)
- grub_util_error (_("cannot open `%s': %s"), core_path,
- strerror (errno));
- fd = fileno (fp);
-
- grub_memset (&fie1, 0, sizeof (fie1));
- fie1.fm_length = core_size;
- fie1.fm_flags = FIEMAP_FLAG_SYNC;
-
- if (ioctl (fd, FS_IOC_FIEMAP, &fie1) < 0)
- {
- int nblocks, i, j;
- int bsize;
- int mul;
-
- grub_util_info ("FIEMAP failed. Reverting to FIBMAP");
-
- if (ioctl (fd, FIGETBSZ, &bsize) < 0)
- grub_util_error (_("can't retrieve blocklists: %s"),
- strerror (errno));
- if (bsize & (GRUB_DISK_SECTOR_SIZE - 1))
- grub_util_error ("%s", _("blocksize is not divisible by 512"));
- mul = bsize >> GRUB_DISK_SECTOR_BITS;
- nblocks = (core_size + bsize - 1) / bsize;
- if (mul == 0 || nblocks == 0)
- grub_util_error ("%s", _("can't retrieve blocklists"));
- for (i = 0; i < nblocks; i++)
- {
- unsigned blk = i;
- if (ioctl (fd, FIBMAP, &blk) < 0)
- grub_util_error (_("can't retrieve blocklists: %s"),
- strerror (errno));
-
- for (j = 0; j < mul; j++)
- {
- int rest = core_size - ((i * mul + j) << GRUB_DISK_SECTOR_BITS);
- if (rest <= 0)
- break;
- if (rest > GRUB_DISK_SECTOR_SIZE)
- rest = GRUB_DISK_SECTOR_SIZE;
- if (i == 0 && j == 0)
- save_first_sector (((grub_uint64_t) blk) * mul
- + container_start,
- 0, rest, &first_sector);
- else
- save_blocklists (((grub_uint64_t) blk) * mul + j
- + container_start,
- 0, rest, &bl);
- }
- }
- }
- else
- {
- struct fiemap *fie2;
- int i, j;
- fie2 = xmalloc (sizeof (*fie2)
- + fie1.fm_mapped_extents
- * sizeof (fie1.fm_extents[1]));
- memset (fie2, 0, sizeof (*fie2)
- + fie1.fm_mapped_extents * sizeof (fie2->fm_extents[1]));
- fie2->fm_length = core_size;
- fie2->fm_flags = FIEMAP_FLAG_SYNC;
- fie2->fm_extent_count = fie1.fm_mapped_extents;
- if (ioctl (fd, FS_IOC_FIEMAP, fie2) < 0)
- grub_util_error (_("can't retrieve blocklists: %s"),
- strerror (errno));
- for (i = 0; i < fie2->fm_mapped_extents; i++)
- {
- for (j = 0;
- j < ((fie2->fm_extents[i].fe_length
- + GRUB_DISK_SECTOR_SIZE - 1)
- >> GRUB_DISK_SECTOR_BITS);
- j++)
- {
- size_t len = (fie2->fm_extents[i].fe_length
- - j * GRUB_DISK_SECTOR_SIZE);
- if (len > GRUB_DISK_SECTOR_SIZE)
- len = GRUB_DISK_SECTOR_SIZE;
- if (first_sector == (grub_disk_addr_t)-1)
- save_first_sector ((fie2->fm_extents[i].fe_physical
- >> GRUB_DISK_SECTOR_BITS)
- + j + container_start,
- fie2->fm_extents[i].fe_physical
- & (GRUB_DISK_SECTOR_SIZE - 1), len,
- &first_sector);
- else
- save_blocklists ((fie2->fm_extents[i].fe_physical
- >> GRUB_DISK_SECTOR_BITS)
- + j + container_start,
- fie2->fm_extents[i].fe_physical
- & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl);
-
-
- }
- }
- if (first_sector == (grub_disk_addr_t)-1)
- grub_util_error ("%s", _("can't retrieve blocklists"));
- }
- fclose (fp);
- }
-#else
- {
- grub_file_t file;
- /* 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;
- file->read_hook_data = &first_sector;
- if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
- != GRUB_DISK_SECTOR_SIZE)
- grub_util_error ("%s", _("failed to read the first sector of the core image"));
-
- bl.block = bl.first_block;
- file->read_hook = save_blocklists;
- file->read_hook_data = &bl;
- 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 ("%s", _("failed to read the rest sectors of the core image"));
- grub_file_close (file);
- }
-#endif
-
-#ifdef GRUB_SETUP_SPARC64
- {
- char *boot_devpath;
- boot_devpath = (char *) (boot_img
- + GRUB_BOOT_AOUT_HEADER_SIZE
- + GRUB_BOOT_MACHINE_BOOT_DEVPATH);
- if (dest_dev->disk->id != root_dev->disk->id
- || dest_dev->disk->dev->id != root_dev->disk->dev->id)
- {
- const char *dest_ofpath;
- dest_ofpath
- = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->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
-
- free (core_path_dev);
- free (tmp_img);
-
- write_rootdev (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': %s"), core_path,
- strerror (errno));
-
- grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path);
- fflush (fp);
- fsync (fileno (fp));
- fclose (fp);
- grub_util_biosdisk_flush (root_dev->disk);
-
- grub_disk_cache_invalidate_all ();
-
- {
- char *buf, *ptr = core_img;
- size_t len = core_size;
- grub_uint64_t blk;
- grub_partition_t container = core_dev->disk->partition;
- grub_err_t err;
-
- core_dev->disk->partition = 0;
-
- buf = xmalloc (core_size);
- blk = first_sector;
- err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf);
- if (err)
- grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
- grub_errmsg);
- if (grub_memcmp (buf, ptr, GRUB_DISK_SECTOR_SIZE) != 0)
- grub_util_error ("%s", _("blocklists are invalid"));
-
- ptr += GRUB_DISK_SECTOR_SIZE;
- len -= GRUB_DISK_SECTOR_SIZE;
-
- bl.block = bl.first_block;
- while (bl.block->len)
- {
- size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS;
- blk = grub_target_to_host64 (bl.block->start);
-
- if (cur > len)
- cur = len;
-
- err = grub_disk_read (core_dev->disk, blk, 0, cur, buf);
- if (err)
- grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
- grub_errmsg);
-
- if (grub_memcmp (buf, ptr, cur) != 0)
- grub_util_error ("%s", _("blocklists are invalid"));
-
- ptr += cur;
- len -= cur;
- bl.block--;
-
- if ((char *) bl.block <= core_img)
- grub_util_error ("%s", _("no terminator in the core image"));
- }
- core_dev->disk->partition = container;
- free (buf);
- }
-
-#ifdef GRUB_SETUP_BIOS
- finish:
-#endif
-
- /* 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},
@@ -1002,10 +84,10 @@
switch (key)
{
case 'b':
- return xasprintf (text, DEFAULT_BOOT_FILE);
+ return xasprintf (text, "boot.img");
case 'c':
- return xasprintf (text, DEFAULT_CORE_FILE);
+ return xasprintf (text, "core.img");
case 'd':
return xasprintf (text, DEFAULT_DIRECTORY);
@@ -1199,12 +281,18 @@
grub_util_info ("Using `%s' as GRUB device", dest_dev);
}
+ char *boot_path;
+
+ boot_path = grub_util_get_path (arguments.dir ? : DEFAULT_DIRECTORY,
+ arguments.boot_file ? : "boot.img");
+
/* Do the real work. */
- setup (arguments.dir ? : DEFAULT_DIRECTORY,
- arguments.boot_file ? : DEFAULT_BOOT_FILE,
- arguments.core_file ? : DEFAULT_CORE_FILE,
- dest_dev, arguments.force,
- arguments.fs_probe, arguments.allow_floppy);
+ GRUB_SETUP_FUNC (arguments.dir ? : DEFAULT_DIRECTORY,
+ boot_path,
+ arguments.core_file,
+ dest_dev, arguments.force,
+ arguments.fs_probe, arguments.allow_floppy);
+ free (boot_path);
/* Free resources. */
grub_fini_all ();
=== added file 'util/mkimage.c'
--- util/mkimage.c 1970-01-01 00:00:00 +0000
+++ util/mkimage.c 2013-10-04 00:39:55 +0000
@@ -0,0 +1,1861 @@
+/* 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 <grub/dl.h>
+#include <time.h>
+#include <multiboot.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <grub/efi/pe32.h>
+#include <grub/uboot/image.h>
+#include <grub/arm/reloc.h>
+#include <grub/ia64/reloc.h>
+#include <grub/util/install.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
+
+struct grub_install_image_target_desc
+{
+ const char *dirname;
+ const char *names[6];
+ grub_size_t voidp_sizeof;
+ int bigendian;
+ enum {
+ IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
+ IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
+ IMAGE_I386_IEEE1275,
+ IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
+ IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
+ IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT
+ } id;
+ enum
+ {
+ PLATFORM_FLAGS_NONE = 0,
+ PLATFORM_FLAGS_DECOMPRESSORS = 2,
+ PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
+ } flags;
+ unsigned total_module_size;
+ unsigned decompressor_compressed_size;
+ unsigned decompressor_uncompressed_size;
+ unsigned decompressor_uncompressed_addr;
+ unsigned link_align;
+ grub_uint16_t elf_target;
+ unsigned section_align;
+ signed vaddr_offset;
+ grub_uint64_t link_addr;
+ unsigned mod_gap, mod_align;
+ grub_compression_t default_compression;
+ grub_uint16_t pe_target;
+};
+
+#define EFI32_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)
+
+#define EFI64_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)
+
+struct grub_install_image_target_desc image_targets[] =
+ {
+ {
+ .dirname = "i386-coreboot",
+ .names = { "i386-coreboot", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_COREBOOT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .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
+ },
+ {
+ .dirname = "i386-multiboot",
+ .names = { "i386-multiboot", NULL},
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_COREBOOT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .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
+ },
+ {
+ .dirname = "i386-pc",
+ .names = { "i386-pc", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_PC,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
+ .default_compression = GRUB_COMPRESSION_LZMA
+ },
+ {
+ .dirname = "i386-pc",
+ .names = { "i386-pc-pxe", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_PC_PXE,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
+ .default_compression = GRUB_COMPRESSION_LZMA
+ },
+ {
+ .dirname = "i386-efi",
+ .names = { "i386-efi", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = EFI32_HEADER_SIZE,
+ .pe_target = GRUB_PE32_MACHINE_I386,
+ .elf_target = EM_386,
+ },
+ {
+ .dirname = "i386-ieee1275",
+ .names = { "i386-ieee1275", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_I386_IEEE1275,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .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,
+ },
+ {
+ .dirname = "i386-qemu",
+ .names = { "i386-qemu", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_QEMU,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
+ },
+ {
+ .dirname = "x86_64-efi",
+ .names = { "x86_64-efi", NULL },
+ .voidp_sizeof = 8,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = EFI64_HEADER_SIZE,
+ .pe_target = GRUB_PE32_MACHINE_X86_64,
+ .elf_target = EM_X86_64,
+ },
+ {
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-yeeloong-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_YEELOONG_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-fuloong2f-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_FULOONG2F_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-loongson",
+ .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
+ "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
+ "mipsel-fuloong-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "powerpc-ieee1275",
+ .names = { "powerpc-ieee1275", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_PPC,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .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
+ },
+ {
+ .dirname = "sparc64-ieee1275",
+ .names = { "sparc64-ieee1275-raw", NULL },
+ .voidp_sizeof = 8,
+ .bigendian = 1,
+ .id = IMAGE_SPARC64_RAW,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
+ },
+ {
+ .dirname = "sparc64-ieee1275",
+ .names = { "sparc64-ieee1275-cdcore", NULL },
+ .voidp_sizeof = 8,
+ .bigendian = 1,
+ .id = IMAGE_SPARC64_CDCORE,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
+ },
+ {
+ .dirname = "sparc64-ieee1275",
+ .names = { "sparc64-ieee1275-aout", NULL },
+ .voidp_sizeof = 8,
+ .bigendian = 1,
+ .id = IMAGE_SPARC64_AOUT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
+ },
+ {
+ .dirname = "ia64-efi",
+ .names = {"ia64-efi", NULL},
+ .voidp_sizeof = 8,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = GRUB_PE32_SECTION_ALIGNMENT,
+ .vaddr_offset = EFI64_HEADER_SIZE,
+ .pe_target = GRUB_PE32_MACHINE_IA64,
+ .elf_target = EM_IA_64,
+ },
+ {
+ .dirname = "mips-arc",
+ .names = {"mips-arc", NULL},
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_MIPS_ARC,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-arc",
+ .names = {"mipsel-arc", NULL},
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_MIPS_ARC,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPSEL_ARC_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-qemu_mips",
+ .names = { "mipsel-qemu_mips-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mips-qemu_mips",
+ .names = { "mips-qemu_mips-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_QEMU_MIPS_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mipsel-qemu_mips",
+ .names = { "mipsel-qemu_mips-flash", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_QEMU_MIPS_FLASH,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "mips-qemu_mips",
+ .names = { "mips-qemu_mips-elf", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 1,
+ .id = IMAGE_LOONGSON_ELF,
+ .flags = PLATFORM_FLAGS_DECOMPRESSORS,
+ .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
+ .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
+ .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
+ .section_align = 1,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
+ .elf_target = EM_MIPS,
+ .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
+ .default_compression = GRUB_COMPRESSION_NONE
+ },
+ {
+ .dirname = "arm-uboot",
+ .names = { "arm-uboot", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_UBOOT,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+ .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
+ .vaddr_offset = 0,
+ .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
+ .elf_target = EM_ARM,
+ .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
+ .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
+ .link_align = 4
+ },
+ {
+ .dirname = "arm-efi",
+ .names = { "arm-efi", NULL },
+ .voidp_sizeof = 4,
+ .bigendian = 0,
+ .id = IMAGE_EFI,
+ .flags = PLATFORM_FLAGS_NONE,
+ .total_module_size = TARGET_NO_FIELD,
+ .decompressor_compressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_size = TARGET_NO_FIELD,
+ .decompressor_uncompressed_addr = 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),
+ .pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
+ .elf_target = EM_ARM,
+ },
+ };
+
+#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 grub_install_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 grub_install_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 grub_install_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 grub_install_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 grub_install_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 grub_install_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 grub_install_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 grub_install_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)
+{
+ 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;
+
+ *core_img = xmalloc (kernel_size);
+
+ *core_size = kernel_size;
+ if (LzmaEncode ((unsigned char *) *core_img, core_size,
+ (unsigned char *) kernel_img,
+ kernel_size,
+ &props, out_props, &out_props_size,
+ 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
+ grub_util_error ("%s", _("cannot compress the kernel image"));
+}
+
+#ifdef HAVE_LIBLZMA
+static void
+compress_kernel_xz (char *kernel_img, size_t kernel_size,
+ char **core_img, size_t *core_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}
+ };
+
+ xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
+ if (xzret != LZMA_OK)
+ grub_util_error ("%s", _("cannot compress the kernel image"));
+
+ *core_img = xmalloc (kernel_size);
+
+ *core_size = kernel_size;
+ strm.next_in = (unsigned char *) kernel_img;
+ strm.avail_in = kernel_size;
+ strm.next_out = (unsigned char *) *core_img;
+ 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 ("%s", _("cannot compress the kernel image"));
+ }
+
+ *core_size -= strm.avail_out;
+}
+#endif
+
+static void
+compress_kernel (struct grub_install_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_DECOMPRESSORS
+ && (comp == GRUB_COMPRESSION_LZMA))
+ {
+ compress_kernel_lzma (kernel_img, kernel_size, core_img,
+ core_size);
+ return;
+ }
+
+#ifdef HAVE_LIBLZMA
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
+ && (comp == GRUB_COMPRESSION_XZ))
+ {
+ compress_kernel_xz (kernel_img, kernel_size, core_img,
+ core_size);
+ return;
+ }
+#endif
+
+ if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
+ && (comp != GRUB_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;
+};
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+#define MKIMAGE_ELF32 1
+#include "grub-mkimagexx.c"
+#undef MKIMAGE_ELF32
+
+#define MKIMAGE_ELF64 1
+#include "grub-mkimagexx.c"
+#undef MKIMAGE_ELF64
+
+struct grub_install_image_target_desc *
+grub_install_get_image_target (const char *arg)
+{
+ unsigned i, j;
+ for (i = 0; i < ARRAY_SIZE (image_targets); i++)
+ for (j = 0; image_targets[i].names[j]
+ && j < ARRAY_SIZE (image_targets[i].names); j++)
+ if (strcmp (arg, image_targets[i].names[j]) == 0)
+ return &image_targets[i];
+ return NULL;
+}
+
+const char *
+grub_util_get_target_dirname (struct grub_install_image_target_desc *t)
+{
+ return t->dirname;
+}
+
+
+char *
+grub_install_get_image_targets_string (void)
+{
+ 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].names[0]) + 2;
+ ptr = formats = xmalloc (format_len);
+ for (i = 0; i < ARRAY_SIZE (image_targets); i++)
+ {
+ strcpy (ptr, image_targets[i].names[0]);
+ ptr += strlen (image_targets[i].names[0]);
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ }
+ ptr[-2] = 0;
+
+ return formats;
+}
+
+void
+grub_install_generate_image (const char *dir, const char *prefix,
+ FILE *out, const char *outname, char *mods[],
+ char *memdisk_path, char **pubkey_paths, size_t npubkeys,
+ char *config_path, struct grub_install_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;
+ size_t prefix_size = 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 = 0;
+ grub_size_t reloc_size = 0, align;
+ size_t decompress_size = 0;
+
+ if (comp == GRUB_COMPRESSION_AUTO)
+ comp = image_target->default_compression;
+
+ if (image_target->id == IMAGE_I386_PC
+ || image_target->id == IMAGE_I386_PC_PXE)
+ comp = GRUB_COMPRESSION_LZMA;
+
+ 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);
+
+ {
+ size_t i;
+ for (i = 0; i < npubkeys; i++)
+ {
+ size_t curs;
+ curs = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[i]));
+ grub_util_info ("the size of public key %zd is 0x%llx",
+ i, (unsigned long long) curs);
+ total_module_size += curs + sizeof (struct grub_module_header);
+ }
+ }
+
+ 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%llx",
+ (unsigned long long) 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%llx",
+ (unsigned long long) config_size);
+ total_module_size += config_size + sizeof (struct grub_module_header);
+ }
+
+ if (prefix)
+ {
+ prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
+ total_module_size += prefix_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%llx",
+ (unsigned long long) 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->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);
+
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ memmove (kernel_img + total_module_size, kernel_img, kernel_size);
+
+ if (image_target->voidp_sizeof == 8)
+ {
+ /* Fill in the grub_module_info structure. */
+ struct grub_module_info64 *modinfo;
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ modinfo = (struct grub_module_info64 *) kernel_img;
+ else
+ 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);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ offset = sizeof (struct grub_module_info64);
+ else
+ offset = kernel_size + sizeof (struct grub_module_info64);
+ }
+ else
+ {
+ /* Fill in the grub_module_info structure. */
+ struct grub_module_info32 *modinfo;
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ modinfo = (struct grub_module_info32 *) kernel_img;
+ else
+ 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);
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ offset = sizeof (struct grub_module_info32);
+ else
+ 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;
+ }
+
+ {
+ size_t i;
+ for (i = 0; i < npubkeys; i++)
+ {
+ size_t curs;
+ struct grub_module_header *header;
+
+ curs = grub_util_get_image_size (pubkey_paths[i]);
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
+ header->size = grub_host_to_target32 (curs + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_util_load_image (pubkey_paths[i], kernel_img + offset);
+ offset += ALIGN_ADDR (curs);
+ }
+ }
+
+ 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 (prefix)
+ {
+ 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_PREFIX);
+ header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_memset (kernel_img + offset, 0, prefix_size);
+ grub_strcpy (kernel_img + offset, prefix);
+ offset += prefix_size;
+ }
+
+ grub_util_info ("kernel_img=%p, kernel_size=0x%llx", kernel_img,
+ (unsigned long long) kernel_size);
+ compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
+ &core_img, &core_size, comp);
+ free (kernel_img);
+
+ grub_util_info ("the core size is 0x%llx", (unsigned long long) 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->flags & PLATFORM_FLAGS_DECOMPRESSORS)
+ {
+ char *full_img;
+ size_t full_size;
+ char *decompress_path, *decompress_img;
+ const char *name;
+
+ switch (comp)
+ {
+ case GRUB_COMPRESSION_XZ:
+ name = "xz_decompress.img";
+ break;
+ case GRUB_COMPRESSION_LZMA:
+ name = "lzma_decompress.img";
+ break;
+ case GRUB_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);
+
+ if ((image_target->id == IMAGE_I386_PC
+ || image_target->id == IMAGE_I386_PC_PXE)
+ && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200)
+ grub_util_error ("%s", _("Decompressor is too big"));
+
+ if (image_target->decompressor_compressed_size != TARGET_NO_FIELD)
+ *((grub_uint32_t *) (decompress_img
+ + image_target->decompressor_compressed_size))
+ = grub_host_to_target32 (core_size);
+
+ if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
+ *((grub_uint32_t *) (decompress_img
+ + image_target->decompressor_uncompressed_size))
+ = grub_host_to_target32 (kernel_size + total_module_size);
+
+ if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
+ {
+ if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+ *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
+ = grub_host_to_target_addr (image_target->link_addr - total_module_size);
+ else
+ *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
+ = grub_host_to_target_addr (image_target->link_addr);
+ }
+ 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:
+ if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
+ || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
+ || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
+ grub_util_error (_("core image is too big (0x%x > 0x%x)"),
+ GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
+ 0x78000);
+ /* fallthrough */
+ case IMAGE_COREBOOT:
+ case IMAGE_QEMU:
+ if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
+ grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
+ (unsigned) kernel_size + (unsigned) bss_size
+ + GRUB_KERNEL_I386_PC_LINK_ADDR,
+ 0x68000);
+ break;
+ case IMAGE_LOONGSON_ELF:
+ case IMAGE_YEELOONG_FLASH:
+ case IMAGE_FULOONG2F_FLASH:
+ case IMAGE_EFI:
+ case IMAGE_MIPS_ARC:
+ case IMAGE_QEMU_MIPS_FLASH:
+ break;
+ case IMAGE_SPARC64_AOUT:
+ case IMAGE_SPARC64_RAW:
+ case IMAGE_SPARC64_CDCORE:
+ case IMAGE_I386_IEEE1275:
+ case IMAGE_PPC:
+ case IMAGE_UBOOT:
+ break;
+ }
+
+ switch (image_target->id)
+ {
+ case IMAGE_I386_PC:
+ case IMAGE_I386_PC_PXE:
+ {
+ unsigned num;
+ char *boot_path, *boot_img;
+ size_t boot_size;
+
+ num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+ if (image_target->id == IMAGE_I386_PC_PXE)
+ {
+ char *pxeboot_path, *pxeboot_img;
+ size_t pxeboot_size;
+ grub_uint32_t *ptr;
+
+ 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,
+ outname);
+ free (pxeboot_img);
+ free (pxeboot_path);
+
+ /* Remove Multiboot header to avoid confusing ipxe. */
+ for (ptr = (grub_uint32_t *) core_img;
+ ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++)
+ if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC)
+ && grub_target_to_host32 (ptr[0])
+ + grub_target_to_host32 (ptr[1])
+ + grub_target_to_host32 (ptr[2]) == 0)
+ {
+ *ptr = 0;
+ break;
+ }
+ }
+
+ 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, outname);
+ 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 = EFI32_HEADER_SIZE;
+ else
+ header_size = EFI64_HEADER_SIZE;
+
+ 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 ((char *) pe_img + header_size, core_img, core_size);
+ memcpy ((char *) 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);
+ c->machine = grub_host_to_target16 (image_target->pe_target);
+
+ 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_target64 (0x10000);
+ o->stack_commit_size = grub_host_to_target64 (0x10000);
+ o->heap_reserve_size = grub_host_to_target64 (0x10000);
+ o->heap_commit_size = grub_host_to_target64 (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;
+ grub_memset (aout_head, 0, sizeof (*aout_head));
+ 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 ((char *) 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 size must be %u bytes"),
+ GRUB_DISK_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, outname);
+ free (boot_img);
+ free (boot_path);
+ }
+ break;
+ case IMAGE_SPARC64_CDCORE:
+ break;
+ case IMAGE_YEELOONG_FLASH:
+ case IMAGE_FULOONG2F_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. */
+ const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
+ {
+ 0x5f, 0x67, 0x46, 0x57, 0x31, 0x30, 0xc5, 0x0a,
+ 0xe9, 0x98, 0x18, 0xc9, 0xf3, 0xca, 0x45, 0xa5,
+ 0x75, 0x64, 0x6b, 0xbb, 0x24, 0xcd, 0xb4, 0xbc,
+ 0xf2, 0x3e, 0x23, 0xf9, 0xc2, 0x6a, 0x8c, 0xde,
+ 0x3b, 0x94, 0x9c, 0xcc, 0xa5, 0xa7, 0x58, 0xb1,
+ 0xbe, 0x8b, 0x3d, 0x73, 0x98, 0x18, 0x7e, 0x68,
+ 0x5e, 0x5f, 0x23, 0x7d, 0x7a, 0xe8, 0x51, 0xf7,
+ 0x1a, 0xaf, 0x2f, 0x54, 0x11, 0x2e, 0x5c, 0x25
+ };
+ const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
+ {
+ 0x76, 0x9b, 0xad, 0x6e, 0xa2, 0x39, 0x47, 0x62,
+ 0x1f, 0xc9, 0x3a, 0x6d, 0x05, 0x5c, 0x43, 0x5c,
+ 0x29, 0x4a, 0x7e, 0x08, 0x2a, 0x31, 0x8f, 0x5d,
+ 0x02, 0x84, 0xa0, 0x85, 0xf2, 0xd1, 0xb9, 0x53,
+ 0xa2, 0xbc, 0xf2, 0xe1, 0x39, 0x1e, 0x51, 0xb5,
+ 0xaf, 0xec, 0x9e, 0xf2, 0xf1, 0xf3, 0x0a, 0x2f,
+ 0xe6, 0xf1, 0x08, 0x89, 0xbe, 0xbc, 0x73, 0xab,
+ 0x46, 0x50, 0xd6, 0x21, 0xce, 0x8e, 0x24, 0xa7
+ };
+ const grub_uint8_t *fwstart_good_hash;
+
+ if (image_target->id == IMAGE_FULOONG2F_FLASH)
+ {
+ fwstart_good_hash = fuloong2f_fwstart_good_hash;
+ boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
+ }
+ else
+ {
+ fwstart_good_hash = yeeloong_fwstart_good_hash;
+ 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)
+ /* TRANSLATORS: fwstart.img may still be good, just it wasn't checked. */
+ grub_util_warn ("%s",
+ _("fwstart.img doesn't match the known good version. "
+ "proceed at your own risk"));
+
+ if (core_size + boot_size > 512 * 1024)
+ grub_util_error ("%s", _("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_QEMU_MIPS_FLASH:
+ {
+ char *rom_img;
+ size_t rom_size;
+
+ if (core_size > 512 * 1024)
+ grub_util_error ("%s", _("firmware image is too big"));
+ rom_size = 512 * 1024;
+
+ rom_img = xmalloc (rom_size);
+ memset (rom_img, 0, rom_size);
+
+ memcpy (rom_img, core_img, core_size);
+
+ memset (rom_img + core_size, 0,
+ rom_size - core_size);
+
+ free (core_img);
+ core_img = rom_img;
+ core_size = rom_size;
+ }
+ break;
+
+ case IMAGE_UBOOT:
+ {
+ struct grub_uboot_image_header *hdr;
+ GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize);
+
+ hdr = xmalloc (core_size + sizeof (struct grub_uboot_image_header));
+ memcpy (hdr + 1, core_img, core_size);
+
+ memset (hdr, 0, sizeof (*hdr));
+ hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
+ hdr->ih_time = grub_cpu_to_be32 (time (0));
+ hdr->ih_size = grub_cpu_to_be32 (core_size);
+ hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
+ hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
+ hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
+ hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
+ hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
+ hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
+
+ GRUB_MD_CRC32->init(crc32_context);
+ GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size);
+ GRUB_MD_CRC32->final(crc32_context);
+ hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
+
+ GRUB_MD_CRC32->init(crc32_context);
+ GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr));
+ GRUB_MD_CRC32->final(crc32_context);
+ hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
+
+ free (core_img);
+ core_img = (char *) hdr;
+ core_size += sizeof (struct grub_uboot_image_header);
+ }
+ break;
+
+ case IMAGE_MIPS_ARC:
+ {
+ char *ecoff_img;
+ struct ecoff_header {
+ grub_uint16_t magic;
+ grub_uint16_t nsec;
+ grub_uint32_t time;
+ grub_uint32_t syms;
+ grub_uint32_t nsyms;
+ grub_uint16_t opt;
+ grub_uint16_t flags;
+ grub_uint16_t magic2;
+ grub_uint16_t version;
+ grub_uint32_t textsize;
+ grub_uint32_t datasize;
+ grub_uint32_t bsssize;
+ grub_uint32_t entry;
+ grub_uint32_t text_start;
+ grub_uint32_t data_start;
+ grub_uint32_t bss_start;
+ grub_uint32_t gprmask;
+ grub_uint32_t cprmask[4];
+ grub_uint32_t gp_value;
+ };
+ struct ecoff_section
+ {
+ char name[8];
+ grub_uint32_t paddr;
+ grub_uint32_t vaddr;
+ grub_uint32_t size;
+ grub_uint32_t file_offset;
+ grub_uint32_t reloc;
+ grub_uint32_t gp;
+ grub_uint16_t nreloc;
+ grub_uint16_t ngp;
+ grub_uint32_t flags;
+ };
+ struct ecoff_header *head;
+ struct ecoff_section *section;
+ grub_uint32_t target_addr;
+ size_t program_size;
+
+ program_size = ALIGN_ADDR (core_size);
+ if (comp == GRUB_COMPRESSION_NONE)
+ target_addr = (image_target->link_addr - decompress_size);
+ else
+ target_addr = ALIGN_UP (image_target->link_addr
+ + kernel_size + total_module_size, 32);
+
+ ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
+ grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
+ head = (void *) ecoff_img;
+ section = (void *) (head + 1);
+ head->magic = image_target->bigendian ? grub_host_to_target16 (0x160)
+ : grub_host_to_target16 (0x166);
+ head->nsec = grub_host_to_target16 (1);
+ head->time = grub_host_to_target32 (0);
+ head->opt = grub_host_to_target16 (0x38);
+ head->flags = image_target->bigendian
+ ? grub_host_to_target16 (0x207)
+ : grub_host_to_target16 (0x103);
+ head->magic2 = grub_host_to_target16 (0x107);
+ head->textsize = grub_host_to_target32 (program_size);
+ head->entry = grub_host_to_target32 (target_addr);
+ head->text_start = grub_host_to_target32 (target_addr);
+ head->data_start = grub_host_to_target32 (target_addr + program_size);
+ grub_memcpy (section->name, ".text", sizeof (".text") - 1);
+ section->vaddr = grub_host_to_target32 (target_addr);
+ section->size = grub_host_to_target32 (program_size);
+ section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
+ if (!image_target->bigendian)
+ {
+ section->paddr = grub_host_to_target32 (0xaa60);
+ section->flags = grub_host_to_target32 (0x20);
+ }
+ memcpy (section + 1, core_img, core_size);
+ free (core_img);
+ core_img = ecoff_img;
+ core_size = program_size + sizeof (*head) + sizeof (*section);
+ }
+ break;
+ case IMAGE_LOONGSON_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_LOONGSON_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_LOONGSON_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_LOONGSON_ELF)
+ {
+ if (comp == GRUB_COMPRESSION_NONE)
+ target_addr = (image_target->link_addr - decompress_size);
+ else
+ 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_LOONGSON_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_LOONGSON_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);
+
+ if (image_target->id == IMAGE_COREBOOT)
+ target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
+ else
+ 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_ptr = (struct grub_ieee1275_note *)
+ (elf_img + program_size + header_size);
+
+ grub_util_info ("adding CHRP NOTE segment");
+
+ note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
+ note_ptr->header.descsz = grub_host_to_target32 (note_size);
+ note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
+ strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME);
+ note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
+ note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
+ note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
+ note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
+ note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
+ note_ptr->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, outname);
+ free (core_img);
+ free (kernel_path);
+
+ while (path_list)
+ {
+ next = path_list->next;
+ free ((void *) path_list->name);
+ free (path_list);
+ path_list = next;
+ }
+}
+
+\f
=== added file 'util/setup.c'
--- util/setup.c 1970-01-01 00:00:00 +0000
+++ util/setup.c 2013-10-04 02:06:06 +0000
@@ -0,0 +1,987 @@
+/* grub-setup.c - make GRUB usable */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 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/term.h>
+#include <grub/i18n.h>
+#include <grub/util/lvm.h>
+#ifdef GRUB_SETUP_SPARC64
+#include <grub/util/ofpath.h>
+#include <grub/sparc64/ieee1275/boot.h>
+#include <grub/sparc64/ieee1275/kernel.h>
+#else
+#include <grub/i386/pc/boot.h>
+#include <grub/i386/pc/kernel.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>
+#include <include/grub/crypto.h>
+#include <grub/util/install.h>
+
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <linux/fiemap.h>
+#endif
+
+#include <errno.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_CORE_FILE "core.img"
+#define DEFAULT_BOOT_FILE "boot.img"
+
+#ifdef GRUB_SETUP_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_SETUP_BIOS)
+#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 (grub_device_t root_dev,
+ char *boot_img, grub_uint64_t first_sector)
+{
+#ifdef GRUB_SETUP_BIOS
+ {
+ grub_uint8_t *boot_drive;
+ void *kernel_sector;
+ boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE);
+ kernel_sector = (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR);
+
+ /* FIXME: can this be skipped? */
+ *boot_drive = 0xFF;
+
+ grub_set_unaligned64 (kernel_sector, grub_cpu_to_le64 (first_sector));
+ }
+#endif
+#ifdef GRUB_SETUP_SPARC64
+ {
+ void *kernel_byte;
+ kernel_byte = (boot_img + GRUB_BOOT_AOUT_HEADER_SIZE
+ + GRUB_BOOT_MACHINE_KERNEL_BYTE);
+ grub_set_unaligned64 (kernel_byte,
+ grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS));
+ }
+#endif
+}
+
+#ifdef GRUB_SETUP_SPARC64
+#define BOOT_SECTOR 1
+#else
+#define BOOT_SECTOR 0
+#endif
+
+/* Helper for setup. */
+static void
+save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ grub_disk_addr_t *first_sector = data;
+ grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
+ sector, offset, length);
+
+ if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
+
+ *first_sector = sector;
+}
+
+struct blocklists
+{
+ struct grub_boot_blocklist *first_block, *block;
+#ifdef GRUB_SETUP_BIOS
+ grub_uint16_t current_segment;
+#endif
+ grub_uint16_t last_length;
+};
+
+/* Helper for setup. */
+static void
+save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
+ void *data)
+{
+ struct blocklists *bl = data;
+ struct grub_boot_blocklist *prev = bl->block + 1;
+
+ grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
+ sector, offset, length);
+
+ if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
+
+ if (bl->block != bl->first_block
+ && (grub_target_to_host64 (prev->start)
+ + grub_target_to_host16 (prev->len)) == sector)
+ {
+ grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
+ prev->len = grub_host_to_target16 (t);
+ }
+ else
+ {
+ bl->block->start = grub_host_to_target64 (sector);
+ bl->block->len = grub_host_to_target16 (1);
+#ifdef GRUB_SETUP_BIOS
+ bl->block->segment = grub_host_to_target16 (bl->current_segment);
+#endif
+
+ bl->block--;
+ if (bl->block->len)
+ grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
+ }
+
+ bl->last_length = length;
+#ifdef GRUB_SETUP_BIOS
+ bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+#endif
+}
+
+#ifdef GRUB_SETUP_BIOS
+/* Context for setup/identify_partmap. */
+struct identify_partmap_ctx
+{
+ grub_partition_map_t dest_partmap;
+ grub_partition_t container;
+ int multiple_partmaps;
+};
+
+/* Helper for setup.
+ Unlike root_dev, with dest_dev we're interested in the partition map even
+ if dest_dev itself is a whole disk. */
+static int
+identify_partmap (grub_disk_t disk __attribute__ ((unused)),
+ const grub_partition_t p, void *data)
+{
+ struct identify_partmap_ctx *ctx = data;
+
+ if (p->parent != ctx->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 (ctx->dest_partmap == NULL)
+ {
+ ctx->dest_partmap = p->partmap;
+ return 0;
+ }
+ if (ctx->dest_partmap == p->partmap)
+ return 0;
+ ctx->multiple_partmaps = 1;
+ return 1;
+}
+#endif
+
+#ifdef GRUB_SETUP_BIOS
+#define SETUP grub_bios_setup
+#elif GRUB_SETUP_SPARC64
+#define SETUP grub_sparc_setup
+#else
+#error "Shouldn't happen"
+#endif
+
+void
+SETUP (const char *dir,
+ const char *boot_file, const char *core_file,
+ const char *dest, int force,
+ int fs_probe, int allow_floppy)
+{
+ char *core_path, *core_path_dev, *core_path_dev_full;
+ char *boot_img, *core_img, *boot_path;
+ char *root = 0;
+ size_t boot_size, core_size;
+#ifdef GRUB_SETUP_BIOS
+ grub_uint16_t core_sectors;
+#endif
+ grub_device_t root_dev = 0, dest_dev, core_dev;
+ struct blocklists bl;
+ char *tmp_img;
+ grub_disk_addr_t first_sector = (grub_disk_addr_t)-1;
+ FILE *fp;
+
+ if (!core_file)
+ core_file = DEFAULT_CORE_FILE;
+ if (!boot_file)
+ boot_file = DEFAULT_BOOT_FILE;
+
+#ifdef GRUB_SETUP_BIOS
+ bl.current_segment =
+ GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
+#endif
+ bl.last_length = GRUB_DISK_SECTOR_SIZE;
+
+ /* 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);
+
+ core_path = grub_util_get_path (dir, core_file);
+ core_size = grub_util_get_image_size (core_path);
+#ifdef GRUB_SETUP_BIOS
+ core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS);
+#endif
+ if (core_size < GRUB_DISK_SECTOR_SIZE)
+ grub_util_error (_("the size of `%s' is too small"), core_path);
+#ifdef GRUB_SETUP_BIOS
+ 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. */
+ bl.first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*bl.block));
+ grub_util_info ("root is `%s', dest is `%s'", root, dest);
+
+ grub_util_info ("Opening dest");
+ dest_dev = grub_device_open (dest);
+ if (! dest_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ core_dev = dest_dev;
+
+ {
+ char **root_devices = grub_guess_root_devices (dir);
+ char **cur;
+ int found = 0;
+
+ for (cur = root_devices; *cur; cur++)
+ {
+ char *drive;
+ grub_device_t try_dev;
+
+ drive = grub_util_get_grub_dev (*cur);
+ if (!drive)
+ continue;
+ try_dev = grub_device_open (drive);
+ if (! try_dev)
+ continue;
+ if (!found && try_dev->disk->id == dest_dev->disk->id
+ && try_dev->disk->dev->id == dest_dev->disk->dev->id)
+ {
+ if (root_dev)
+ grub_device_close (root_dev);
+ free (root);
+ root_dev = try_dev;
+ root = drive;
+ found = 1;
+ continue;
+ }
+ if (!root_dev)
+ {
+ root_dev = try_dev;
+ root = drive;
+ continue;
+ }
+ grub_device_close (try_dev);
+ free (drive);
+ }
+ if (!root_dev)
+ {
+ grub_util_error ("guessing the root device failed, because of `%s'",
+ grub_errmsg);
+ }
+ grub_util_info ("guessed root_dev `%s' from "
+ "dir `%s'", root_dev->disk->name, dir);
+ }
+
+ 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_SETUP_BIOS
+ /* 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_SETUP_BIOS
+ {
+ grub_uint8_t *boot_drive_check;
+ boot_drive_check = (grub_uint8_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[0] = 0x90;
+ boot_drive_check[1] = 0x90;
+ }
+ }
+#endif
+
+#ifdef GRUB_SETUP_BIOS
+ {
+ struct identify_partmap_ctx ctx = {
+ .dest_partmap = NULL,
+ .container = dest_dev->disk->partition,
+ .multiple_partmaps = 0
+ };
+ int is_ldm;
+ grub_err_t err;
+ grub_disk_addr_t *sectors;
+ int i;
+ grub_fs_t fs;
+ unsigned int nsec, maxsec;
+
+ grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
+
+ if (ctx.container
+ && grub_strcmp (ctx.container->partmap->name, "msdos") == 0
+ && ctx.dest_partmap
+ && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
+ || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
+ {
+ grub_util_warn ("%s", _("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;
+
+ is_ldm = grub_util_is_ldm (dest_dev->disk);
+
+ if (fs_probe)
+ {
+ if (!fs && !ctx.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)
+ /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */
+ 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 (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
+ && strcmp (ctx.dest_partmap->name, "gpt") != 0
+ && strcmp (ctx.dest_partmap->name, "bsd") != 0
+ && strcmp (ctx.dest_partmap->name, "netbsd") != 0
+ && strcmp (ctx.dest_partmap->name, "openbsd") != 0
+ && strcmp (ctx.dest_partmap->name, "sunpc") != 0)
+ /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
+ 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, ctx.dest_partmap->name);
+ if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
+ && strcmp (ctx.dest_partmap->name, "gpt") != 0)
+ grub_util_error (_("%s appears to contain a %s partition map and "
+ "LDM which isn't known to be a safe combination."
+ " 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, ctx.dest_partmap->name);
+
+ }
+
+ /* Copy the partition table. */
+ if (ctx.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 (! ctx.dest_partmap && ! fs && !is_ldm)
+ {
+ grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea."));
+ goto unable_to_embed;
+ }
+ if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs))
+ {
+ grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet."));
+ goto unable_to_embed;
+ }
+
+ if (ctx.dest_partmap && !ctx.dest_partmap->embed)
+ {
+ grub_util_warn (_("Partition style `%s' doesn't support embedding"),
+ ctx.dest_partmap->name);
+ goto unable_to_embed;
+ }
+
+ if (fs && !fs->embed)
+ {
+ grub_util_warn (_("File system `%s' doesn't support embedding"),
+ fs->name);
+ goto unable_to_embed;
+ }
+
+ nsec = core_sectors;
+
+ maxsec = 2 * core_sectors;
+ if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
+ >> GRUB_DISK_SECTOR_BITS))
+ maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
+ >> GRUB_DISK_SECTOR_BITS);
+
+ if (is_ldm)
+ err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
+ GRUB_EMBED_PCBIOS, §ors);
+ else if (ctx.dest_partmap)
+ err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
+ GRUB_EMBED_PCBIOS, §ors);
+ else
+ err = fs->embed (dest_dev, &nsec, maxsec,
+ GRUB_EMBED_PCBIOS, §ors);
+ if (!err && nsec < core_sectors)
+ {
+ err = grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Your embedding area is unusually small. "
+ "core.img won't fit in it."));
+ }
+
+ if (err)
+ {
+ grub_util_warn ("%s", grub_errmsg);
+ grub_errno = GRUB_ERR_NONE;
+ goto unable_to_embed;
+ }
+
+ assert (nsec <= maxsec);
+
+ /* Clean out the blocklists. */
+ bl.block = bl.first_block;
+ while (bl.block->len)
+ {
+ grub_memset (bl.block, 0, sizeof (bl.block));
+
+ bl.block--;
+
+ if ((char *) bl.block <= core_img)
+ grub_util_error ("%s", _("no terminator in the core image"));
+ }
+
+ save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
+ 0, GRUB_DISK_SECTOR_SIZE, &first_sector);
+
+ bl.block = bl.first_block;
+ for (i = 1; i < nsec; i++)
+ save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
+ 0, GRUB_DISK_SECTOR_SIZE, &bl);
+
+ /* Make sure that the last blocklist is a terminator. */
+ if (bl.block == bl.first_block)
+ bl.block--;
+ bl.block->start = 0;
+ bl.block->len = 0;
+ bl.block->segment = 0;
+
+ write_rootdev (root_dev, boot_img, first_sector);
+
+ core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
+ bl.first_block = (struct grub_boot_blocklist *) (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ - sizeof (*bl.block));
+
+ grub_size_t no_rs_length;
+ grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE
+ + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY),
+ grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size));
+ no_rs_length = grub_target_to_host16
+ (grub_get_unaligned16 (core_img
+ + GRUB_DISK_SECTOR_SIZE
+ + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH));
+
+ if (no_rs_length == 0xffff)
+ grub_util_error ("%s", _("core.img version mismatch"));
+
+ void *tmp = xmalloc (core_size);
+ grub_memcpy (tmp, core_img, core_size);
+ grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE,
+ core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE,
+ nsec * GRUB_DISK_SECTOR_SIZE
+ - core_size);
+ assert (grub_memcmp (tmp, core_img, core_size) == 0);
+ free (tmp);
+
+ /* 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;
+ }
+
+unable_to_embed:
+#endif
+
+ if (dest_dev->disk->dev->id != root_dev->disk->dev->id)
+ grub_util_error ("%s", _("embedding is not possible, but this is required for "
+ "RAID and LVM install"));
+
+ {
+ grub_fs_t fs;
+ fs = grub_fs_probe (root_dev);
+ if (!fs)
+ grub_util_error (_("can't determine filesystem on %s"), root);
+
+ if (!fs->blocklist_install)
+ grub_util_error (_("filesystem `%s' doesn't support blocklists"),
+ fs->name);
+ }
+
+#ifdef GRUB_SETUP_BIOS
+ if (dest_dev->disk->id != root_dev->disk->id
+ || dest_dev->disk->dev->id != root_dev->disk->dev->id)
+ /* TRANSLATORS: cross-disk refers to /boot being on one disk
+ but MBR on another. */
+ grub_util_error ("%s", _("embedding is not possible, but this is required for "
+ "cross-disk install"));
+#else
+ core_dev = root_dev;
+#endif
+
+ grub_util_warn ("%s", _("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)
+ /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */
+ grub_util_error ("%s", _("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);
+
+#ifndef __linux__
+
+#define MAX_TRIES 5
+ {
+ int i;
+ for (i = 0; i < MAX_TRIES; i++)
+ {
+ grub_file_t file;
+
+ 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);
+ }
+
+#endif
+
+ /* Clean out the blocklists. */
+ bl.block = bl.first_block;
+ while (bl.block->len)
+ {
+ bl.block->start = 0;
+ bl.block->len = 0;
+#ifdef GRUB_SETUP_BIOS
+ bl.block->segment = 0;
+#endif
+
+ bl.block--;
+
+ if ((char *) bl.block <= core_img)
+ grub_util_error ("%s", _("no terminator in the core image"));
+ }
+
+ bl.block = bl.first_block;
+
+#ifdef __linux__
+ {
+ grub_partition_t container = root_dev->disk->partition;
+ grub_uint64_t container_start = grub_partition_get_start (container);
+ struct fiemap fie1;
+ int fd;
+
+ /* 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, "rb");
+ if (! fp)
+ grub_util_error (_("cannot open `%s': %s"), core_path,
+ strerror (errno));
+ fd = fileno (fp);
+
+ grub_memset (&fie1, 0, sizeof (fie1));
+ fie1.fm_length = core_size;
+ fie1.fm_flags = FIEMAP_FLAG_SYNC;
+
+ if (ioctl (fd, FS_IOC_FIEMAP, &fie1) < 0)
+ {
+ int nblocks, i, j;
+ int bsize;
+ int mul;
+
+ grub_util_info ("FIEMAP failed. Reverting to FIBMAP");
+
+ if (ioctl (fd, FIGETBSZ, &bsize) < 0)
+ grub_util_error (_("can't retrieve blocklists: %s"),
+ strerror (errno));
+ if (bsize & (GRUB_DISK_SECTOR_SIZE - 1))
+ grub_util_error ("%s", _("blocksize is not divisible by 512"));
+ mul = bsize >> GRUB_DISK_SECTOR_BITS;
+ nblocks = (core_size + bsize - 1) / bsize;
+ if (mul == 0 || nblocks == 0)
+ grub_util_error ("%s", _("can't retrieve blocklists"));
+ for (i = 0; i < nblocks; i++)
+ {
+ unsigned blk = i;
+ if (ioctl (fd, FIBMAP, &blk) < 0)
+ grub_util_error (_("can't retrieve blocklists: %s"),
+ strerror (errno));
+
+ for (j = 0; j < mul; j++)
+ {
+ int rest = core_size - ((i * mul + j) << GRUB_DISK_SECTOR_BITS);
+ if (rest <= 0)
+ break;
+ if (rest > GRUB_DISK_SECTOR_SIZE)
+ rest = GRUB_DISK_SECTOR_SIZE;
+ if (i == 0 && j == 0)
+ save_first_sector (((grub_uint64_t) blk) * mul
+ + container_start,
+ 0, rest, &first_sector);
+ else
+ save_blocklists (((grub_uint64_t) blk) * mul + j
+ + container_start,
+ 0, rest, &bl);
+ }
+ }
+ }
+ else
+ {
+ struct fiemap *fie2;
+ int i, j;
+ fie2 = xmalloc (sizeof (*fie2)
+ + fie1.fm_mapped_extents
+ * sizeof (fie1.fm_extents[1]));
+ memset (fie2, 0, sizeof (*fie2)
+ + fie1.fm_mapped_extents * sizeof (fie2->fm_extents[1]));
+ fie2->fm_length = core_size;
+ fie2->fm_flags = FIEMAP_FLAG_SYNC;
+ fie2->fm_extent_count = fie1.fm_mapped_extents;
+ if (ioctl (fd, FS_IOC_FIEMAP, fie2) < 0)
+ grub_util_error (_("can't retrieve blocklists: %s"),
+ strerror (errno));
+ for (i = 0; i < fie2->fm_mapped_extents; i++)
+ {
+ for (j = 0;
+ j < ((fie2->fm_extents[i].fe_length
+ + GRUB_DISK_SECTOR_SIZE - 1)
+ >> GRUB_DISK_SECTOR_BITS);
+ j++)
+ {
+ size_t len = (fie2->fm_extents[i].fe_length
+ - j * GRUB_DISK_SECTOR_SIZE);
+ if (len > GRUB_DISK_SECTOR_SIZE)
+ len = GRUB_DISK_SECTOR_SIZE;
+ if (first_sector == (grub_disk_addr_t)-1)
+ save_first_sector ((fie2->fm_extents[i].fe_physical
+ >> GRUB_DISK_SECTOR_BITS)
+ + j + container_start,
+ fie2->fm_extents[i].fe_physical
+ & (GRUB_DISK_SECTOR_SIZE - 1), len,
+ &first_sector);
+ else
+ save_blocklists ((fie2->fm_extents[i].fe_physical
+ >> GRUB_DISK_SECTOR_BITS)
+ + j + container_start,
+ fie2->fm_extents[i].fe_physical
+ & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl);
+
+
+ }
+ }
+ if (first_sector == (grub_disk_addr_t)-1)
+ grub_util_error ("%s", _("can't retrieve blocklists"));
+ }
+ fclose (fp);
+ }
+#else
+ {
+ grub_file_t file;
+ /* 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;
+ file->read_hook_data = &first_sector;
+ if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
+ != GRUB_DISK_SECTOR_SIZE)
+ grub_util_error ("%s", _("failed to read the first sector of the core image"));
+
+ bl.block = bl.first_block;
+ file->read_hook = save_blocklists;
+ file->read_hook_data = &bl;
+ 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 ("%s", _("failed to read the rest sectors of the core image"));
+ grub_file_close (file);
+ }
+#endif
+
+#ifdef GRUB_SETUP_SPARC64
+ {
+ char *boot_devpath;
+ boot_devpath = (char *) (boot_img
+ + GRUB_BOOT_AOUT_HEADER_SIZE
+ + GRUB_BOOT_MACHINE_BOOT_DEVPATH);
+ if (dest_dev->disk->id != root_dev->disk->id
+ || dest_dev->disk->dev->id != root_dev->disk->dev->id)
+ {
+ const char *dest_ofpath;
+ dest_ofpath
+ = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->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
+
+ free (core_path_dev);
+ free (tmp_img);
+
+ write_rootdev (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': %s"), core_path,
+ strerror (errno));
+
+ grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path);
+ fflush (fp);
+ fsync (fileno (fp));
+ fclose (fp);
+ grub_util_biosdisk_flush (root_dev->disk);
+
+ grub_disk_cache_invalidate_all ();
+
+ {
+ char *buf, *ptr = core_img;
+ size_t len = core_size;
+ grub_uint64_t blk;
+ grub_partition_t container = core_dev->disk->partition;
+ grub_err_t err;
+
+ core_dev->disk->partition = 0;
+
+ buf = xmalloc (core_size);
+ blk = first_sector;
+ err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf);
+ if (err)
+ grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
+ grub_errmsg);
+ if (grub_memcmp (buf, ptr, GRUB_DISK_SECTOR_SIZE) != 0)
+ grub_util_error ("%s", _("blocklists are invalid"));
+
+ ptr += GRUB_DISK_SECTOR_SIZE;
+ len -= GRUB_DISK_SECTOR_SIZE;
+
+ bl.block = bl.first_block;
+ while (bl.block->len)
+ {
+ size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS;
+ blk = grub_target_to_host64 (bl.block->start);
+
+ if (cur > len)
+ cur = len;
+
+ err = grub_disk_read (core_dev->disk, blk, 0, cur, buf);
+ if (err)
+ grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
+ grub_errmsg);
+
+ if (grub_memcmp (buf, ptr, cur) != 0)
+ grub_util_error ("%s", _("blocklists are invalid"));
+
+ ptr += cur;
+ len -= cur;
+ bl.block--;
+
+ if ((char *) bl.block <= core_img)
+ grub_util_error ("%s", _("no terminator in the core image"));
+ }
+ core_dev->disk->partition = container;
+ free (buf);
+ }
+
+#ifdef GRUB_SETUP_BIOS
+ finish:
+#endif
+
+ /* 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);
+}
=== added file 'util/setup_bios.c'
--- util/setup_bios.c 1970-01-01 00:00:00 +0000
+++ util/setup_bios.c 2013-10-04 00:39:55 +0000
@@ -0,0 +1,2 @@
+#define GRUB_SETUP_BIOS 1
+#include "setup.c"
=== added file 'util/setup_sparc.c'
--- util/setup_sparc.c 1970-01-01 00:00:00 +0000
+++ util/setup_sparc.c 2013-10-04 00:39:55 +0000
@@ -0,0 +1,2 @@
+#define GRUB_SETUP_SPARC64 1
+#include "setup.c"
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 291 bytes --]
next prev parent reply other threads:[~2013-10-06 14:55 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-26 13:08 [RFC] grub-install C rewrite Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-26 13:35 ` Lennart Sorensen
2013-09-26 13:59 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-26 14:44 ` Lennart Sorensen
2013-09-26 18:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-26 20:22 ` Lennart Sorensen
2013-09-26 20:29 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-26 20:51 ` Chris Murphy
2013-09-26 22:15 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-27 3:10 ` Andrey Borzenkov
2013-09-26 17:10 ` Seth Goldberg
2013-09-26 18:51 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-09-26 18:56 ` Darren J Moffat
2013-09-26 18:57 ` Seth Goldberg
2013-09-26 14:49 ` Andrey Borzenkov
2013-09-26 15:01 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-10-06 14:54 ` Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2013-10-06 15:56 ` Andrey Borzenkov
2013-10-06 18:05 ` Vladimir 'φ-coder/phcoder' Serbinenko
-- strict thread matches above, loose matches on Subject: below --
2013-09-26 17:52 Kalamatee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52517990.1020505@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.