Implement better integration with Mac firmware.
This commit is contained in:
parent
1f032575bb
commit
b8765fa082
15 changed files with 835 additions and 39 deletions
|
@ -1,3 +1,7 @@
|
|||
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
|
||||
|
|
|
@ -62,6 +62,7 @@ library = {
|
|||
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;
|
||||
|
@ -401,6 +402,21 @@ program = {
|
|||
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;
|
||||
|
@ -585,6 +601,9 @@ program = {
|
|||
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;
|
||||
|
|
4
docs/man/grub-macbless.h2m
Normal file
4
docs/man/grub-macbless.h2m
Normal file
|
@ -0,0 +1,4 @@
|
|||
[NAME]
|
||||
grub-macbless \- bless a mac file/directory
|
||||
[SEE ALSO]
|
||||
.BR grub-install (1)
|
|
@ -1450,6 +1450,11 @@ module = {
|
|||
common = fs/zfs/zfsinfo.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = macbless;
|
||||
common = commands/macbless.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = pxe;
|
||||
i386_pc = net/drivers/i386/pc/pxe.c;
|
||||
|
|
234
grub-core/commands/macbless.c
Normal file
234
grub-core/commands/macbless.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
|
@ -1229,14 +1229,18 @@ grub_hfs_dir_hook (struct grub_hfs_record *rec, void *hook_arg)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,11 +34,6 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -919,6 +914,8 @@ grub_hfsplus_dir_iter (const char *filename,
|
|||
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);
|
||||
|
|
|
@ -38,7 +38,9 @@ struct grub_dirhook_info
|
|||
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,
|
||||
|
|
|
@ -50,11 +50,20 @@ struct grub_hfs_sblock
|
|||
/* 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;
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
/*
|
||||
* 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
|
||||
{
|
||||
|
@ -30,7 +51,16 @@ struct grub_hfsplus_volheader
|
|||
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;
|
||||
|
@ -216,3 +246,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
|
|||
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);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <grub/gpt_partition.h>
|
||||
#include <grub/emu/config.h>
|
||||
#include <grub/util/ofpath.h>
|
||||
#include <grub/hfsplus.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -60,6 +61,7 @@ static int allow_floppy = 0;
|
|||
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;
|
||||
|
@ -68,6 +70,10 @@ static int have_load_cfg = 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
|
||||
|
@ -96,6 +102,11 @@ 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;
|
||||
|
@ -119,6 +130,25 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
|||
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:
|
||||
|
@ -138,6 +168,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
|||
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);
|
||||
|
@ -255,9 +290,15 @@ static struct argp_option options[] = {
|
|||
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}
|
||||
};
|
||||
|
||||
|
@ -697,6 +738,63 @@ is_prep_empty (grub_device_t dev)
|
|||
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[])
|
||||
{
|
||||
|
@ -714,8 +812,14 @@ 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);
|
||||
|
||||
|
@ -800,9 +904,12 @@ main (int argc, char *argv[])
|
|||
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:
|
||||
|
@ -850,6 +957,9 @@ main (int argc, char *argv[])
|
|||
/* Initialize all modules. */
|
||||
grub_init_all ();
|
||||
grub_gcry_init_all ();
|
||||
grub_hostfs_init ();
|
||||
grub_host_init ();
|
||||
|
||||
switch (platform)
|
||||
{
|
||||
case GRUB_INSTALL_PLATFORM_I386_EFI:
|
||||
|
@ -927,7 +1037,13 @@ main (int argc, char *argv[])
|
|||
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
|
||||
|
@ -1001,6 +1117,76 @@ main (int argc, char *argv[])
|
|||
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);
|
||||
|
||||
|
@ -1491,8 +1677,59 @@ main (int argc, char *argv[])
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -1512,14 +1749,14 @@ main (int argc, char *argv[])
|
|||
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;
|
||||
|
@ -1531,16 +1768,13 @@ main (int argc, char *argv[])
|
|||
grub_install_register_ieee1275 (0, dev,
|
||||
partno, relpath);
|
||||
}
|
||||
else
|
||||
grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),
|
||||
0, NULL);
|
||||
}
|
||||
break;
|
||||
case GRUB_INSTALL_PLATFORM_MIPS_ARC:
|
||||
grub_install_sgi_setup (install_device, imgfile, "grub");
|
||||
break;
|
||||
|
||||
case GRUB_INSTALL_PLATFORM_I386_EFI:
|
||||
if (!efidir_is_mac)
|
||||
{
|
||||
char *dst = grub_util_path_concat (2, efidir, "grub.efi");
|
||||
/* For old macs. Suggested by Peter Jones. */
|
||||
|
@ -1549,6 +1783,50 @@ main (int argc, char *argv[])
|
|||
}
|
||||
|
||||
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:
|
||||
|
|
199
util/grub-macbless.c
Normal file
199
util/grub-macbless.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* 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;
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
#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>
|
||||
|
@ -378,6 +379,10 @@ main (int argc, char *argv[])
|
|||
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");
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/color.h>
|
||||
#include <grub/util/install.h>
|
||||
#include <grub/emu/hostdisk.h>
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
|
@ -166,6 +167,10 @@ main (int argc, char *argv[])
|
|||
fclose (in);
|
||||
}
|
||||
|
||||
grub_init_all ();
|
||||
grub_hostfs_init ();
|
||||
grub_host_init ();
|
||||
|
||||
grub_util_render_label (arguments.font,
|
||||
arguments.bgcolor,
|
||||
arguments.fgcolor,
|
||||
|
|
|
@ -167,10 +167,6 @@ grub_util_render_label (const char *label_font,
|
|||
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)
|
||||
|
|
Loading…
Reference in a new issue