From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [RFC] grub-install C rewrite
Date: Thu, 26 Sep 2013 15:08:54 +0200 [thread overview]
Message-ID: <524431E6.60807@gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1221 bytes --]
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.
I'd like to know the opinion of other people on possible switchover. If
switched then it'll have to be all grub-install, grub-mkrescue,
grub-mknetdir and grub-mkstandalone.
I'd like to hear from other people.
[-- 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: 293476 bytes --]
=== modified file 'Makefile.util.def'
--- Makefile.util.def 2013-09-23 12:09:56 +0000
+++ Makefile.util.def 2013-09-25 17:00:37 +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;
@@ -222,6 +223,7 @@
common = util/grub-mkpasswd-pbkdf2.c;
common = grub-core/kern/emu/argp_common.c;
+ common = util/random.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
@@ -307,6 +309,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;
@@ -315,7 +318,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 = {
@@ -323,6 +326,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;
@@ -332,7 +336,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 = {
@@ -463,14 +467,32 @@
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 = 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 'grub-core/disk/cryptodisk.c'
--- grub-core/disk/cryptodisk.c 2013-09-23 09:58:19 +0000
+++ grub-core/disk/cryptodisk.c 2013-09-25 02:49:50 +0000
@@ -746,31 +746,33 @@
}
void
-grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
+grub_util_cryptodisk_get_abstraction (grub_disk_t disk,
+ void (*cb) (const char *val))
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
- grub_printf ("cryptodisk %s ", dev->modname);
+ cb ("cryptodisk");
+ cb (dev->modname);
if (dev->cipher)
- grub_printf ("%s ", dev->cipher->cipher->modname);
+ cb (dev->cipher->cipher->modname);
if (dev->secondary_cipher)
- grub_printf ("%s ", dev->secondary_cipher->cipher->modname);
+ cb (dev->secondary_cipher->cipher->modname);
if (dev->essiv_cipher)
- grub_printf ("%s ", dev->essiv_cipher->cipher->modname);
+ cb (dev->essiv_cipher->cipher->modname);
if (dev->hash)
- grub_printf ("%s ", dev->hash->modname);
+ cb (dev->hash->modname);
if (dev->essiv_hash)
- grub_printf ("%s ", dev->essiv_hash->modname);
+ cb (dev->essiv_hash->modname);
if (dev->iv_hash)
- grub_printf ("%s ", dev->iv_hash->modname);
+ cb (dev->iv_hash->modname);
}
-void
-grub_util_cryptodisk_print_uuid (grub_disk_t disk)
+const char *
+grub_util_cryptodisk_get_uuid (grub_disk_t disk)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
- grub_printf ("%s ", dev->uuid);
+ return dev->uuid;
}
#endif
=== modified file 'grub-core/disk/diskfilter.c'
--- grub-core/disk/diskfilter.c 2013-09-20 18:37:03 +0000
+++ grub-core/disk/diskfilter.c 2013-09-25 01:49:58 +0000
@@ -353,7 +353,8 @@
}
void
-grub_diskfilter_print_partmap (grub_disk_t disk)
+grub_diskfilter_get_partmap (grub_disk_t disk,
+ void (*cb) (const char *pm))
{
struct grub_diskfilter_lv *lv = disk->data;
struct grub_diskfilter_pv *pv;
@@ -375,7 +376,7 @@
continue;
}
for (s = 0; pv->partmaps[s]; s++)
- grub_printf ("%s ", pv->partmaps[s]);
+ cb (pv->partmaps[s]);
}
}
=== modified file 'include/grub/crypto.h'
--- include/grub/crypto.h 2013-08-22 14:03:47 +0000
+++ include/grub/crypto.h 2013-09-25 11:33:34 +0000
@@ -406,6 +406,10 @@
#ifdef GRUB_UTIL
void grub_gcry_init_all (void);
void grub_gcry_fini_all (void);
+
+int
+grub_get_random (void *out, grub_size_t len);
+
#endif
#endif
=== modified file 'include/grub/cryptodisk.h'
--- include/grub/cryptodisk.h 2013-09-23 09:58:19 +0000
+++ include/grub/cryptodisk.h 2013-09-25 10:37:06 +0000
@@ -144,7 +144,9 @@
grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
grub_disk_t source, const char *cheat);
void
-grub_util_cryptodisk_print_abstraction (grub_disk_t disk);
+grub_util_cryptodisk_get_abstraction (grub_disk_t disk,
+ void (*cb) (const char *val));
+
char *
grub_util_get_geli_uuid (const char *dev);
#endif
=== modified file 'include/grub/diskfilter.h'
--- include/grub/diskfilter.h 2013-09-20 18:37:03 +0000
+++ include/grub/diskfilter.h 2013-09-25 10:35:02 +0000
@@ -201,7 +201,8 @@
grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
struct grub_diskfilter_vg **vg);
void
-grub_diskfilter_print_partmap (grub_disk_t disk);
+grub_diskfilter_get_partmap (grub_disk_t disk,
+ void (*cb) (const char *val));
#endif
#endif /* ! GRUB_RAID_H */
=== modified file 'include/grub/emu/getroot.h'
--- include/grub/emu/getroot.h 2013-09-23 10:06:00 +0000
+++ include/grub/emu/getroot.h 2013-09-25 10:46:19 +0000
@@ -79,6 +79,8 @@
#include <sys/types.h>
pid_t
grub_util_exec_pipe (char **argv, int *fd);
+void
+grub_util_exec (char **argv);
#endif
void
grub_util_pull_lvm_by_command (const char *os_dev);
=== modified file 'include/grub/emu/hostdisk.h'
--- include/grub/emu/hostdisk.h 2013-09-24 17:17:24 +0000
+++ include/grub/emu/hostdisk.h 2013-09-25 10:36:17 +0000
@@ -65,7 +65,8 @@
ssize_t grub_util_fd_write (grub_util_fd_t fd, const char *buf, size_t len);
grub_err_t
grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat);
-void grub_util_cryptodisk_print_uuid (grub_disk_t disk);
+const char *
+grub_util_cryptodisk_get_uuid (grub_disk_t disk);
char *
grub_util_get_ldm (grub_disk_t disk, grub_disk_addr_t start);
int
=== 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-09-25 18:25:47 +0000
@@ -0,0 +1,169 @@
+/*
+ * 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, \
+ 0, 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);
+
+#endif
=== modified file 'util/getroot_unix.c'
--- util/getroot_unix.c 2013-09-24 17:19:31 +0000
+++ util/getroot_unix.c 2013-09-25 09:50:46 +0000
@@ -143,6 +143,32 @@
return path;
}
+void
+grub_util_exec (char **argv)
+{
+ 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)
+ {
+ /* 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);
+ }
+ else
+ return;
+}
+
pid_t
grub_util_exec_pipe (char **argv, int *fd)
{
=== 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-09-25 21:51:40 +0000
@@ -0,0 +1,796 @@
+/*
+ * 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++ = '/';
+ first = 0;
+ p = stpcpy (p, l[i]);
+ while (p != r && *(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);
+ }
+ 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)
+ {
+ /* FIXME. */
+ 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);
+ }
+ 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_MODULES:
+ handle_install_list (&install_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 = 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_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)))
+ {
+ /* FIXME: use concat */
+ 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;
+}
+
+static int
+is_regular_file (const char *dir)
+{
+ /* FIXME */
+ (void) dir;
+ return 0;
+}
+
+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)
+ /* FIXME */
+ pkgdatadir = "@pkgdatadir@";
+
+ 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)
+ {
+ /* FIXME: use concat */
+ 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++)
+ {
+ /* FIXME: use concat */
+ 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 (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-09-25 21:59:57 +0000
@@ -0,0 +1,1469 @@
+/*
+ * 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 <string.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 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 = 0;
+ 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, N_("FILE"), OPTION_HIDDEN, 0, 2},
+ {"grub-mkrelpath", OPTION_MKRELPATH, N_("FILE"), OPTION_HIDDEN, 0, 2},
+ {"grub-mkdevicemap", OPTION_MKDEVICEMAP, N_("FILE"), OPTION_HIDDEN, 0, 2},
+ {"grub-probe", OPTION_PROBE, N_("FILE"), OPTION_HIDDEN, 0, 2},
+ {"grub-editenv", OPTION_EDITENV, N_("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)
+{
+ /* FIXME */
+ (void) dir;
+ return 0;
+}
+
+#ifdef __linux__
+static int
+is_not_empty_directory (const char *dir)
+{
+ /* FIXME */
+ (void) dir;
+ return 0;
+}
+
+static int
+is_64_kernel (void)
+{
+ /* FIXME */
+ return 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:
+ /* FIXME */
+ return xasprintf (text, "@grubdirname@", "$grubdir");
+ case OPTION_TARGET:
+ return xasprintf (text, get_default_platform ());
+ case ARGP_KEY_HELP_POST_DOC:
+ /* FIXME */
+ return xasprintf (text, program_name, "$grubdir");
+ 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;
+ }
+
+ 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 (void)
+{
+ /* FIXME */
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int is_efi = 0;
+ const char *efi_distributor = bootloader_id;
+ 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;
+
+ 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");
+
+ /*
+ FIXME:
+ grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,// *,/,g'`"
+
+ # Get GRUB_DISTRIBUTOR.
+ if test -f "${sysconfdir}/default/grub" ; then
+ . "${sysconfdir}/default/grub"
+ fi
+
+ bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr 'A-Z' 'a-z' | cut -d' ' -f1)"
+ if test -z "$bootloader_id"; then
+ bootloader_id=grub
+ fi
+ */
+
+ if (!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
+ && (platform == GRUB_INSTALL_PLATFORM_I386_PC
+ || platform == GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275))
+ 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)
+ {
+ /* FIXME */
+ if (rootdir)
+ bootdir = grub_install_concat (2, rootdir, "@bootdirname@");
+ else
+ bootdir = xstrdup ("/@bootdirname@");
+ }
+
+ {
+ char * t = grub_install_concat (2, bootdir, "@grubdirname@");
+ grub_install_mkdir_p (t);
+ grubdir = canonicalize_file_name (t);
+ free (t);
+ }
+ device_map = grub_install_concat (2, grubdir, "device.map");
+
+ if (recheck)
+ unlink (device_map);
+
+ /*
+ FIXME
+ # Device map file is optional
+ if test -f "$device_map"; then
+ # Make sure that there is no duplicated entry.
+ tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).* /\1/p' "$device_map" \
+ | sort | uniq -d | sed -n 1p`
+ if test -n "$tmp"; then
+ gettext_printf "The drive %s is defined multiple times in the device map %s\n" "$tmp" "$device_map" 1>&2
+ exit 1
+ fi
+ else
+ device_map=
+ fi
+ */
+ 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)
+ {
+ char ** device_names;
+ char *gd;
+ grub_fs_t fs;
+ grub_device_t dev = NULL;
+ 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"));
+ device_names = grub_guess_root_devices (efidir);
+ if (!device_names || !device_names[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ efidir);
+ install_device = device_names[0];
+
+ for (curdev = device_names; *curdev; curdev++)
+ grub_util_pull_device (*curdev);
+
+ gd = grub_util_get_grub_dev (device_names[0]);
+ if (!gd)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ device_names[0]);
+
+ dev = grub_device_open (gd);
+ if (! dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ fs = grub_fs_probe (dev);
+ if (! fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (grub_strcmp (fs->name, "fat") != 0)
+ {
+ printf (_("%s doesn't look like an EFI partition.\n"), efidir);
+ free (efidir);
+ efidir = 0;
+ }
+ free (device_names);
+ grub_device_close (dev);
+
+ if (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);
+ }
+ else
+ {
+ /* We don't know what's going on. Fall back to traditional
+ (non-specification-compliant) behaviour. */
+ efidir = xstrdup (grubdir);
+ efi_distributor = "";
+ efi_file = "grub.efi";
+ }
+ }
+
+ grub_install_copy_files (grub_install_source_directory,
+ grubdir, platform);
+
+
+ /* FIXME
+if ! test -f "${grubdir}"/grubenv; then
+ "$grub_editenv" "${grubdir}"/grubenv create
+fi
+*/
+
+ /* FIXME
+
+ # ... or if we can't figure out the abstraction module, for example if
+ # memberlist fails on an LVM volume group.
+ if abstractions="`"${grub_probe}" -t abstraction "$path"`" 2> /dev/null ; then
+ :
+ else
+ return 1
+ fi
+
+ if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+ return 0
+ fi
+
+ for abstraction in $abstractions; do
+ if [ "x$abstraction" = xcryptodisk ]; then
+ return 1
+ fi
+ done
+
+if ! is_path_readable_by_grub "${grubdir}"; then
+ gettext_printf "Path \`%s' is not readable by GRUB on boot. Installation is impossible. Aborting.\n" "${grubdir}" 1>&2
+ exit 1
+fi
+
+*/
+
+ 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 (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);
+ load_cfg = grub_install_concat (3, grubdir,
+ platname,
+ "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)
+ {
+ /*
+
+ grub_drive="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=drive --device`" || exit 1
+
+ # Strip partition number
+ grub_partition="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\3/'`"
+ grub_drive="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\1/'`"
+ */
+ if ((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");
+ }
+ /* FIXME
+ if [ x"$disk_module" != x ] && [ x"$disk_module" != xbiosdisk ]; then
+ hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`"
+ elif [ x"$grub_modinfo_platform" = xpc ]; then
+ hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=bios_hints --device`"
+ elif [ x"$grub_modinfo_platform" = xefi ]; then
+ hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=efi_hints --device`"
+ elif [ x"$grub_modinfo_platform" = xieee1275 ]; then
+ hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=ieee1275_hints --device`"
+ elif [ x"$grub_modinfo_platform" = xloongson ] || [ x"$grub_modinfo_platform" = xqemu ] || [ x"$grub_modinfo_platform" = xcoreboot ] || [ x"$grub_modinfo_platform" = xmultiboot ] || [ x"$grub_modinfo_platform" = xqemu-mips ]; then
+ hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`"
+ else
+ gettext "No hints available for your platform. Expect reduced performance." 1>&2
+ echo 1>&2
+ hints=
+ fi */
+ 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 (3, grubdir, platname,
+ 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 (3, grubdir, platname,
+ "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 *dir = grub_install_concat (2, grubdir, platname);
+ char *boot_img = grub_install_concat (2, grub_install_source_directory,
+ "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 " : "",
+ dir,
+ device_map,
+ install_device);
+
+ /* Now perform the installation. */
+ grub_bios_setup (dir, boot_img, NULL,
+ install_drive, force,
+ 1, allow_floppy);
+ break;
+ }
+ case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+ {
+ char *dir = grub_install_concat (2, grubdir, platname);
+ char *boot_img = grub_install_concat (2, grub_install_source_directory,
+ "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 " : "",
+ dir,
+ device_map,
+ install_drive);
+
+ /* Now perform the installation. */
+ grub_sparc_setup (dir, boot_img, NULL,
+ install_device, force,
+ 1, allow_floppy);
+ break;
+ }
+
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ /*
+ FIXME
+ # If a install device is defined, copy the core.elf to PReP partition.
+ if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "powerpc-ieee1275" ] && [ -n "${install_device}" ]; then
+
+ if [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t msdos_parttype)" != "41" ] \
+ && [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t gpt_parttype)" != "9e1a2d38-c612-4316-aa26-8b49521e5a8b" ]; then
+ gettext "The chosen partition is not a PReP partition." 1>&2
+ echo 1>&2
+ exit 1
+ fi
+
+ if [ "$(file -s -b -L "${install_device}" | awk '{ print $1 }')" = ELF ] || [ x$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t zero_check) = xtrue ]; then
+ dd if="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" of="${install_device}" status=noxfer || {
+ gettext "Failed to copy Grub to the PReP partition." 1>&2
+ echo 1>&2
+ exit 1
+ }
+ else
+ gettext "The PReP partition is not empty. If you are sure you want to use it, run dd to clear it:" 1>&2
+ echo 1>&2
+ echo " dd if=/dev/zero of=${install_device}"
+ exit 1
+ fi
+ fi
+
+ */
+ /* fallthrough. */
+ case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
+ if (update_nvram)
+ {
+ /* FIXME
+ ofpathname="`which ofpathname`"
+ nvsetenv="`which nvsetenv`"
+ set "$ofpathname" dummy
+ if test -f "$1"; then
+ :
+ else
+ # TRANSLATORS: This message is shown when required executable `%s'
+ # isn't found
+ gettext_printf "%s: Not found.\n" "$1" 1>&2
+ exit 1
+ fi
+ set "$nvsetenv" dummy
+ if test -f "$1"; then
+ :
+ else
+ # TRANSLATORS: This message is shown when required executable `%s'
+ # isn't found
+ gettext_printf "%s: Not found.\n" "$1" 1>&2
+ exit 1
+ fi
+ if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" != "powerpc-ieee1275" ] \
+ || [ -z "${install_device}" ]; then
+ # Get the Open Firmware device tree path translation.
+ dev="`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`"
+ partno="`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'`"
+ ofpath="`$ofpathname $dev`" || {
+ # TRANSLATORS: "device tree path" is the name of the device
+ # for IEEE1275
+ gettext_printf "Couldn't find IEEE1275 device tree path for %s.\nYou will have to set \`boot-device' variable manually.\n" "$dev" 1>&2
+ exit 1
+ }
+
+ # Point boot-device at the new grub install
+ boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" | sed 's,/,\\\\,g'`
+
+ else
+
+ dev="`echo "${install_device}" | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`"
+ boot_device="`$ofpathname "$dev"`" || {
+ # TRANSLATORS: "device tree path" is the name of the device
+ # for IEEE1275
+ gettext_printf "Couldn't find IEEE1275 device tree path for %s.\nYou will have to set \`boot-device' variable manually.\n" "$dev" 1>&2
+ exit 1
+ }
+ fi
+
+ "$nvsetenv" boot-device "$boot_device" || {
+ # TRANSLATORS: The %s will be replaced by an external program name.
+ gettext_printf "\`%s' failed.\n" "$nvsetenv" 1>&2
+ gettext "You will have to set \`boot-device' variable manually. At the IEEE1275 prompt, type:" 1>&2
+ echo 1>&2
+ echo " setenv boot-device $boot_device" 1>&2
+ exit 1
+ }
+*/
+ }
+ break;
+ case GRUB_INSTALL_PLATFORM_MIPS_ARC:
+ /* FIXME
+ dvhtool -d "${install_device}" --unix-to-vh "${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/core.${imgext}" grub
+ echo 1>&2
+ */
+ 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. */
+
+ /* FIXME
+ efibootmgr="`which efibootmgr`" || {
+ # TRANSLATORS: This message is shown when required executable `%s'
+ # isn't found
+ gettext_printf "%s: Not found.\n" "efibootmgr" 1>&2
+ exit 1
+ } */
+ 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
+ (void) efi_quiet;
+ /* FIXME
+
+ # Delete old entries from the same distributor.
+ for bootnum in `efibootmgr | grep '^Boot[0-9]' | \
+ fgrep -i " $efi_distributor" | cut -b5-8`; do
+ efibootmgr $efi_quiet -b "$bootnum" -B
+ done
+
+ # Add a new entry for the image we just created. efibootmgr needs to be
+ # given the disk device and partition number separately, so we have to
+ # fiddle about with grub-probe to get hold of this reasonably reliably.
+ # Use fresh device map text to avoid any problems with stale data, since
+ # all we need here is a one-to-one mapping.
+ efidir_drive="$("$grub_probe" --target=drive --device-map= "$efidir")"
+ efidir_disk="$("$grub_probe" --target=disk --device-map= "$efidir")"
+ if test -z "$efidir_drive" || test -z "$efidir_disk"; then
+ gettext_printf "Can't find GRUB drive for %s; unable to create EFI Boot Manager entry.\n" "$efidir" >&2
+ else
+ efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]* //; s/[^0-9].* //')"
+ efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \
+ -L "$bootloader_id" -l "\\EFI\\$efi_distributor\\$efi_file"
+ fi
+ */
+ }
+ 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-09-25 15:44:40 +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-09-25 12:42:12 +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-mkpasswd-pbkdf2.c'
--- util/grub-mkpasswd-pbkdf2.c 2013-09-22 01:28:32 +0000
+++ util/grub-mkpasswd-pbkdf2.c 2013-09-25 15:47:18 +0000
@@ -34,11 +34,6 @@
#include <argp.h>
-#if defined (_WIN32) || defined (__CYGWIN__)
-#include <windows.h>
-#include <wincrypt.h>
-#endif
-
#include "progname.h"
static struct argp_option options[] = {
@@ -109,48 +104,6 @@
*hex = 0;
}
-static int
-grub_get_random (void *out, grub_size_t len)
-{
-#if ! defined (__linux__) && ! defined (__FreeBSD__) && ! defined (__OpenBSD__) && !defined (__GNU__) && ! defined (_WIN32) && !defined(__CYGWIN__)
- /* TRANSLATORS: The generator might still be secure just GRUB isn't sure about it. */
- printf ("%s", _("WARNING: your random generator isn't known to be secure\n"));
-#warning "your random generator isn't known to be secure"
-#endif
-
-#if defined (_WIN32) || defined (__CYGWIN__)
- HCRYPTPROV hCryptProv;
- if (!CryptAcquireContext (&hCryptProv,
- NULL,
- MS_DEF_PROV,
- PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT))
- return 1;
- if (!CryptGenRandom (hCryptProv, len, out))
- {
- CryptReleaseContext (hCryptProv, 0);
- return 1;
- }
-
- CryptReleaseContext (hCryptProv, 0);
-
- return 0;
-#else
- FILE *f;
- size_t rd;
-
- f = fopen ("/dev/urandom", "rb");
- if (!f)
- return 1;
- rd = fread (out, 1, len, f);
- fclose (f);
-
- if (rd != len)
- return 1;
- return 0;
-#endif
-}
-
int
main (int argc, char *argv[])
{
=== modified file 'util/grub-probe.c'
--- util/grub-probe.c 2013-09-23 20:42:32 +0000
+++ util/grub-probe.c 2013-09-25 02:50:37 +0000
@@ -77,6 +77,12 @@
static unsigned int argument_is_device = 0;
static void
+do_print (const char *x)
+{
+ grub_printf ("%s ", x);
+}
+
+static void
probe_partmap (grub_disk_t disk)
{
grub_partition_t part;
@@ -91,7 +97,7 @@
printf ("%s ", part->partmap->name);
if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
- grub_diskfilter_print_partmap (disk);
+ grub_diskfilter_get_partmap (disk, do_print);
/* In case of LVM/RAID, check the member devices as well. */
if (disk->dev->memberlist)
@@ -125,7 +131,10 @@
list = tmp;
}
if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
- grub_util_cryptodisk_print_uuid (disk);
+ {
+ const char *uu = grub_util_cryptodisk_get_uuid (disk);
+ grub_printf ("%s ", uu);
+ }
}
static int
@@ -303,7 +312,7 @@
printf ("ldm ");
if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
- grub_util_cryptodisk_print_abstraction (disk);
+ grub_util_cryptodisk_get_abstraction (disk, do_print);
raid_level = probe_raid_level (disk);
if (raid_level >= 0)
=== modified file 'util/grub-setup.c'
--- util/grub-setup.c 2013-04-04 06:55:06 +0000
+++ util/grub-setup.c 2013-09-25 20:39:49 +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-09-25 15:45:06 +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/random.c'
--- util/random.c 1970-01-01 00:00:00 +0000
+++ util/random.c 2013-09-25 15:50:10 +0000
@@ -0,0 +1,5 @@
+#if defined (_WIN32) || defined (__CYGWIN__)
+#include "random_windows.c"
+#else
+#include "random_unix.c"
+#endif
=== added file 'util/random_unix.c'
--- util/random_unix.c 1970-01-01 00:00:00 +0000
+++ util/random_unix.c 2013-09-25 15:50:26 +0000
@@ -0,0 +1,53 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1992-1999,2001,2003,2004,2005,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/crypto.h>
+#include <grub/auth.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+grub_get_random (void *out, grub_size_t len)
+{
+#if ! defined (__linux__) && ! defined (__FreeBSD__) && ! defined (__OpenBSD__) && !defined (__GNU__) && ! defined (_WIN32) && !defined(__CYGWIN__)
+ /* TRANSLATORS: The generator might still be secure just GRUB isn't sure about it. */
+ printf ("%s", _("WARNING: your random generator isn't known to be secure\n"));
+#warning "your random generator isn't known to be secure"
+#endif
+ FILE *f;
+ size_t rd;
+
+ f = fopen ("/dev/urandom", "rb");
+ if (!f)
+ return 1;
+ rd = fread (out, 1, len, f);
+ fclose (f);
+
+ if (rd != len)
+ return 1;
+ return 0;
+}
=== added file 'util/random_windows.c'
--- util/random_windows.c 1970-01-01 00:00:00 +0000
+++ util/random_windows.c 2013-09-25 15:50:38 +0000
@@ -0,0 +1,55 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1992-1999,2001,2003,2004,2005,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/crypto.h>
+#include <grub/auth.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+int
+grub_get_random (void *out, grub_size_t len)
+{
+ HCRYPTPROV hCryptProv;
+ if (!CryptAcquireContext (&hCryptProv,
+ NULL,
+ MS_DEF_PROV,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return 1;
+ if (!CryptGenRandom (hCryptProv, len, out))
+ {
+ CryptReleaseContext (hCryptProv, 0);
+ return 1;
+ }
+
+ CryptReleaseContext (hCryptProv, 0);
+
+ return 0;
+}
=== added file 'util/setup.c'
--- util/setup.c 1970-01-01 00:00:00 +0000
+++ util/setup.c 2013-09-25 20:40:04 +0000
@@ -0,0 +1,983 @@
+/* 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"
+
+#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_path, 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;
+ 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;
+
+#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_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-09-25 13:01:02 +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-09-25 13:01:22 +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 reply other threads:[~2013-09-26 13:09 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-26 13:08 Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2013-09-26 13:35 ` [RFC] grub-install C rewrite 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
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=524431E6.60807@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).