* [patch] rough Mac OS X loader
@ 2006-01-02 0:38 Hollis Blanchard
2006-01-02 17:29 ` Marco Gerards
0 siblings, 1 reply; 6+ messages in thread
From: Hollis Blanchard @ 2006-01-02 0:38 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1589 bytes --]
I've been working on a Mac OS X loader for GRUB. During the usual OS X
boot process, the firmware loads the BootX bootloader (which is a
hybrid CHRP script and XCOFF binary), which has a Mach-O loader and
loads the OS X Mach kernel.
Rather than trying to load and run the Mach kernel directly, I chose to
focus on the BootX bootloader, since it seems to do a fair amount of
setup work that I would rather not duplicate in GRUB. Also important:
if OS X is ever updated (for example, the parameter-passing mechanism
between BootX and the kernel), we would need to track those changes,
which is a lot more long-term maintenance.
Unfortunately, BootX attempts to claim all memory from 0 to 96MiB,
which conflicts with GRUB running in this area. To get around that
problem, I install a trampoline just above 96MiB which releases all of
GRUB's memory and jumps into BootX. It's a bit of a hack, and for
example if the code being copied exceeds some fixed size (currently
0x200 bytes) things will fail mysteriously. I'm open to suggestions on
that problem.
I'm afraid I don't know if this code works yet. Because the current
HFS+ driver doesn't support the HFS wrapper found on all Apple
filesystems, I can't boot from an HFS+ installation. I've copied BootX
to a plain HFS partition, and that works somewhat (I expect it fails
when it cannot find /mach_kernel). I'm relatively optimistic, and I'm
working on the HFS wrapper support now.
There are a few rough edges still, but if there are no comments I will
be checking this patch in largely unchanged some day.
-Hollis
[-- Attachment #2: macosx.txt --]
[-- Type: text/plain, Size: 19113 bytes --]
Index: conf/powerpc-ieee1275.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/powerpc-ieee1275.rmk,v
retrieving revision 1.52
diff -u -p -r1.52 powerpc-ieee1275.rmk
--- conf/powerpc-ieee1275.rmk 25 Dec 2005 15:59:50 -0000 1.52
+++ conf/powerpc-ieee1275.rmk 2 Jan 2006 00:34:11 -0000
@@ -9,7 +9,7 @@ COMMON_CFLAGS = -ffreestanding -msoft-fl
MOSTLYCLEANFILES += grubof_symlist.c kernel_syms.lst
DEFSYMFILES += kernel_syms.lst
-grubof_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
+grubof_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h env.h err.h \
file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h symbol.h \
term.h types.h powerpc/libgcc.h loader.h \
partition.h pc_partition.h ieee1275/ieee1275.h machine/time.h \
@@ -65,7 +65,7 @@ grubof_SOURCES = kern/powerpc/ieee1275/c
kern/powerpc/ieee1275/init.c term/ieee1275/ofconsole.c \
kern/powerpc/ieee1275/openfw.c disk/ieee1275/ofdisk.c \
kern/parser.c kern/partition.c kern/env.c kern/powerpc/dl.c \
- grubof_symlist.c kern/powerpc/cache.S
+ grubof_symlist.c kern/powerpc/cache.S kern/powerpc/misc.S
grubof_HEADERS = grub/powerpc/ieee1275/ieee1275.h
grubof_CFLAGS = $(COMMON_CFLAGS)
grubof_ASFLAGS = $(COMMON_ASFLAGS)
@@ -84,6 +84,8 @@ grub_install_SOURCES = util/powerpc/ieee
pkgdata_MODULES = halt.mod \
_linux.mod \
linux.mod \
+ _macosx.mod \
+ macosx.mod \
normal.mod \
reboot.mod \
suspend.mod
@@ -117,4 +119,12 @@ reboot_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_SOURCES = commands/ieee1275/halt.c
halt_mod_CFLAGS = $(COMMON_CFLAGS)
+# For _macosx.mod.
+_macosx_mod_SOURCES = loader/powerpc/ieee1275/macosx.c
+_macosx_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For macosx.mod.
+macosx_mod_SOURCES = loader/powerpc/ieee1275/macosx_normal.c
+macosx_mod_CFLAGS = $(COMMON_CFLAGS)
+
include $(srcdir)/conf/common.mk
Index: include/grub/xcoff.h
===================================================================
RCS file: include/grub/xcoff.h
diff -N include/grub/xcoff.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/grub/xcoff.h 2 Jan 2006 00:34:11 -0000
@@ -0,0 +1,90 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* See http://www16.boulder.ibm.com/pseries/en_US/files/aixfiles/XCOFF.htm */
+
+#ifndef GRUB_XCOFF_HEADER
+#define GRUB_XCOFF_HEADER 1
+
+#include <grub/types.h>
+
+struct xcoff_func_desc
+{
+ grub_uint32_t address;
+ grub_uint32_t toc;
+};
+
+struct xcoff_filehdr
+{
+ grub_uint16_t f_magic;
+ grub_uint16_t f_nscns;
+ grub_uint32_t f_timdat;
+ grub_uint32_t f_symptr;
+ grub_uint32_t f_nsyms;
+ grub_uint16_t f_opthdr;
+ grub_uint16_t f_flags;
+};
+
+#define XCOFF32_MAGIC 0x01df
+
+struct xcoff_auxhdr
+{
+ grub_uint16_t o_mflag;
+ grub_uint16_t o_vstamp;
+ grub_uint32_t o_tsize;
+ grub_uint32_t o_dsize;
+ grub_uint32_t o_bsize;
+ grub_uint32_t o_entry;
+ grub_uint32_t o_text_start;
+ grub_uint32_t o_data_start;
+ grub_uint32_t o_toc;
+ grub_uint16_t o_snentry;
+ grub_uint16_t o_sntext;
+ grub_uint16_t o_sndata;
+ grub_uint16_t o_sntoc;
+ grub_uint16_t o_snloader;
+ grub_uint16_t o_snbss;
+ grub_uint16_t o_algntext;
+ grub_uint16_t o_algndata;
+ grub_uint16_t o_modtype;
+ grub_uint8_t o_cpuflag;
+ grub_uint8_t o_cputype;
+ grub_uint32_t o_maxstack;
+ grub_uint32_t o_maxdata;
+ grub_uint32_t o_debugger;
+ char o_resv2[8];
+};
+
+#define XCOFF_MFLAGS_PAGEALIGNED 0x010b
+
+struct xcoff_scnhdr
+{
+ char s_name[8];
+ grub_uint32_t s_paddr;
+ grub_uint32_t s_vaddr;
+ grub_uint32_t s_size;
+ grub_uint32_t s_scnptr;
+ grub_uint32_t s_relptr;
+ grub_uint32_t s_lnnoptr;
+ grub_uint16_t s_nreloc;
+ grub_uint16_t s_nlnno;
+ grub_uint16_t s_flags;
+};
+
+#endif
Index: include/grub/powerpc/ieee1275/kernel.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/kernel.h,v
retrieving revision 1.3
diff -u -p -r1.3 kernel.h
--- include/grub/powerpc/ieee1275/kernel.h 3 Aug 2005 22:53:50 -0000 1.3
+++ include/grub/powerpc/ieee1275/kernel.h 2 Jan 2006 00:34:11 -0000
@@ -26,6 +26,9 @@ void EXPORT_FUNC (abort) (void);
void EXPORT_FUNC (grub_reboot) (void);
void EXPORT_FUNC (grub_halt) (void);
+void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long stack,
+ unsigned long arg1, unsigned long arg2);
+
/* Where grub-mkimage places the core modules in memory. */
#define GRUB_IEEE1275_MODULE_BASE 0x00300000
Index: include/grub/powerpc/ieee1275/loader.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/loader.h,v
retrieving revision 1.4
diff -u -p -r1.4 loader.h
--- include/grub/powerpc/ieee1275/loader.h 31 Jan 2005 21:44:35 -0000 1.4
+++ include/grub/powerpc/ieee1275/loader.h 2 Jan 2006 00:34:11 -0000
@@ -24,6 +24,7 @@
loader. */
void grub_rescue_cmd_linux (int argc, char *argv[]);
void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_macosx (int argc, char *argv[]);
void grub_linux_init (void);
void grub_linux_fini (void);
Index: kern/powerpc/misc.S
===================================================================
RCS file: kern/powerpc/misc.S
diff -N kern/powerpc/misc.S
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ kern/powerpc/misc.S 2 Jan 2006 00:34:11 -0000
@@ -0,0 +1,30 @@
+/* misc.S - Miscellaneous assembly routines. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ .text
+
+ /* Jump to a function and switch to a new stack. */
+ .globl grub_jump
+grub_jump:
+ mtctr 3
+ mr 1, 4
+ mr 3, 5
+ mr 4, 6
+ bctr
Index: loader/powerpc/ieee1275/macosx.c
===================================================================
RCS file: loader/powerpc/ieee1275/macosx.c
diff -N loader/powerpc/ieee1275/macosx.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ loader/powerpc/ieee1275/macosx.c 2 Jan 2006 00:34:11 -0000
@@ -0,0 +1,324 @@
+/* macosx.c - boot Mac OS X */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* BootX, the Mac OS X bootloader, is an XCOFF executable with a CHRP script
+ * prepended to it. We skip the script and load the XCOFF file. */
+
+#include <grub/xcoff.h>
+#include <grub/loader.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/rescue.h>
+#include <grub/misc.h>
+#include <grub/cache.h>
+#include <grub/ieee1275/ieee1275.h>
+
+#define MAX_XCOFF_POS (8<<10) /* Search first 8 KiB. */
+#define READ_SIZE 512
+#define END_STRING "</CHRP-BOOT>\n\x04"
+
+#define GRUB_MACOSX_CHAIN_AREA 0x06000000
+#define GRUB_MACOSX_RELEASE_AREA 0x06000200
+#define GRUB_MACOSX_STACK_AREA 0x06000400
+
+static grub_dl_t my_mod;
+
+static int loaded;
+static grub_addr_t macosx_entry;
+
+
+static grub_err_t
+grub_macosx_boot (void)
+{
+ grub_dprintf ("loader", "entry point: 0x%x\n", macosx_entry);
+ grub_dprintf ("loader", "jumping to Mac OS X...\n");
+
+ /* Call the trampoline to boot the kernel. */
+ grub_jump (GRUB_MACOSX_CHAIN_AREA, GRUB_MACOSX_STACK_AREA + 0x200,
+ macosx_entry, GRUB_MACOSX_RELEASE_AREA);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_macosx_release_mem (void)
+{
+ /* XXX write me */
+#if 0
+ if (macosx_addr && grub_ieee1275_release (macosx_addr, macosx_size))
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory");
+
+ macosx_addr = 0;
+#endif
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_macosx_unload (void)
+{
+ grub_err_t err;
+
+ err = grub_macosx_release_mem ();
+ grub_dl_unref (my_mod);
+
+ loaded = 0;
+
+ return err;
+}
+
+static grub_err_t
+grub_xcoff_load_section (grub_file_t file, grub_off_t xcoff_pos,
+ struct xcoff_scnhdr *scnhdr)
+{
+ int rc;
+
+ grub_dprintf ("loader", "section %.8s:\n", scnhdr->s_name);
+ grub_dprintf ("loader", " paddr 0x%08x\n", scnhdr->s_paddr);
+ grub_dprintf ("loader", " vaddr 0x%08x\n", scnhdr->s_vaddr);
+ grub_dprintf ("loader", " size 0x%x\n", scnhdr->s_size);
+ grub_dprintf ("loader", " scnptr 0x%x\n", scnhdr->s_scnptr);
+ grub_dprintf ("loader", " flags 0x%x\n", scnhdr->s_flags);
+
+ rc = grub_claimmap (scnhdr->s_paddr, scnhdr->s_size);
+ if (rc == -1)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not claim 0x%x",
+ scnhdr->s_paddr);
+
+ if (scnhdr->s_scnptr)
+ {
+ grub_file_seek (file, xcoff_pos + scnhdr->s_scnptr);
+
+ if (grub_file_read (file, (void *)scnhdr->s_paddr, scnhdr->s_size)
+ != (grub_ssize_t)scnhdr->s_size)
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "could not load section %.8s\n",
+ scnhdr->s_name);
+ grub_arch_sync_caches ((void *) scnhdr->s_paddr, scnhdr->s_size);
+ }
+ else
+ /* BSS. */
+ grub_memset ((void *) scnhdr->s_paddr, 0, scnhdr->s_size);
+
+ return 0;
+}
+
+static grub_err_t
+grub_xcoff_load_file (grub_file_t file, grub_off_t xcoff_pos)
+{
+ struct xcoff_filehdr _filehdr;
+ struct xcoff_auxhdr _auxhdr;
+ struct xcoff_filehdr *filehdr = &_filehdr;
+ struct xcoff_auxhdr *auxhdr = &_auxhdr;
+ struct xcoff_scnhdr *scnhdrs;
+ struct xcoff_func_desc *desc;
+ int scnhdr_bytes;
+ int i;
+
+ /* Read the file header. */
+ if (grub_file_read (file, (void *)filehdr, sizeof (struct xcoff_filehdr))
+ != sizeof (struct xcoff_filehdr))
+ {
+ grub_error (GRUB_ERR_READ_ERROR, "could not read the XCOFF file header");
+ goto out;
+ }
+
+ if (filehdr->f_magic != XCOFF32_MAGIC)
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "bad XCOFF magic: 0x%x",
+ filehdr->f_magic);
+ goto out;
+ }
+
+ grub_dprintf ("loader", "number of sections: %d\n", filehdr->f_nscns);
+ grub_dprintf ("loader", "flags: 0x%x\n", filehdr->f_flags);
+
+ /* Read the auxiliary header. */
+ if (filehdr->f_opthdr != sizeof (struct xcoff_auxhdr))
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "missing auxiliary header");
+ goto out;
+ }
+
+ if (grub_file_read (file, (void *)auxhdr, sizeof (struct xcoff_auxhdr))
+ != sizeof (struct xcoff_auxhdr))
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "could not read the XCOFF auxiliary header");
+
+ if (auxhdr->o_mflag != XCOFF_MFLAGS_PAGEALIGNED)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "unknown auxiliary header flags: 0x%x\n",
+ auxhdr->o_mflag);
+
+ /* Load all section headers. */
+ scnhdr_bytes = filehdr->f_nscns * sizeof (struct xcoff_scnhdr);
+ scnhdrs = grub_malloc (scnhdr_bytes);
+ if (! scnhdrs)
+ return grub_errno;
+
+ if (grub_file_read (file, (void *)scnhdrs, scnhdr_bytes) != scnhdr_bytes)
+ return grub_error (GRUB_ERR_READ_ERROR,
+ "could not read XCOFF section headers");
+
+ for (i = 0; i < filehdr->f_nscns; i++)
+ {
+ if (grub_xcoff_load_section (file, xcoff_pos, scnhdrs + i))
+ break;
+ }
+
+ /* Find the entry point. */
+ desc = (struct xcoff_func_desc *)auxhdr->o_entry;
+ macosx_entry = desc->address;
+ grub_dprintf ("loader", "entry point 0x%08x\n", macosx_entry);
+
+ out:
+ return grub_errno;
+}
+
+/* Find NULL-terminated `needle' in non-terminated `haystack'. */
+static void *
+grub_memstr (void *haystack, int len, char *needle)
+{
+ char *ptr = haystack;
+ int needle_len = grub_strlen (needle);
+ int i;
+
+ for (i = 0; i < len - needle_len; i++)
+ {
+ if (0 == grub_memcmp (ptr + i, needle, needle_len))
+ return ptr + i;
+ }
+
+ return 0;
+}
+
+/* grub_chain_trampoline is copied somewhere other than its link address
+ * and executes after all other code has been blown away. In order to call
+ * other functions from here, they must have been copied into a safe place and
+ * their addresses passed as parameters. */
+typedef void (*kernel_entry_t) (unsigned long, unsigned long, int (void *));
+typedef int (*release_t) (grub_addr_t addr, grub_size_t size);
+static void
+grub_chain_trampoline (kernel_entry_t entry, release_t release)
+{
+ release (0x00003000, 0x06000000 - 0x3000);
+ entry (0, 0, grub_ieee1275_entry_fn);
+}
+
+static int
+grub_macosx_install_trampoline (void)
+{
+ int rc;
+
+ /* XXX don't use magic numbers here */
+ rc = grub_claimmap (GRUB_MACOSX_CHAIN_AREA, 0x200);
+ rc |= grub_claimmap (GRUB_MACOSX_RELEASE_AREA, 0x200);
+ rc |= grub_claimmap (GRUB_MACOSX_STACK_AREA, 0x200);
+ if (rc)
+ return rc;
+
+ grub_memcpy ((void *) GRUB_MACOSX_CHAIN_AREA, grub_chain_trampoline, 0x200);
+ grub_arch_sync_caches ((void *) GRUB_MACOSX_CHAIN_AREA, 0x200);
+ grub_memcpy ((void *) GRUB_MACOSX_RELEASE_AREA, grub_ieee1275_release, 0x200);
+ grub_arch_sync_caches ((void *) GRUB_MACOSX_RELEASE_AREA, 0x200);
+}
+
+void
+grub_rescue_cmd_macosx (int argc, char *argv[])
+{
+ static char _buf[READ_SIZE];
+ char *buf = _buf;
+ grub_file_t file = 0;
+ grub_off_t pos = 0;
+ grub_ssize_t bytes_read;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+ goto out;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto out;
+
+ /* Search for the end of the script to find the XCOFF header. */
+ while (pos < MAX_XCOFF_POS) {
+ char *match;
+
+ bytes_read = grub_file_read (file, buf, READ_SIZE);
+ if (bytes_read < 0)
+ goto out;
+
+ match = grub_memstr (buf, bytes_read, END_STRING);
+ if (match)
+ {
+ pos += (int) (match - buf) + grub_strlen (END_STRING);
+ grub_dprintf ("loader", "XCOFF header at file offset 0x%x\n", pos);
+ grub_file_seek (file, pos);
+ break;
+ }
+
+ pos += READ_SIZE;
+ }
+
+ if (pos < MAX_XCOFF_POS)
+ {
+ /* Install the trampoline we need to jump through. */
+ if (grub_macosx_install_trampoline ())
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "Failed to install trampoline.\n");
+ goto out;
+ }
+ /* Load the XCOFF. */
+ grub_xcoff_load_file (file, pos);
+ }
+
+ out:
+
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_macosx_release_mem ();
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ return;
+ }
+
+ grub_loader_set (grub_macosx_boot, grub_macosx_unload);
+ loaded = 1;
+}
+
+\f
+GRUB_MOD_INIT (macosx)
+{
+ grub_rescue_register_command ("macosx", grub_rescue_cmd_macosx,
+ "load BootX, the Mac OS X bootloader");
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI (macosx)
+{
+ grub_rescue_unregister_command ("macosx");
+}
Index: loader/powerpc/ieee1275/macosx_normal.c
===================================================================
RCS file: loader/powerpc/ieee1275/macosx_normal.c
diff -N loader/powerpc/ieee1275/macosx_normal.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ loader/powerpc/ieee1275/macosx_normal.c 2 Jan 2006 00:34:11 -0000
@@ -0,0 +1,49 @@
+/* macosx_normal.c - boot Mac OS X */
+/*
+ * GRUB -- Preliminary Universal Programming Architecture for GRUB
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/machine/loader.h>
+
+static const struct grub_arg_option options[] =
+ {
+ {0, 0, 0, 0, 0, 0}
+ };
+
+static grub_err_t
+grub_cmd_macosx (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_rescue_cmd_macosx (argc, args);
+ return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(macosx_normal)
+{
+ (void) mod;
+ grub_register_command ("macosx", grub_cmd_macosx, GRUB_COMMAND_FLAG_BOTH,
+ "macosx [KERNELARGS...]",
+ "Loads BootX, the Mac OS X bootloader.", options);
+}
+
+GRUB_MOD_FINI(macosx_normal)
+{
+ grub_unregister_command ("macosx");
+}
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [patch] rough Mac OS X loader 2006-01-02 0:38 [patch] rough Mac OS X loader Hollis Blanchard @ 2006-01-02 17:29 ` Marco Gerards 2006-01-02 17:50 ` Hollis Blanchard 0 siblings, 1 reply; 6+ messages in thread From: Marco Gerards @ 2006-01-02 17:29 UTC (permalink / raw) To: The development of GRUB 2 Hollis Blanchard <hollis@penguinppc.org> writes: Hi Hollis, > I've been working on a Mac OS X loader for GRUB. During the usual OS X > boot process, the firmware loads the BootX bootloader (which is a > hybrid CHRP script and XCOFF binary), which has a Mach-O loader and > loads the OS X Mach kernel. This is really great news! Thanks a lot for doing this great job. :-) > Rather than trying to load and run the Mach kernel directly, I chose > to focus on the BootX bootloader, since it seems to do a fair amount > of setup work that I would rather not duplicate in GRUB. Also > important: if OS X is ever updated (for example, the parameter-passing > mechanism between BootX and the kernel), we would need to track those > changes, which is a lot more long-term maintenance. Agreed. > Unfortunately, BootX attempts to claim all memory from 0 to 96MiB, > which conflicts with GRUB running in this area. To get around that > problem, I install a trampoline just above 96MiB which releases all of > GRUB's memory and jumps into BootX. It's a bit of a hack, and for > example if the code being copied exceeds some fixed size (currently > 0x200 bytes) things will fail mysteriously. I'm open to suggestions on > that problem. > > I'm afraid I don't know if this code works yet. Because the current > HFS+ driver doesn't support the HFS wrapper found on all Apple > filesystems, I can't boot from an HFS+ installation. I've copied BootX > to a plain HFS partition, and that works somewhat (I expect it fails > when it cannot find /mach_kernel). I'm relatively optimistic, and I'm > working on the HFS wrapper support now. Cool. If you need any help let me know. I will look into this as well, I assume we can discuss things in detail on IRC. > There are a few rough edges still, but if there are no comments I will > be checking this patch in largely unchanged some day. Can you provide a changelog entry? :-) There are some comments below, I hope some of them even make sense. ;) > include $(srcdir)/conf/common.mk > Index: include/grub/xcoff.h > =================================================================== Is it possible to use the grub_ namespace in this file? In elf.h this is not done because it should be possible to update it from glibc, AFAIK. > Index: include/grub/powerpc/ieee1275/kernel.h > =================================================================== > RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/kernel.h,v > retrieving revision 1.3 > diff -u -p -r1.3 kernel.h > --- include/grub/powerpc/ieee1275/kernel.h 3 Aug 2005 22:53:50 -0000 1.3 > +++ include/grub/powerpc/ieee1275/kernel.h 2 Jan 2006 00:34:11 -0000 > @@ -26,6 +26,9 @@ void EXPORT_FUNC (abort) (void); > void EXPORT_FUNC (grub_reboot) (void); > void EXPORT_FUNC (grub_halt) (void); > > +void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long stack, > + unsigned long arg1, unsigned long arg2); Shouldn't a pointer be used here? > +/* BootX, the Mac OS X bootloader, is an XCOFF executable with a CHRP script > + * prepended to it. We skip the script and load the XCOFF file. */ What is in this script? Are you completely sure it can be skipped? Can you please remove the `*' on the second line so the comment matches the style of the other sourcecode? > +static grub_err_t > +grub_macosx_release_mem (void) > +{ > + /* XXX write me */ I assume you encountered a bug in the firmware while writing this function? :-) > + /* Load all section headers. */ > + scnhdr_bytes = filehdr->f_nscns * sizeof (struct xcoff_scnhdr); > + scnhdrs = grub_malloc (scnhdr_bytes); > + if (! scnhdrs) > + return grub_errno; > + > + if (grub_file_read (file, (void *)scnhdrs, scnhdr_bytes) != scnhdr_bytes) > + return grub_error (GRUB_ERR_READ_ERROR, > + "could not read XCOFF section headers"); You don't free scnhdrs here, is that intentional? > +/* Find NULL-terminated `needle' in non-terminated `haystack'. */ > +static void * > +grub_memstr (void *haystack, int len, char *needle) Perhaps it is better to move this to kern/misc.c? > +/* grub_chain_trampoline is copied somewhere other than its link address > + * and executes after all other code has been blown away. In order to call > + * other functions from here, they must have been copied into a safe place and > + * their addresses passed as parameters. */ Same as above. > +typedef void (*kernel_entry_t) (unsigned long, unsigned long, int (void *)); > +typedef int (*release_t) (grub_addr_t addr, grub_size_t size); > +static void > +grub_chain_trampoline (kernel_entry_t entry, release_t release) > +{ > + release (0x00003000, 0x06000000 - 0x3000); > + entry (0, 0, grub_ieee1275_entry_fn); > +} > + > +static int > +grub_macosx_install_trampoline (void) > +{ > + int rc; > + > + /* XXX don't use magic numbers here */ > + rc = grub_claimmap (GRUB_MACOSX_CHAIN_AREA, 0x200); > + rc |= grub_claimmap (GRUB_MACOSX_RELEASE_AREA, 0x200); > + rc |= grub_claimmap (GRUB_MACOSX_STACK_AREA, 0x200); > + if (rc) > + return rc; > + > + grub_memcpy ((void *) GRUB_MACOSX_CHAIN_AREA, grub_chain_trampoline, 0x200); > + grub_arch_sync_caches ((void *) GRUB_MACOSX_CHAIN_AREA, 0x200); > + grub_memcpy ((void *) GRUB_MACOSX_RELEASE_AREA, grub_ieee1275_release, 0x200); > + grub_arch_sync_caches ((void *) GRUB_MACOSX_RELEASE_AREA, 0x200); What is 0x200? The maximum size of grub_chain_trampoline? Perhaps you can do something like: `grub_macosx_release_area - grub_chain_trampoline', or do you think that is too unpredictable and too ugly? Thanks, Marco ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] rough Mac OS X loader 2006-01-02 17:29 ` Marco Gerards @ 2006-01-02 17:50 ` Hollis Blanchard 2006-01-02 18:02 ` Marco Gerards 0 siblings, 1 reply; 6+ messages in thread From: Hollis Blanchard @ 2006-01-02 17:50 UTC (permalink / raw) To: The development of GRUB 2 Thanks for your comments. On Jan 2, 2006, at 11:29 AM, Marco Gerards wrote: > >> Index: include/grub/xcoff.h >> =================================================================== > > Is it possible to use the grub_ namespace in this file? In elf.h this > is not done because it should be possible to update it from glibc, > AFAIK. Ok, that should be fine. >> Index: include/grub/powerpc/ieee1275/kernel.h >> =================================================================== >> RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/kernel.h,v >> retrieving revision 1.3 >> diff -u -p -r1.3 kernel.h >> --- include/grub/powerpc/ieee1275/kernel.h 3 Aug 2005 22:53:50 >> -0000 1.3 >> +++ include/grub/powerpc/ieee1275/kernel.h 2 Jan 2006 00:34:11 -0000 >> @@ -26,6 +26,9 @@ void EXPORT_FUNC (abort) (void); >> void EXPORT_FUNC (grub_reboot) (void); >> void EXPORT_FUNC (grub_halt) (void); >> >> +void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long >> stack, >> + unsigned long arg1, unsigned long arg2); > > Shouldn't a pointer be used here? Used where? >> +/* BootX, the Mac OS X bootloader, is an XCOFF executable with a >> CHRP script >> + * prepended to it. We skip the script and load the XCOFF file. */ > > What is in this script? Are you completely sure it can be skipped? It loads the XCOFF into memory. Yes. > Can you please remove the `*' on the second line so the comment > matches the style of the other sourcecode? Yes. >> +static grub_err_t >> +grub_macosx_release_mem (void) >> +{ >> + /* XXX write me */ > > I assume you encountered a bug in the firmware while writing this > function? :-) No, just haven't written it yet. :) I think the XCOFF sections in BootX are contiguous though, so if that's true it should not be difficult. >> + /* Load all section headers. */ >> + scnhdr_bytes = filehdr->f_nscns * sizeof (struct xcoff_scnhdr); >> + scnhdrs = grub_malloc (scnhdr_bytes); >> + if (! scnhdrs) >> + return grub_errno; >> + >> + if (grub_file_read (file, (void *)scnhdrs, scnhdr_bytes) != >> scnhdr_bytes) >> + return grub_error (GRUB_ERR_READ_ERROR, >> + "could not read XCOFF section headers"); > > You don't free scnhdrs here, is that intentional? Accidental, thanks. >> +/* Find NULL-terminated `needle' in non-terminated `haystack'. */ >> +static void * >> +grub_memstr (void *haystack, int len, char *needle) > > Perhaps it is better to move this to kern/misc.c? I had that thought, but "memstr" is not a standard POSIX function so I wasn't sure. >> +/* grub_chain_trampoline is copied somewhere other than its link >> address >> + * and executes after all other code has been blown away. In order >> to call >> + * other functions from here, they must have been copied into a safe >> place and >> + * their addresses passed as parameters. */ > > Same as above. > >> +typedef void (*kernel_entry_t) (unsigned long, unsigned long, int >> (void *)); >> +typedef int (*release_t) (grub_addr_t addr, grub_size_t size); >> +static void >> +grub_chain_trampoline (kernel_entry_t entry, release_t release) >> +{ >> + release (0x00003000, 0x06000000 - 0x3000); >> + entry (0, 0, grub_ieee1275_entry_fn); >> +} >> + >> +static int >> +grub_macosx_install_trampoline (void) >> +{ >> + int rc; >> + >> + /* XXX don't use magic numbers here */ >> + rc = grub_claimmap (GRUB_MACOSX_CHAIN_AREA, 0x200); >> + rc |= grub_claimmap (GRUB_MACOSX_RELEASE_AREA, 0x200); >> + rc |= grub_claimmap (GRUB_MACOSX_STACK_AREA, 0x200); >> + if (rc) >> + return rc; >> + >> + grub_memcpy ((void *) GRUB_MACOSX_CHAIN_AREA, >> grub_chain_trampoline, 0x200); >> + grub_arch_sync_caches ((void *) GRUB_MACOSX_CHAIN_AREA, 0x200); >> + grub_memcpy ((void *) GRUB_MACOSX_RELEASE_AREA, >> grub_ieee1275_release, 0x200); >> + grub_arch_sync_caches ((void *) GRUB_MACOSX_RELEASE_AREA, 0x200); > > What is 0x200? The maximum size of grub_chain_trampoline? Perhaps > you can do something like: `grub_macosx_release_area - > grub_chain_trampoline', or do you think that is too unpredictable and > too ugly? We're copying several functions elsewhere. The problem is this: how big is that function? In other words, how many bytes do we need to copy? I don't have an answer. -Hollis ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] rough Mac OS X loader 2006-01-02 17:50 ` Hollis Blanchard @ 2006-01-02 18:02 ` Marco Gerards 2006-01-03 0:39 ` Hollis Blanchard 0 siblings, 1 reply; 6+ messages in thread From: Marco Gerards @ 2006-01-02 18:02 UTC (permalink / raw) To: The development of GRUB 2 Hollis Blanchard <hollis@penguinppc.org> writes: >>> +void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long >>> stack, >>> + unsigned long arg1, unsigned long arg2); >> >> Shouldn't a pointer be used here? > > Used where? For grub_jump's arguments. It jumps to some address, right? >>> +/* BootX, the Mac OS X bootloader, is an XCOFF executable with a >>> CHRP script >>> + * prepended to it. We skip the script and load the XCOFF file. */ >> >> What is in this script? Are you completely sure it can be skipped? > > It loads the XCOFF into memory. Yes. Ah! :) >>> +static grub_err_t >>> +grub_macosx_release_mem (void) >>> +{ >>> + /* XXX write me */ >> >> I assume you encountered a bug in the firmware while writing this >> function? :-) > > No, just haven't written it yet. :) I think the XCOFF sections in > BootX are contiguous though, so if that's true it should not be > difficult. Oh, ok. In that case please add it to the to do list after this patch is committed. >>> +/* Find NULL-terminated `needle' in non-terminated `haystack'. */ >>> +static void * >>> +grub_memstr (void *haystack, int len, char *needle) >> >> Perhaps it is better to move this to kern/misc.c? > > I had that thought, but "memstr" is not a standard POSIX function so I > wasn't sure. It's looks like a useful function to me. We can always move it back if it turns out no one uses it... Thanks, Marco ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] rough Mac OS X loader 2006-01-02 18:02 ` Marco Gerards @ 2006-01-03 0:39 ` Hollis Blanchard 2006-01-03 18:02 ` Marco Gerards 0 siblings, 1 reply; 6+ messages in thread From: Hollis Blanchard @ 2006-01-03 0:39 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 603 bytes --] On Jan 2, 2006, at 12:02 PM, Marco Gerards wrote: > Hollis Blanchard <hollis@penguinppc.org> writes: > >>>> +void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long >>>> stack, >>>> + unsigned long arg1, unsigned long arg2); >>> >>> Shouldn't a pointer be used here? >> >> Used where? > > For grub_jump's arguments. It jumps to some address, right? Yes, but I don't believe using pointers would be appropriate here. The addresses passed in are addresses, so would need to be cast into pointers. Here is the updated patch. I believe I've resolved all your other comments. -Hollis [-- Attachment #2: macosx.txt --] [-- Type: text/plain, Size: 24046 bytes --] Index: ChangeLog =================================================================== RCS file: /cvsroot/grub/grub2/ChangeLog,v retrieving revision 1.217 diff -u -p -r1.217 ChangeLog --- ChangeLog 25 Dec 2005 19:40:31 -0000 1.217 +++ ChangeLog 3 Jan 2006 00:35:01 -0000 @@ -1,3 +1,22 @@ +2006-01-02 Hollis Blanchard <hollis@penguinppc.org> + + * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add cache.h. + (grubof_SOURCES): Add kern/powerpc/misc.S. + (pkgdata_MODULES): Add _macosx.mod and macosx.mod. + (_macosx_mod_SOURCES): New variable. + (_macosx_mod_CFLAGS): Likewise. + (macosx_mod_SOURCES): Likewise. + (macosx_mod_CFLAGS): Likewise. + * include/grub/misc.h (grub_memstr): New prototype. + * include/grub/powerpc/ieee1275/kernel.h (grub_jump): Likewise. + * include/grub/powerpc/ieee1275/loader.h (grub_rescue_cmd_macosx): + Likewise. + * kern/misc.c (grub_memstr): New function. + * include/grub/xcoff.h: New file. + * kern/powerpc/misc.S: Likewise. + * loader/powerpc/ieee1275/macosx.c: Likewise. + * loader/powerpc/ieee1275/macosx_normal.c: Likewise. + 2005-12-25 Yoshinori K. Okuji <okuji@enbug.org> * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRP_ADDR): Index: conf/powerpc-ieee1275.rmk =================================================================== RCS file: /cvsroot/grub/grub2/conf/powerpc-ieee1275.rmk,v retrieving revision 1.52 diff -u -p -r1.52 powerpc-ieee1275.rmk --- conf/powerpc-ieee1275.rmk 25 Dec 2005 15:59:50 -0000 1.52 +++ conf/powerpc-ieee1275.rmk 3 Jan 2006 00:35:02 -0000 @@ -9,7 +9,7 @@ COMMON_CFLAGS = -ffreestanding -msoft-fl MOSTLYCLEANFILES += grubof_symlist.c kernel_syms.lst DEFSYMFILES += kernel_syms.lst -grubof_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \ +grubof_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h env.h err.h \ file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h symbol.h \ term.h types.h powerpc/libgcc.h loader.h \ partition.h pc_partition.h ieee1275/ieee1275.h machine/time.h \ @@ -65,7 +65,7 @@ grubof_SOURCES = kern/powerpc/ieee1275/c kern/powerpc/ieee1275/init.c term/ieee1275/ofconsole.c \ kern/powerpc/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/powerpc/dl.c \ - grubof_symlist.c kern/powerpc/cache.S + grubof_symlist.c kern/powerpc/cache.S kern/powerpc/misc.S grubof_HEADERS = grub/powerpc/ieee1275/ieee1275.h grubof_CFLAGS = $(COMMON_CFLAGS) grubof_ASFLAGS = $(COMMON_ASFLAGS) @@ -84,6 +84,8 @@ grub_install_SOURCES = util/powerpc/ieee pkgdata_MODULES = halt.mod \ _linux.mod \ linux.mod \ + _macosx.mod \ + macosx.mod \ normal.mod \ reboot.mod \ suspend.mod @@ -117,4 +119,12 @@ reboot_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_SOURCES = commands/ieee1275/halt.c halt_mod_CFLAGS = $(COMMON_CFLAGS) +# For _macosx.mod. +_macosx_mod_SOURCES = loader/powerpc/ieee1275/macosx.c +_macosx_mod_CFLAGS = $(COMMON_CFLAGS) + +# For macosx.mod. +macosx_mod_SOURCES = loader/powerpc/ieee1275/macosx_normal.c +macosx_mod_CFLAGS = $(COMMON_CFLAGS) + include $(srcdir)/conf/common.mk Index: include/grub/misc.h =================================================================== RCS file: /cvsroot/grub/grub2/include/grub/misc.h,v retrieving revision 1.17 diff -u -p -r1.17 misc.h --- include/grub/misc.h 24 Oct 2005 10:23:46 -0000 1.17 +++ include/grub/misc.h 3 Jan 2006 00:35:02 -0000 @@ -1,7 +1,7 @@ /* misc.h - prototypes for misc functions */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2005 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2005,2006 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 @@ -75,5 +75,6 @@ grub_uint8_t *EXPORT_FUNC(grub_utf16_to_ grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, const grub_uint8_t *src, grub_size_t size); +void *EXPORT_FUNC(grub_memstr) (void *haystack, int len, char *needle); #endif /* ! GRUB_MISC_HEADER */ Index: include/grub/xcoff.h =================================================================== RCS file: include/grub/xcoff.h diff -N include/grub/xcoff.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/grub/xcoff.h 3 Jan 2006 00:35:02 -0000 @@ -0,0 +1,90 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* See http://www16.boulder.ibm.com/pseries/en_US/files/aixfiles/XCOFF.htm */ + +#ifndef GRUB_XCOFF_HEADER +#define GRUB_XCOFF_HEADER 1 + +#include <grub/types.h> + +struct grub_xcoff_func_desc +{ + grub_uint32_t address; + grub_uint32_t toc; +}; + +struct grub_xcoff_filehdr +{ + grub_uint16_t f_magic; + grub_uint16_t f_nscns; + grub_uint32_t f_timdat; + grub_uint32_t f_symptr; + grub_uint32_t f_nsyms; + grub_uint16_t f_opthdr; + grub_uint16_t f_flags; +}; + +#define GRUB_XCOFF32_MAGIC 0x01df + +struct grub_xcoff_auxhdr +{ + grub_uint16_t o_mflag; + grub_uint16_t o_vstamp; + grub_uint32_t o_tsize; + grub_uint32_t o_dsize; + grub_uint32_t o_bsize; + grub_uint32_t o_entry; + grub_uint32_t o_text_start; + grub_uint32_t o_data_start; + grub_uint32_t o_toc; + grub_uint16_t o_snentry; + grub_uint16_t o_sntext; + grub_uint16_t o_sndata; + grub_uint16_t o_sntoc; + grub_uint16_t o_snloader; + grub_uint16_t o_snbss; + grub_uint16_t o_algntext; + grub_uint16_t o_algndata; + grub_uint16_t o_modtype; + grub_uint8_t o_cpuflag; + grub_uint8_t o_cputype; + grub_uint32_t o_maxstack; + grub_uint32_t o_maxdata; + grub_uint32_t o_debugger; + char o_resv2[8]; +}; + +#define GRUB_XCOFF_MFLAGS_PAGEALIGNED 0x010b + +struct grub_xcoff_scnhdr +{ + char s_name[8]; + grub_uint32_t s_paddr; + grub_uint32_t s_vaddr; + grub_uint32_t s_size; + grub_uint32_t s_scnptr; + grub_uint32_t s_relptr; + grub_uint32_t s_lnnoptr; + grub_uint16_t s_nreloc; + grub_uint16_t s_nlnno; + grub_uint16_t s_flags; +}; + +#endif Index: include/grub/powerpc/ieee1275/kernel.h =================================================================== RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/kernel.h,v retrieving revision 1.3 diff -u -p -r1.3 kernel.h --- include/grub/powerpc/ieee1275/kernel.h 3 Aug 2005 22:53:50 -0000 1.3 +++ include/grub/powerpc/ieee1275/kernel.h 3 Jan 2006 00:35:02 -0000 @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,9 @@ void EXPORT_FUNC (abort) (void); void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); +void EXPORT_FUNC (grub_jump) (unsigned long text, unsigned long stack, + unsigned long arg1, unsigned long arg2); + /* Where grub-mkimage places the core modules in memory. */ #define GRUB_IEEE1275_MODULE_BASE 0x00300000 Index: include/grub/powerpc/ieee1275/loader.h =================================================================== RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/loader.h,v retrieving revision 1.4 diff -u -p -r1.4 loader.h --- include/grub/powerpc/ieee1275/loader.h 31 Jan 2005 21:44:35 -0000 1.4 +++ include/grub/powerpc/ieee1275/loader.h 3 Jan 2006 00:35:02 -0000 @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004,2005,2006 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ loader. */ void grub_rescue_cmd_linux (int argc, char *argv[]); void grub_rescue_cmd_initrd (int argc, char *argv[]); +void grub_rescue_cmd_macosx (int argc, char *argv[]); void grub_linux_init (void); void grub_linux_fini (void); Index: kern/misc.c =================================================================== RCS file: /cvsroot/grub/grub2/kern/misc.c,v retrieving revision 1.25 diff -u -p -r1.25 misc.c --- kern/misc.c 28 Oct 2005 03:14:33 -0000 1.25 +++ kern/misc.c 3 Jan 2006 00:35:02 -0000 @@ -1,7 +1,7 @@ /* misc.c - definitions of misc functions */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006 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 @@ -875,3 +875,20 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, return p - dest; } + +/* Find NULL-terminated `needle' in non-terminated `haystack'. */ +void * +grub_memstr (void *haystack, int len, char *needle) +{ + char *ptr = haystack; + int needle_len = grub_strlen (needle); + int i; + + for (i = 0; i < len - needle_len; i++) + { + if (0 == grub_memcmp (ptr + i, needle, needle_len)) + return ptr + i; + } + + return 0; +} Index: kern/powerpc/misc.S =================================================================== RCS file: kern/powerpc/misc.S diff -N kern/powerpc/misc.S --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ kern/powerpc/misc.S 3 Jan 2006 00:35:02 -0000 @@ -0,0 +1,30 @@ +/* misc.S - Miscellaneous assembly routines. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + .text + + /* Jump to a function and switch to a new stack. */ + .globl grub_jump +grub_jump: + mtctr 3 + mr 1, 4 + mr 3, 5 + mr 4, 6 + bctr Index: loader/powerpc/ieee1275/macosx.c =================================================================== RCS file: loader/powerpc/ieee1275/macosx.c diff -N loader/powerpc/ieee1275/macosx.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ loader/powerpc/ieee1275/macosx.c 3 Jan 2006 00:35:02 -0000 @@ -0,0 +1,329 @@ +/* macosx.c - boot Mac OS X */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* BootX, the Mac OS X bootloader, is an XCOFF executable with a CHRP script + prepended to it. We skip the script and load the XCOFF file. */ + +#include <grub/xcoff.h> +#include <grub/loader.h> +#include <grub/dl.h> +#include <grub/mm.h> +#include <grub/rescue.h> +#include <grub/misc.h> +#include <grub/cache.h> +#include <grub/machine/kernel.h> +#include <grub/machine/loader.h> +#include <grub/ieee1275/ieee1275.h> + +#define MAX_XCOFF_POS (8<<10) /* Search first 8 KiB. */ +#define READ_SIZE 512 +#define END_STRING "</CHRP-BOOT>\n\x04" + +/* This must be larger than the functions copied into high memory. */ +#define TRAMPOLINE_SIZE 0x200 + +#define GRUB_MACOSX_CHAIN_AREA 0x06000000 +#define GRUB_MACOSX_RELEASE_AREA (GRUB_MACOSX_CHAIN_AREA + TRAMPOLINE_SIZE) +#define GRUB_MACOSX_STACK_AREA (GRUB_MACOSX_RELEASE_AREA + TRAMPOLINE_SIZE) + +/* BootX will fail poorly if it is unable to claim this region. */ +#define GRUB_BOOTX_CLAIM_BASE 0x00003000 +#define GRUB_BOOTX_CLAIM_SIZE (0x06000000 - GRUB_BOOTX_CLAIM_BASE) + +static grub_dl_t my_mod; + +static grub_addr_t macosx_entry; +static grub_size_t macosx_size; + + +static grub_err_t +grub_macosx_boot (void) +{ + grub_dprintf ("loader", "BootX entry point: 0x%x\n", macosx_entry); + grub_dprintf ("loader", "trampoline entry point: 0x%x\n", + GRUB_MACOSX_CHAIN_AREA); + grub_dprintf ("loader", "trampoline stack pointer: 0x%x\n", + GRUB_MACOSX_STACK_AREA + TRAMPOLINE_SIZE); + grub_dprintf ("loader", "jumping to trampoline...\n"); + + /* Call the trampoline to boot the kernel. */ + grub_jump (GRUB_MACOSX_CHAIN_AREA, GRUB_MACOSX_STACK_AREA + TRAMPOLINE_SIZE, + macosx_entry, GRUB_MACOSX_RELEASE_AREA); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_macosx_release_mem (void) +{ + if (macosx_entry && grub_ieee1275_release (macosx_entry, macosx_size)) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory"); + + macosx_entry = 0; + macosx_size = 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_macosx_unload (void) +{ + grub_err_t err; + + err = grub_macosx_release_mem (); + grub_dl_unref (my_mod); + + return err; +} + +static grub_err_t +grub_xcoff_load_section (grub_file_t file, grub_off_t xcoff_pos, + struct grub_xcoff_scnhdr *scnhdr) +{ + int rc; + + grub_dprintf ("loader", "section %.8s:\n", scnhdr->s_name); + grub_dprintf ("loader", " paddr 0x%08x\n", scnhdr->s_paddr); + grub_dprintf ("loader", " vaddr 0x%08x\n", scnhdr->s_vaddr); + grub_dprintf ("loader", " size 0x%x\n", scnhdr->s_size); + grub_dprintf ("loader", " scnptr 0x%x\n", scnhdr->s_scnptr); + grub_dprintf ("loader", " flags 0x%x\n", scnhdr->s_flags); + + rc = grub_claimmap (scnhdr->s_paddr, scnhdr->s_size); + if (rc == -1) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not claim 0x%x", + scnhdr->s_paddr); + + if (scnhdr->s_scnptr) + { + grub_file_seek (file, xcoff_pos + scnhdr->s_scnptr); + + if (grub_file_read (file, (void *)scnhdr->s_paddr, scnhdr->s_size) + != (grub_ssize_t)scnhdr->s_size) + return grub_error (GRUB_ERR_READ_ERROR, + "could not load section %.8s\n", + scnhdr->s_name); + grub_arch_sync_caches ((void *) scnhdr->s_paddr, scnhdr->s_size); + } + else + /* BSS. */ + grub_memset ((void *) scnhdr->s_paddr, 0, scnhdr->s_size); + + /* Assume sections are contiguous. */ + macosx_size += scnhdr->s_size; + + return 0; +} + +static grub_err_t +grub_xcoff_load_file (grub_file_t file, grub_off_t xcoff_pos) +{ + struct grub_xcoff_filehdr _filehdr; + struct grub_xcoff_auxhdr _auxhdr; + struct grub_xcoff_filehdr *filehdr = &_filehdr; + struct grub_xcoff_auxhdr *auxhdr = &_auxhdr; + struct grub_xcoff_scnhdr *scnhdrs; + struct grub_xcoff_func_desc *desc; + int scnhdr_bytes; + int i; + + /* Read the file header. */ + if (grub_file_read (file, (void *)filehdr, sizeof (struct grub_xcoff_filehdr)) + != sizeof (struct grub_xcoff_filehdr)) + { + grub_error (GRUB_ERR_READ_ERROR, "could not read the XCOFF file header"); + goto out; + } + + if (filehdr->f_magic != GRUB_XCOFF32_MAGIC) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "bad XCOFF magic: 0x%x", + filehdr->f_magic); + goto out; + } + + grub_dprintf ("loader", "number of sections: %d\n", filehdr->f_nscns); + grub_dprintf ("loader", "flags: 0x%x\n", filehdr->f_flags); + + /* Read the auxiliary header. */ + if (filehdr->f_opthdr != sizeof (struct grub_xcoff_auxhdr)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "missing auxiliary header"); + goto out; + } + + if (grub_file_read (file, (void *)auxhdr, sizeof (struct grub_xcoff_auxhdr)) + != sizeof (struct grub_xcoff_auxhdr)) + return grub_error (GRUB_ERR_READ_ERROR, + "could not read the XCOFF auxiliary header"); + + if (auxhdr->o_mflag != GRUB_XCOFF_MFLAGS_PAGEALIGNED) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "unknown auxiliary header flags: 0x%x\n", + auxhdr->o_mflag); + + /* Load all section headers. */ + scnhdr_bytes = filehdr->f_nscns * sizeof (struct grub_xcoff_scnhdr); + scnhdrs = grub_malloc (scnhdr_bytes); + if (! scnhdrs) + return grub_errno; + + if (grub_file_read (file, (void *) scnhdrs, scnhdr_bytes) != scnhdr_bytes) + { + grub_free (scnhdrs); + return grub_error (GRUB_ERR_READ_ERROR, + "could not read XCOFF section headers"); + } + + for (i = 0; i < filehdr->f_nscns; i++) + { + if (grub_xcoff_load_section (file, xcoff_pos, scnhdrs + i)) + break; + } + + /* Find the entry point. */ + desc = (struct grub_xcoff_func_desc *) auxhdr->o_entry; + macosx_entry = desc->address; + grub_dprintf ("loader", "entry point 0x%08x\n", macosx_entry); + + out: + return grub_errno; +} + +/* grub_chain_trampoline is copied somewhere other than its link address + and executes after all other code has been blown away. In order to call + other functions from here, they must have been copied into a safe place and + their addresses passed as parameters. */ +typedef void (*kernel_entry_t) (unsigned long, unsigned long, int (void *)); +typedef int (*release_t) (grub_addr_t addr, grub_size_t size); +static void +grub_chain_trampoline (kernel_entry_t entry, release_t release) +{ + /* Release all memory BootX will claim. */ + release (GRUB_BOOTX_CLAIM_BASE, GRUB_BOOTX_CLAIM_SIZE); + entry (0, 0, grub_ieee1275_entry_fn); +} + +static int +grub_macosx_install_trampoline (void) +{ + int rc; + + /* We want to copy grub_chain_trampoline and grub_ieee1275_release into high + memory for use after we release all other code. Unfortunately, we don't + know exactly how big those functions are, so we just hope that + TRAMPOLINE_SIZE is big enough. */ + + rc = grub_claimmap (GRUB_MACOSX_CHAIN_AREA, TRAMPOLINE_SIZE); + rc |= grub_claimmap (GRUB_MACOSX_RELEASE_AREA, TRAMPOLINE_SIZE); + rc |= grub_claimmap (GRUB_MACOSX_STACK_AREA, TRAMPOLINE_SIZE); + if (rc) + return rc; + + grub_memcpy ((void *) GRUB_MACOSX_CHAIN_AREA, grub_chain_trampoline, + TRAMPOLINE_SIZE); + grub_arch_sync_caches ((void *) GRUB_MACOSX_CHAIN_AREA, TRAMPOLINE_SIZE); + grub_memcpy ((void *) GRUB_MACOSX_RELEASE_AREA, grub_ieee1275_release, + TRAMPOLINE_SIZE); + grub_arch_sync_caches ((void *) GRUB_MACOSX_RELEASE_AREA, TRAMPOLINE_SIZE); + + return 0; +} + +void +grub_rescue_cmd_macosx (int argc, char *argv[]) +{ + static char _buf[READ_SIZE]; + char *buf = _buf; + grub_file_t file = 0; + grub_off_t pos = 0; + grub_ssize_t bytes_read; + + grub_dl_ref (my_mod); + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + goto out; + } + + file = grub_file_open (argv[0]); + if (! file) + goto out; + + /* Search for the end of the script to find the XCOFF header. */ + while (pos < MAX_XCOFF_POS) { + char *match; + + bytes_read = grub_file_read (file, buf, READ_SIZE); + if (bytes_read < 0) + goto out; + + match = grub_memstr (buf, bytes_read, END_STRING); + if (match) + { + pos += (int) (match - buf) + grub_strlen (END_STRING); + grub_dprintf ("loader", "XCOFF header at file offset 0x%x\n", pos); + grub_file_seek (file, pos); + break; + } + + pos += READ_SIZE; + } + + if (pos < MAX_XCOFF_POS) + { + /* Install the trampoline we need to jump through. */ + if (grub_macosx_install_trampoline ()) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Failed to install trampoline.\n"); + goto out; + } + /* Load the XCOFF. */ + grub_xcoff_load_file (file, pos); + } + + out: + + if (file) + grub_file_close (file); + + if (grub_errno != GRUB_ERR_NONE) + { + grub_macosx_release_mem (); + grub_dl_unref (my_mod); + return; + } + + grub_loader_set (grub_macosx_boot, grub_macosx_unload); +} + +\f +GRUB_MOD_INIT (macosx) +{ + grub_rescue_register_command ("macosx", grub_rescue_cmd_macosx, + "load BootX, the Mac OS X bootloader"); + my_mod = mod; +} + +GRUB_MOD_FINI (macosx) +{ + grub_rescue_unregister_command ("macosx"); +} Index: loader/powerpc/ieee1275/macosx_normal.c =================================================================== RCS file: loader/powerpc/ieee1275/macosx_normal.c diff -N loader/powerpc/ieee1275/macosx_normal.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ loader/powerpc/ieee1275/macosx_normal.c 3 Jan 2006 00:35:02 -0000 @@ -0,0 +1,49 @@ +/* macosx_normal.c - boot Mac OS X */ +/* + * GRUB -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <grub/normal.h> +#include <grub/dl.h> +#include <grub/machine/loader.h> + +static const struct grub_arg_option options[] = + { + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +grub_cmd_macosx (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_macosx (argc, args); + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT(macosx_normal) +{ + (void) mod; + grub_register_command ("macosx", grub_cmd_macosx, GRUB_COMMAND_FLAG_BOTH, + "macosx [KERNELARGS...]", + "Loads BootX, the Mac OS X bootloader.", options); +} + +GRUB_MOD_FINI(macosx_normal) +{ + grub_unregister_command ("macosx"); +} ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] rough Mac OS X loader 2006-01-03 0:39 ` Hollis Blanchard @ 2006-01-03 18:02 ` Marco Gerards 0 siblings, 0 replies; 6+ messages in thread From: Marco Gerards @ 2006-01-03 18:02 UTC (permalink / raw) To: The development of GRUB 2 Hollis Blanchard <hollis@penguinppc.org> writes: > Here is the updated patch. I believe I've resolved all your other > comments. Great! Feel free to commit it, although it would be nice if you could test it first (I am really curious if it all works now). ;-) Thanks, Marco ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-01-03 18:04 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-01-02 0:38 [patch] rough Mac OS X loader Hollis Blanchard 2006-01-02 17:29 ` Marco Gerards 2006-01-02 17:50 ` Hollis Blanchard 2006-01-02 18:02 ` Marco Gerards 2006-01-03 0:39 ` Hollis Blanchard 2006-01-03 18:02 ` Marco Gerards
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.