grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
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, &sectors);
-    else if (ctx.dest_partmap)
-      err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
-				     GRUB_EMBED_PCBIOS, &sectors);
-    else
-      err = fs->embed (dest_dev, &nsec, maxsec,
-		       GRUB_EMBED_PCBIOS, &sectors);
-    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, &sectors);
+    else if (ctx.dest_partmap)
+      err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
+				     GRUB_EMBED_PCBIOS, &sectors);
+    else
+      err = fs->embed (dest_dev, &nsec, maxsec,
+		       GRUB_EMBED_PCBIOS, &sectors);
+    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 --]

             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).