=== 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 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 . + */ + +#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/]"), 1 }, \ + { "override-directory", GRUB_INSTALL_OPTIONS_DIRECTORY2, \ + N_("DIR"), OPTION_HIDDEN, \ + N_("use images and modules under DIR [default=%s/]"), 1 }, \ + { "grub-mkimage", GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE, \ + 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +char * +grub_install_help_filter (int key, const char *text, + void *input __attribute__ ((unused))) +{ + switch (key) + { + case GRUB_INSTALL_OPTIONS_INSTALL_THEMES: + return xasprintf(text, "starfield"); + case GRUB_INSTALL_OPTIONS_INSTALL_FONTS: + return xasprintf(text, "unicode"); + case GRUB_INSTALL_OPTIONS_DIRECTORY: + case GRUB_INSTALL_OPTIONS_DIRECTORY2: + return xasprintf(text, GRUB_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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "argp.h" + +#include "progname.h" + +static char *target; +static int removable = 0; +static int recheck = 0; +static int update_nvram = 1; +static char *install_device = NULL; +static char *debug_image = NULL; +static char *rootdir = NULL; +static char *bootdir = NULL; +static int 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 #include #include +#include +#include #define _GNU_SOURCE 1 #include #include "progname.h" -#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) - -#ifdef HAVE_LIBLZMA -#include -#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 - -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; - } -} - 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 -#if defined (_WIN32) || defined (__CYGWIN__) -#include -#include -#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 #include #include -#ifdef GRUB_SETUP_SPARC64 -#include -#include -#include -#else -#include -#include -#endif #include #include @@ -53,6 +45,7 @@ #include #include #include +#include #ifdef __linux__ #include @@ -63,917 +56,6 @@ #define _GNU_SOURCE 1 #include -/* On SPARC this program fills in various fields inside of the 'boot' and 'core' - * image files. - * - * The 'boot' image needs to know the OBP path name of the root - * device. It also needs to know the initial block number of - * 'core' (which is 'diskboot' concatenated with 'kernel' and - * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the second block - * of a partition. - * - * The initial 'diskboot' block acts as a loader for the actual GRUB - * kernel. It contains the loading code and then a block list. - * - * The block list of 'core' starts at the end of the 'diskboot' image - * and works it's way backwards towards the end of the code of 'diskboot'. - * - * We patch up the images with the necessary values and write out the - * result. - */ - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#ifdef GRUB_SETUP_SPARC64 -#define grub_target_to_host16(x) grub_be_to_cpu16(x) -#define grub_target_to_host32(x) grub_be_to_cpu32(x) -#define grub_target_to_host64(x) grub_be_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_be16(x) -#define grub_host_to_target32(x) grub_cpu_to_be32(x) -#define grub_host_to_target64(x) grub_cpu_to_be64(x) -#elif defined (GRUB_SETUP_BIOS) -#define grub_target_to_host16(x) grub_le_to_cpu16(x) -#define grub_target_to_host32(x) grub_le_to_cpu32(x) -#define grub_target_to_host64(x) grub_le_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_le16(x) -#define grub_host_to_target32(x) grub_cpu_to_le32(x) -#define grub_host_to_target64(x) grub_cpu_to_le64(x) -#else -#error Complete this -#endif - -static void -write_rootdev (grub_device_t root_dev, - char *boot_img, grub_uint64_t first_sector) -{ -#ifdef GRUB_SETUP_BIOS - { - grub_uint8_t *boot_drive; - void *kernel_sector; - boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - grub_set_unaligned64 (kernel_sector, grub_cpu_to_le64 (first_sector)); - } -#endif -#ifdef GRUB_SETUP_SPARC64 - { - void *kernel_byte; - kernel_byte = (boot_img + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_KERNEL_BYTE); - grub_set_unaligned64 (kernel_byte, - grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS)); - } -#endif -} - -#ifdef GRUB_SETUP_SPARC64 -#define BOOT_SECTOR 1 -#else -#define BOOT_SECTOR 0 -#endif - -/* Helper for setup. */ -static void -save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length, - void *data) -{ - grub_disk_addr_t *first_sector = data; - grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>", - sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("%s", _("the first sector of the core file is not sector-aligned")); - - *first_sector = sector; -} - -struct blocklists -{ - struct grub_boot_blocklist *first_block, *block; -#ifdef GRUB_SETUP_BIOS - grub_uint16_t current_segment; -#endif - grub_uint16_t last_length; -}; - -/* Helper for setup. */ -static void -save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length, - void *data) -{ - struct blocklists *bl = data; - struct grub_boot_blocklist *prev = bl->block + 1; - - grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>", - sector, offset, length); - - if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("%s", _("non-sector-aligned data is found in the core file")); - - if (bl->block != bl->first_block - && (grub_target_to_host64 (prev->start) - + grub_target_to_host16 (prev->len)) == sector) - { - grub_uint16_t t = grub_target_to_host16 (prev->len) + 1; - prev->len = grub_host_to_target16 (t); - } - else - { - bl->block->start = grub_host_to_target64 (sector); - bl->block->len = grub_host_to_target16 (1); -#ifdef GRUB_SETUP_BIOS - bl->block->segment = grub_host_to_target16 (bl->current_segment); -#endif - - bl->block--; - if (bl->block->len) - grub_util_error ("%s", _("the sectors of the core file are too fragmented")); - } - - bl->last_length = length; -#ifdef GRUB_SETUP_BIOS - bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4; -#endif -} - -#ifdef GRUB_SETUP_BIOS -/* Context for setup/identify_partmap. */ -struct identify_partmap_ctx -{ - grub_partition_map_t dest_partmap; - grub_partition_t container; - int multiple_partmaps; -}; - -/* Helper for setup. - Unlike root_dev, with dest_dev we're interested in the partition map even - if dest_dev itself is a whole disk. */ -static int -identify_partmap (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p, void *data) -{ - struct identify_partmap_ctx *ctx = data; - - if (p->parent != ctx->container) - return 0; - /* NetBSD and OpenBSD subpartitions have metadata inside a partition, - so they are safe to ignore. - */ - if (grub_strcmp (p->partmap->name, "netbsd") == 0 - || grub_strcmp (p->partmap->name, "openbsd") == 0) - return 0; - if (ctx->dest_partmap == NULL) - { - ctx->dest_partmap = p->partmap; - return 0; - } - if (ctx->dest_partmap == p->partmap) - return 0; - ctx->multiple_partmaps = 1; - return 1; -} -#endif - -static void -setup (const char *dir, - const char *boot_file, const char *core_file, - const char *dest, int force, - int fs_probe, int allow_floppy) -{ - char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; - char *boot_img, *core_img; - char *root = 0; - size_t boot_size, core_size; -#ifdef GRUB_SETUP_BIOS - grub_uint16_t core_sectors; -#endif - grub_device_t root_dev = 0, dest_dev, core_dev; - struct blocklists bl; - char *tmp_img; - grub_disk_addr_t first_sector = (grub_disk_addr_t)-1; - FILE *fp; - -#ifdef GRUB_SETUP_BIOS - bl.current_segment = - GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); -#endif - bl.last_length = GRUB_DISK_SECTOR_SIZE; - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is not %u"), - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); -#ifdef GRUB_SETUP_BIOS - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); -#endif - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too small"), core_path); -#ifdef GRUB_SETUP_BIOS - if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too large"), core_path); -#endif - - core_img = grub_util_read_image (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - bl.first_block = (struct grub_boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*bl.block)); - grub_util_info ("root is `%s', dest is `%s'", root, dest); - - grub_util_info ("Opening dest"); - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - core_dev = dest_dev; - - { - char **root_devices = grub_guess_root_devices (dir); - char **cur; - int found = 0; - - for (cur = root_devices; *cur; cur++) - { - char *drive; - grub_device_t try_dev; - - drive = grub_util_get_grub_dev (*cur); - if (!drive) - continue; - try_dev = grub_device_open (drive); - if (! try_dev) - continue; - if (!found && try_dev->disk->id == dest_dev->disk->id - && try_dev->disk->dev->id == dest_dev->disk->dev->id) - { - if (root_dev) - grub_device_close (root_dev); - free (root); - root_dev = try_dev; - root = drive; - found = 1; - continue; - } - if (!root_dev) - { - root_dev = try_dev; - root = drive; - continue; - } - grub_device_close (try_dev); - free (drive); - } - if (!root_dev) - { - grub_util_error ("guessing the root device failed, because of `%s'", - grub_errmsg); - } - grub_util_info ("guessed root_dev `%s' from " - "dir `%s'", root_dev->disk->name, dir); - } - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - -#ifdef GRUB_SETUP_BIOS - /* Read the original sector from the disk. */ - tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); - if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", grub_errmsg); -#endif - -#ifdef GRUB_SETUP_BIOS - { - grub_uint8_t *boot_drive_check; - boot_drive_check = (grub_uint8_t *) (boot_img - + GRUB_BOOT_MACHINE_DRIVE_CHECK); - /* Copy the possible DOS BPB. */ - memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, - tmp_img + GRUB_BOOT_MACHINE_BPB_START, - GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); - - /* If DEST_DRIVE is a hard disk, enable the workaround, which is - for buggy BIOSes which don't pass boot drive correctly. Instead, - they pass 0x00 or 0x01 even when booted from 0x80. */ - if (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)) - { - /* Replace the jmp (2 bytes) with double nop's. */ - boot_drive_check[0] = 0x90; - boot_drive_check[1] = 0x90; - } - } -#endif - -#ifdef GRUB_SETUP_BIOS - { - struct identify_partmap_ctx ctx = { - .dest_partmap = NULL, - .container = dest_dev->disk->partition, - .multiple_partmaps = 0 - }; - int is_ldm; - grub_err_t err; - grub_disk_addr_t *sectors; - int i; - grub_fs_t fs; - unsigned int nsec, maxsec; - - grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx); - - if (ctx.container - && grub_strcmp (ctx.container->partmap->name, "msdos") == 0 - && ctx.dest_partmap - && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD - || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD)) - { - grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); - goto unable_to_embed; - } - - fs = grub_fs_probe (dest_dev); - if (!fs) - grub_errno = GRUB_ERR_NONE; - - is_ldm = grub_util_is_ldm (dest_dev->disk); - - if (fs_probe) - { - if (!fs && !ctx.dest_partmap) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); - if (fs && !fs->reserved_first_sector) - /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */ - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); - - if (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0 - && strcmp (ctx.dest_partmap->name, "gpt") != 0 - && strcmp (ctx.dest_partmap->name, "bsd") != 0 - && strcmp (ctx.dest_partmap->name, "netbsd") != 0 - && strcmp (ctx.dest_partmap->name, "openbsd") != 0 - && strcmp (ctx.dest_partmap->name, "sunpc") != 0) - /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */ - grub_util_error (_("%s appears to contain a %s partition map which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, ctx.dest_partmap->name); - if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0 - && strcmp (ctx.dest_partmap->name, "gpt") != 0) - grub_util_error (_("%s appears to contain a %s partition map and " - "LDM which isn't known to be a safe combination." - " Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data" - " is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), - dest_dev->disk->name, ctx.dest_partmap->name); - - } - - /* Copy the partition table. */ - if (ctx.dest_partmap || - (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk))) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - - free (tmp_img); - - if (! ctx.dest_partmap && ! fs && !is_ldm) - { - grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); - goto unable_to_embed; - } - if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs)) - { - grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); - goto unable_to_embed; - } - - if (ctx.dest_partmap && !ctx.dest_partmap->embed) - { - grub_util_warn (_("Partition style `%s' doesn't support embedding"), - ctx.dest_partmap->name); - goto unable_to_embed; - } - - if (fs && !fs->embed) - { - grub_util_warn (_("File system `%s' doesn't support embedding"), - fs->name); - goto unable_to_embed; - } - - nsec = core_sectors; - - maxsec = 2 * core_sectors; - if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) - >> GRUB_DISK_SECTOR_BITS)) - maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) - >> GRUB_DISK_SECTOR_BITS); - - if (is_ldm) - err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec, - GRUB_EMBED_PCBIOS, §ors); - else if (ctx.dest_partmap) - err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec, - GRUB_EMBED_PCBIOS, §ors); - else - err = fs->embed (dest_dev, &nsec, maxsec, - GRUB_EMBED_PCBIOS, §ors); - if (!err && nsec < core_sectors) - { - err = grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("Your embedding area is unusually small. " - "core.img won't fit in it.")); - } - - if (err) - { - grub_util_warn ("%s", grub_errmsg); - grub_errno = GRUB_ERR_NONE; - goto unable_to_embed; - } - - assert (nsec <= maxsec); - - /* Clean out the blocklists. */ - bl.block = bl.first_block; - while (bl.block->len) - { - grub_memset (bl.block, 0, sizeof (bl.block)); - - bl.block--; - - if ((char *) bl.block <= core_img) - grub_util_error ("%s", _("no terminator in the core image")); - } - - save_first_sector (sectors[0] + grub_partition_get_start (ctx.container), - 0, GRUB_DISK_SECTOR_SIZE, &first_sector); - - bl.block = bl.first_block; - for (i = 1; i < nsec; i++) - save_blocklists (sectors[i] + grub_partition_get_start (ctx.container), - 0, GRUB_DISK_SECTOR_SIZE, &bl); - - /* Make sure that the last blocklist is a terminator. */ - if (bl.block == bl.first_block) - bl.block--; - bl.block->start = 0; - bl.block->len = 0; - bl.block->segment = 0; - - write_rootdev (root_dev, boot_img, first_sector); - - core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); - bl.first_block = (struct grub_boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*bl.block)); - - grub_size_t no_rs_length; - grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY), - grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size)); - no_rs_length = grub_target_to_host16 - (grub_get_unaligned16 (core_img - + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH)); - - if (no_rs_length == 0xffff) - grub_util_error ("%s", _("core.img version mismatch")); - - void *tmp = xmalloc (core_size); - grub_memcpy (tmp, core_img, core_size); - grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, - core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, - nsec * GRUB_DISK_SECTOR_SIZE - - core_size); - assert (grub_memcmp (tmp, core_img, core_size) == 0); - free (tmp); - - /* Write the core image onto the disk. */ - for (i = 0; i < nsec; i++) - grub_disk_write (dest_dev->disk, sectors[i], 0, - GRUB_DISK_SECTOR_SIZE, - core_img + i * GRUB_DISK_SECTOR_SIZE); - - grub_free (sectors); - - goto finish; - } - -unable_to_embed: -#endif - - if (dest_dev->disk->dev->id != root_dev->disk->dev->id) - grub_util_error ("%s", _("embedding is not possible, but this is required for " - "RAID and LVM install")); - - { - grub_fs_t fs; - fs = grub_fs_probe (root_dev); - if (!fs) - grub_util_error (_("can't determine filesystem on %s"), root); - - if (!fs->blocklist_install) - grub_util_error (_("filesystem `%s' doesn't support blocklists"), - fs->name); - } - -#ifdef GRUB_SETUP_BIOS - if (dest_dev->disk->id != root_dev->disk->id - || dest_dev->disk->dev->id != root_dev->disk->dev->id) - /* TRANSLATORS: cross-disk refers to /boot being on one disk - but MBR on another. */ - grub_util_error ("%s", _("embedding is not possible, but this is required for " - "cross-disk install")); -#else - core_dev = root_dev; -#endif - - grub_util_warn ("%s", _("Embedding is not possible. GRUB can only be installed in this " - "setup by using blocklists. However, blocklists are UNRELIABLE and " - "their use is discouraged.")); - if (! force) - /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */ - grub_util_error ("%s", _("will not proceed with blocklists")); - - /* The core image must be put on a filesystem unfortunately. */ - grub_util_info ("will leave the core image on the filesystem"); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path_dev_full = grub_util_get_path (dir, core_file); - core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full); - free (core_path_dev_full); - - grub_util_biosdisk_flush (root_dev->disk); - -#ifndef __linux__ - -#define MAX_TRIES 5 - { - int i; - for (i = 0; i < MAX_TRIES; i++) - { - grub_file_t file; - - grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") - : _("attempting to read the core image `%s' from GRUB again"), - core_path_dev); - - grub_disk_cache_invalidate_all (); - - grub_file_filter_disable_compression (); - file = grub_file_open (core_path_dev); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - grub_util_biosdisk_flush (root_dev->disk); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error (_("cannot read `%s' correctly"), core_path_dev); - } - -#endif - - /* Clean out the blocklists. */ - bl.block = bl.first_block; - while (bl.block->len) - { - bl.block->start = 0; - bl.block->len = 0; -#ifdef GRUB_SETUP_BIOS - bl.block->segment = 0; -#endif - - bl.block--; - - if ((char *) bl.block <= core_img) - grub_util_error ("%s", _("no terminator in the core image")); - } - - bl.block = bl.first_block; - -#ifdef __linux__ - { - grub_partition_t container = root_dev->disk->partition; - grub_uint64_t container_start = grub_partition_get_start (container); - struct fiemap fie1; - int fd; - - /* Write the first two sectors of the core image onto the disk. */ - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "rb"); - if (! fp) - grub_util_error (_("cannot open `%s': %s"), core_path, - strerror (errno)); - fd = fileno (fp); - - grub_memset (&fie1, 0, sizeof (fie1)); - fie1.fm_length = core_size; - fie1.fm_flags = FIEMAP_FLAG_SYNC; - - if (ioctl (fd, FS_IOC_FIEMAP, &fie1) < 0) - { - int nblocks, i, j; - int bsize; - int mul; - - grub_util_info ("FIEMAP failed. Reverting to FIBMAP"); - - if (ioctl (fd, FIGETBSZ, &bsize) < 0) - grub_util_error (_("can't retrieve blocklists: %s"), - strerror (errno)); - if (bsize & (GRUB_DISK_SECTOR_SIZE - 1)) - grub_util_error ("%s", _("blocksize is not divisible by 512")); - mul = bsize >> GRUB_DISK_SECTOR_BITS; - nblocks = (core_size + bsize - 1) / bsize; - if (mul == 0 || nblocks == 0) - grub_util_error ("%s", _("can't retrieve blocklists")); - for (i = 0; i < nblocks; i++) - { - unsigned blk = i; - if (ioctl (fd, FIBMAP, &blk) < 0) - grub_util_error (_("can't retrieve blocklists: %s"), - strerror (errno)); - - for (j = 0; j < mul; j++) - { - int rest = core_size - ((i * mul + j) << GRUB_DISK_SECTOR_BITS); - if (rest <= 0) - break; - if (rest > GRUB_DISK_SECTOR_SIZE) - rest = GRUB_DISK_SECTOR_SIZE; - if (i == 0 && j == 0) - save_first_sector (((grub_uint64_t) blk) * mul - + container_start, - 0, rest, &first_sector); - else - save_blocklists (((grub_uint64_t) blk) * mul + j - + container_start, - 0, rest, &bl); - } - } - } - else - { - struct fiemap *fie2; - int i, j; - fie2 = xmalloc (sizeof (*fie2) - + fie1.fm_mapped_extents - * sizeof (fie1.fm_extents[1])); - memset (fie2, 0, sizeof (*fie2) - + fie1.fm_mapped_extents * sizeof (fie2->fm_extents[1])); - fie2->fm_length = core_size; - fie2->fm_flags = FIEMAP_FLAG_SYNC; - fie2->fm_extent_count = fie1.fm_mapped_extents; - if (ioctl (fd, FS_IOC_FIEMAP, fie2) < 0) - grub_util_error (_("can't retrieve blocklists: %s"), - strerror (errno)); - for (i = 0; i < fie2->fm_mapped_extents; i++) - { - for (j = 0; - j < ((fie2->fm_extents[i].fe_length - + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - j++) - { - size_t len = (fie2->fm_extents[i].fe_length - - j * GRUB_DISK_SECTOR_SIZE); - if (len > GRUB_DISK_SECTOR_SIZE) - len = GRUB_DISK_SECTOR_SIZE; - if (first_sector == (grub_disk_addr_t)-1) - save_first_sector ((fie2->fm_extents[i].fe_physical - >> GRUB_DISK_SECTOR_BITS) - + j + container_start, - fie2->fm_extents[i].fe_physical - & (GRUB_DISK_SECTOR_SIZE - 1), len, - &first_sector); - else - save_blocklists ((fie2->fm_extents[i].fe_physical - >> GRUB_DISK_SECTOR_BITS) - + j + container_start, - fie2->fm_extents[i].fe_physical - & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl); - - - } - } - if (first_sector == (grub_disk_addr_t)-1) - grub_util_error ("%s", _("can't retrieve blocklists")); - } - fclose (fp); - } -#else - { - grub_file_t file; - /* Now read the core image to determine where the sectors are. */ - grub_file_filter_disable_compression (); - file = grub_file_open (core_path_dev); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - file->read_hook_data = &first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("%s", _("failed to read the first sector of the core image")); - - bl.block = bl.first_block; - file->read_hook = save_blocklists; - file->read_hook_data = &bl; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("%s", _("failed to read the rest sectors of the core image")); - grub_file_close (file); - } -#endif - -#ifdef GRUB_SETUP_SPARC64 - { - char *boot_devpath; - boot_devpath = (char *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - if (dest_dev->disk->id != root_dev->disk->id - || dest_dev->disk->dev->id != root_dev->disk->dev->id) - { - const char *dest_ofpath; - dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->disk)); - grub_util_info ("dest_ofpath is `%s'", dest_ofpath); - strncpy (boot_devpath, dest_ofpath, - GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); - boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; - } - else - { - grub_util_info ("non cross-disk install"); - memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH); - } - grub_util_info ("boot device path %s", boot_devpath); - } -#endif - - free (core_path_dev); - free (tmp_img); - - write_rootdev (root_dev, boot_img, first_sector); - - /* Write the first two sectors of the core image onto the disk. */ - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error (_("cannot open `%s': %s"), core_path, - strerror (errno)); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path); - fflush (fp); - fsync (fileno (fp)); - fclose (fp); - grub_util_biosdisk_flush (root_dev->disk); - - grub_disk_cache_invalidate_all (); - - { - char *buf, *ptr = core_img; - size_t len = core_size; - grub_uint64_t blk; - grub_partition_t container = core_dev->disk->partition; - grub_err_t err; - - core_dev->disk->partition = 0; - - buf = xmalloc (core_size); - blk = first_sector; - err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf); - if (err) - grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name, - grub_errmsg); - if (grub_memcmp (buf, ptr, GRUB_DISK_SECTOR_SIZE) != 0) - grub_util_error ("%s", _("blocklists are invalid")); - - ptr += GRUB_DISK_SECTOR_SIZE; - len -= GRUB_DISK_SECTOR_SIZE; - - bl.block = bl.first_block; - while (bl.block->len) - { - size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS; - blk = grub_target_to_host64 (bl.block->start); - - if (cur > len) - cur = len; - - err = grub_disk_read (core_dev->disk, blk, 0, cur, buf); - if (err) - grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name, - grub_errmsg); - - if (grub_memcmp (buf, ptr, cur) != 0) - grub_util_error ("%s", _("blocklists are invalid")); - - ptr += cur; - len -= cur; - bl.block--; - - if ((char *) bl.block <= core_img) - grub_util_error ("%s", _("no terminator in the core image")); - } - core_dev->disk->partition = container; - free (buf); - } - -#ifdef GRUB_SETUP_BIOS - finish: -#endif - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, - 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - grub_util_biosdisk_flush (root_dev->disk); - grub_util_biosdisk_flush (dest_dev->disk); - - free (core_path); - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - static struct argp_option options[] = { {"boot-image", 'b', N_("FILE"), 0, N_("use FILE as the boot image [default=%s]"), 0}, @@ -1002,10 +84,10 @@ switch (key) { case 'b': - return xasprintf (text, DEFAULT_BOOT_FILE); + return xasprintf (text, "boot.img"); case 'c': - return xasprintf (text, DEFAULT_CORE_FILE); + return xasprintf (text, "core.img"); case 'd': return xasprintf (text, DEFAULT_DIRECTORY); @@ -1199,12 +281,18 @@ grub_util_info ("Using `%s' as GRUB device", dest_dev); } + char *boot_path; + + boot_path = grub_util_get_path (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : "boot.img"); + /* Do the real work. */ - setup (arguments.dir ? : DEFAULT_DIRECTORY, - arguments.boot_file ? : DEFAULT_BOOT_FILE, - arguments.core_file ? : DEFAULT_CORE_FILE, - dest_dev, arguments.force, - arguments.fs_probe, arguments.allow_floppy); + GRUB_SETUP_FUNC (arguments.dir ? : DEFAULT_DIRECTORY, + boot_path, + arguments.core_file, + dest_dev, arguments.force, + arguments.fs_probe, arguments.allow_floppy); + free (boot_path); /* Free resources. */ grub_fini_all (); === added file 'util/mkimage.c' --- util/mkimage.c 1970-01-01 00:00:00 +0000 +++ util/mkimage.c 2013-09-25 15:45:06 +0000 @@ -0,0 +1,1861 @@ +/* grub-mkimage.c - make a bootable image */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "progname.h" + +#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) + +#ifdef HAVE_LIBLZMA +#include +#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 + +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; + } +} + + === 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 . + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 . + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_SETUP_SPARC64 +#include +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "progname.h" +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#include +#endif + +#include + +/* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * + * The 'boot' image needs to know the OBP path name of the root + * device. It also needs to know the initial block number of + * 'core' (which is 'diskboot' concatenated with 'kernel' and + * all the modules, this is created by grub-mkimage). This resulting + * 'boot' image is 512 bytes in size and is placed in the second block + * of a partition. + * + * The initial 'diskboot' block acts as a loader for the actual GRUB + * kernel. It contains the loading code and then a block list. + * + * The block list of 'core' starts at the end of the 'diskboot' image + * and works it's way backwards towards the end of the code of 'diskboot'. + * + * We patch up the images with the necessary values and write out the + * result. + */ + +#define DEFAULT_CORE_FILE "core.img" + +#ifdef GRUB_SETUP_SPARC64 +#define grub_target_to_host16(x) grub_be_to_cpu16(x) +#define grub_target_to_host32(x) grub_be_to_cpu32(x) +#define grub_target_to_host64(x) grub_be_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_be16(x) +#define grub_host_to_target32(x) grub_cpu_to_be32(x) +#define grub_host_to_target64(x) grub_cpu_to_be64(x) +#elif defined (GRUB_SETUP_BIOS) +#define grub_target_to_host16(x) grub_le_to_cpu16(x) +#define grub_target_to_host32(x) grub_le_to_cpu32(x) +#define grub_target_to_host64(x) grub_le_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_le16(x) +#define grub_host_to_target32(x) grub_cpu_to_le32(x) +#define grub_host_to_target64(x) grub_cpu_to_le64(x) +#else +#error Complete this +#endif + +static void +write_rootdev (grub_device_t root_dev, + char *boot_img, grub_uint64_t first_sector) +{ +#ifdef GRUB_SETUP_BIOS + { + grub_uint8_t *boot_drive; + void *kernel_sector; + boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); + kernel_sector = (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR); + + /* FIXME: can this be skipped? */ + *boot_drive = 0xFF; + + grub_set_unaligned64 (kernel_sector, grub_cpu_to_le64 (first_sector)); + } +#endif +#ifdef GRUB_SETUP_SPARC64 + { + void *kernel_byte; + kernel_byte = (boot_img + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_KERNEL_BYTE); + grub_set_unaligned64 (kernel_byte, + grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS)); + } +#endif +} + +#ifdef GRUB_SETUP_SPARC64 +#define BOOT_SECTOR 1 +#else +#define BOOT_SECTOR 0 +#endif + +/* Helper for setup. */ +static void +save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length, + void *data) +{ + grub_disk_addr_t *first_sector = data; + grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>", + sector, offset, length); + + if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) + grub_util_error ("%s", _("the first sector of the core file is not sector-aligned")); + + *first_sector = sector; +} + +struct blocklists +{ + struct grub_boot_blocklist *first_block, *block; +#ifdef GRUB_SETUP_BIOS + grub_uint16_t current_segment; +#endif + grub_uint16_t last_length; +}; + +/* Helper for setup. */ +static void +save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length, + void *data) +{ + struct blocklists *bl = data; + struct grub_boot_blocklist *prev = bl->block + 1; + + grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>", + sector, offset, length); + + if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE) + grub_util_error ("%s", _("non-sector-aligned data is found in the core file")); + + if (bl->block != bl->first_block + && (grub_target_to_host64 (prev->start) + + grub_target_to_host16 (prev->len)) == sector) + { + grub_uint16_t t = grub_target_to_host16 (prev->len) + 1; + prev->len = grub_host_to_target16 (t); + } + else + { + bl->block->start = grub_host_to_target64 (sector); + bl->block->len = grub_host_to_target16 (1); +#ifdef GRUB_SETUP_BIOS + bl->block->segment = grub_host_to_target16 (bl->current_segment); +#endif + + bl->block--; + if (bl->block->len) + grub_util_error ("%s", _("the sectors of the core file are too fragmented")); + } + + bl->last_length = length; +#ifdef GRUB_SETUP_BIOS + bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4; +#endif +} + +#ifdef GRUB_SETUP_BIOS +/* Context for setup/identify_partmap. */ +struct identify_partmap_ctx +{ + grub_partition_map_t dest_partmap; + grub_partition_t container; + int multiple_partmaps; +}; + +/* Helper for setup. + Unlike root_dev, with dest_dev we're interested in the partition map even + if dest_dev itself is a whole disk. */ +static int +identify_partmap (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p, void *data) +{ + struct identify_partmap_ctx *ctx = data; + + if (p->parent != ctx->container) + return 0; + /* NetBSD and OpenBSD subpartitions have metadata inside a partition, + so they are safe to ignore. + */ + if (grub_strcmp (p->partmap->name, "netbsd") == 0 + || grub_strcmp (p->partmap->name, "openbsd") == 0) + return 0; + if (ctx->dest_partmap == NULL) + { + ctx->dest_partmap = p->partmap; + return 0; + } + if (ctx->dest_partmap == p->partmap) + return 0; + ctx->multiple_partmaps = 1; + return 1; +} +#endif + +#ifdef GRUB_SETUP_BIOS +#define SETUP grub_bios_setup +#elif GRUB_SETUP_SPARC64 +#define SETUP grub_sparc_setup +#else +#error "Shouldn't happen" +#endif + +void +SETUP (const char *dir, + const char *boot_path, const char *core_file, + const char *dest, int force, + int fs_probe, int allow_floppy) +{ + char *core_path, *core_path_dev, *core_path_dev_full; + char *boot_img, *core_img; + char *root = 0; + size_t boot_size, core_size; +#ifdef GRUB_SETUP_BIOS + grub_uint16_t core_sectors; +#endif + grub_device_t root_dev = 0, dest_dev, core_dev; + struct blocklists bl; + char *tmp_img; + grub_disk_addr_t first_sector = (grub_disk_addr_t)-1; + FILE *fp; + + if (!core_file) + core_file = DEFAULT_CORE_FILE; + +#ifdef GRUB_SETUP_BIOS + bl.current_segment = + GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); +#endif + bl.last_length = GRUB_DISK_SECTOR_SIZE; + + /* Read the boot image by the OS service. */ + boot_size = grub_util_get_image_size (boot_path); + if (boot_size != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is not %u"), + boot_path, GRUB_DISK_SECTOR_SIZE); + boot_img = grub_util_read_image (boot_path); + + core_path = grub_util_get_path (dir, core_file); + core_size = grub_util_get_image_size (core_path); +#ifdef GRUB_SETUP_BIOS + core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS); +#endif + if (core_size < GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too small"), core_path); +#ifdef GRUB_SETUP_BIOS + if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too large"), core_path); +#endif + + core_img = grub_util_read_image (core_path); + + /* Have FIRST_BLOCK to point to the first blocklist. */ + bl.first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*bl.block)); + grub_util_info ("root is `%s', dest is `%s'", root, dest); + + grub_util_info ("Opening dest"); + dest_dev = grub_device_open (dest); + if (! dest_dev) + grub_util_error ("%s", grub_errmsg); + + core_dev = dest_dev; + + { + char **root_devices = grub_guess_root_devices (dir); + char **cur; + int found = 0; + + for (cur = root_devices; *cur; cur++) + { + char *drive; + grub_device_t try_dev; + + drive = grub_util_get_grub_dev (*cur); + if (!drive) + continue; + try_dev = grub_device_open (drive); + if (! try_dev) + continue; + if (!found && try_dev->disk->id == dest_dev->disk->id + && try_dev->disk->dev->id == dest_dev->disk->dev->id) + { + if (root_dev) + grub_device_close (root_dev); + free (root); + root_dev = try_dev; + root = drive; + found = 1; + continue; + } + if (!root_dev) + { + root_dev = try_dev; + root = drive; + continue; + } + grub_device_close (try_dev); + free (drive); + } + if (!root_dev) + { + grub_util_error ("guessing the root device failed, because of `%s'", + grub_errmsg); + } + grub_util_info ("guessed root_dev `%s' from " + "dir `%s'", root_dev->disk->name, dir); + } + + grub_util_info ("setting the root device to `%s'", root); + if (grub_env_set ("root", root) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + +#ifdef GRUB_SETUP_BIOS + /* Read the original sector from the disk. */ + tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); + if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) + grub_util_error ("%s", grub_errmsg); +#endif + +#ifdef GRUB_SETUP_BIOS + { + grub_uint8_t *boot_drive_check; + boot_drive_check = (grub_uint8_t *) (boot_img + + GRUB_BOOT_MACHINE_DRIVE_CHECK); + /* Copy the possible DOS BPB. */ + memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, + tmp_img + GRUB_BOOT_MACHINE_BPB_START, + GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); + + /* If DEST_DRIVE is a hard disk, enable the workaround, which is + for buggy BIOSes which don't pass boot drive correctly. Instead, + they pass 0x00 or 0x01 even when booted from 0x80. */ + if (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)) + { + /* Replace the jmp (2 bytes) with double nop's. */ + boot_drive_check[0] = 0x90; + boot_drive_check[1] = 0x90; + } + } +#endif + +#ifdef GRUB_SETUP_BIOS + { + struct identify_partmap_ctx ctx = { + .dest_partmap = NULL, + .container = dest_dev->disk->partition, + .multiple_partmaps = 0 + }; + int is_ldm; + grub_err_t err; + grub_disk_addr_t *sectors; + int i; + grub_fs_t fs; + unsigned int nsec, maxsec; + + grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx); + + if (ctx.container + && grub_strcmp (ctx.container->partmap->name, "msdos") == 0 + && ctx.dest_partmap + && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD + || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD)) + { + grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); + goto unable_to_embed; + } + + fs = grub_fs_probe (dest_dev); + if (!fs) + grub_errno = GRUB_ERR_NONE; + + is_ldm = grub_util_is_ldm (dest_dev->disk); + + if (fs_probe) + { + if (!fs && !ctx.dest_partmap) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + if (fs && !fs->reserved_first_sector) + /* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */ + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + + if (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0 + && strcmp (ctx.dest_partmap->name, "gpt") != 0 + && strcmp (ctx.dest_partmap->name, "bsd") != 0 + && strcmp (ctx.dest_partmap->name, "netbsd") != 0 + && strcmp (ctx.dest_partmap->name, "openbsd") != 0 + && strcmp (ctx.dest_partmap->name, "sunpc") != 0) + /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */ + grub_util_error (_("%s appears to contain a %s partition map which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, ctx.dest_partmap->name); + if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0 + && strcmp (ctx.dest_partmap->name, "gpt") != 0) + grub_util_error (_("%s appears to contain a %s partition map and " + "LDM which isn't known to be a safe combination." + " Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data" + " is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), + dest_dev->disk->name, ctx.dest_partmap->name); + + } + + /* Copy the partition table. */ + if (ctx.dest_partmap || + (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk))) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); + + free (tmp_img); + + if (! ctx.dest_partmap && ! fs && !is_ldm) + { + grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); + goto unable_to_embed; + } + if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs)) + { + grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); + goto unable_to_embed; + } + + if (ctx.dest_partmap && !ctx.dest_partmap->embed) + { + grub_util_warn (_("Partition style `%s' doesn't support embedding"), + ctx.dest_partmap->name); + goto unable_to_embed; + } + + if (fs && !fs->embed) + { + grub_util_warn (_("File system `%s' doesn't support embedding"), + fs->name); + goto unable_to_embed; + } + + nsec = core_sectors; + + maxsec = 2 * core_sectors; + if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS)) + maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS); + + if (is_ldm) + err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec, + GRUB_EMBED_PCBIOS, §ors); + else if (ctx.dest_partmap) + err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec, + GRUB_EMBED_PCBIOS, §ors); + else + err = fs->embed (dest_dev, &nsec, maxsec, + GRUB_EMBED_PCBIOS, §ors); + if (!err && nsec < core_sectors) + { + err = grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("Your embedding area is unusually small. " + "core.img won't fit in it.")); + } + + if (err) + { + grub_util_warn ("%s", grub_errmsg); + grub_errno = GRUB_ERR_NONE; + goto unable_to_embed; + } + + assert (nsec <= maxsec); + + /* Clean out the blocklists. */ + bl.block = bl.first_block; + while (bl.block->len) + { + grub_memset (bl.block, 0, sizeof (bl.block)); + + bl.block--; + + if ((char *) bl.block <= core_img) + grub_util_error ("%s", _("no terminator in the core image")); + } + + save_first_sector (sectors[0] + grub_partition_get_start (ctx.container), + 0, GRUB_DISK_SECTOR_SIZE, &first_sector); + + bl.block = bl.first_block; + for (i = 1; i < nsec; i++) + save_blocklists (sectors[i] + grub_partition_get_start (ctx.container), + 0, GRUB_DISK_SECTOR_SIZE, &bl); + + /* Make sure that the last blocklist is a terminator. */ + if (bl.block == bl.first_block) + bl.block--; + bl.block->start = 0; + bl.block->len = 0; + bl.block->segment = 0; + + write_rootdev (root_dev, boot_img, first_sector); + + core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); + bl.first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*bl.block)); + + grub_size_t no_rs_length; + grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY), + grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size)); + no_rs_length = grub_target_to_host16 + (grub_get_unaligned16 (core_img + + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH)); + + if (no_rs_length == 0xffff) + grub_util_error ("%s", _("core.img version mismatch")); + + void *tmp = xmalloc (core_size); + grub_memcpy (tmp, core_img, core_size); + grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, + core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, + nsec * GRUB_DISK_SECTOR_SIZE + - core_size); + assert (grub_memcmp (tmp, core_img, core_size) == 0); + free (tmp); + + /* Write the core image onto the disk. */ + for (i = 0; i < nsec; i++) + grub_disk_write (dest_dev->disk, sectors[i], 0, + GRUB_DISK_SECTOR_SIZE, + core_img + i * GRUB_DISK_SECTOR_SIZE); + + grub_free (sectors); + + goto finish; + } + +unable_to_embed: +#endif + + if (dest_dev->disk->dev->id != root_dev->disk->dev->id) + grub_util_error ("%s", _("embedding is not possible, but this is required for " + "RAID and LVM install")); + + { + grub_fs_t fs; + fs = grub_fs_probe (root_dev); + if (!fs) + grub_util_error (_("can't determine filesystem on %s"), root); + + if (!fs->blocklist_install) + grub_util_error (_("filesystem `%s' doesn't support blocklists"), + fs->name); + } + +#ifdef GRUB_SETUP_BIOS + if (dest_dev->disk->id != root_dev->disk->id + || dest_dev->disk->dev->id != root_dev->disk->dev->id) + /* TRANSLATORS: cross-disk refers to /boot being on one disk + but MBR on another. */ + grub_util_error ("%s", _("embedding is not possible, but this is required for " + "cross-disk install")); +#else + core_dev = root_dev; +#endif + + grub_util_warn ("%s", _("Embedding is not possible. GRUB can only be installed in this " + "setup by using blocklists. However, blocklists are UNRELIABLE and " + "their use is discouraged.")); + if (! force) + /* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */ + grub_util_error ("%s", _("will not proceed with blocklists")); + + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + + /* Make sure that GRUB reads the identical image as the OS. */ + tmp_img = xmalloc (core_size); + core_path_dev_full = grub_util_get_path (dir, core_file); + core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full); + free (core_path_dev_full); + + grub_util_biosdisk_flush (root_dev->disk); + +#ifndef __linux__ + +#define MAX_TRIES 5 + { + int i; + for (i = 0; i < MAX_TRIES; i++) + { + grub_file_t file; + + grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") + : _("attempting to read the core image `%s' from GRUB again"), + core_path_dev); + + grub_disk_cache_invalidate_all (); + + grub_file_filter_disable_compression (); + file = grub_file_open (core_path_dev); + if (file) + { + if (grub_file_size (file) != core_size) + grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", + (int) grub_file_size (file), (int) core_size); + else if (grub_file_read (file, tmp_img, core_size) + != (grub_ssize_t) core_size) + grub_util_info ("succeeded in opening the core image but cannot read %d bytes", + (int) core_size); + else if (memcmp (core_img, tmp_img, core_size) != 0) + { +#if 0 + FILE *dump; + FILE *dump2; + + dump = fopen ("dump.img", "wb"); + if (dump) + { + fwrite (tmp_img, 1, core_size, dump); + fclose (dump); + } + + dump2 = fopen ("dump2.img", "wb"); + if (dump2) + { + fwrite (core_img, 1, core_size, dump2); + fclose (dump2); + } + +#endif + grub_util_info ("succeeded in opening the core image but the data is different"); + } + else + { + grub_file_close (file); + break; + } + + grub_file_close (file); + } + else + grub_util_info ("couldn't open the core image"); + + if (grub_errno) + grub_util_info ("error message = %s", grub_errmsg); + + grub_errno = GRUB_ERR_NONE; + grub_util_biosdisk_flush (root_dev->disk); + sleep (1); + } + + if (i == MAX_TRIES) + grub_util_error (_("cannot read `%s' correctly"), core_path_dev); + } + +#endif + + /* Clean out the blocklists. */ + bl.block = bl.first_block; + while (bl.block->len) + { + bl.block->start = 0; + bl.block->len = 0; +#ifdef GRUB_SETUP_BIOS + bl.block->segment = 0; +#endif + + bl.block--; + + if ((char *) bl.block <= core_img) + grub_util_error ("%s", _("no terminator in the core image")); + } + + bl.block = bl.first_block; + +#ifdef __linux__ + { + grub_partition_t container = root_dev->disk->partition; + grub_uint64_t container_start = grub_partition_get_start (container); + struct fiemap fie1; + int fd; + + /* Write the first two sectors of the core image onto the disk. */ + grub_util_info ("opening the core image `%s'", core_path); + fp = fopen (core_path, "rb"); + if (! fp) + grub_util_error (_("cannot open `%s': %s"), core_path, + strerror (errno)); + fd = fileno (fp); + + grub_memset (&fie1, 0, sizeof (fie1)); + fie1.fm_length = core_size; + fie1.fm_flags = FIEMAP_FLAG_SYNC; + + if (ioctl (fd, FS_IOC_FIEMAP, &fie1) < 0) + { + int nblocks, i, j; + int bsize; + int mul; + + grub_util_info ("FIEMAP failed. Reverting to FIBMAP"); + + if (ioctl (fd, FIGETBSZ, &bsize) < 0) + grub_util_error (_("can't retrieve blocklists: %s"), + strerror (errno)); + if (bsize & (GRUB_DISK_SECTOR_SIZE - 1)) + grub_util_error ("%s", _("blocksize is not divisible by 512")); + mul = bsize >> GRUB_DISK_SECTOR_BITS; + nblocks = (core_size + bsize - 1) / bsize; + if (mul == 0 || nblocks == 0) + grub_util_error ("%s", _("can't retrieve blocklists")); + for (i = 0; i < nblocks; i++) + { + unsigned blk = i; + if (ioctl (fd, FIBMAP, &blk) < 0) + grub_util_error (_("can't retrieve blocklists: %s"), + strerror (errno)); + + for (j = 0; j < mul; j++) + { + int rest = core_size - ((i * mul + j) << GRUB_DISK_SECTOR_BITS); + if (rest <= 0) + break; + if (rest > GRUB_DISK_SECTOR_SIZE) + rest = GRUB_DISK_SECTOR_SIZE; + if (i == 0 && j == 0) + save_first_sector (((grub_uint64_t) blk) * mul + + container_start, + 0, rest, &first_sector); + else + save_blocklists (((grub_uint64_t) blk) * mul + j + + container_start, + 0, rest, &bl); + } + } + } + else + { + struct fiemap *fie2; + int i, j; + fie2 = xmalloc (sizeof (*fie2) + + fie1.fm_mapped_extents + * sizeof (fie1.fm_extents[1])); + memset (fie2, 0, sizeof (*fie2) + + fie1.fm_mapped_extents * sizeof (fie2->fm_extents[1])); + fie2->fm_length = core_size; + fie2->fm_flags = FIEMAP_FLAG_SYNC; + fie2->fm_extent_count = fie1.fm_mapped_extents; + if (ioctl (fd, FS_IOC_FIEMAP, fie2) < 0) + grub_util_error (_("can't retrieve blocklists: %s"), + strerror (errno)); + for (i = 0; i < fie2->fm_mapped_extents; i++) + { + for (j = 0; + j < ((fie2->fm_extents[i].fe_length + + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS); + j++) + { + size_t len = (fie2->fm_extents[i].fe_length + - j * GRUB_DISK_SECTOR_SIZE); + if (len > GRUB_DISK_SECTOR_SIZE) + len = GRUB_DISK_SECTOR_SIZE; + if (first_sector == (grub_disk_addr_t)-1) + save_first_sector ((fie2->fm_extents[i].fe_physical + >> GRUB_DISK_SECTOR_BITS) + + j + container_start, + fie2->fm_extents[i].fe_physical + & (GRUB_DISK_SECTOR_SIZE - 1), len, + &first_sector); + else + save_blocklists ((fie2->fm_extents[i].fe_physical + >> GRUB_DISK_SECTOR_BITS) + + j + container_start, + fie2->fm_extents[i].fe_physical + & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl); + + + } + } + if (first_sector == (grub_disk_addr_t)-1) + grub_util_error ("%s", _("can't retrieve blocklists")); + } + fclose (fp); + } +#else + { + grub_file_t file; + /* Now read the core image to determine where the sectors are. */ + grub_file_filter_disable_compression (); + file = grub_file_open (core_path_dev); + if (! file) + grub_util_error ("%s", grub_errmsg); + + file->read_hook = save_first_sector; + file->read_hook_data = &first_sector; + if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) + != GRUB_DISK_SECTOR_SIZE) + grub_util_error ("%s", _("failed to read the first sector of the core image")); + + bl.block = bl.first_block; + file->read_hook = save_blocklists; + file->read_hook_data = &bl; + if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) + != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) + grub_util_error ("%s", _("failed to read the rest sectors of the core image")); + grub_file_close (file); + } +#endif + +#ifdef GRUB_SETUP_SPARC64 + { + char *boot_devpath; + boot_devpath = (char *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_BOOT_DEVPATH); + if (dest_dev->disk->id != root_dev->disk->id + || dest_dev->disk->dev->id != root_dev->disk->dev->id) + { + const char *dest_ofpath; + dest_ofpath + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->disk)); + grub_util_info ("dest_ofpath is `%s'", dest_ofpath); + strncpy (boot_devpath, dest_ofpath, + GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); + boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; + } + else + { + grub_util_info ("non cross-disk install"); + memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH); + } + grub_util_info ("boot device path %s", boot_devpath); + } +#endif + + free (core_path_dev); + free (tmp_img); + + write_rootdev (root_dev, boot_img, first_sector); + + /* Write the first two sectors of the core image onto the disk. */ + grub_util_info ("opening the core image `%s'", core_path); + fp = fopen (core_path, "r+b"); + if (! fp) + grub_util_error (_("cannot open `%s': %s"), core_path, + strerror (errno)); + + grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path); + fflush (fp); + fsync (fileno (fp)); + fclose (fp); + grub_util_biosdisk_flush (root_dev->disk); + + grub_disk_cache_invalidate_all (); + + { + char *buf, *ptr = core_img; + size_t len = core_size; + grub_uint64_t blk; + grub_partition_t container = core_dev->disk->partition; + grub_err_t err; + + core_dev->disk->partition = 0; + + buf = xmalloc (core_size); + blk = first_sector; + err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf); + if (err) + grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name, + grub_errmsg); + if (grub_memcmp (buf, ptr, GRUB_DISK_SECTOR_SIZE) != 0) + grub_util_error ("%s", _("blocklists are invalid")); + + ptr += GRUB_DISK_SECTOR_SIZE; + len -= GRUB_DISK_SECTOR_SIZE; + + bl.block = bl.first_block; + while (bl.block->len) + { + size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS; + blk = grub_target_to_host64 (bl.block->start); + + if (cur > len) + cur = len; + + err = grub_disk_read (core_dev->disk, blk, 0, cur, buf); + if (err) + grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name, + grub_errmsg); + + if (grub_memcmp (buf, ptr, cur) != 0) + grub_util_error ("%s", _("blocklists are invalid")); + + ptr += cur; + len -= cur; + bl.block--; + + if ((char *) bl.block <= core_img) + grub_util_error ("%s", _("no terminator in the core image")); + } + core_dev->disk->partition = container; + free (buf); + } + +#ifdef GRUB_SETUP_BIOS + finish: +#endif + + /* Write the boot image onto the disk. */ + if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, + 0, GRUB_DISK_SECTOR_SIZE, boot_img)) + grub_util_error ("%s", grub_errmsg); + + grub_util_biosdisk_flush (root_dev->disk); + grub_util_biosdisk_flush (dest_dev->disk); + + free (core_path); + free (core_img); + free (boot_img); + grub_device_close (dest_dev); + grub_device_close (root_dev); +} === added file 'util/setup_bios.c' --- util/setup_bios.c 1970-01-01 00:00:00 +0000 +++ util/setup_bios.c 2013-09-25 13:01:02 +0000 @@ -0,0 +1,2 @@ +#define GRUB_SETUP_BIOS 1 +#include "setup.c" === added file 'util/setup_sparc.c' --- util/setup_sparc.c 1970-01-01 00:00:00 +0000 +++ util/setup_sparc.c 2013-09-25 13:01:22 +0000 @@ -0,0 +1,2 @@ +#define GRUB_SETUP_SPARC64 1 +#include "setup.c"