grub2/util/grub-mkrescue.c
Dimitri John Ledkov 8ddbdc3bc2 grub-install: Add backup and restore
Refactor clean_grub_dir() to create a backup of all the files, instead
of just irrevocably removing them as the first action. If available,
register atexit() handler to restore the backup if errors occur before
point of no return, or remove the backup if everything was successful.
If atexit() is not available, the backup remains on disk for manual
recovery.

Some platforms defined a point of no return, i.e. after modules & core
images were updated. Failures from any commands after that stage are
ignored, and backup is cleaned up. For example, on EFI platforms update
is not reverted when efibootmgr fails.

Extra care is taken to ensure atexit() handler is only invoked by the
parent process and not any children forks. Some older GRUB codebases
can invoke parent atexit() hooks from forks, which can mess up the
backup.

This allows safer upgrades of MBR & modules, such that
modules/images/fonts/translations are consistent with MBR in case of
errors. For example accidental grub-install /dev/non-existent-disk
currently clobbers and upgrades modules in /boot/grub, despite not
actually updating any MBR.

This patch only handles backup and restore of files copied to /boot/grub.
This patch does not perform backup (or restoration) of MBR itself or
blocklists. Thus when installing i386-pc platform, corruption may still
occur with MBR and blocklists which will not be attempted to be
automatically recovered.

Also add modinfo.sh and *.efi to the cleanup/backup/restore code path,
to ensure it is also cleaned, backed up and restored.

Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-06-01 17:20:20 +02:00

1000 lines
30 KiB
C

