+2013-12-17 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Implement better integration with Mac firmware.
+
2013-12-17 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/multiboot_mbi2.c: Implement special value for
common_nodist = grub_script.tab.h;
common = grub-core/commands/blocklist.c;
+ common = grub-core/commands/macbless.c;
common = grub-core/commands/xnu_uuid.c;
common = grub-core/commands/testload.c;
common = grub-core/commands/ls.c;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
+program = {
+ name = grub-macbless;
+ installdir = sbin;
+ mansection = 1;
+ common = util/grub-macbless.c;
+ common = grub-core/osdep/init.c;
+ common = grub-core/kern/emu/argp_common.c;
+
+ ldadd = libgrubmods.a;
+ ldadd = libgrubgcry.a;
+ ldadd = libgrubkern.a;
+ ldadd = grub-core/gnulib/libgnu.a;
+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+};
+
data = {
common = util/grub.d/README;
installdir = grubconf;
common = grub-core/osdep/blocklist.c;
common = grub-core/osdep/config.c;
common = util/config.c;
+ common = util/render-label.c;
+ common = grub-core/kern/emu/hostfs.c;
+ common = grub-core/disk/host.c;
common = util/resolve.c;
enable = noemu;
--- /dev/null
+[NAME]
+grub-macbless \- bless a mac file/directory
+[SEE ALSO]
+.BR grub-install (1)
common = fs/zfs/zfsinfo.c;
};
+module = {
+ name = macbless;
+ common = commands/macbless.c;
+};
+
module = {
name = pxe;
i386_pc = net/drivers/i386/pc/pxe.c;
--- /dev/null
+/* hfspbless.c - set the hfs+ boot directory. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2005,2007,2008,2009,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/command.h>
+#include <grub/fs.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/hfsplus.h>
+#include <grub/hfs.h>
+#include <grub/partition.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+
+struct find_node_context
+{
+ grub_uint64_t inode_found;
+ char *dirname;
+ enum
+ { NONE, FILE, DIR } found;
+};
+
+static int
+find_inode (const char *filename,
+ const struct grub_dirhook_info *info, void *data)
+{
+ struct find_node_context *ctx = data;
+ if (!info->inodeset)
+ return 0;
+
+ if ((grub_strcmp (ctx->dirname, filename) == 0
+ || (info->case_insensitive
+ && grub_strcasecmp (ctx->dirname, filename) == 0)))
+ {
+ ctx->inode_found = info->inode;
+ ctx->found = info->dir ? DIR : FILE;
+ }
+ return 0;
+}
+
+grub_err_t
+grub_mac_bless_inode (grub_device_t dev, grub_uint64_t inode, int is_dir,
+ int intel)
+{
+ grub_err_t err;
+ union
+ {
+ struct grub_hfs_sblock hfs;
+ struct grub_hfsplus_volheader hfsplus;
+ } volheader;
+ grub_disk_addr_t embedded_offset;
+
+ if (intel && is_dir)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "can't bless a directory for mactel");
+ if (!intel && !is_dir)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "can't bless a file for mac PPC");
+
+ /* Read the bootblock. */
+ err = grub_disk_read (dev->disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
+ (char *) &volheader);
+ if (err)
+ return err;
+
+ embedded_offset = 0;
+ if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
+ {
+ int extent_start;
+ int ablk_size;
+ int ablk_start;
+
+ /* See if there's an embedded HFS+ filesystem. */
+ if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
+ {
+ if (intel)
+ volheader.hfs.intel_bootfile = grub_be_to_cpu32 (inode);
+ else
+ volheader.hfs.ppc_bootdir = grub_be_to_cpu32 (inode);
+ return GRUB_ERR_NONE;
+ }
+
+ /* Calculate the offset needed to translate HFS+ sector numbers. */
+ extent_start =
+ grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block);
+ ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
+ ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
+ embedded_offset = (ablk_start
+ + extent_start
+ * (ablk_size >> GRUB_DISK_SECTOR_BITS));
+
+ err =
+ grub_disk_read (dev->disk, embedded_offset + GRUB_HFSPLUS_SBLOCK, 0,
+ sizeof (volheader), (char *) &volheader);
+ if (err)
+ return err;
+ }
+
+ if ((grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUS_MAGIC)
+ && (grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUSX_MAGIC))
+ return grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
+ if (intel)
+ volheader.hfsplus.intel_bootfile = grub_be_to_cpu32 (inode);
+ else
+ volheader.hfsplus.ppc_bootdir = grub_be_to_cpu32 (inode);
+
+ return grub_disk_write (dev->disk, embedded_offset + GRUB_HFSPLUS_SBLOCK, 0,
+ sizeof (volheader), (char *) &volheader);
+}
+
+grub_err_t
+grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel)
+{
+ grub_fs_t fs;
+
+ char *path, *tail;
+ struct find_node_context ctx;
+
+ fs = grub_fs_probe (dev);
+ if (!fs || (grub_strcmp (fs->name, "hfsplus") != 0
+ && grub_strcmp (fs->name, "hfs") != 0))
+ return grub_error (GRUB_ERR_BAD_FS, "no suitable FS found");
+
+ path = grub_strdup (path_in);
+ if (!path)
+ return grub_errno;
+
+ tail = path + grub_strlen (path) - 1;
+
+ /* Remove trailing '/'. */
+ while (tail != path && *tail == '/')
+ *(tail--) = 0;
+
+ tail = grub_strrchr (path, '/');
+ ctx.found = 0;
+
+ if (tail)
+ {
+ *tail = 0;
+ ctx.dirname = tail + 1;
+
+ (fs->dir) (dev, *path == 0 ? "/" : path, find_inode, &ctx);
+ }
+ else
+ {
+ ctx.dirname = path + 1;
+ (fs->dir) (dev, "/", find_inode, &ctx);
+ }
+ if (!ctx.found)
+ {
+ grub_free (path);
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
+ path_in);
+ }
+ grub_free (path);
+
+ return grub_mac_bless_inode (dev, ctx.inode_found, (ctx.found == DIR),
+ intel);
+}
+
+static grub_err_t
+grub_cmd_macbless (grub_command_t cmd, int argc, char **args)
+{
+ char *device_name;
+ char *path = 0;
+ grub_device_t dev;
+ grub_err_t err;
+
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+ device_name = grub_file_get_device_name (args[0]);
+ dev = grub_device_open (device_name);
+
+ path = grub_strchr (args[0], ')');
+ if (!path)
+ path = args[0];
+ else
+ path = path + 1;
+
+ if (!path || *path == 0 || !device_name)
+ {
+ if (dev)
+ grub_device_close (dev);
+
+ grub_free (device_name);
+ grub_free (path);
+
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
+ }
+
+ err = grub_mac_bless_file (dev, path, cmd->name[3] == 't');
+
+ grub_device_close (dev);
+ grub_free (device_name);
+ return err;
+}
+
+static grub_command_t cmd, cmd_ppc;
+\f
+GRUB_MOD_INIT(macbless)
+{
+ cmd = grub_register_command ("mactelbless", grub_cmd_macbless,
+ N_("FILE"),
+ N_
+ ("Bless FILE of HFS or HFS+ partition for intel macs."));
+ cmd_ppc =
+ grub_register_command ("macppcbless", grub_cmd_macbless, N_("DIR"),
+ N_
+ ("Bless DIR of HFS or HFS+ partition for PPC macs."));
+}
+
+GRUB_MOD_FINI(macbless)
+{
+ grub_unregister_command (cmd);
+ grub_unregister_command (cmd_ppc);
+}
{
info.dir = 1;
info.mtimeset = 1;
+ info.inodeset = 1;
info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
+ info.inode = grub_be_to_cpu32 (drec->dirid);
return ctx->hook (fname, &info, ctx->hook_data);
}
if (frec->type == GRUB_HFS_FILETYPE_FILE)
{
info.dir = 0;
info.mtimeset = 1;
+ info.inodeset = 1;
info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
+ info.inode = grub_be_to_cpu32 (frec->fileid);
return ctx->hook (fname, &info, ctx->hook_data);
}
GRUB_MOD_LICENSE ("GPLv3+");
-#define GRUB_HFSPLUS_MAGIC 0x482B
-#define GRUB_HFSPLUSX_MAGIC 0x4858
-#define GRUB_HFSPLUS_SBLOCK 2
-
-
/* The type of node. */
enum grub_hfsplus_btnode_type
{
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1;
info.mtime = node->mtime;
+ info.inodeset = 1;
+ info.inode = node->fileid;
info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE);
grub_free (node);
return ctx->hook (filename, &info, ctx->hook_data);
unsigned dir:1;
unsigned mtimeset:1;
unsigned case_insensitive:1;
+ unsigned inodeset:1;
grub_int32_t mtime;
+ grub_uint64_t inode;
};
typedef int (*grub_fs_dir_hook_t) (const char *filename,
/* A pascal style string that holds the volumename. */
grub_uint8_t volname[28];
- grub_uint8_t unused5[52];
+ grub_uint8_t unused5[28];
+
+ grub_uint32_t ppc_bootdir;
+ grub_uint32_t intel_bootfile;
+ /* Folder opened when disk is mounted. Unused by GRUB. */
+ grub_uint32_t showfolder;
+ grub_uint32_t os9folder;
+ grub_uint8_t unused6[4];
+ grub_uint32_t osxfolder;
+
grub_uint64_t num_serial;
grub_uint16_t embed_sig;
struct grub_hfs_extent embed_extent;
- grub_uint8_t unused6[4];
+ grub_uint8_t unused7[4];
grub_hfs_datarecord_t extent_recs;
grub_uint32_t catalog_size;
grub_hfs_datarecord_t catalog_recs;
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009,2012,2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
#include <grub/types.h>
#include <grub/disk.h>
+#define GRUB_HFSPLUS_MAGIC 0x482B
+#define GRUB_HFSPLUSX_MAGIC 0x4858
+#define GRUB_HFSPLUS_SBLOCK 2
+
/* A HFS+ extent. */
struct grub_hfsplus_extent
{
grub_uint32_t utime;
grub_uint8_t unused2[16];
grub_uint32_t blksize;
- grub_uint8_t unused3[60];
+ grub_uint8_t unused3[36];
+
+ grub_uint32_t ppc_bootdir;
+ grub_uint32_t intel_bootfile;
+ /* Folder opened when disk is mounted. Unused by GRUB. */
+ grub_uint32_t showfolder;
+ grub_uint32_t os9folder;
+ grub_uint8_t unused4[4];
+ grub_uint32_t osxfolder;
+
grub_uint64_t num_serial;
struct grub_hfsplus_forkdata allocations_file;
struct grub_hfsplus_forkdata extents_file;
struct grub_hfsplus_key_internal *keyb),
struct grub_hfsplus_btnode **matchnode,
grub_off_t *keyoffset);
+grub_err_t
+grub_mac_bless_inode (grub_device_t dev, grub_uint64_t inode, int is_dir,
+ int intel);
+grub_err_t
+grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel);
#include <grub/gpt_partition.h>
#include <grub/emu/config.h>
#include <grub/util/ofpath.h>
+#include <grub/hfsplus.h>
#include <string.h>
static int force_file_id = 0;
static char *disk_module = NULL;
static char *efidir = NULL;
+static char *macppcdir = NULL;
static int force = 0;
static int have_abstractions = 0;
static int have_cryptodisk = 0;
static FILE * load_cfg_f = NULL;
static char *load_cfg;
static int install_bootsector = 1;
+static char *label_font;
+static char *label_color;
+static char *label_bgcolor;
+static char *product_version;
static int add_rs_codes = 1;
enum
OPTION_DISK_MODULE,
OPTION_NO_BOOTSECTOR,
OPTION_NO_RS_CODES,
+ OPTION_MACPPC_DIRECTORY,
+ OPTION_LABEL_FONT,
+ OPTION_LABEL_COLOR,
+ OPTION_LABEL_BGCOLOR,
+ OPTION_PRODUCT_VERSION
};
static int fs_probe = 1;
install_bootsector = 0;
return 0;
+ case OPTION_PRODUCT_VERSION:
+ free (product_version);
+ product_version = xstrdup (arg);
+ 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;
+
/* Accept and ignore for compatibility. */
case OPTION_FONT:
case OPTION_MKRELPATH:
bootdir = xstrdup (arg);
return 0;
+ case OPTION_MACPPC_DIRECTORY:
+ free (macppcdir);
+ macppcdir = xstrdup (arg);
+ return 0;
+
case OPTION_EFI_DIRECTORY:
free (efidir);
efidir = xstrdup (arg);
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},
+ N_("the ID of bootloader. This option is only available on EFI and Macs."), 2},
{"efi-directory", OPTION_EFI_DIRECTORY, N_("DIR"), 0,
N_("use DIR as the EFI System Partition root."), 2},
+ {"macppc-directory", OPTION_MACPPC_DIRECTORY, N_("DIR"), 0,
+ N_("use DIR for PPC MAC install."), 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-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
{0, 0, 0, 0, 0, 0}
};
return 1;
}
+static void
+bless (grub_device_t dev, const char *path, int x86)
+{
+ struct stat st;
+ grub_err_t err;
+
+ grub_util_info ("blessing %s", path);
+
+ if (stat (path, &st) < 0)
+ grub_util_error (N_("cannot stat `%s': %s"),
+ path, strerror (errno));
+
+ err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86);
+ if (err)
+ grub_util_error ("%s", grub_errmsg);
+ grub_util_info ("blessed\n");
+}
+
+static void
+fill_core_services (const char *core_services)
+{
+ char *label;
+ FILE *f;
+ char *label_text;
+ char *label_string = xasprintf ("%s %s", bootloader_id, product_version);
+ char *sysv_plist;
+
+ label = grub_util_path_concat (2, core_services, ".disk_label");
+ grub_util_info ("rendering label %s", label_string);
+ grub_util_render_label (label_font, label_bgcolor ? : "white",
+ label_color ? : "black", label_string, label);
+ grub_util_info ("label rendered");
+ 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);
+
+ sysv_plist = grub_util_path_concat (2, core_services, "SystemVersion.plist");
+ f = grub_util_fopen (sysv_plist, "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", bootloader_id, product_version);
+ fclose (f);
+ free (sysv_plist);
+}
+
int
main (int argc, char *argv[])
{
char **efidir_device_names = NULL;
grub_device_t efidir_grub_dev = NULL;
char *efidir_grub_devname;
+ int efidir_is_mac = 0;
+ int is_prep = 0;
+ const char *pkgdatadir;
grub_util_host_init (&argc, &argv);
+ product_version = xstrdup (PACKAGE_VERSION);
+ pkgdatadir = grub_util_get_pkgdatadir ();
+ label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
argp_parse (&argp, argc, argv, 0, 0, 0);
if (!install_device)
grub_util_error ("%s", _("install device isn't specified"));
break;
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ if (install_device)
+ is_prep = 1;
+ 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:
/* Initialize all modules. */
grub_init_all ();
grub_gcry_init_all ();
+ grub_hostfs_init ();
+ grub_host_init ();
+
switch (platform)
{
case GRUB_INSTALL_PLATFORM_I386_EFI:
if (! fs)
grub_util_error ("%s", grub_errmsg);
- if (grub_strcmp (fs->name, "fat") != 0)
+ efidir_is_mac = 0;
+
+ if (grub_strcmp (fs->name, "hfs") == 0
+ || grub_strcmp (fs->name, "hfsplus") == 0)
+ efidir_is_mac = 1;
+
+ if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
grub_util_error (_("%s doesn't look like an EFI partition.\n"), efidir);
/* The EFI specification requires that an EFI System Partition must
grub_install_mkdir_p (efidir);
}
+ if (platform == GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+ {
+ int is_guess = 0;
+ if (!macppcdir)
+ {
+ char *d;
+
+ is_guess = 1;
+ d = grub_util_path_concat (2, bootdir, "macppc");
+ if (!grub_util_is_directory (d))
+ {
+ free (d);
+ d = grub_util_path_concat (2, bootdir, "efi");
+ }
+ /* Find the Mac HFS(+) System Partition. */
+ if (!grub_util_is_directory (d))
+ {
+ free (d);
+ d = grub_util_path_concat (2, bootdir, "EFI");
+ }
+ if (!grub_util_is_directory (d))
+ {
+ free (d);
+ d = 0;
+ }
+ if (d)
+ macppcdir = d;
+ }
+ if (macppcdir)
+ {
+ char **macppcdir_device_names = NULL;
+ grub_device_t macppcdir_grub_dev = NULL;
+ char *macppcdir_grub_devname;
+ grub_fs_t fs;
+
+ macppcdir_device_names = grub_guess_root_devices (macppcdir);
+ if (!macppcdir_device_names || !macppcdir_device_names[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ macppcdir);
+
+ for (curdev = macppcdir_device_names; *curdev; curdev++)
+ grub_util_pull_device (*curdev);
+
+ macppcdir_grub_devname = grub_util_get_grub_dev (macppcdir_device_names[0]);
+ if (!macppcdir_grub_devname)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ macppcdir_device_names[0]);
+
+ macppcdir_grub_dev = grub_device_open (macppcdir_grub_devname);
+ if (! macppcdir_grub_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ fs = grub_fs_probe (macppcdir_grub_dev);
+ if (! fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (grub_strcmp (fs->name, "hfs") != 0
+ && grub_strcmp (fs->name, "hfsplus") != 0
+ && !is_guess)
+ grub_util_error (_("%s is neither hfs nor hfsplue"),
+ macppcdir);
+ if (grub_strcmp (fs->name, "hfs") == 0
+ || grub_strcmp (fs->name, "hfsplus") == 0)
+ {
+ install_device = macppcdir_device_names[0];
+ is_prep = 0;
+ }
+ }
+ }
+
grub_install_copy_files (grub_install_source_directory,
grubdir, platform);
}
case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ if (macppcdir)
+ {
+ char *core_services = grub_util_path_concat (4, macppcdir,
+ "System", "Library",
+ "CoreServices");
+ char *mach_kernel = grub_util_path_concat (2, macppcdir,
+ "mach_kernel");
+ char *grub_elf, *bootx;
+ FILE *f;
+ grub_device_t ins_dev;
+ char *grub_chrp = grub_util_path_concat (2,
+ grub_install_source_directory,
+ "grub.chrp");
+
+ grub_install_mkdir_p (core_services);
+
+ bootx = grub_util_path_concat (2, core_services, "BootX");
+ grub_install_copy_file (grub_chrp, bootx, 1);
+
+ grub_elf = grub_util_path_concat (2, core_services, "grub.elf");
+ grub_install_copy_file (imgfile, grub_elf, 1);
+
+ f = grub_util_fopen (mach_kernel, "r+");
+ if (!f)
+ grub_util_error ("Can't create file: %s", strerror (errno));
+ fclose (f);
+
+ fill_core_services (core_services);
+
+ ins_dev = grub_device_open (install_drive);
+
+ bless (ins_dev, core_services, 0);
+
+ if (update_nvram)
+ {
+ const char *dev;
+ int partno;
+
+ partno = ins_dev->disk->partition
+ ? ins_dev->disk->partition->number + 1 : 0;
+ dev = grub_util_get_os_disk (install_device);
+ grub_install_register_ieee1275 (0, dev, partno,
+ "\\\\BootX");
+ }
+ grub_device_close (ins_dev);
+ free (grub_elf);
+ free (bootx);
+ free (mach_kernel);
+ free (grub_chrp);
+ break;
+ }
/* If a install device is defined, copy the core.elf to PReP partition. */
- if (install_device && install_device[0])
+ if (is_prep && install_device && install_device[0])
{
grub_device_t ins_dev;
ins_dev = grub_device_open (install_drive);
s);
}
grub_device_close (ins_dev);
+ if (update_nvram)
+ grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),
+ 0, NULL);
+ break;
}
/* fallthrough. */
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
if (update_nvram)
{
- if (platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275
- || !install_device
- || install_device[0] == '\0')
- {
- const char *dev;
- char *relpath;
- int partno;
- relpath = grub_make_system_path_relative_to_its_root (imgfile);
- partno = grub_dev->disk->partition
- ? grub_dev->disk->partition->number + 1 : 0;
- dev = grub_util_get_os_disk (grub_devices[0]);
- grub_install_register_ieee1275 (0, dev,
- partno, relpath);
- }
- else
- grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),
- 0, NULL);
+ const char *dev;
+ char *relpath;
+ int partno;
+ relpath = grub_make_system_path_relative_to_its_root (imgfile);
+ partno = grub_dev->disk->partition
+ ? grub_dev->disk->partition->number + 1 : 0;
+ dev = grub_util_get_os_disk (grub_devices[0]);
+ grub_install_register_ieee1275 (0, dev,
+ partno, relpath);
}
break;
case GRUB_INSTALL_PLATFORM_MIPS_ARC:
break;
case GRUB_INSTALL_PLATFORM_I386_EFI:
- {
- char *dst = grub_util_path_concat (2, efidir, "grub.efi");
- /* For old macs. Suggested by Peter Jones. */
- grub_install_copy_file (imgfile, dst, 1);
- free (dst);
- }
+ if (!efidir_is_mac)
+ {
+ char *dst = grub_util_path_concat (2, efidir, "grub.efi");
+ /* For old macs. Suggested by Peter Jones. */
+ grub_install_copy_file (imgfile, dst, 1);
+ free (dst);
+ }
case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ if (efidir_is_mac)
+ {
+ char *boot_efi;
+ char *core_services = grub_util_path_concat (4, efidir,
+ "System", "Library",
+ "CoreServices");
+ char *mach_kernel = grub_util_path_concat (2, efidir,
+ "mach_kernel");
+ FILE *f;
+ grub_device_t ins_dev;
+
+ grub_install_mkdir_p (core_services);
+
+ boot_efi = grub_util_path_concat (2, core_services, "boot.efi");
+ grub_install_copy_file (imgfile, boot_efi, 1);
+
+ f = grub_util_fopen (mach_kernel, "r+");
+ if (!f)
+ grub_util_error ("Can't create file: %s", strerror (errno));
+ fclose (f);
+
+ fill_core_services(core_services);
+
+ ins_dev = grub_device_open (install_drive);
+
+ bless (ins_dev, boot_efi, 1);
+ if (!removable && update_nvram)
+ {
+ char * efidir_disk;
+ int efidir_part;
+
+ /* Try to make this image bootable using the EFI Boot Manager, if available. */
+ efidir_disk = grub_util_get_os_disk (efidir_device_names[0]);
+ efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+ grub_install_register_efi (efidir_disk, efidir_part,
+ "\\System\\Library\\CoreServices",
+ efi_distributor);
+ }
+
+ grub_device_close (ins_dev);
+ free (boot_efi);
+ free (mach_kernel);
+ break;
+ }
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
--- /dev/null
+/* grub-probe.c - probe device information for a given path */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/partition.h>
+#include <grub/msdos_partition.h>
+#include <grub/emu/hostdisk.h>
+#include <grub/emu/getroot.h>
+#include <grub/term.h>
+#include <grub/env.h>
+#include <grub/diskfilter.h>
+#include <grub/i18n.h>
+#include <grub/crypto.h>
+#include <grub/cryptodisk.h>
+#include <grub/hfsplus.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#define _GNU_SOURCE 1
+#include <argp.h>
+
+#include "progname.h"
+
+static void
+bless (const char *path, int x86)
+{
+ char *drive_name = NULL;
+ char **devices;
+ char *grub_path = NULL;
+ char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
+ grub_device_t dev = NULL;
+ grub_err_t err;
+ struct stat st;
+
+ grub_path = canonicalize_file_name (path);
+
+ if (stat (grub_path, &st) < 0)
+ grub_util_error (N_("cannot stat `%s': %s"),
+ grub_path, strerror (errno));
+
+ devices = grub_guess_root_devices (grub_path);
+
+ if (! devices || !devices[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path);
+
+ drive_name = grub_util_get_grub_dev (devices[0]);
+ if (! drive_name)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ devices[0]);
+
+ grub_util_info ("opening %s", drive_name);
+ dev = grub_device_open (drive_name);
+ if (! dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ err = grub_mac_bless_inode (dev, st.st_ino, S_ISDIR (st.st_mode), x86);
+ if (err)
+ grub_util_error ("%s", grub_errmsg);
+ free (grub_path);
+ free (filebuf_via_grub);
+ free (filebuf_via_sys);
+ free (drive_name);
+}
+
+static struct argp_option options[] = {
+ {"x86", 'x', 0, 0,
+ N_("bless for x86-based macs"), 0},
+ {"ppc", 'p', 0, 0,
+ N_("bless for ppc-based macs"), 0},
+ {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+struct arguments
+{
+ char *arg;
+ int ppc;
+};
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+ /* Get the input argument from argp_parse, which we
+ know is a pointer to our arguments structure. */
+ struct arguments *arguments = state->input;
+
+ switch (key)
+ {
+ case 'v':
+ verbosity++;
+ break;
+
+ case 'x':
+ arguments->ppc = 0;
+ break;
+
+ case 'p':
+ arguments->ppc = 1;
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ fprintf (stderr, "%s", _("No path or device is specified.\n"));
+ argp_usage (state);
+ break;
+
+ case ARGP_KEY_ARG:
+ if (arguments->arg)
+ {
+ fprintf (stderr, _("Unknown extra argument `%s'."), arg);
+ fprintf (stderr, "\n");
+ return ARGP_ERR_UNKNOWN;
+ }
+ arguments->arg = xstrdup (arg);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp argp = {
+ options, argp_parser, N_("--ppc PATH|--x86 FILE"),
+ N_("Mac-style bless on HFS or HFS+"),
+ NULL, NULL, NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+ struct arguments arguments;
+
+ grub_util_host_init (&argc, &argv);
+
+ /* Check for options. */
+ memset (&arguments, 0, sizeof (struct arguments));
+ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
+ {
+ fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
+ exit(1);
+ }
+
+ if (verbosity > 1)
+ grub_env_set ("debug", "all");
+
+ /* Initialize the emulated biosdisk driver. */
+ grub_util_biosdisk_init (NULL);
+
+ /* Initialize all modules. */
+ grub_init_all ();
+ grub_gcry_init_all ();
+
+ grub_lvm_fini ();
+ grub_mdraid09_fini ();
+ grub_mdraid1x_fini ();
+ grub_diskfilter_fini ();
+ grub_diskfilter_init ();
+ grub_mdraid09_init ();
+ grub_mdraid1x_init ();
+ grub_lvm_init ();
+
+ /* Do it. */
+ bless (arguments.arg, !arguments.ppc);
+
+ /* Free resources. */
+ grub_gcry_fini_all ();
+ grub_fini_all ();
+ grub_util_biosdisk_fini ();
+
+ return 0;
+}
#include <grub/util/misc.h>
#include <grub/emu/exec.h>
#include <grub/emu/config.h>
+#include <grub/emu/hostdisk.h>
#include <argp.h>
#include <sys/types.h>
if (!output_image)
grub_util_error ("%s", _("output file must be specified"));
+ grub_init_all ();
+ grub_hostfs_init ();
+ grub_host_init ();
+
xorriso_push (xorriso);
xorriso_push ("-as");
xorriso_push ("mkisofs");
#include <grub/gfxmenu_view.h>
#include <grub/color.h>
#include <grub/util/install.h>
+#include <grub/emu/hostdisk.h>
#define _GNU_SOURCE 1
fclose (in);
}
+ grub_init_all ();
+ grub_hostfs_init ();
+ grub_host_init ();
+
grub_util_render_label (arguments.font,
arguments.bgcolor,
arguments.fgcolor,
fontfull = xasprintf ("(host)/%s", t);
free (t);
- grub_init_all ();
- grub_hostfs_init ();
- grub_host_init ();
-
grub_font_loader_init ();
font = grub_font_load (fontfull);
if (!font)