5 kx /*
5 kx * GRUB -- GRand Unified Bootloader
5 kx * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
5 kx *
5 kx * GRUB is free software: you can redistribute it and/or modify
5 kx * it under the terms of the GNU General Public License as published by
5 kx * the Free Software Foundation, either version 3 of the License, or
5 kx * (at your option) any later version.
5 kx *
5 kx * GRUB is distributed in the hope that it will be useful,
5 kx * but WITHOUT ANY WARRANTY; without even the implied warranty of
5 kx * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5 kx * GNU General Public License for more details.
5 kx *
5 kx * You should have received a copy of the GNU General Public License
5 kx * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
5 kx */
5 kx
5 kx #include <config.h>
5 kx #include <grub/types.h>
5 kx #include <grub/emu/misc.h>
5 kx #include <grub/util/misc.h>
5 kx #include <grub/misc.h>
5 kx #include <grub/device.h>
5 kx #include <grub/disk.h>
5 kx #include <grub/file.h>
5 kx #include <grub/fs.h>
5 kx #include <grub/env.h>
5 kx #include <grub/term.h>
5 kx #include <grub/mm.h>
5 kx #include <grub/lib/hexdump.h>
5 kx #include <grub/crypto.h>
5 kx #include <grub/command.h>
5 kx #include <grub/i18n.h>
5 kx #include <grub/zfs/zfs.h>
5 kx #include <grub/util/install.h>
5 kx #include <grub/emu/getroot.h>
5 kx #include <grub/diskfilter.h>
5 kx #include <grub/cryptodisk.h>
5 kx #include <grub/legacy_parse.h>
5 kx #include <grub/gpt_partition.h>
5 kx #include <grub/emu/config.h>
5 kx #include <grub/util/ofpath.h>
5 kx #include <grub/hfsplus.h>
5 kx
5 kx #include <string.h>
5 kx
5 kx #pragma GCC diagnostic ignored "-Wmissing-prototypes"
5 kx #pragma GCC diagnostic ignored "-Wmissing-declarations"
5 kx #include <argp.h>
5 kx #pragma GCC diagnostic error "-Wmissing-prototypes"
5 kx #pragma GCC diagnostic error "-Wmissing-declarations"
5 kx
5 kx #include "progname.h"
5 kx
5 kx static char *target;
5 kx static int removable = 0;
5 kx static int recheck = 0;
5 kx static int update_nvram = 1;
5 kx static char *install_device = NULL;
5 kx static char *debug_image = NULL;
5 kx static char *rootdir = NULL;
5 kx static char *bootdir = NULL;
5 kx static int allow_floppy = 0;
5 kx static int force_file_id = 0;
5 kx static char *disk_module = NULL;
5 kx static char *efidir = NULL;
5 kx static char *macppcdir = NULL;
5 kx static int force = 0;
5 kx static int have_abstractions = 0;
5 kx static int have_cryptodisk = 0;
5 kx static char * bootloader_id;
5 kx static int have_load_cfg = 0;
5 kx static FILE * load_cfg_f = NULL;
5 kx static char *load_cfg;
5 kx static int install_bootsector = 1;
5 kx static char *label_font;
5 kx static char *label_color;
5 kx static char *label_bgcolor;
5 kx static char *product_version;
5 kx static int add_rs_codes = 1;
5 kx
5 kx enum
5 kx {
5 kx OPTION_BOOT_DIRECTORY = 0x301,
5 kx OPTION_ROOT_DIRECTORY,
5 kx OPTION_TARGET,
5 kx OPTION_SETUP,
5 kx OPTION_MKRELPATH,
5 kx OPTION_MKDEVICEMAP,
5 kx OPTION_PROBE,
5 kx OPTION_EDITENV,
5 kx OPTION_ALLOW_FLOPPY,
5 kx OPTION_RECHECK,
5 kx OPTION_FORCE,
5 kx OPTION_FORCE_FILE_ID,
5 kx OPTION_NO_NVRAM,
5 kx OPTION_REMOVABLE,
5 kx OPTION_BOOTLOADER_ID,
5 kx OPTION_EFI_DIRECTORY,
5 kx OPTION_FONT,
5 kx OPTION_DEBUG,
5 kx OPTION_DEBUG_IMAGE,
5 kx OPTION_NO_FLOPPY,
5 kx OPTION_DISK_MODULE,
5 kx OPTION_NO_BOOTSECTOR,
5 kx OPTION_NO_RS_CODES,
5 kx OPTION_MACPPC_DIRECTORY,
5 kx OPTION_LABEL_FONT,
5 kx OPTION_LABEL_COLOR,
5 kx OPTION_LABEL_BGCOLOR,
5 kx OPTION_PRODUCT_VERSION
5 kx };
5 kx
5 kx static int fs_probe = 1;
5 kx
5 kx static error_t
5 kx argp_parser (int key, char *arg, struct argp_state *state)
5 kx {
5 kx if (grub_install_parse (key, arg))
5 kx return 0;
5 kx switch (key)
5 kx {
5 kx case OPTION_FORCE_FILE_ID:
5 kx force_file_id = 1;
5 kx return 0;
5 kx case 's':
5 kx fs_probe = 0;
5 kx return 0;
5 kx
5 kx case OPTION_SETUP:
5 kx if (!grub_strstr (arg, "setup"))
5 kx install_bootsector = 0;
5 kx return 0;
5 kx
5 kx case OPTION_PRODUCT_VERSION:
5 kx free (product_version);
5 kx product_version = xstrdup (arg);
5 kx return 0;
5 kx case OPTION_LABEL_FONT:
5 kx free (label_font);
5 kx label_font = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_LABEL_COLOR:
5 kx free (label_color);
5 kx label_color = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_LABEL_BGCOLOR:
5 kx free (label_bgcolor);
5 kx label_bgcolor = xstrdup (arg);
5 kx return 0;
5 kx
5 kx /* Accept and ignore for compatibility. */
5 kx case OPTION_FONT:
5 kx case OPTION_MKRELPATH:
5 kx case OPTION_PROBE:
5 kx case OPTION_EDITENV:
5 kx case OPTION_MKDEVICEMAP:
5 kx case OPTION_NO_FLOPPY:
5 kx return 0;
5 kx case OPTION_ROOT_DIRECTORY:
5 kx /* Accept for compatibility. */
5 kx free (rootdir);
5 kx rootdir = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_BOOT_DIRECTORY:
5 kx free (bootdir);
5 kx bootdir = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_MACPPC_DIRECTORY:
5 kx free (macppcdir);
5 kx macppcdir = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_EFI_DIRECTORY:
5 kx free (efidir);
5 kx efidir = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_DISK_MODULE:
5 kx free (disk_module);
5 kx disk_module = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_TARGET:
5 kx free (target);
5 kx target = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_DEBUG_IMAGE:
5 kx free (debug_image);
5 kx debug_image = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case OPTION_NO_NVRAM:
5 kx update_nvram = 0;
5 kx return 0;
5 kx
5 kx case OPTION_FORCE:
5 kx force = 1;
5 kx return 0;
5 kx
5 kx case OPTION_RECHECK:
5 kx recheck = 1;
5 kx return 0;
5 kx
5 kx case OPTION_REMOVABLE:
5 kx removable = 1;
5 kx return 0;
5 kx
5 kx case OPTION_ALLOW_FLOPPY:
5 kx allow_floppy = 1;
5 kx return 0;
5 kx
5 kx case OPTION_NO_BOOTSECTOR:
5 kx install_bootsector = 0;
5 kx return 0;
5 kx
5 kx case OPTION_NO_RS_CODES:
5 kx add_rs_codes = 0;
5 kx return 0;
5 kx
5 kx case OPTION_DEBUG:
5 kx verbosity++;
5 kx return 0;
5 kx
5 kx case OPTION_BOOTLOADER_ID:
5 kx free (bootloader_id);
5 kx bootloader_id = xstrdup (arg);
5 kx return 0;
5 kx
5 kx case ARGP_KEY_ARG:
5 kx if (install_device)
5 kx grub_util_error ("%s", _("More than one install device?"));
5 kx install_device = xstrdup (arg);
5 kx return 0;
5 kx
5 kx default:
5 kx return ARGP_ERR_UNKNOWN;
5 kx }
5 kx }
5 kx
5 kx
5 kx static struct argp_option options[] = {
5 kx GRUB_INSTALL_OPTIONS,
5 kx {"boot-directory", OPTION_BOOT_DIRECTORY, N_("DIR"),
5 kx 0, N_("install GRUB images under the directory DIR/%s instead of the %s directory"), 2},
5 kx {"root-directory", OPTION_ROOT_DIRECTORY, N_("DIR"),
5 kx OPTION_HIDDEN, 0, 2},
5 kx {"font", OPTION_FONT, N_("FILE"),
5 kx OPTION_HIDDEN, 0, 2},
5 kx {"target", OPTION_TARGET, N_("TARGET"),
5 kx /* TRANSLATORS: "TARGET" as in "target platform". */
5 kx 0, N_("install GRUB for TARGET platform [default=%s]; available targets: %s"), 2},
5 kx {"grub-setup", OPTION_SETUP, "FILE", OPTION_HIDDEN, 0, 2},
5 kx {"grub-mkrelpath", OPTION_MKRELPATH, "FILE", OPTION_HIDDEN, 0, 2},
5 kx {"grub-mkdevicemap", OPTION_MKDEVICEMAP, "FILE", OPTION_HIDDEN, 0, 2},
5 kx {"grub-probe", OPTION_PROBE, "FILE", OPTION_HIDDEN, 0, 2},
5 kx {"grub-editenv", OPTION_EDITENV, "FILE", OPTION_HIDDEN, 0, 2},
5 kx {"allow-floppy", OPTION_ALLOW_FLOPPY, 0, 0,
5 kx /* TRANSLATORS: "may break" doesn't just mean that option wouldn't have any
5 kx effect but that it will make the resulting install unbootable from HDD. */
5 kx N_("make the drive also bootable as floppy (default for fdX devices)."
5 kx " May break on some BIOSes."), 2},
5 kx {"recheck", OPTION_RECHECK, 0, 0,
5 kx N_("delete device map if it already exists"), 2},
5 kx {"force", OPTION_FORCE, 0, 0,
5 kx N_("install even if problems are detected"), 2},
5 kx {"force-file-id", OPTION_FORCE_FILE_ID, 0, 0,
5 kx N_("use identifier file even if UUID is available"), 2},
5 kx {"disk-module", OPTION_DISK_MODULE, N_("MODULE"), 0,
5 kx N_("disk module to use (biosdisk or native). "
5 kx "This option is only available on BIOS target."), 2},
5 kx {"no-nvram", OPTION_NO_NVRAM, 0, 0,
5 kx N_("don't update the `boot-device'/`Boot*' NVRAM variables. "
5 kx "This option is only available on EFI and IEEE1275 targets."), 2},
5 kx {"skip-fs-probe",'s',0, 0,
5 kx N_("do not probe for filesystems in DEVICE"), 0},
5 kx {"no-bootsector", OPTION_NO_BOOTSECTOR, 0, 0,
5 kx N_("do not install bootsector"), 0},
5 kx {"no-rs-codes", OPTION_NO_RS_CODES, 0, 0,
5 kx N_("Do not apply any reed-solomon codes when embedding core.img. "
5 kx "This option is only available on x86 BIOS targets."), 0},
5 kx
5 kx {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
5 kx {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2},
5 kx {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
5 kx {"removable", OPTION_REMOVABLE, 0, 0,
5 kx N_("the installation device is removable. "
5 kx "This option is only available on EFI."), 2},
5 kx {"bootloader-id", OPTION_BOOTLOADER_ID, N_("ID"), 0,
5 kx N_("the ID of bootloader. This option is only available on EFI and Macs."), 2},
5 kx {"efi-directory", OPTION_EFI_DIRECTORY, N_("DIR"), 0,
5 kx N_("use DIR as the EFI System Partition root."), 2},
5 kx {"macppc-directory", OPTION_MACPPC_DIRECTORY, N_("DIR"), 0,
5 kx N_("use DIR for PPC MAC install."), 2},
5 kx {"label-font", OPTION_LABEL_FONT, N_("FILE"), 0, N_("use FILE as font for label"), 2},
5 kx {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
5 kx {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
5 kx {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
5 kx {0, 0, 0, 0, 0, 0}
5 kx };
5 kx
5 kx static const char *
5 kx get_default_platform (void)
5 kx {
5 kx #ifdef __powerpc__
5 kx return "powerpc-ieee1275";
5 kx #elif defined (__sparc__) || defined (__sparc64__)
5 kx return "sparc64-ieee1275";
5 kx #elif defined (__MIPSEL__)
5 kx return "mipsel-loongson";
5 kx #elif defined (__MIPSEB__)
5 kx return "mips-arc";
5 kx #elif defined (__ia64__)
5 kx return "ia64-efi";
5 kx #elif defined (__arm__)
5 kx return grub_install_get_default_arm_platform ();
5 kx #elif defined (__aarch64__)
5 kx return "arm64-efi";
5 kx #elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__)
5 kx return grub_install_get_default_x86_platform ();
5 kx #elif defined (__riscv)
5 kx #if __riscv_xlen == 32
5 kx return "riscv32-efi";
5 kx #elif __riscv_xlen == 64
5 kx return "riscv64-efi";
5 kx #else
5 kx return NULL;
5 kx #endif
5 kx #else
5 kx return NULL;
5 kx #endif
5 kx }
5 kx
5 kx #pragma GCC diagnostic ignored "-Wformat-nonliteral"
5 kx
5 kx static char *
5 kx help_filter (int key, const char *text, void *input __attribute__ ((unused)))
5 kx {
5 kx switch (key)
5 kx {
5 kx case OPTION_BOOT_DIRECTORY:
5 kx return xasprintf (text, GRUB_DIR_NAME, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
5 kx case OPTION_TARGET:
5 kx {
5 kx char *plats = grub_install_get_platforms_string ();
5 kx char *ret;
5 kx ret = xasprintf (text, get_default_platform (), plats);
5 kx free (plats);
5 kx return ret;
5 kx }
5 kx case ARGP_KEY_HELP_POST_DOC:
5 kx return xasprintf (text, program_name, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
5 kx default:
5 kx return grub_install_help_filter (key, text, input);
5 kx }
5 kx }
5 kx
5 kx #pragma GCC diagnostic error "-Wformat-nonliteral"
5 kx
5 kx /* TRANSLATORS: INSTALL_DEVICE isn't an identifier and is the DEVICE you
5 kx install to. */
5 kx struct argp argp = {
5 kx options, argp_parser, N_("[OPTION] [INSTALL_DEVICE]"),
5 kx N_("Install GRUB on your drive.")"\v"
5 kx N_("INSTALL_DEVICE must be system device filename.\n"
5 kx "%s copies GRUB images into %s. On some platforms, it"
5 kx " may also install GRUB into the boot sector."),
5 kx NULL, help_filter, NULL
5 kx };
5 kx
5 kx static int
5 kx probe_raid_level (grub_disk_t disk)
5 kx {
5 kx /* disk might be NULL in the case of a LVM physical volume with no LVM
5 kx signature. Ignore such cases here. */
5 kx if (!disk)
5 kx return -1;
5 kx
5 kx if (disk->dev->id != GRUB_DISK_DEVICE_DISKFILTER_ID)
5 kx return -1;
5 kx
5 kx if (disk->name[0] != 'm' || disk->name[1] != 'd')
5 kx return -1;
5 kx
5 kx if (!((struct grub_diskfilter_lv *) disk->data)->segments)
5 kx return -1;
5 kx return ((struct grub_diskfilter_lv *) disk->data)->segments->type;
5 kx }
5 kx
5 kx static void
5 kx push_partmap_module (const char *map, void *data __attribute__ ((unused)))
5 kx {
5 kx char buf[50];
5 kx
5 kx if (strcmp (map, "openbsd") == 0 || strcmp (map, "netbsd") == 0)
5 kx {
5 kx grub_install_push_module ("part_bsd");
5 kx return;
5 kx }
5 kx
5 kx snprintf (buf, sizeof (buf), "part_%s", map);
5 kx grub_install_push_module (buf);
5 kx }
5 kx
5 kx static void
5 kx push_cryptodisk_module (const char *mod, void *data __attribute__ ((unused)))
5 kx {
5 kx grub_install_push_module (mod);
5 kx }
5 kx
5 kx static void
5 kx probe_mods (grub_disk_t disk)
5 kx {
5 kx grub_partition_t part;
5 kx grub_disk_memberlist_t list = NULL, tmp;
5 kx int raid_level;
5 kx
5 kx if (disk->partition == NULL)
5 kx grub_util_info ("no partition map found for %s", disk->name);
5 kx
5 kx for (part = disk->partition; part; part = part->parent)
5 kx push_partmap_module (part->partmap->name, NULL);
5 kx
5 kx if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
5 kx {
5 kx grub_diskfilter_get_partmap (disk, push_partmap_module, NULL);
5 kx have_abstractions = 1;
5 kx }
5 kx
5 kx if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
5 kx && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 ||
5 kx grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0))
5 kx grub_install_push_module ("lvm");
5 kx
5 kx if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
5 kx && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0)
5 kx grub_install_push_module ("ldm");
5 kx
5 kx if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
5 kx {
5 kx grub_util_cryptodisk_get_abstraction (disk,
5 kx push_cryptodisk_module, NULL);
5 kx have_abstractions = 1;
5 kx have_cryptodisk = 1;
5 kx }
5 kx
5 kx raid_level = probe_raid_level (disk);
5 kx if (raid_level >= 0)
5 kx {
5 kx grub_install_push_module ("diskfilter");
5 kx if (disk->dev->disk_raidname)
5 kx grub_install_push_module (disk->dev->disk_raidname (disk));
5 kx }
5 kx if (raid_level == 5)
5 kx grub_install_push_module ("raid5rec");
5 kx if (raid_level == 6)
5 kx grub_install_push_module ("raid6rec");
5 kx
5 kx /* In case of LVM/RAID, check the member devices as well. */
5 kx if (disk->dev->disk_memberlist)
5 kx list = disk->dev->disk_memberlist (disk);
5 kx while (list)
5 kx {
5 kx probe_mods (list->disk);
5 kx tmp = list->next;
5 kx free (list);
5 kx list = tmp;
5 kx }
5 kx }
5 kx
5 kx static int
5 kx have_bootdev (enum grub_install_plat pl)
5 kx {
5 kx switch (pl)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx return 1;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx return 0;
5 kx
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx return 0;
5 kx }
5 kx return 0;
5 kx }
5 kx
5 kx static void
5 kx probe_cryptodisk_uuid (grub_disk_t disk)
5 kx {
5 kx grub_disk_memberlist_t list = NULL, tmp;
5 kx
5 kx /* In case of LVM/RAID, check the member devices as well. */
5 kx if (disk->dev->disk_memberlist)
5 kx {
5 kx list = disk->dev->disk_memberlist (disk);
5 kx }
5 kx while (list)
5 kx {
5 kx probe_cryptodisk_uuid (list->disk);
5 kx tmp = list->next;
5 kx free (list);
5 kx list = tmp;
5 kx }
5 kx if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
5 kx {
5 kx const char *uuid = grub_util_cryptodisk_get_uuid (disk);
5 kx if (!load_cfg_f)
5 kx load_cfg_f = grub_util_fopen (load_cfg, "wb");
5 kx have_load_cfg = 1;
5 kx
5 kx fprintf (load_cfg_f, "cryptomount -u %s\n",
5 kx uuid);
5 kx }
5 kx }
5 kx
5 kx static int
5 kx is_same_disk (const char *a, const char *b)
5 kx {
5 kx while (1)
5 kx {
5 kx if ((*a == ',' || *a == '\0') && (*b == ',' || *b == '\0'))
5 kx return 1;
5 kx if (*a != *b)
5 kx return 0;
5 kx if (*a == '\\')
5 kx {
5 kx if (a[1] != b[1])
5 kx return 0;
5 kx a += 2;
5 kx b += 2;
5 kx continue;
5 kx }
5 kx a++;
5 kx b++;
5 kx }
5 kx }
5 kx
5 kx static char *
5 kx get_rndstr (void)
5 kx {
5 kx grub_uint8_t rnd[15];
5 kx const size_t sz = sizeof (rnd) * GRUB_CHAR_BIT / 5;
5 kx char * ret = xmalloc (sz + 1);
5 kx size_t i;
5 kx if (grub_get_random (rnd, sizeof (rnd)))
5 kx grub_util_error ("%s", _("couldn't retrieve random data"));
5 kx for (i = 0; i < sz; i++)
5 kx {
5 kx grub_size_t b = i * 5;
5 kx grub_uint8_t r;
5 kx grub_size_t f1 = GRUB_CHAR_BIT - b % GRUB_CHAR_BIT;
5 kx grub_size_t f2;
5 kx if (f1 > 5)
5 kx f1 = 5;
5 kx f2 = 5 - f1;
5 kx r = (rnd[b / GRUB_CHAR_BIT] >> (b % GRUB_CHAR_BIT)) & ((1 << f1) - 1);
5 kx if (f2)
5 kx r |= (rnd[b / GRUB_CHAR_BIT + 1] & ((1 << f2) - 1)) << f1;
5 kx if (r < 10)
5 kx ret[i] = '0' + r;
5 kx else
5 kx ret[i] = 'a' + (r - 10);
5 kx }
5 kx ret[sz] = '\0';
5 kx return ret;
5 kx }
5 kx
5 kx static char *
5 kx escape (const char *in)
5 kx {
5 kx char *ptr;
5 kx char *ret;
5 kx int overhead = 0;
5 kx
5 kx for (ptr = (char*)in; *ptr; ptr++)
5 kx if (*ptr == '\'')
5 kx overhead += 3;
5 kx ret = grub_malloc (ptr - in + overhead + 1);
5 kx if (!ret)
5 kx return NULL;
5 kx
5 kx grub_strchrsub (ret, in, '\'', "'\\''");
5 kx return ret;
5 kx }
5 kx
5 kx static struct grub_util_config config;
5 kx
5 kx static void
5 kx device_map_check_duplicates (const char *dev_map)
5 kx {
5 kx FILE *fp;
5 kx char buf[1024]; /* XXX */
5 kx size_t alloced = 8;
5 kx size_t filled = 0;
5 kx char **d;
5 kx size_t i;
5 kx
5 kx if (dev_map[0] == '\0')
5 kx return;
5 kx
5 kx fp = grub_util_fopen (dev_map, "r");
5 kx if (! fp)
5 kx return;
5 kx
5 kx d = xcalloc (alloced, sizeof (d[0]));
5 kx
5 kx while (fgets (buf, sizeof (buf), fp))
5 kx {
5 kx char *p = buf;
5 kx char *e;
5 kx
5 kx /* Skip leading spaces. */
5 kx while (*p && grub_isspace (*p))
5 kx p++;
5 kx
5 kx /* If the first character is `#' or NUL, skip this line. */
5 kx if (*p == '\0' || *p == '#')
5 kx continue;
5 kx
5 kx if (*p != '(')
5 kx continue;
5 kx
5 kx p++;
5 kx
5 kx e = p;
5 kx p = strchr (p, ')');
5 kx if (! p)
5 kx continue;
5 kx
5 kx if (filled >= alloced)
5 kx {
5 kx alloced *= 2;
5 kx d = xrealloc (d, alloced * sizeof (d[0]));
5 kx }
5 kx
5 kx *p = '\0';
5 kx
5 kx d[filled++] = xstrdup (e);
5 kx }
5 kx
5 kx fclose (fp);
5 kx
5 kx qsort (d, filled, sizeof (d[0]), grub_qsort_strcmp);
5 kx
5 kx for (i = 0; i + 1 < filled; i++)
5 kx if (strcmp (d[i], d[i+1]) == 0)
5 kx {
5 kx grub_util_error (_("the drive %s is defined multiple times in the device map %s"),
5 kx d[i], dev_map);
5 kx }
5 kx
5 kx for (i = 0; i < filled; i++)
5 kx free (d[i]);
5 kx
5 kx free (d);
5 kx }
5 kx
5 kx static grub_err_t
5 kx write_to_disk (grub_device_t dev, const char *fn)
5 kx {
5 kx char *core_img;
5 kx size_t core_size;
5 kx grub_err_t err;
5 kx
5 kx core_size = grub_util_get_image_size (fn);
5 kx
5 kx core_img = grub_util_read_image (fn);
5 kx
5 kx grub_util_info ("writing `%s' to `%s'", fn, dev->disk->name);
5 kx err = grub_disk_write (dev->disk, 0, 0,
5 kx core_size, core_img);
5 kx free (core_img);
5 kx return err;
5 kx }
5 kx
5 kx static int
5 kx is_prep_partition (grub_device_t dev)
5 kx {
5 kx if (!dev->disk)
5 kx return 0;
5 kx if (!dev->disk->partition)
5 kx return 0;
5 kx if (strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
5 kx return (dev->disk->partition->msdostype == 0x41);
5 kx
5 kx if (strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
5 kx {
5 kx struct grub_gpt_partentry gptdata;
5 kx grub_partition_t p = dev->disk->partition;
5 kx int ret = 0;
5 kx dev->disk->partition = dev->disk->partition->parent;
5 kx
5 kx if (grub_disk_read (dev->disk, p->offset, p->index,
5 kx sizeof (gptdata), &gptdata) == 0)
5 kx {
5 kx const grub_gpt_part_guid_t template = {
5 kx grub_cpu_to_le32_compile_time (0x9e1a2d38),
5 kx grub_cpu_to_le16_compile_time (0xc612),
5 kx grub_cpu_to_le16_compile_time (0x4316),
5 kx { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b }
5 kx };
5 kx
5 kx ret = grub_memcmp (&template, &gptdata.type,
5 kx sizeof (template)) == 0;
5 kx }
5 kx dev->disk->partition = p;
5 kx return ret;
5 kx }
5 kx
5 kx return 0;
5 kx }
5 kx
5 kx static int
5 kx is_prep_empty (grub_device_t dev)
5 kx {
5 kx grub_disk_addr_t dsize, addr;
5 kx grub_uint32_t buffer[32768];
5 kx
5 kx dsize = grub_disk_native_sectors (dev->disk);
5 kx for (addr = 0; addr < dsize;
5 kx addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
5 kx {
5 kx grub_size_t sz = sizeof (buffer);
5 kx grub_uint32_t *ptr;
5 kx
5 kx if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr)
5 kx sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE;
5 kx grub_disk_read (dev->disk, addr, 0, sz, buffer);
5 kx
5 kx if (addr == 0 && grub_memcmp (buffer, ELFMAG, SELFMAG) == 0)
5 kx return 1;
5 kx
5 kx for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++)
5 kx if (*ptr)
5 kx return 0;
5 kx }
5 kx
5 kx return 1;
5 kx }
5 kx
5 kx static void
5 kx bless (grub_device_t dev, const char *path, int x86)
5 kx {
5 kx struct stat st;
5 kx grub_err_t err;
5 kx
5 kx grub_util_info ("blessing %s", path);
5 kx
5 kx if (stat (path, &st) < 0)
5 kx grub_util_error (N_("cannot stat `%s': %s"),
5 kx path, strerror (errno));
5 kx
5 kx err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86);
5 kx if (err)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx grub_util_info ("blessed");
5 kx }
5 kx
5 kx static void
5 kx fill_core_services (const char *core_services)
5 kx {
5 kx char *label;
5 kx FILE *f;
5 kx char *label_text;
5 kx char *label_string = xasprintf ("%s %s", bootloader_id, product_version);
5 kx char *sysv_plist;
5 kx
5 kx label = grub_util_path_concat (2, core_services, ".disk_label");
5 kx grub_util_info ("rendering label %s", label_string);
5 kx grub_util_render_label (label_font, label_bgcolor ? : "white",
5 kx label_color ? : "black", label_string, label);
5 kx grub_util_info ("label rendered");
5 kx free (label);
5 kx label_text = grub_util_path_concat (2, core_services, ".disk_label.contentDetails");
5 kx f = grub_util_fopen (label_text, "wb");
5 kx fprintf (f, "%s\n", label_string);
5 kx fclose (f);
5 kx free (label_string);
5 kx free (label_text);
5 kx
5 kx sysv_plist = grub_util_path_concat (2, core_services, "SystemVersion.plist");
5 kx f = grub_util_fopen (sysv_plist, "wb");
5 kx fprintf (f,
5 kx "<plist version=\"1.0\">\n"
5 kx "<dict>\n"
5 kx " <key>ProductBuildVersion</key>\n"
5 kx " <string></string>\n"
5 kx " <key>ProductName</key>\n"
5 kx " <string>%s</string>\n"
5 kx " <key>ProductVersion</key>\n"
5 kx " <string>%s</string>\n"
5 kx "</dict>\n"
5 kx "</plist>\n", bootloader_id, product_version);
5 kx fclose (f);
5 kx free (sysv_plist);
5 kx }
5 kx
5 kx int
5 kx main (int argc, char *argv[])
5 kx {
5 kx int is_efi = 0;
5 kx const char *efi_distributor = NULL;
5 kx const char *efi_file = NULL;
5 kx char **grub_devices;
5 kx grub_fs_t grub_fs;
5 kx grub_device_t grub_dev = NULL;
5 kx enum grub_install_plat platform;
5 kx char *grubdir, *device_map;
5 kx char **curdev, **curdrive;
5 kx char **grub_drives;
5 kx char *relative_grubdir;
5 kx char **efidir_device_names = NULL;
5 kx grub_device_t efidir_grub_dev = NULL;
5 kx char *efidir_grub_devname;
5 kx int efidir_is_mac = 0;
5 kx int is_prep = 0;
5 kx const char *pkgdatadir;
5 kx
5 kx grub_util_host_init (&argc, &argv);
5 kx product_version = xstrdup (PACKAGE_VERSION);
5 kx pkgdatadir = grub_util_get_pkgdatadir ();
5 kx label_font = grub_util_path_concat (2, pkgdatadir, "dejavusansmono.pf2");
5 kx
5 kx argp_parse (&argp, argc, argv, 0, 0, 0);
5 kx
5 kx if (verbosity > 1)
5 kx grub_env_set ("debug", "all");
5 kx
5 kx grub_util_load_config (&config);
5 kx
5 kx if (!bootloader_id && config.grub_distributor)
5 kx {
5 kx char *ptr;
5 kx bootloader_id = xstrdup (config.grub_distributor);
5 kx for (ptr = bootloader_id; *ptr && *ptr != ' '; ptr++)
5 kx if (*ptr >= 'A' && *ptr <= 'Z')
5 kx *ptr = *ptr - 'A' + 'a';
5 kx *ptr = '\0';
5 kx }
5 kx if (!bootloader_id || bootloader_id[0] == '\0')
5 kx {
5 kx free (bootloader_id);
5 kx bootloader_id = xstrdup ("grub");
5 kx }
5 kx
5 kx if (!grub_install_source_directory)
5 kx {
5 kx if (!target)
5 kx {
5 kx const char * t;
5 kx t = get_default_platform ();
5 kx if (!t)
5 kx grub_util_error ("%s",
5 kx _("Unable to determine your platform."
5 kx " Use --target.")
5 kx );
5 kx target = xstrdup (t);
5 kx }
5 kx grub_install_source_directory
5 kx = grub_util_path_concat (2, grub_util_get_pkglibdir (), target);
5 kx }
5 kx
5 kx platform = grub_install_get_target (grub_install_source_directory);
5 kx
5 kx {
5 kx char *platname = grub_install_get_platform_name (platform);
5 kx fprintf (stderr, _("Installing for %s platform.\n"), platname);
5 kx free (platname);
5 kx }
5 kx
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx if (!disk_module)
5 kx disk_module = xstrdup ("biosdisk");
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx disk_module = xstrdup ("native");
5 kx break;
5 kx
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx if (!install_device)
5 kx grub_util_error ("%s", _("install device isn't specified"));
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx if (install_device)
5 kx is_prep = 1;
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx free (install_device);
5 kx install_device = NULL;
5 kx break;
5 kx
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx if (!bootdir)
5 kx bootdir = grub_util_path_concat (3, "/", rootdir, GRUB_BOOT_DIR_NAME);
5 kx
5 kx {
5 kx char * t = grub_util_path_concat (2, bootdir, GRUB_DIR_NAME);
5 kx grub_install_mkdir_p (t);
5 kx grubdir = grub_canonicalize_file_name (t);
5 kx if (!grubdir)
5 kx grub_util_error (_("failed to get canonical path of `%s'"), t);
5 kx free (t);
5 kx }
5 kx device_map = grub_util_path_concat (2, grubdir, "device.map");
5 kx
5 kx if (recheck)
5 kx grub_util_unlink (device_map);
5 kx
5 kx device_map_check_duplicates (device_map);
5 kx grub_util_biosdisk_init (device_map);
5 kx
5 kx /* Initialize all modules. */
5 kx grub_init_all ();
5 kx grub_gcry_init_all ();
5 kx grub_hostfs_init ();
5 kx grub_host_init ();
5 kx
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx is_efi = 1;
5 kx break;
5 kx default:
5 kx is_efi = 0;
5 kx break;
5 kx
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx /* Find the EFI System Partition. */
5 kx
5 kx if (is_efi)
5 kx {
5 kx grub_fs_t fs;
5 kx free (install_device);
5 kx install_device = NULL;
5 kx if (!efidir)
5 kx {
5 kx char *d = grub_util_path_concat (2, bootdir, "efi");
5 kx char *dr = NULL;
5 kx if (!grub_util_is_directory (d))
5 kx {
5 kx free (d);
5 kx d = grub_util_path_concat (2, bootdir, "EFI");
5 kx }
5 kx /*
5 kx The EFI System Partition may have been given directly using
5 kx --root-directory.
5 kx */
5 kx if (!grub_util_is_directory (d)
5 kx && rootdir && grub_strcmp (rootdir, "/") != 0)
5 kx {
5 kx free (d);
5 kx d = xstrdup (rootdir);
5 kx }
5 kx if (grub_util_is_directory (d))
5 kx dr = grub_make_system_path_relative_to_its_root (d);
5 kx /* Is it a mount point? */
5 kx if (dr && dr[0] == '\0')
5 kx efidir = d;
5 kx else
5 kx free (d);
5 kx free (dr);
5 kx }
5 kx if (!efidir)
5 kx grub_util_error ("%s", _("cannot find EFI directory"));
5 kx efidir_device_names = grub_guess_root_devices (efidir);
5 kx if (!efidir_device_names || !efidir_device_names[0])
5 kx grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
5 kx efidir);
5 kx install_device = efidir_device_names[0];
5 kx
5 kx for (curdev = efidir_device_names; *curdev; curdev++)
5 kx grub_util_pull_device (*curdev);
5 kx
5 kx efidir_grub_devname = grub_util_get_grub_dev (efidir_device_names[0]);
5 kx if (!efidir_grub_devname)
5 kx grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
5 kx efidir_device_names[0]);
5 kx
5 kx efidir_grub_dev = grub_device_open (efidir_grub_devname);
5 kx if (! efidir_grub_dev)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx fs = grub_fs_probe (efidir_grub_dev);
5 kx if (! fs)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx efidir_is_mac = 0;
5 kx
5 kx if (grub_strcmp (fs->name, "hfs") == 0
5 kx || grub_strcmp (fs->name, "hfsplus") == 0)
5 kx efidir_is_mac = 1;
5 kx
5 kx if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
5 kx grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
5 kx
5 kx /* The EFI specification requires that an EFI System Partition must
5 kx contain an "EFI" subdirectory, and that OS loaders are stored in
5 kx subdirectories below EFI. Vendors are expected to pick names that do
5 kx not collide with other vendors. To minimise collisions, we use the
5 kx name of our distributor if possible.
5 kx */
5 kx char *t;
5 kx efi_distributor = bootloader_id;
5 kx if (removable)
5 kx {
5 kx /* The specification makes stricter requirements of removable
5 kx devices, in order that only one image can be automatically loaded
5 kx from them. The image must always reside under /EFI/BOOT, and it
5 kx must have a specific file name depending on the architecture.
5 kx */
5 kx efi_distributor = "BOOT";
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx efi_file = "BOOTIA32.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx efi_file = "BOOTX64.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx efi_file = "BOOTIA64.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx efi_file = "BOOTARM.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx efi_file = "BOOTAA64.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx efi_file = "BOOTRISCV32.EFI";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx efi_file = "BOOTRISCV64.EFI";
5 kx break;
5 kx default:
5 kx grub_util_error ("%s", _("You've found a bug"));
5 kx break;
5 kx }
5 kx }
5 kx else
5 kx {
5 kx /* It is convenient for each architecture to have a different
5 kx efi_file, so that different versions can be installed in parallel.
5 kx */
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx efi_file = "grubia32.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx efi_file = "grubx64.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx efi_file = "grubia64.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx efi_file = "grubarm.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx efi_file = "grubaa64.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx efi_file = "grubriscv32.efi";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx efi_file = "grubriscv64.efi";
5 kx break;
5 kx default:
5 kx efi_file = "grub.efi";
5 kx break;
5 kx }
5 kx }
5 kx t = grub_util_path_concat (3, efidir, "EFI", efi_distributor);
5 kx free (efidir);
5 kx efidir = t;
5 kx grub_install_mkdir_p (efidir);
5 kx }
5 kx
5 kx if (platform == GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
5 kx {
5 kx int is_guess = 0;
5 kx if (!macppcdir)
5 kx {
5 kx char *d;
5 kx
5 kx is_guess = 1;
5 kx d = grub_util_path_concat (2, bootdir, "macppc");
5 kx if (!grub_util_is_directory (d))
5 kx {
5 kx free (d);
5 kx d = grub_util_path_concat (2, bootdir, "efi");
5 kx }
5 kx /* Find the Mac HFS(+) System Partition. */
5 kx if (!grub_util_is_directory (d))
5 kx {
5 kx free (d);
5 kx d = grub_util_path_concat (2, bootdir, "EFI");
5 kx }
5 kx if (!grub_util_is_directory (d))
5 kx {
5 kx free (d);
5 kx d = 0;
5 kx }
5 kx if (d)
5 kx macppcdir = d;
5 kx }
5 kx if (macppcdir)
5 kx {
5 kx char **macppcdir_device_names = NULL;
5 kx grub_device_t macppcdir_grub_dev = NULL;
5 kx char *macppcdir_grub_devname;
5 kx grub_fs_t fs;
5 kx
5 kx macppcdir_device_names = grub_guess_root_devices (macppcdir);
5 kx if (!macppcdir_device_names || !macppcdir_device_names[0])
5 kx grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
5 kx macppcdir);
5 kx
5 kx for (curdev = macppcdir_device_names; *curdev; curdev++)
5 kx grub_util_pull_device (*curdev);
5 kx
5 kx macppcdir_grub_devname = grub_util_get_grub_dev (macppcdir_device_names[0]);
5 kx if (!macppcdir_grub_devname)
5 kx grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
5 kx macppcdir_device_names[0]);
5 kx
5 kx macppcdir_grub_dev = grub_device_open (macppcdir_grub_devname);
5 kx if (! macppcdir_grub_dev)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx fs = grub_fs_probe (macppcdir_grub_dev);
5 kx if (! fs)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx if (grub_strcmp (fs->name, "hfs") != 0
5 kx && grub_strcmp (fs->name, "hfsplus") != 0
5 kx && !is_guess)
5 kx grub_util_error (_("filesystem on %s is neither HFS nor HFS+"),
5 kx macppcdir);
5 kx if (grub_strcmp (fs->name, "hfs") == 0
5 kx || grub_strcmp (fs->name, "hfsplus") == 0)
5 kx {
5 kx install_device = macppcdir_device_names[0];
5 kx is_prep = 0;
5 kx }
5 kx }
5 kx }
5 kx
5 kx grub_install_copy_files (grub_install_source_directory,
5 kx grubdir, platform);
5 kx
5 kx char *envfile = grub_util_path_concat (2, grubdir, "grubenv");
5 kx if (!grub_util_is_regular (envfile))
5 kx grub_util_create_envblk_file (envfile);
5 kx
5 kx size_t ndev = 0;
5 kx
5 kx /* Write device to a variable so we don't have to traverse /dev every time. */
5 kx grub_devices = grub_guess_root_devices (grubdir);
5 kx if (!grub_devices || !grub_devices[0])
5 kx grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
5 kx grubdir);
5 kx
5 kx for (curdev = grub_devices; *curdev; curdev++)
5 kx {
5 kx grub_util_pull_device (*curdev);
5 kx ndev++;
5 kx }
5 kx
5 kx grub_drives = xcalloc (ndev + 1, sizeof (grub_drives[0]));
5 kx
5 kx for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++,
5 kx curdrive++)
5 kx {
5 kx *curdrive = grub_util_get_grub_dev (*curdev);
5 kx if (! *curdrive)
5 kx grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
5 kx *curdev);
5 kx }
5 kx *curdrive = 0;
5 kx
5 kx grub_dev = grub_device_open (grub_drives[0]);
5 kx if (! grub_dev)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx grub_fs = grub_fs_probe (grub_dev);
5 kx if (! grub_fs)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx grub_install_push_module (grub_fs->name);
5 kx
5 kx if (grub_dev->disk)
5 kx probe_mods (grub_dev->disk);
5 kx
5 kx for (curdrive = grub_drives + 1; *curdrive; curdrive++)
5 kx {
5 kx grub_device_t dev = grub_device_open (*curdrive);
5 kx if (!dev)
5 kx continue;
5 kx if (dev->disk)
5 kx probe_mods (dev->disk);
5 kx grub_device_close (dev);
5 kx }
5 kx
5 kx if (!config.is_cryptodisk_enabled && have_cryptodisk)
5 kx grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. "
5 kx "Set `%s' in file `%s'"), "GRUB_ENABLE_CRYPTODISK=y",
5 kx grub_util_get_config_filename ());
5 kx
5 kx if (disk_module && grub_strcmp (disk_module, "ata") == 0)
5 kx grub_install_push_module ("pata");
5 kx else if (disk_module && grub_strcmp (disk_module, "native") == 0)
5 kx {
5 kx grub_install_push_module ("pata");
5 kx grub_install_push_module ("ahci");
5 kx grub_install_push_module ("ohci");
5 kx grub_install_push_module ("uhci");
5 kx grub_install_push_module ("ehci");
5 kx grub_install_push_module ("usbms");
5 kx }
5 kx else if (disk_module && disk_module[0])
5 kx grub_install_push_module (disk_module);
5 kx
5 kx relative_grubdir = grub_make_system_path_relative_to_its_root (grubdir);
5 kx if (relative_grubdir[0] == '\0')
5 kx {
5 kx free (relative_grubdir);
5 kx relative_grubdir = xstrdup ("/");
5 kx }
5 kx
5 kx char *platname = grub_install_get_platform_name (platform);
5 kx char *platdir;
5 kx {
5 kx char *t = grub_util_path_concat (2, grubdir,
5 kx platname);
5 kx platdir = grub_canonicalize_file_name (t);
5 kx if (!platdir)
5 kx grub_util_error (_("failed to get canonical path of `%s'"),
5 kx t);
5 kx free (t);
5 kx }
5 kx load_cfg = grub_util_path_concat (2, platdir,
5 kx "load.cfg");
5 kx
5 kx grub_util_unlink (load_cfg);
5 kx
5 kx if (debug_image && debug_image[0])
5 kx {
5 kx load_cfg_f = grub_util_fopen (load_cfg, "wb");
5 kx have_load_cfg = 1;
5 kx fprintf (load_cfg_f, "set debug='%s'\n",
5 kx debug_image);
5 kx }
5 kx char *prefix_drive = NULL;
5 kx char *install_drive = NULL;
5 kx
5 kx if (install_device)
5 kx {
5 kx if (install_device[0] == '('
5 kx && install_device[grub_strlen (install_device) - 1] == ')')
5 kx {
5 kx size_t len = grub_strlen (install_device) - 2;
5 kx install_drive = xmalloc (len + 1);
5 kx memcpy (install_drive, install_device + 1, len);
5 kx install_drive[len] = '\0';
5 kx }
5 kx else
5 kx {
5 kx grub_util_pull_device (install_device);
5 kx install_drive = grub_util_get_grub_dev (install_device);
5 kx if (!install_drive)
5 kx grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
5 kx install_device);
5 kx }
5 kx }
5 kx
5 kx if (!have_abstractions)
5 kx {
5 kx if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
5 kx || grub_drives[1]
5 kx || (!install_drive
5 kx && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
5 kx || (install_drive && !is_same_disk (grub_drives[0], install_drive))
5 kx || !have_bootdev (platform))
5 kx {
5 kx char *uuid = NULL;
5 kx /* generic method (used on coreboot and ata mod). */
5 kx if (!force_file_id
5 kx && grub_fs->fs_uuid && grub_fs->fs_uuid (grub_dev, &uuid))
5 kx {
5 kx grub_print_error ();
5 kx grub_errno = 0;
5 kx uuid = NULL;
5 kx }
5 kx
5 kx if (!load_cfg_f)
5 kx load_cfg_f = grub_util_fopen (load_cfg, "wb");
5 kx have_load_cfg = 1;
5 kx if (uuid)
5 kx {
5 kx fprintf (load_cfg_f, "search.fs_uuid %s root ",
5 kx uuid);
5 kx grub_install_push_module ("search_fs_uuid");
5 kx }
5 kx else
5 kx {
5 kx char *rndstr = get_rndstr ();
5 kx char *fl = grub_util_path_concat (3, grubdir,
5 kx "uuid", rndstr);
5 kx char *fldir = grub_util_path_concat (2, grubdir,
5 kx "uuid");
5 kx char *relfl;
5 kx FILE *flf;
5 kx grub_install_mkdir_p (fldir);
5 kx flf = grub_util_fopen (fl, "w");
5 kx if (!flf)
5 kx grub_util_error (_("Can't create file: %s"), strerror (errno));
5 kx fclose (flf);
5 kx relfl = grub_make_system_path_relative_to_its_root (fl);
5 kx fprintf (load_cfg_f, "search.file %s root ",
5 kx relfl);
5 kx grub_install_push_module ("search_fs_file");
5 kx }
5 kx for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++,
5 kx curdrive++)
5 kx {
5 kx const char *map;
5 kx char *g = NULL;
5 kx grub_device_t dev;
5 kx if (curdrive == grub_drives)
5 kx dev = grub_dev;
5 kx else
5 kx dev = grub_device_open (*curdrive);
5 kx if (!dev)
5 kx continue;
5 kx
5 kx if (dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID)
5 kx {
5 kx grub_util_fprint_full_disk_name (load_cfg_f,
5 kx dev->disk->name,
5 kx dev);
5 kx fprintf (load_cfg_f, " ");
5 kx if (dev != grub_dev)
5 kx grub_device_close (dev);
5 kx continue;
5 kx }
5 kx
5 kx map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
5 kx
5 kx if (map)
5 kx {
5 kx grub_util_fprint_full_disk_name (load_cfg_f, map, dev);
5 kx fprintf (load_cfg_f, " ");
5 kx }
5 kx
5 kx
5 kx if (disk_module && disk_module[0]
5 kx && grub_strcmp (disk_module, "biosdisk") != 0)
5 kx g = grub_util_guess_baremetal_drive (*curdev);
5 kx else
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx g = grub_util_guess_bios_drive (*curdev);
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx g = grub_util_guess_efi_drive (*curdev);
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx {
5 kx const char * ofpath = grub_util_devname_to_ofpath (*curdev);
5 kx g = xasprintf ("ieee1275/%s", ofpath);
5 kx break;
5 kx }
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx g = grub_util_guess_baremetal_drive (*curdev);
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx grub_util_warn ("%s", _("no hints available for your platform. Expect reduced performance"));
5 kx break;
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx if (g)
5 kx {
5 kx grub_util_fprint_full_disk_name (load_cfg_f, g, dev);
5 kx fprintf (load_cfg_f, " ");
5 kx free (g);
5 kx }
5 kx if (dev != grub_dev)
5 kx grub_device_close (dev);
5 kx }
5 kx fprintf (load_cfg_f, "\n");
5 kx char *escaped_relpath = escape (relative_grubdir);
5 kx fprintf (load_cfg_f, "set prefix=($root)'%s'\n",
5 kx escaped_relpath);
5 kx }
5 kx else
5 kx {
5 kx /* We need to hardcode the partition number in the core image's prefix. */
5 kx char *p;
5 kx for (p = grub_drives[0]; *p; )
5 kx {
5 kx if (*p == '\\' && p[1])
5 kx {
5 kx p += 2;
5 kx continue;
5 kx }
5 kx if (*p == ',' || *p == '\0')
5 kx break;
5 kx p++;
5 kx }
5 kx prefix_drive = xasprintf ("(%s)", p);
5 kx }
5 kx }
5 kx else
5 kx {
5 kx if (config.is_cryptodisk_enabled)
5 kx {
5 kx if (grub_dev->disk)
5 kx probe_cryptodisk_uuid (grub_dev->disk);
5 kx
5 kx for (curdrive = grub_drives + 1; *curdrive; curdrive++)
5 kx {
5 kx grub_device_t dev = grub_device_open (*curdrive);
5 kx if (!dev)
5 kx continue;
5 kx if (dev->disk)
5 kx probe_cryptodisk_uuid (dev->disk);
5 kx grub_device_close (dev);
5 kx }
5 kx }
5 kx prefix_drive = xasprintf ("(%s)", grub_drives[0]);
5 kx }
5 kx
5 kx char mkimage_target[200];
5 kx const char *core_name = NULL;
5 kx
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx core_name = "core.efi";
5 kx snprintf (mkimage_target, sizeof (mkimage_target),
5 kx "%s-%s",
5 kx grub_install_get_platform_cpu (platform),
5 kx grub_install_get_platform_platform (platform));
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx core_name = "core.elf";
5 kx snprintf (mkimage_target, sizeof (mkimage_target),
5 kx "%s-%s-elf",
5 kx grub_install_get_platform_cpu (platform),
5 kx grub_install_get_platform_platform (platform));
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx core_name = "core.elf";
5 kx snprintf (mkimage_target, sizeof (mkimage_target),
5 kx "%s-%s",
5 kx grub_install_get_platform_cpu (platform),
5 kx grub_install_get_platform_platform (platform));
5 kx break;
5 kx
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx snprintf (mkimage_target, sizeof (mkimage_target),
5 kx "%s-%s",
5 kx grub_install_get_platform_cpu (platform),
5 kx grub_install_get_platform_platform (platform));
5 kx core_name = "core.img";
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx strcpy (mkimage_target, "sparc64-ieee1275-raw");
5 kx core_name = "core.img";
5 kx break;
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx if (!core_name)
5 kx grub_util_error ("%s", _("You've found a bug"));
5 kx
5 kx if (load_cfg_f)
5 kx fclose (load_cfg_f);
5 kx
5 kx char *imgfile = grub_util_path_concat (2, platdir,
5 kx core_name);
5 kx char *prefix = xasprintf ("%s%s", prefix_drive ? : "",
5 kx relative_grubdir);
5 kx grub_install_make_image_wrap (/* source dir */ grub_install_source_directory,
5 kx /*prefix */ prefix,
5 kx /* output */ imgfile,
5 kx /* memdisk */ NULL,
5 kx have_load_cfg ? load_cfg : NULL,
5 kx /* image target */ mkimage_target, 0);
5 kx /* Backward-compatibility kludges. */
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx {
5 kx char *dst = grub_util_path_concat (2, bootdir, "grub.elf");
5 kx grub_install_copy_file (imgfile, dst, 1);
5 kx free (dst);
5 kx }
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx {
5 kx char *dst = grub_util_path_concat (2, grubdir, "grub");
5 kx grub_install_copy_file (imgfile, dst, 1);
5 kx free (dst);
5 kx }
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx {
5 kx char *dst = grub_util_path_concat (2, platdir, "grub.efi");
5 kx grub_install_make_image_wrap (/* source dir */ grub_install_source_directory,
5 kx /* prefix */ "",
5 kx /* output */ dst,
5 kx /* memdisk */ NULL,
5 kx have_load_cfg ? load_cfg : NULL,
5 kx /* image target */ mkimage_target, 0);
5 kx }
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx break;
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx /* Perform the platform-dependent install */
5 kx
5 kx switch (platform)
5 kx {
5 kx case GRUB_INSTALL_PLATFORM_I386_PC:
5 kx {
5 kx char *boot_img_src = grub_util_path_concat (2,
5 kx grub_install_source_directory,
5 kx "boot.img");
5 kx char *boot_img = grub_util_path_concat (2, platdir,
5 kx "boot.img");
5 kx grub_install_copy_file (boot_img_src, boot_img, 1);
5 kx
5 kx grub_util_info ("%sgrub-bios-setup %s %s %s %s %s --directory='%s' --device-map='%s' '%s'",
5 kx /* TRANSLATORS: This is a prefix in the log to indicate that usually
5 kx a command would be executed but due to an option was skipped. */
5 kx install_bootsector ? "" : _("NOT RUNNING: "),
5 kx allow_floppy ? "--allow-floppy " : "",
5 kx verbosity ? "--verbose " : "",
5 kx force ? "--force " : "",
5 kx !fs_probe ? "--skip-fs-probe" : "",
5 kx !add_rs_codes ? "--no-rs-codes" : "",
5 kx platdir,
5 kx device_map,
5 kx install_device);
5 kx
5 kx /* Now perform the installation. */
5 kx if (install_bootsector)
5 kx {
5 kx grub_util_bios_setup (platdir, "boot.img", "core.img",
5 kx install_drive, force,
5 kx fs_probe, allow_floppy, add_rs_codes,
5 kx !grub_install_is_short_mbrgap_supported ());
5 kx
5 kx grub_set_install_backup_ponr ();
5 kx }
5 kx break;
5 kx }
5 kx case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
5 kx {
5 kx char *boot_img_src = grub_util_path_concat (2,
5 kx grub_install_source_directory,
5 kx "boot.img");
5 kx char *boot_img = grub_util_path_concat (2, platdir,
5 kx "boot.img");
5 kx grub_install_copy_file (boot_img_src, boot_img, 1);
5 kx
5 kx grub_util_info ("%sgrub-sparc64-setup %s %s %s %s --directory='%s' --device-map='%s' '%s'",
5 kx install_bootsector ? "" : "NOT RUNNING: ",
5 kx allow_floppy ? "--allow-floppy " : "",
5 kx verbosity ? "--verbose " : "",
5 kx force ? "--force " : "",
5 kx !fs_probe ? "--skip-fs-probe" : "",
5 kx platdir,
5 kx device_map,
5 kx install_drive);
5 kx
5 kx /* Now perform the installation. */
5 kx if (install_bootsector)
5 kx {
5 kx grub_util_sparc_setup (platdir, "boot.img", "core.img",
5 kx install_drive, force,
5 kx fs_probe, allow_floppy,
5 kx 0 /* unused */, 0 /* unused */ );
5 kx
5 kx grub_set_install_backup_ponr ();
5 kx }
5 kx break;
5 kx }
5 kx
5 kx case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
5 kx if (macppcdir)
5 kx {
5 kx char *core_services = grub_util_path_concat (4, macppcdir,
5 kx "System", "Library",
5 kx "CoreServices");
5 kx char *mach_kernel = grub_util_path_concat (2, macppcdir,
5 kx "mach_kernel");
5 kx char *grub_elf, *bootx;
5 kx FILE *f;
5 kx grub_device_t ins_dev;
5 kx char *grub_chrp = grub_util_path_concat (2,
5 kx grub_install_source_directory,
5 kx "grub.chrp");
5 kx
5 kx grub_install_mkdir_p (core_services);
5 kx
5 kx bootx = grub_util_path_concat (2, core_services, "BootX");
5 kx grub_install_copy_file (grub_chrp, bootx, 1);
5 kx
5 kx grub_elf = grub_util_path_concat (2, core_services, "grub.elf");
5 kx grub_install_copy_file (imgfile, grub_elf, 1);
5 kx
5 kx grub_set_install_backup_ponr ();
5 kx
5 kx f = grub_util_fopen (mach_kernel, "a+");
5 kx if (!f)
5 kx grub_util_error (_("Can't create file: %s"), strerror (errno));
5 kx fclose (f);
5 kx
5 kx fill_core_services (core_services);
5 kx
5 kx ins_dev = grub_device_open (install_drive);
5 kx if (ins_dev == NULL)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx bless (ins_dev, core_services, 0);
5 kx
5 kx if (update_nvram)
5 kx {
5 kx const char *dev;
5 kx int partno;
5 kx
5 kx partno = ins_dev->disk->partition
5 kx ? ins_dev->disk->partition->number + 1 : 0;
5 kx dev = grub_util_get_os_disk (install_device);
5 kx grub_install_register_ieee1275 (0, dev, partno,
5 kx "\\\\BootX");
5 kx }
5 kx grub_device_close (ins_dev);
5 kx free (grub_elf);
5 kx free (bootx);
5 kx free (mach_kernel);
5 kx free (grub_chrp);
5 kx break;
5 kx }
5 kx /* If a install device is defined, copy the core.elf to PReP partition. */
5 kx if (is_prep && install_device && install_device[0])
5 kx {
5 kx grub_device_t ins_dev;
5 kx ins_dev = grub_device_open (install_drive);
5 kx if (!ins_dev || !is_prep_partition (ins_dev))
5 kx {
5 kx grub_util_error ("%s", _("the chosen partition is not a PReP partition"));
5 kx }
5 kx if (is_prep_empty (ins_dev))
5 kx {
5 kx if (write_to_disk (ins_dev, imgfile))
5 kx grub_util_error ("%s", _("failed to copy Grub to the PReP partition"));
5 kx }
5 kx else
5 kx {
5 kx char *s = xasprintf ("dd if=/dev/zero of=%s", install_device);
5 kx grub_util_error (_("the PReP partition is not empty. If you are sure you want to use it, run dd to clear it: `%s'"),
5 kx s);
5 kx }
5 kx grub_device_close (ins_dev);
5 kx if (update_nvram)
5 kx grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),
5 kx 0, NULL);
5 kx break;
5 kx }
5 kx /* fallthrough. */
5 kx case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
5 kx if (update_nvram)
5 kx {
5 kx const char *dev;
5 kx char *relpath;
5 kx int partno;
5 kx relpath = grub_make_system_path_relative_to_its_root (imgfile);
5 kx partno = grub_dev->disk->partition
5 kx ? grub_dev->disk->partition->number + 1 : 0;
5 kx dev = grub_util_get_os_disk (grub_devices[0]);
5 kx grub_install_register_ieee1275 (0, dev,
5 kx partno, relpath);
5 kx }
5 kx break;
5 kx case GRUB_INSTALL_PLATFORM_MIPS_ARC:
5 kx grub_install_sgi_setup (install_device, imgfile, "grub");
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_I386_EFI:
5 kx if (!efidir_is_mac)
5 kx {
5 kx char *dst = grub_util_path_concat (2, efidir, "grub.efi");
5 kx /* For old macs. Suggested by Peter Jones. */
5 kx grub_install_copy_file (imgfile, dst, 1);
5 kx free (dst);
5 kx }
5 kx /* Fallthrough. */
5 kx case GRUB_INSTALL_PLATFORM_X86_64_EFI:
5 kx if (efidir_is_mac)
5 kx {
5 kx char *boot_efi;
5 kx char *core_services = grub_util_path_concat (4, efidir,
5 kx "System", "Library",
5 kx "CoreServices");
5 kx char *mach_kernel = grub_util_path_concat (2, efidir,
5 kx "mach_kernel");
5 kx FILE *f;
5 kx grub_device_t ins_dev;
5 kx
5 kx grub_install_mkdir_p (core_services);
5 kx
5 kx boot_efi = grub_util_path_concat (2, core_services, "boot.efi");
5 kx grub_install_copy_file (imgfile, boot_efi, 1);
5 kx
5 kx grub_set_install_backup_ponr ();
5 kx
5 kx f = grub_util_fopen (mach_kernel, "r+");
5 kx if (!f)
5 kx grub_util_error (_("Can't create file: %s"), strerror (errno));
5 kx fclose (f);
5 kx
5 kx fill_core_services(core_services);
5 kx
5 kx ins_dev = grub_device_open (install_drive);
5 kx if (ins_dev == NULL)
5 kx grub_util_error ("%s", grub_errmsg);
5 kx
5 kx bless (ins_dev, boot_efi, 1);
5 kx if (!removable && update_nvram)
5 kx {
5 kx /* Try to make this image bootable using the EFI Boot Manager, if available. */
5 kx int ret;
5 kx ret = grub_install_register_efi (efidir_grub_dev,
5 kx "\\System\\Library\\CoreServices",
5 kx efi_distributor);
5 kx if (ret)
5 kx grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
5 kx strerror (ret));
5 kx }
5 kx
5 kx grub_device_close (ins_dev);
5 kx free (boot_efi);
5 kx free (mach_kernel);
5 kx break;
5 kx }
5 kx /* FALLTHROUGH */
5 kx case GRUB_INSTALL_PLATFORM_ARM_EFI:
5 kx case GRUB_INSTALL_PLATFORM_ARM64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
5 kx case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
5 kx case GRUB_INSTALL_PLATFORM_IA64_EFI:
5 kx {
5 kx char *dst = grub_util_path_concat (2, efidir, efi_file);
5 kx grub_install_copy_file (imgfile, dst, 1);
5 kx
5 kx grub_set_install_backup_ponr ();
5 kx
5 kx free (dst);
5 kx }
5 kx if (!removable && update_nvram)
5 kx {
5 kx char * efifile_path;
5 kx char * part;
5 kx int ret;
5 kx
5 kx /* Try to make this image bootable using the EFI Boot Manager, if available. */
5 kx if (!efi_distributor || efi_distributor[0] == '\0')
5 kx grub_util_error ("%s", _("EFI bootloader id isn't specified."));
5 kx efifile_path = xasprintf ("\\EFI\\%s\\%s",
5 kx efi_distributor,
5 kx efi_file);
5 kx part = (efidir_grub_dev->disk->partition
5 kx ? grub_partition_get_name (efidir_grub_dev->disk->partition)
5 kx : 0);
5 kx grub_util_info ("Registering with EFI: distributor = `%s',"
5 kx " path = `%s', ESP at %s%s%s",
5 kx efi_distributor, efifile_path,
5 kx efidir_grub_dev->disk->name,
5 kx (part ? ",": ""), (part ? : ""));
5 kx grub_free (part);
5 kx ret = grub_install_register_efi (efidir_grub_dev,
5 kx efifile_path, efi_distributor);
5 kx if (ret)
5 kx grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
5 kx strerror (ret));
5 kx }
5 kx break;
5 kx
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
5 kx case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
5 kx case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
5 kx case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
5 kx case GRUB_INSTALL_PLATFORM_I386_QEMU:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN:
5 kx case GRUB_INSTALL_PLATFORM_X86_64_XEN:
5 kx case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
5 kx grub_util_warn ("%s",
5 kx _("WARNING: no platform-specific install was performed"));
5 kx break;
5 kx /* pacify warning. */
5 kx case GRUB_INSTALL_PLATFORM_MAX:
5 kx break;
5 kx }
5 kx
5 kx /*
5 kx * Either there are no platform specific code, or it didn't raise
5 kx * ponr. Raise it here, because usually this is already past point
5 kx * of no return. If we leave this flag false, at exit all the modules
5 kx * will be removed from the prefix which would be very confusing.
5 kx */
5 kx grub_set_install_backup_ponr ();
5 kx
5 kx fprintf (stderr, "%s\n", _("Installation finished. No error reported."));
5 kx
5 kx /* Free resources. */
5 kx grub_gcry_fini_all ();
5 kx grub_fini_all ();
5 kx
5 kx return 0;
5 kx }