diff --git a/conf/common.rmk b/conf/common.rmk index 1b9a6cd..1d0427d 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -125,6 +125,16 @@ endif grub_pe2elf_SOURCES = util/grub-pe2elf.c util/misc.c CLEANFILES += grub-pe2elf +# grub_macho2img assumes a lot about source file. +# So installing it definitively is useless +# But adding to bin_UTILITIES is needed for +# genmk.rb to work +ifeq (0,1) +bin_UTILITIES += grub-macho2img +endif +grub_macho2img_SOURCES = util/grub-macho2img.c +CLEANFILES += grub-macho2img + # For grub-mkconfig grub-mkconfig: util/grub-mkconfig.in config.status ./config.status --file=$@:$< diff --git a/genmk.rb b/genmk.rb index 249dcb5..05ecc96 100644 --- a/genmk.rb +++ b/genmk.rb @@ -56,8 +56,18 @@ class Image "CLEANFILES += address@hidden #{exe} #{objs_str} MOSTLYCLEANFILES += #{deps_str} +ifneq ($(TARGET_APPLE_CC),1) address@hidden: #{exe} $(OBJCOPY) -O $(#{prefix}_FORMAT) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id $< $@ +else +ifneq (#{exe},kernel.exec) address@hidden: #{exe} ./grub-macho2img + ./grub-macho2img $< $@ +else address@hidden: #{exe} ./grub-macho2img + ./grub-macho2img --bss $< $@ +endif +endif #{exe}: #{objs_str} $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) diff --git a/include/grub/list.h b/include/grub/list.h index eba1237..6e03492 100644 --- a/include/grub/list.h +++ b/include/grub/list.h @@ -41,7 +41,18 @@ void EXPORT_FUNC(grub_list_insert) (grub_list_t *head, grub_list_t item, /* This function doesn't exist, so if assertion is false for some reason, the linker would fail. */ +#ifdef APPLE_CC +/* This approach fails with Apple's gcc. Use grub_abort. */ +#include +static inline void * +grub_assert_fail (void) +{ + grub_abort (); + return 0; +} +#else extern void* grub_assert_fail (void); +#endif #define GRUB_FIELD_MATCH(ptr, type, field) \ ((char *) &(ptr)->field == (char *) &((type) (ptr))->field) diff --git a/include/grub/misc.h b/include/grub/misc.h index 5c8baa1..23e0ce6 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -40,8 +40,10 @@ char *EXPORT_FUNC(grub_strcat) (char *dest, const char *src); char *EXPORT_FUNC(grub_strncat) (char *dest, const char *src, int c); /* Prototypes for aliases. */ +#if !defined (GRUB_UTIL) || !defined (APPLE_CC) void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n); void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n); +#endif int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n); int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2); diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 23f84ed..6cdc79a 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -110,6 +110,13 @@ VARIABLE(grub_prefix) . = _start + GRUB_KERNEL_MACHINE_DATA_END +#ifdef APPLE_CC +bss_start: + .long 0 +bss_end: + .long 0 +#endif + /* * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). * This uses the a.out kludge to load raw binary to the area starting at 1MB, diff --git a/kern/misc.c b/kern/misc.c index 4c71ca8..4b46c67 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -44,11 +44,23 @@ grub_memmove (void *dest, const void *src, grub_size_t n) return dest; } + +#ifndef APPLE_CC void *memmove (void *dest, const void *src, grub_size_t n) __attribute__ ((alias ("grub_memmove"))); /* GCC emits references to memcpy() for struct copies etc. */ void *memcpy (void *dest, const void *src, grub_size_t n) __attribute__ ((alias ("grub_memmove"))); +#else +void *memcpy (void *dest, const void *src, grub_size_t n) +{ + return grub_memmove (dest, src, n); +} +void *memmove (void *dest, const void *src, grub_size_t n) +{ + return grub_memmove (dest, src, n); +} +#endif char * grub_strcpy (char *dest, const char *src) @@ -134,7 +146,22 @@ grub_printf (const char *fmt, ...) return ret; } -#ifndef GRUB_UTIL +#if defined (APPLE_CC) && ! defined (GRUB_UTIL) +int +grub_err_printf (const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start (ap, fmt); + ret = grub_vprintf (fmt, ap); + va_end (ap); + + return ret; +} +#endif + +#if ! defined (APPLE_CC) && ! defined (GRUB_UTIL) int grub_err_printf (const char *fmt, ...) __attribute__ ((alias("grub_printf"))); #endif @@ -185,8 +212,10 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n) return 0; } +#ifndef APPLE_CC int memcmp (const void *s1, const void *s2, grub_size_t n) __attribute__ ((alias ("grub_memcmp"))); +#endif int grub_strcmp (const char *s1, const char *s2) @@ -534,8 +563,10 @@ grub_memset (void *s, int c, grub_size_t n) return s; } +#ifndef APPLE_CC void *memset (void *s, int c, grub_size_t n) __attribute__ ((alias ("grub_memset"))); +#endif grub_size_t grub_strlen (const char *s) @@ -1066,8 +1097,11 @@ grub_abort (void) grub_exit (); } + +#ifndef APPLE_CC /* GCC emits references to abort(). */ void abort (void) __attribute__ ((alias ("grub_abort"))); +#endif #ifdef NEED_ENABLE_EXECUTE_STACK /* Some gcc versions generate a call to this function diff --git a/util/grub-macho2img.c b/util/grub-macho2img.c new file mode 100644 index 0000000..63c94c7 --- /dev/null +++ b/util/grub-macho2img.c @@ -0,0 +1,116 @@ +/* macho2img.c - tool to convert Mach-O to raw imagw. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 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 . + */ + +#include +#include +#include +#include +#include + +/* XXX: this file assumes particular Mach-O layout and does no checks. */ +/* However as build system ensures correct usage of this tool this + shouldn't be a problem. */ + +int +main (int argc, char **argv) +{ + FILE *in, *out; + int do_bss = 0; + char *buf; + int bufsize; + struct grub_macho_header32 *head; + struct grub_macho_segment32 *curcmd; + unsigned i; + unsigned bssstart = 0; + unsigned bssend = 0; + + if (argc && strcmp (argv[1], "--bss") == 0) + do_bss = 1; + if (argc < 2 + do_bss) + { + printf ("Usage: %s [--bss] filename.exec filename.img\n" + "Convert Mach-O into raw image\n", argv[0]); + return 0; + } + in = fopen (argv[1 + do_bss], "rb"); + if (! in) + { + printf ("Couldn't open %s\n", argv[1 + do_bss]); + return 1; + } + out = fopen (argv[2 + do_bss], "wb"); + if (! out) + { + fclose (in); + printf ("Couldn't open %s\n", argv[2 + do_bss]); + return 2; + } + fseek (in, 0, SEEK_END); + bufsize = ftell (in); + fseek (in, 0, SEEK_SET); + buf = malloc (bufsize); + if (! buf) + { + fclose (in); + fclose (out); + printf ("Couldn't allocate buffer\n"); + return 3; + } + fread (buf, 1, bufsize, in); + head = (struct grub_macho_header32 *) buf; + if (grub_le_to_cpu32 (head->magic) != GRUB_MACHO_MAGIC32) + { + fclose (in); + fclose (out); + free (buf); + printf ("Invalid Mach-O fle\n"); + return 4; + } + curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head)); + for (i = 0; i < grub_le_to_cpu32 (head->ncmds); i++, + curcmd = (struct grub_macho_segment32 *) + (((char *) curcmd) + curcmd->cmdsize)) + { + if (curcmd->cmd != GRUB_MACHO_CMD_SEGMENT32) + continue; + fwrite (buf + grub_le_to_cpu32 (curcmd->fileoff), 1, + grub_le_to_cpu32 (curcmd->filesize), out); + if (grub_le_to_cpu32 (curcmd->vmsize) + > grub_le_to_cpu32 (curcmd->filesize)) + { + bssstart = grub_le_to_cpu32 (curcmd->vmaddr) + + grub_le_to_cpu32 (curcmd->filesize) ; + bssend = grub_le_to_cpu32 (curcmd->vmaddr) + + grub_le_to_cpu32 (curcmd->vmsize) ; + } + } + if (do_bss) + { + grub_uint32_t tmp; + fseek (out, 0x5c, SEEK_SET); + tmp = grub_cpu_to_le32 (bssstart); + fwrite (&tmp, 4, 1, out); + tmp = grub_cpu_to_le32 (bssend); + fwrite (&tmp, 4, 1, out); + } + fclose (in); + fclose (out); + printf("macho2img complete\n"); + return 0; +}