/*
* Make GRUB rescue image
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/util/install.h>
#include <grub/util/misc.h>
#include <grub/emu/exec.h>
#include <grub/emu/config.h>
#include <grub/emu/hostdisk.h>
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#include <argp.h>
#pragma GCC diagnostic error "-Wmissing-prototypes"
#pragma GCC diagnostic error "-Wmissing-declarations"
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <time.h>
static char *source_dirs[GRUB_INSTALL_PLATFORM_MAX];
static char *rom_directory;
static char *label_font;
static char *label_color;
static char *label_bgcolor;
static char *product_name;
static char *product_version;
static char *output_image;
static char *xorriso;
static char *boot_grub;
static int xorriso_argc;
static int xorriso_arg_alloc;
static char **xorriso_argv;
static char *iso_uuid;
static char *iso9660_dir;
static void
xorriso_push (const char *val)
{
if (xorriso_arg_alloc <= xorriso_argc + 1)
{
xorriso_arg_alloc = 2 * (4 + xorriso_argc);
xorriso_argv = xrealloc (xorriso_argv,
sizeof (xorriso_argv[0])
* xorriso_arg_alloc);
}
xorriso_argv[xorriso_argc++] = xstrdup (val);
}
static void
xorriso_link (const char *from, const char *to)
{
char *tof = grub_util_path_concat (2, iso9660_dir, to);
char *val = xasprintf ("%s=%s", from, tof);
xorriso_push (val);
free (val);
free (tof);
}
enum
{
OPTION_OUTPUT = 'o',
OPTION_ROM_DIRECTORY = 0x301,
OPTION_XORRISO,
OPTION_GLUE_EFI,
OPTION_RENDER_LABEL,
OPTION_LABEL_FONT,
OPTION_LABEL_COLOR,
OPTION_LABEL_BGCOLOR,
OPTION_PRODUCT_NAME,
OPTION_PRODUCT_VERSION,
OPTION_SPARC_BOOT,
OPTION_ARCS_BOOT
};
static struct argp_option options[] = {
GRUB_INSTALL_OPTIONS,
{"output", 'o', N_("FILE"),
0, N_("save output in FILE [required]"), 2},
{"rom-directory", OPTION_ROM_DIRECTORY, N_("DIR"),
0, N_("save ROM images in DIR [optional]"), 2},
{"xorriso", OPTION_XORRISO, N_("FILE"),
/* TRANSLATORS: xorriso is a program for creating ISOs and burning CDs. */
0, N_("use FILE as xorriso [optional]"), 2},
{"grub-glue-efi", OPTION_GLUE_EFI, N_("FILE"), OPTION_HIDDEN, 0, 2},
{"grub-render-label", OPTION_RENDER_LABEL, N_("FILE"), OPTION_HIDDEN, 0, 2},
{"label-font", OPTION_LABEL_FONT, N_("FILE"), 0, N_("use FILE as font for label"), 2},
{"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
{"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
{"product-name", OPTION_PRODUCT_NAME, N_("STRING"), 0, N_("use STRING as product name"), 2},
{"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
{"sparc-boot", OPTION_SPARC_BOOT, 0, 0, N_("enable sparc boot. Disables HFS+, APM, ARCS and boot as disk image for i386-pc"), 2},
{"arcs-boot", OPTION_ARCS_BOOT, 0, 0, N_("enable ARCS (big-endian mips machines, mostly SGI) boot. Disables HFS+, APM, sparc64 and boot as disk image for i386-pc"), 2},
{0, 0, 0, 0, 0, 0}
};
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static char *
help_filter (int key, const char *text, void *input __attribute__ ((unused)))
{
switch (key)
{
case ARGP_KEY_HELP_PRE_DOC:
/* TRANSLATORS: it generates one single image which is bootable through any method. */
return strdup (_("Make GRUB CD-ROM, disk, pendrive and floppy bootable image."));
case ARGP_KEY_HELP_POST_DOC:
{
char *p1, *out;
p1 = xasprintf (_("Generates a bootable CD/USB/floppy image. Arguments other than options to this program"
" are passed to xorriso, and indicate source files, source directories, or any of the "
"mkisofs options listed by the output of `%s'."), "xorriso -as mkisofs -help");
out = xasprintf ("%s\n\n%s\n\n%s", p1,
_("Option -- switches to native xorriso command mode."),
_("Mail xorriso support requests to <bug-xorriso@gnu.org>."));
free (p1);
return out;
}
default:
return grub_install_help_filter (key, text, input);
}
}
#pragma GCC diagnostic error "-Wformat-nonliteral"
enum {
SYS_AREA_AUTO,
SYS_AREA_COMMON,
SYS_AREA_SPARC,
SYS_AREA_ARCS
} system_area = SYS_AREA_AUTO;
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_OUTPUT:
free (output_image);
output_image = xstrdup (arg);
return 0;
case OPTION_ROM_DIRECTORY:
free (rom_directory);
rom_directory = xstrdup (arg);
return 0;
/*
FIXME:
# Intentionally undocumented
--grub-mkimage-extra)
mkimage_extra_arg="$mkimage_extra_arg `argument $option "$@"`"; shift ;;
--grub-mkimage-extra=*)
mkimage_extra_arg="$mkimage_extra_arg `echo "$option" | sed 's/--grub-mkimage-extra=//'`" ;;
*/
case OPTION_SPARC_BOOT:
system_area = SYS_AREA_SPARC;
return 0;
case OPTION_ARCS_BOOT:
system_area = SYS_AREA_ARCS;
return 0;
case OPTION_PRODUCT_NAME:
free (product_name);
product_name = xstrdup (arg);
return 0;
case OPTION_PRODUCT_VERSION:
free (product_version);
product_version = xstrdup (arg);
return 0;
/* Accept and ignore for compatibility. */
case OPTION_GLUE_EFI:
case OPTION_RENDER_LABEL:
return 0;
case OPTION_LABEL_FONT:
free (label_font);
label_font = xstrdup (arg);
return 0;
case OPTION_LABEL_COLOR:
free (label_color);
label_color = xstrdup (arg);
return 0;
case OPTION_LABEL_BGCOLOR:
free (label_bgcolor);
label_bgcolor = xstrdup (arg);
return 0;
case OPTION_XORRISO:
free (xorriso);
xorriso = xstrdup (arg);
return 0;
default:
return ARGP_ERR_UNKNOWN;
}
}
struct argp argp = {
options, argp_parser, N_("[OPTION] SOURCE..."),
NULL, NULL, help_filter, NULL
};
static void
write_part (FILE *f, const char *srcdir)
{
FILE *in;
char *inname = grub_util_path_concat (2, srcdir, "partmap.lst");
char buf[260];
in = grub_util_fopen (inname, "rb");
if (!in)
return;
while (fgets (buf, 256, in))
{
char *ptr;
for (ptr = buf + strlen (buf) - 1;
ptr >= buf && (*ptr == '\n' || *ptr == '\r');
ptr--);
ptr[1] = '\0';
fprintf (f, "insmod %s\n", buf);
}
fclose (in);
}
static void
make_image_abs (enum grub_install_plat plat,
const char *mkimage_target,
const char *output)
{
char *load_cfg;
FILE *load_cfg_f;
if (!source_dirs[plat])
return;
grub_util_info (N_("enabling %s support ..."),
mkimage_target);
load_cfg = grub_util_make_temporary_file ();
load_cfg_f = grub_util_fopen (load_cfg, "wb");
fprintf (load_cfg_f, "search --fs-uuid --set=root %s\n", iso_uuid);
fprintf (load_cfg_f, "set prefix=(${root})/boot/grub\n");
write_part (load_cfg_f, source_dirs[plat]);
fclose (load_cfg_f);
grub_install_push_module ("search");
grub_install_push_module ("iso9660");
grub_install_make_image_wrap (source_dirs[plat], "/boot/grub", output,
0, load_cfg,
mkimage_target, 0);
grub_install_pop_module ();
grub_install_pop_module ();
grub_util_unlink (load_cfg);
}
static void
make_image (enum grub_install_plat plat,
const char *mkimage_target,
const char *output_sub)
{
char *out = grub_util_path_concat (2, boot_grub, output_sub);
make_image_abs (plat, mkimage_target, out);
free (out);
}
static void
make_image_fwdisk_abs (enum grub_install_plat plat,
const char *mkimage_target,
const char *output)
{
char *load_cfg;
FILE *load_cfg_f;
if (!source_dirs[plat])
return;
grub_util_info (N_("enabling %s support ..."),
mkimage_target);
load_cfg = grub_util_make_temporary_file ();
load_cfg_f = grub_util_fopen (load_cfg, "wb");
write_part (load_cfg_f, source_dirs[plat]);
fclose (load_cfg_f);
grub_install_push_module ("iso9660");
grub_install_make_image_wrap (source_dirs[plat], "()/boot/grub", output,
0, load_cfg, mkimage_target, 0);
grub_install_pop_module ();
grub_util_unlink (load_cfg);
}
static int
check_xorriso (const char *val)
{
const char *argv[5];
int fd;
pid_t pid;
FILE *mdadm;
char *buf = NULL;
size_t len = 0;
int ret = 0;
int wstatus = 0;
argv[0] = xorriso;
argv[1] = "-as";
argv[2] = "mkisofs";
argv[3] = "-help";
argv[4] = NULL;
pid = grub_util_exec_pipe_stderr (argv, &fd);
if (!pid)
return 0;
/* Parent. Read mdadm's output. */
mdadm = fdopen (fd, "r");
if (! mdadm)
return 0;
while (getline (&buf, &len, mdadm) > 0)
{
if (grub_strstr (buf, val))
ret = 1;
}
close (fd);
waitpid (pid, &wstatus, 0);
free (buf);
if (!WIFEXITED (wstatus) || WEXITSTATUS(wstatus) != 0)
return 0;
return ret;
}
static void
make_image_fwdisk (enum grub_install_plat plat,
const char *mkimage_target,
const char *output_sub)
{
char *out = grub_util_path_concat (2, boot_grub, output_sub);
make_image_fwdisk_abs (plat, mkimage_target, out);
free (out);
}
static int
option_is_end (const struct argp_option *opt)
{
return !opt->key && !opt->name && !opt->doc && !opt->group;
}
static int
args_to_eat (const char *arg)
{
int j;
if (arg[0] != '-')
return 0;
if (arg[1] == '-')
{
for (j = 0; !option_is_end(&options[j]); j++)
{
size_t len = strlen (options[j].name);
if (strncmp (arg + 2, options[j].name, len) == 0)
{
if (arg[2 + len] == '=')
return 1;
if (arg[2 + len] == '\0' && options[j].arg)
return 2;
if (arg[2 + len] == '\0')
return 1;
}
}
if (strcmp (arg, "--help") == 0)
return 1;
if (strcmp (arg, "--usage") == 0)
return 1;
if (strcmp (arg, "--version") == 0)
return 1;
return 0;
}
if (arg[2] && arg[3])
return 0;
for (j = 0; !option_is_end(&options[j]); j++)
{
if (options[j].key > 0 && options[j].key < 128 && arg[1] == options[j].key)
{
if (options[j].arg)
return 2;
return 1;
}
if (arg[1] == '?')
return 1;
}
return 0;
}
int
main (int argc, char *argv[])
{
char *romdir;
char *sysarea_img = NULL;
const char *pkgdatadir;
int argp_argc;
char **argp_argv;
int xorriso_tail_argc;
char **xorriso_tail_argv;
int rv;
grub_util_host_init (&argc, &argv);
grub_util_disable_fd_syncs ();
pkgdatadir = grub_util_get_pkgdatadir ();
product_name = xstrdup (PACKAGE_NAME);
product_version = xstrdup (PACKAGE_VERSION);
xorriso = xstrdup ("xorriso");
label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
argp_argv = xcalloc (argc, sizeof (argp_argv[0]));
xorriso_tail_argv = xcalloc (argc, sizeof (argp_argv[0]));
xorriso_tail_argc = 0;
/* Program name */
argp_argv[0] = argv[0];
argp_argc = 1;
/* argp doesn't allow us to catch unknwon arguments,
so catch them before passing to argp
*/
{
int i;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-output") == 0) {
argp_argv[argp_argc++] = (char *) "--output";
i++;
argp_argv[argp_argc++] = argv[i];
continue;
}
switch (args_to_eat (argv[i]))
{
case 2:
argp_argv[argp_argc++] = argv[i++];
/* Fallthrough */
case 1:
argp_argv[argp_argc++] = argv[i];
break;
case 0:
xorriso_tail_argv[xorriso_tail_argc++] = argv[i];
break;
}
}
}
argp_parse (&argp, argp_argc, argp_argv, 0, 0, 0);
if (!output_image)
grub_util_error ("%s", _("output file must be specified"));
if (!check_xorriso ("graft-points")) {
grub_util_error ("%s", _("xorriso not found"));
}
grub_init_all ();
grub_hostfs_init ();
grub_host_init ();
xorriso_push (xorriso);
xorriso_push ("-as");
xorriso_push ("mkisofs");
xorriso_push ("-graft-points");
iso9660_dir = grub_util_make_temporary_dir ();
grub_util_info ("temporary iso9660 dir is `%s'", iso9660_dir);
boot_grub = grub_util_path_concat (3, iso9660_dir, "boot", "grub");
grub_install_mkdir_p (boot_grub);
romdir = grub_util_path_concat (2, boot_grub, "roms");
grub_util_mkdir (romdir);
if (!grub_install_source_directory)
{
const char *pkglibdir = grub_util_get_pkglibdir ();
enum grub_install_plat plat;
for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++)
{
char *platdir = grub_util_path_concat (2, pkglibdir,
grub_install_get_platform_name (plat));
if (!grub_util_is_directory (platdir))
{
free (platdir);
continue;
}
source_dirs[plat] = platdir;
grub_install_copy_files (platdir,
boot_grub, plat);
}
}
else
{
enum grub_install_plat plat;
plat = grub_install_get_target (grub_install_source_directory);
grub_install_copy_files (grub_install_source_directory,
boot_grub, plat);
source_dirs[plat] = xstrdup (grub_install_source_directory);
}
grub_set_install_backup_ponr ();
if (system_area == SYS_AREA_AUTO || grub_install_source_directory)
{
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]
|| source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275]
|| source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
system_area = SYS_AREA_COMMON;
else if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275])
system_area = SYS_AREA_SPARC;
else if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC])
system_area = SYS_AREA_ARCS;
}
/* obtain date-based UUID. */
{
time_t tim;
struct tm *tmm;
tim = time (NULL);
tmm = gmtime (&tim);
iso_uuid = xmalloc (55);
grub_snprintf (iso_uuid, 50,
"%04d-%02d-%02d-%02d-%02d-%02d-00",
tmm->tm_year + 1900,
tmm->tm_mon + 1,
tmm->tm_mday,
tmm->tm_hour,
tmm->tm_min,
tmm->tm_sec);
}
{
char *uuid_out = xmalloc (strlen (iso_uuid) + 1 + 40);
char *optr;
const char *iptr;
optr = grub_stpcpy (uuid_out, "--modification-date=");
for (iptr = iso_uuid; *iptr; iptr++)
if (*iptr != '-')
*optr++ = *iptr;
*optr = '\0';
xorriso_push (uuid_out);
free (uuid_out);
}
/* build BIOS core.img. */
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC])
{
char *load_cfg;
FILE *load_cfg_f;
char *output = grub_util_path_concat (3, boot_grub, "i386-pc", "eltorito.img");
load_cfg = grub_util_make_temporary_file ();
grub_util_info (N_("enabling %s support ..."), "BIOS");
load_cfg_f = grub_util_fopen (load_cfg, "wb");
write_part (load_cfg_f, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]);
fclose (load_cfg_f);
grub_install_push_module ("biosdisk");
grub_install_push_module ("iso9660");
grub_install_make_image_wrap (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
"/boot/grub", output,
0, load_cfg,
"i386-pc-eltorito", 0);
xorriso_push ("-b");
xorriso_push ("boot/grub/i386-pc/eltorito.img");
xorriso_push ("-no-emul-boot");
xorriso_push ("-boot-load-size");
xorriso_push ("4");
xorriso_push ("-boot-info-table");
if (system_area == SYS_AREA_COMMON)
{
if (check_xorriso ("grub2-boot-info"))
{
char *boot_hybrid = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
"boot_hybrid.img");
xorriso_push ("--grub2-boot-info");
xorriso_push ("--grub2-mbr");
xorriso_push (boot_hybrid);
}
else
{
FILE *sa, *bi;
size_t sz;
char buf[512];
char *bin = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
"boot.img");
grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Some features are disabled. Please use xorriso 1.2.9 or later."));
sysarea_img = grub_util_make_temporary_file ();
sa = grub_util_fopen (sysarea_img, "wb");
if (!sa)
grub_util_error (_("cannot open `%s': %s"), sysarea_img,
strerror (errno));
bi = grub_util_fopen (bin, "rb");
if (!bi)
grub_util_error (_("cannot open `%s': %s"), bin,
strerror (errno));
if (fread (buf, 1, 512, bi) != 512)
grub_util_error (_("cannot read `%s': %s"), bin,
strerror (errno));
fclose (bi);
fwrite (buf, 1, 512, sa);
grub_install_make_image_wrap_file (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
"/boot/grub", sa, sysarea_img,
0, load_cfg,
"i386-pc", 0);
sz = ftello (sa);
fflush (sa);
grub_util_fd_sync (fileno (sa));
fclose (sa);
if (sz > 32768)
{
grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Your core image is too big. Boot as disk is disabled. Please use xorriso 1.2.9 or later."));
}
else
{
xorriso_push ("-G");
xorriso_push (sysarea_img);
}
}
}
grub_install_pop_module ();
grub_install_pop_module ();
grub_util_unlink (load_cfg);
}
/** build multiboot core.img */
grub_install_push_module ("pata");
grub_install_push_module ("ahci");
grub_install_push_module ("at_keyboard");
make_image (GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, "i386-multiboot", "i386-multiboot/core.elf");
grub_install_pop_module ();
grub_install_pop_module ();
grub_install_pop_module ();
make_image_fwdisk (GRUB_INSTALL_PLATFORM_I386_IEEE1275, "i386-ieee1275", "ofwx86.elf");
char *core_services = NULL;
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275])
{
char *mach_ker, *sv, *label, *label_text;
FILE *f;
core_services = grub_util_path_concat (4, iso9660_dir, "System", "Library", "CoreServices");
grub_install_mkdir_p (core_services);
mach_ker = grub_util_path_concat (2, iso9660_dir, "mach_kernel");
f = grub_util_fopen (mach_ker, "wb");
fclose (f);
free (mach_ker);
sv = grub_util_path_concat (2, core_services, "SystemVersion.plist");
f = grub_util_fopen (sv, "wb");
fprintf (f, "<plist version=\"1.0\">\n"
"<dict>\n"
" <key>ProductBuildVersion</key>\n"
" <string></string>\n"
" <key>ProductName</key>\n"
" <string>%s</string>\n"
" <key>ProductVersion</key>\n"
" <string>%s</string>\n"
"</dict>\n"
"</plist>\n", product_name, product_version);
fclose (f);
free (sv);
label = grub_util_path_concat (2, core_services, ".disk_label");
char *label_string = xasprintf ("%s %s", product_name, product_version);
grub_util_render_label (label_font, label_bgcolor ? : "white",
label_color ? : "black", label_string, label);
free (label);
label_text = grub_util_path_concat (2, core_services, ".disk_label.contentDetails");
f = grub_util_fopen (label_text, "wb");
fprintf (f, "%s\n", label_string);
fclose (f);
free (label_string);
free (label_text);
if (system_area == SYS_AREA_COMMON)
{
xorriso_push ("-hfsplus");
xorriso_push ("-apm-block-size");
xorriso_push ("2048");
xorriso_push ("-hfsplus-file-creator-type");
xorriso_push ("chrp");
xorriso_push ("tbxj");
xorriso_push ("/System/Library/CoreServices/.disk_label");
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
{
xorriso_push ("-hfs-bless-by");
xorriso_push ("i");
xorriso_push ("/System/Library/CoreServices/boot.efi");
}
}
}
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI])
{
char *efidir = grub_util_make_temporary_dir ();
char *efidir_efi = grub_util_path_concat (2, efidir, "efi");
char *efidir_efi_boot = grub_util_path_concat (3, efidir, "efi", "boot");
char *imgname, *img32, *img64, *img_mac = NULL;
char *efiimgfat;
grub_install_mkdir_p (efidir_efi_boot);
grub_install_push_module ("part_gpt");
grub_install_push_module ("part_msdos");
imgname = grub_util_path_concat (2, efidir_efi_boot, "bootia64.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname);
free (imgname);
grub_install_push_module ("part_apple");
img64 = grub_util_path_concat (2, efidir_efi_boot, "bootx64.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64-efi", img64);
grub_install_pop_module ();
grub_install_push_module ("part_apple");
img32 = grub_util_path_concat (2, efidir_efi_boot, "bootia32.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_I386_EFI, "i386-efi", img32);
grub_install_pop_module ();
imgname = grub_util_path_concat (2, efidir_efi_boot, "bootarm.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname);
free (imgname);
imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaa64.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM64_EFI, "arm64-efi",
imgname);
free (imgname);
imgname = grub_util_path_concat (2, efidir_efi_boot, "bootriscv32.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_RISCV32_EFI, "riscv32-efi",
imgname);
free (imgname);
imgname = grub_util_path_concat (2, efidir_efi_boot, "bootriscv64.efi");
make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_RISCV64_EFI, "riscv64-efi",
imgname);
free (imgname);
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
{
imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi");
/* For old macs. Suggested by Peter Jones. */
grub_install_copy_file (img32, imgname, 1);
}
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
|| source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
img_mac = grub_util_path_concat (2, core_services, "boot.efi");
if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
&& source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
grub_util_glue_efi (img32, img64, img_mac);
else if (source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
grub_install_copy_file (img64, img_mac, 1);
else if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
grub_install_copy_file (img32, img_mac, 1);
free (img_mac);
free (img32);
free (img64);
free (efidir_efi_boot);
efiimgfat = grub_util_path_concat (2, iso9660_dir, "efi.img");
rv = grub_util_exec ((const char * []) { "mformat", "-C", "-f", "2880", "-L", "16", "-i",
efiimgfat, "::", NULL });
if (rv != 0)
grub_util_error ("`%s` invocation failed\n", "mformat");
rv = grub_util_exec ((const char * []) { "mcopy", "-s", "-i", efiimgfat, efidir_efi, "::/", NULL });
if (rv != 0)
grub_util_error ("`%s` invocation failed\n", "mcopy");
xorriso_push ("--efi-boot");
xorriso_push ("efi.img");
xorriso_push ("-efi-boot-part");
xorriso_push ("--efi-boot-image");
grub_util_unlink_recursive (efidir);
free (efiimgfat);
free (efidir_efi);
free (efidir);
grub_install_pop_module ();
grub_install_pop_module ();
}
grub_install_push_module ("part_apple");
make_image_fwdisk (GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc-ieee1275", "powerpc-ieee1275/core.elf");
grub_install_pop_module ();
if (source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275])
{
char *grub_chrp = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275],
"grub.chrp");
char *bisrc = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275],
"bootinfo.txt");
char *bootx = grub_util_path_concat (2, core_services, "BootX");
char *ppc_chrp = grub_util_path_concat (3, iso9660_dir, "ppc", "chrp");
char *bitgt = grub_util_path_concat (3, iso9660_dir, "ppc", "bootinfo.txt");
grub_install_copy_file (grub_chrp, bootx, 1);
grub_install_mkdir_p (ppc_chrp);
grub_install_copy_file (bisrc, bitgt, 1);
xorriso_link ("/System/Library/CoreServices/grub.elf", "/boot/grub/powerpc-ieee1275/core.elf");
xorriso_link ("/boot/grub/powerpc.elf", "/boot/grub/powerpc-ieee1275/core.elf");
/* FIXME: add PreP */
if (system_area == SYS_AREA_COMMON)
{
xorriso_push ("-hfsplus-file-creator-type");
xorriso_push ("chrp");
xorriso_push ("tbxi");
xorriso_push ("/System/Library/CoreServices/BootX");
xorriso_push ("-hfs-bless-by");
xorriso_push ("p");
xorriso_push ("/System/Library/CoreServices");
}
xorriso_push ("-sysid");
xorriso_push ("PPC");
}
make_image_fwdisk (GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275,
"sparc64-ieee1275-cdcore", "sparc64-ieee1275/core.img");
if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275]
&& system_area == SYS_AREA_SPARC)
{
char *cdboot;
FILE *in, *out;
char buf[512];
sysarea_img = grub_util_make_temporary_file ();
cdboot = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275],
"cdboot.img");
in = grub_util_fopen (cdboot, "rb");
if (!in)
grub_util_error (_("cannot open `%s': %s"), cdboot,
strerror (errno));
out = grub_util_fopen (sysarea_img, "wb");
if (!out)
grub_util_error (_("cannot open `%s': %s"), sysarea_img,
strerror (errno));
memset (buf, 0, 512);
fwrite (buf, 1, 512, out);
if (fread (buf, 1, 512, in) != 512)
grub_util_error (_("cannot read `%s': %s"), cdboot,
strerror (errno));
fwrite (buf, 1, 512, out);
fclose (in);
fclose (out);
xorriso_push ("-G");
xorriso_push (sysarea_img);
xorriso_push ("-B");
xorriso_push (",");
xorriso_push ("--grub2-sparc-core");
xorriso_push ("/boot/grub/sparc64-ieee1275/core.img");
}
make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPS_ARC, "mips-arc", "mips-arc/core.img");
if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC])
{
xorriso_link ("/boot/grub/mips-arc/grub", "/boot/grub/mips-arc/core.img");
xorriso_link ("/boot/grub/mips-arc/sashARCS", "/boot/grub/mips-arc/core.img");
xorriso_link ("/boot/grub/mips-arc/sash", "/boot/grub/mips-arc/core.img");
}
if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC] && system_area == SYS_AREA_ARCS)
{
xorriso_push ("-mips-boot");
xorriso_push ("/boot/grub/mips-arc/sashARCS");
xorriso_push ("-mips-boot");
xorriso_push ("/boot/grub/mips-arc/sash");
xorriso_push ("-mips-boot");
xorriso_push ("/boot/grub/mips-arc/grub");
}
make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPSEL_ARC, "mipsel-arc", "arc.exe");
grub_install_push_module ("pata");
make_image (GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "mipsel-qemu_mips-elf", "roms/mipsel-qemu_mips.elf");
make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-loongson-elf", "loongson.elf");
make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-yeeloong-flash", "mipsel-yeeloong.bin");
make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-fuloong2f-flash", "mipsel-fuloong2f.bin");
make_image (GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "mips-qemu_mips-elf", "roms/mips-qemu_mips.elf");
grub_install_push_module ("at_keyboard");
make_image (GRUB_INSTALL_PLATFORM_I386_QEMU, "i386-qemu", "roms/qemu.img");
grub_install_push_module ("ahci");
make_image (GRUB_INSTALL_PLATFORM_I386_COREBOOT, "i386-coreboot", "roms/coreboot.elf");
grub_install_pop_module ();
grub_install_pop_module ();
grub_install_pop_module ();
if (rom_directory)
{
const struct
{
enum grub_install_plat plat;
const char *from, *to;
} roms[] =
{
{GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "roms/mipsel-qemu_mips.elf", "mipsel-qemu_mips.elf"},
{GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "loongson.elf", "mipsel-loongson.elf"},
{GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-yeeloong.bin", "mipsel-yeeloong.bin"},
{GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-fulong.bin", "mipsel-fulong.bin"},
{GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "roms/mips-qemu_mips.elf", "mips-qemu_mips.elf"},
{GRUB_INSTALL_PLATFORM_I386_QEMU, "roms/qemu.img", "qemu.img"},
{GRUB_INSTALL_PLATFORM_I386_COREBOOT, "roms/coreboot.elf", "coreboot.elf"},
};
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (roms); i++)
{
char *from = grub_util_path_concat (2, boot_grub, roms[i].from);
char *to = grub_util_path_concat (2, rom_directory, roms[i].to);
grub_install_copy_file (from, to, 0);
}
}
xorriso_push ("--protective-msdos-label");
xorriso_push ("-o");
xorriso_push (output_image);
xorriso_push ("-r");
xorriso_push (iso9660_dir);
xorriso_push ("--sort-weight");
xorriso_push ("0");
xorriso_push ("/");
xorriso_push ("--sort-weight");
xorriso_push ("1");
xorriso_push ("/boot");
int i;
for (i = 0; i < xorriso_tail_argc; i++)
xorriso_push (xorriso_tail_argv[i]);
xorriso_argv[xorriso_argc] = NULL;
rv = grub_util_exec ((const char *const *)xorriso_argv);
if (rv != 0)
grub_util_error ("`%s` invocation failed\n", "xorriso");
grub_util_unlink_recursive (iso9660_dir);
if (sysarea_img)
grub_util_unlink (sysarea_img);
free (core_services);
free (romdir);
return 0;
}