diff --git a/ChangeLog b/ChangeLog index c4b1ae4c8..51ea4d5dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2012-02-29 Vladimir Serbinenko + + Add LZSS Mach-O support (needed for new xnu kernelcache). + + * grub-core/Makefile.core.def (xnu): Add file lzss.c + * grub-core/loader/lzss.c: New file. + * grub-core/loader/xnu.c (grub_xnu_load_driver): Close binaryfile + on Mach-O open failure. + * grub-core/loader/macho.c (grub_macho_close): Free uncompressedXX. + Don't free cmdsXX in uncompressedXX is set. + (grub_macho_file): Init new fields. + New argument is_64bit. All users updated. + Handle compressed. Error out if no suitable architecture is found. + Don't close file. + (grub_macho_open): New argument is_64bit. All users updated. + * grub-core/loader/macho32.c: Add defines for new fields. + * grub-core/loader/macho64.c: Likewise. + * grub-core/loader/machoXX.c (grub_macho_contains_macho): Make static. + (grub_macho_parse): Handle compressed. + Defer actual processing if compressed. + (grub_macho_cmds_iterate): Decompress if compressed. New argument + "filename". All users updated. + (grub_macho_size): New argument "filename". All users updated. + (grub_macho_get_entry_point): Likewise. + (grub_macho_load): Handle compressed. + * include/grub/macho.h (grub_macho_lzss_header): New struct. + (GRUB_MACHO_LZSS_OFFSET): New define. + (grub_decompress_lzss): New proto. + * include/grub/machoload.h (grub_macho_file): New fields to handle + compressed. + (grub_macho_contains_macho64): Remove proto. + (grub_macho_contains_macho32): Likewise. + * util/grub.d/30_os-prober.in: Use kernel cache if available. + 2012-02-29 Vladimir Serbinenko * grub-core/disk/pata.c (grub_pata_readwrite): Fix ATAPI protocol error. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 947a43ab3..4139dd034 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1378,6 +1378,7 @@ module = { x86 = loader/macho64.c; x86 = loader/macho.c; x86 = loader/xnu.c; + x86 = loader/lzss.c; extra_dist = loader/machoXX.c; enable = x86; diff --git a/grub-core/loader/lzss.c b/grub-core/loader/lzss.c new file mode 100644 index 000000000..532d8e4a3 --- /dev/null +++ b/grub-core/loader/lzss.c @@ -0,0 +1,56 @@ +/************************************************************** + LZSS.C -- A Data Compression Program + (tab = 4 spaces) +*************************************************************** + 4/6/1989 Haruhiko Okumura + Use, distribute, and modify this program freely. + Please send me your improved versions. + PC-VAN SCIENCE + NIFTY-Serve PAF01022 + CompuServe 74050,1022 +**************************************************************/ + +#include +#include + +#define N 4096 /* size of ring buffer */ +#define F 18 /* upper limit for match_length */ +#define THRESHOLD 2 /* encode string into position and length + if match_length is greater than this */ +#define NIL N /* index for root of binary search trees */ + +#define EOF -1 +#define getc(file) ((src < srcend) ? *src++ : EOF) +#define putc(c, file) (dst < dstend) ? (*dst++ = (c)) : 0; + +grub_size_t +grub_decompress_lzss (grub_uint8_t *dst, grub_uint8_t *dstend, + grub_uint8_t *src, grub_uint8_t *srcend) +{ + int i, j, k, r, c; + unsigned int flags; + static unsigned char text_buf[N + F - 1]; + grub_uint8_t *dst0 = dst; + + for (i = 0; i < N - F; i++) text_buf[i] = ' '; + r = N - F; flags = 0; + for ( ; ; ) { + if (((flags >>= 1) & 256) == 0) { + if ((c = getc(infile)) == EOF) break; + flags = c | 0xff00; /* uses higher byte cleverly */ + } /* to count eight */ + if (flags & 1) { + if ((c = getc(infile)) == EOF) break; + putc(c, outfile); text_buf[r++] = c; r &= (N - 1); + } else { + if ((i = getc(infile)) == EOF) break; + if ((j = getc(infile)) == EOF) break; + i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD; + for (k = 0; k <= j; k++) { + c = text_buf[(i + k) & (N - 1)]; + putc(c, outfile); text_buf[r++] = c; r &= (N - 1); + } + } + } + return dst - dst0; +} diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c index 0a1717fbb..bf0bf74f7 100644 --- a/grub-core/loader/macho.c +++ b/grub-core/loader/macho.c @@ -35,8 +35,12 @@ grub_macho_close (grub_macho_t macho) { grub_file_t file = macho->file; - grub_free (macho->cmds32); - grub_free (macho->cmds64); + if (!macho->uncompressed32) + grub_free (macho->cmds32); + grub_free (macho->uncompressed32); + if (!macho->uncompressed64) + grub_free (macho->cmds64); + grub_free (macho->uncompressed64); grub_free (macho); @@ -47,7 +51,7 @@ grub_macho_close (grub_macho_t macho) } grub_macho_t -grub_macho_file (grub_file_t file, const char *filename) +grub_macho_file (grub_file_t file, const char *filename, int is_64bit) { grub_macho_t macho; union grub_macho_filestart filestart; @@ -63,6 +67,10 @@ grub_macho_file (grub_file_t file, const char *filename) macho->end64 = -1; macho->cmds32 = 0; macho->cmds64 = 0; + macho->uncompressed32 = 0; + macho->uncompressed64 = 0; + macho->compressed32 = 0; + macho->compressed64 = 0; if (grub_file_seek (macho->file, 0) == (grub_off_t) -1) goto fail; @@ -104,14 +112,14 @@ grub_macho_file (grub_file_t file, const char *filename) for (i = 0; i < narchs; i++) { if (GRUB_MACHO_CPUTYPE_IS_HOST32 - (grub_be_to_cpu32 (archs[i].cputype))) + (grub_be_to_cpu32 (archs[i].cputype)) && !is_64bit) { macho->offset32 = grub_be_to_cpu32 (archs[i].offset); macho->end32 = grub_be_to_cpu32 (archs[i].offset) + grub_be_to_cpu32 (archs[i].size); } if (GRUB_MACHO_CPUTYPE_IS_HOST64 - (grub_be_to_cpu32 (archs[i].cputype))) + (grub_be_to_cpu32 (archs[i].cputype)) && is_64bit) { macho->offset64 = grub_be_to_cpu32 (archs[i].offset); macho->end64 = grub_be_to_cpu32 (archs[i].offset) @@ -122,14 +130,29 @@ grub_macho_file (grub_file_t file, const char *filename) } /* Is it a thin 32-bit file? */ - if (filestart.thin32.magic == GRUB_MACHO_MAGIC32) + if (filestart.thin32.magic == GRUB_MACHO_MAGIC32 && !is_64bit) { macho->offset32 = 0; macho->end32 = grub_file_size (file); } /* Is it a thin 64-bit file? */ - if (filestart.thin64.magic == GRUB_MACHO_MAGIC64) + if (filestart.thin64.magic == GRUB_MACHO_MAGIC64 && is_64bit) + { + macho->offset64 = 0; + macho->end64 = grub_file_size (file); + } + + if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC, + sizeof (filestart.lzss.magic)) == 0 && !is_64bit) + { + macho->offset32 = 0; + macho->end32 = grub_file_size (file); + } + + /* Is it a thin 64-bit file? */ + if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC, + sizeof (filestart.lzss.magic)) == 0 && is_64bit) { macho->offset64 = 0; macho->end64 = grub_file_size (file); @@ -138,15 +161,30 @@ grub_macho_file (grub_file_t file, const char *filename) grub_macho_parse32 (macho, filename); grub_macho_parse64 (macho, filename); + if (macho->offset32 == -1 && !is_64bit) + { + grub_error (GRUB_ERR_BAD_OS, + "Mach-O doesn't contain suitable 32-bit architecture"); + goto fail; + } + + if (macho->offset64 == -1 && is_64bit) + { + grub_error (GRUB_ERR_BAD_OS, + "Mach-O doesn't contain suitable 64-bit architecture"); + goto fail; + } + return macho; fail: + macho->file = 0; grub_macho_close (macho); return 0; } grub_macho_t -grub_macho_open (const char *name) +grub_macho_open (const char *name, int is_64bit) { grub_file_t file; grub_macho_t macho; @@ -155,7 +193,7 @@ grub_macho_open (const char *name) if (! file) return 0; - macho = grub_macho_file (file, name); + macho = grub_macho_file (file, name, is_64bit); if (! macho) grub_file_close (file); diff --git a/grub-core/loader/macho32.c b/grub-core/loader/macho32.c index 0d740eda7..eda8d9ed7 100644 --- a/grub-core/loader/macho32.c +++ b/grub-core/loader/macho32.c @@ -11,6 +11,10 @@ typedef struct grub_macho_thread32 grub_macho_thread_t; #define cmdsizeXX cmdsize32 #define cmdsXX cmds32 #define endXX end32 +#define uncompressedXX uncompressed32 +#define compressedXX compressed32 +#define uncompressed_sizeXX uncompressed_size32 +#define compressed_sizeXX compressed_size32 #define XX "32" #define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC32 #define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT32 diff --git a/grub-core/loader/macho64.c b/grub-core/loader/macho64.c index 17a8021e0..417a4a83d 100644 --- a/grub-core/loader/macho64.c +++ b/grub-core/loader/macho64.c @@ -11,6 +11,10 @@ typedef struct grub_macho_thread64 grub_macho_thread_t; #define cmdsizeXX cmdsize64 #define cmdsXX cmds64 #define endXX end64 +#define uncompressedXX uncompressed64 +#define compressedXX compressed64 +#define uncompressed_sizeXX uncompressed_size64 +#define compressed_sizeXX compressed_size64 #define XX "64" #define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC64 #define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT64 diff --git a/grub-core/loader/machoXX.c b/grub-core/loader/machoXX.c index 313c5baa7..0778831ab 100644 --- a/grub-core/loader/machoXX.c +++ b/grub-core/loader/machoXX.c @@ -6,7 +6,7 @@ #define min(a,b) (((a) < (b)) ? (a) : (b)) -int +static int SUFFIX (grub_macho_contains_macho) (grub_macho_t macho) { return macho->offsetXX != -1; @@ -15,16 +15,19 @@ SUFFIX (grub_macho_contains_macho) (grub_macho_t macho) void SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename) { - grub_macho_header_t head; + union { + struct grub_macho_lzss_header lzss; + grub_macho_header_t macho; + } head; /* Is there any candidate at all? */ if (macho->offsetXX == -1) return; - /* Read header and check magic*/ + /* Read header and check magic. */ if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1 || grub_file_read (macho->file, &head, sizeof (head)) - != sizeof(head)) + != sizeof (head)) { if (!grub_errno) grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), @@ -32,7 +35,25 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename) macho->offsetXX = -1; return; } - if (head.magic != GRUB_MACHO_MAGIC) + if (grub_memcmp (head.lzss.magic, GRUB_MACHO_LZSS_MAGIC, + sizeof (head.lzss.magic)) == 0) + { + macho->compressed_sizeXX = grub_be_to_cpu32 (head.lzss.compressed_size); + macho->uncompressed_sizeXX + = grub_be_to_cpu32 (head.lzss.uncompressed_size); + if (macho->uncompressed_sizeXX < sizeof (head.macho)) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + macho->offsetXX = -1; + return; + } + /* Skip header check. */ + macho->compressedXX = 1; + return; + } + + if (head.macho.magic != GRUB_MACHO_MAGIC) { grub_error (GRUB_ERR_BAD_OS, "invalid Mach-O " XX "-bit header"); macho->offsetXX = -1; @@ -40,12 +61,14 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename) } /* Read commands. */ - macho->ncmdsXX = head.ncmds; - macho->cmdsizeXX = head.sizeofcmds; - macho->cmdsXX = grub_malloc(macho->cmdsizeXX); + macho->ncmdsXX = head.macho.ncmds; + macho->cmdsizeXX = head.macho.sizeofcmds; + macho->cmdsXX = grub_malloc (macho->cmdsizeXX); if (! macho->cmdsXX) return; - if (grub_file_read (macho->file, macho->cmdsXX, + if (grub_file_seek (macho->file, macho->offsetXX + + sizeof (grub_macho_header_t)) == (grub_off_t) -1 + || grub_file_read (macho->file, macho->cmdsXX, (grub_size_t) macho->cmdsizeXX) != (grub_ssize_t) macho->cmdsizeXX) { @@ -63,12 +86,76 @@ typedef int NESTED_FUNC_ATTR (*grub_macho_iter_hook_t) static grub_err_t grub_macho_cmds_iterate (grub_macho_t macho, grub_macho_iter_hook_t hook, - void *hook_arg) + void *hook_arg, + const char *filename) { - grub_uint8_t *hdrs = macho->cmdsXX; + grub_uint8_t *hdrs; int i; + + if (macho->compressedXX && !macho->uncompressedXX) + { + grub_uint8_t *tmp; + grub_macho_header_t *head; + macho->uncompressedXX = grub_malloc (macho->uncompressed_sizeXX); + if (!macho->uncompressedXX) + return grub_errno; + tmp = grub_malloc (macho->compressed_sizeXX); + if (!tmp) + { + grub_free (macho->uncompressedXX); + macho->uncompressedXX = 0; + return grub_errno; + } + if (grub_file_seek (macho->file, macho->offsetXX + + GRUB_MACHO_LZSS_OFFSET) == (grub_off_t) -1 + || grub_file_read (macho->file, tmp, + (grub_size_t) macho->compressed_sizeXX) + != (grub_ssize_t) macho->compressed_sizeXX) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + grub_free (tmp); + grub_free (macho->uncompressedXX); + macho->uncompressedXX = 0; + macho->offsetXX = -1; + return grub_errno; + } + if (grub_decompress_lzss (macho->uncompressedXX, + macho->uncompressedXX + + macho->uncompressed_sizeXX, + tmp, tmp + macho->compressed_sizeXX) + != macho->uncompressed_sizeXX) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + grub_free (tmp); + grub_free (macho->uncompressedXX); + macho->uncompressedXX = 0; + macho->offsetXX = -1; + return grub_errno; + } + grub_free (tmp); + head = (grub_macho_header_t *) macho->uncompressedXX; + macho->ncmdsXX = head->ncmds; + macho->cmdsizeXX = head->sizeofcmds; + macho->cmdsXX = macho->uncompressedXX + sizeof (grub_macho_header_t); + if (sizeof (grub_macho_header_t) + macho->cmdsizeXX + >= macho->uncompressed_sizeXX) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + grub_free (macho->uncompressedXX); + macho->uncompressedXX = 0; + macho->offsetXX = -1; + return grub_errno; + } + } + if (! macho->cmdsXX) return grub_error (GRUB_ERR_BAD_OS, "couldn't find " XX "-bit Mach-O"); + hdrs = macho->cmdsXX; for (i = 0; i < macho->ncmdsXX; i++) { struct grub_macho_cmd *hdr = (struct grub_macho_cmd *) hdrs; @@ -116,7 +203,8 @@ SUFFIX (grub_macho_readfile) (grub_macho_t macho, /* Calculate the amount of memory spanned by the segments. */ grub_err_t SUFFIX (grub_macho_size) (grub_macho_t macho, grub_macho_addr_t *segments_start, - grub_macho_addr_t *segments_end, int flags) + grub_macho_addr_t *segments_end, int flags, + const char *filename) { int nr_phdrs = 0; @@ -149,7 +237,7 @@ SUFFIX (grub_macho_size) (grub_macho_t macho, grub_macho_addr_t *segments_start, *segments_start = (grub_macho_addr_t) -1; *segments_end = 0; - grub_macho_cmds_iterate (macho, calcsize, 0); + grub_macho_cmds_iterate (macho, calcsize, 0, filename); if (nr_phdrs == 0) return grub_error (GRUB_ERR_BAD_OS, "no program headers present"); @@ -183,16 +271,31 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename, if (! hdr->vmsize) return 0; - if (grub_file_seek (_macho->file, hdr->fileoff - + _macho->offsetXX) == (grub_off_t) -1) - return 1; - if (hdr->filesize) { - grub_ssize_t read; - read = grub_file_read (_macho->file, offset + hdr->vmaddr, - min (hdr->filesize, hdr->vmsize)); - if (read != (grub_ssize_t) min (hdr->filesize, hdr->vmsize)) + grub_ssize_t read, toread = min (hdr->filesize, hdr->vmsize); + if (macho->uncompressedXX) + { + if (hdr->fileoff + toread + > _macho->uncompressed_sizeXX) + read = -1; + else + { + read = toread; + grub_memcpy (offset + hdr->vmaddr, + _macho->uncompressedXX + hdr->fileoff, read); + } + } + else + { + if (grub_file_seek (_macho->file, hdr->fileoff + + _macho->offsetXX) == (grub_off_t) -1) + return 1; + read = grub_file_read (_macho->file, offset + hdr->vmaddr, + toread); + } + + if (read != toread) { /* XXX How can we free memory from `load_hook'? */ if (!grub_errno) @@ -229,13 +332,13 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename, if (darwin_version) *darwin_version = 0; - grub_macho_cmds_iterate (macho, do_load, 0); + grub_macho_cmds_iterate (macho, do_load, 0, filename); return grub_errno; } grub_macho_addr_t -SUFFIX (grub_macho_get_entry_point) (grub_macho_t macho) +SUFFIX (grub_macho_get_entry_point) (grub_macho_t macho, const char *filename) { grub_macho_addr_t entry_point = 0; auto int NESTED_FUNC_ATTR hook(grub_macho_t _macho, @@ -249,6 +352,6 @@ SUFFIX (grub_macho_get_entry_point) (grub_macho_t macho) entry_point = ((grub_macho_thread_t *) hdr)->entry_point; return 0; } - grub_macho_cmds_iterate (macho, hook, 0); + grub_macho_cmds_iterate (macho, hook, 0, filename); return entry_point; } diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index 88c17a582..ed3fc72a7 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -351,17 +351,12 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), grub_xnu_unload (); - macho = grub_macho_open (args[0]); + macho = grub_macho_open (args[0], 0); if (! macho) return grub_errno; - if (! grub_macho_contains_macho32 (macho)) - { - grub_macho_close (macho); - return grub_error (GRUB_ERR_BAD_OS, - "kernel doesn't contain suitable 32-bit architecture"); - } - err = grub_macho_size32 (macho, &startcode, &endcode, GRUB_MACHO_NOBSS); + err = grub_macho_size32 (macho, &startcode, &endcode, GRUB_MACHO_NOBSS, + args[0]); if (err) { grub_macho_close (macho); @@ -396,7 +391,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), return err; } - grub_xnu_entry_point = grub_macho_get_entry_point32 (macho); + grub_xnu_entry_point = grub_macho_get_entry_point32 (macho, args[0]); if (! grub_xnu_entry_point) { grub_macho_close (macho); @@ -461,17 +456,12 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), grub_xnu_unload (); - macho = grub_macho_open (args[0]); + macho = grub_macho_open (args[0], 1); if (! macho) return grub_errno; - if (! grub_macho_contains_macho64 (macho)) - { - grub_macho_close (macho); - return grub_error (GRUB_ERR_BAD_OS, - "kernel doesn't contain suitable 64-bit architecture"); - } - err = grub_macho_size64 (macho, &startcode, &endcode, GRUB_MACHO_NOBSS); + err = grub_macho_size64 (macho, &startcode, &endcode, GRUB_MACHO_NOBSS, + args[0]); if (err) { grub_macho_close (macho); @@ -509,7 +499,8 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), return err; } - grub_xnu_entry_point = grub_macho_get_entry_point64 (macho) & 0x0fffffff; + grub_xnu_entry_point = grub_macho_get_entry_point64 (macho, args[0]) + & 0x0fffffff; if (! grub_xnu_entry_point) { grub_macho_close (macho); @@ -667,18 +658,16 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile, /* Compute the needed space. */ if (binaryfile) { - macho = grub_macho_file (binaryfile, filename); - if (! macho || ! grub_macho_contains_macho32 (macho)) - { - if (macho) - grub_macho_close (macho); - return grub_error (GRUB_ERR_BAD_OS, - "extension doesn't contain suitable architecture"); - } - if (grub_xnu_is_64bit) - machosize = grub_macho_filesize64 (macho); + macho = grub_macho_file (binaryfile, filename, grub_xnu_is_64bit); + if (!macho) + grub_file_close (binaryfile); else - machosize = grub_macho_filesize32 (macho); + { + if (grub_xnu_is_64bit) + machosize = grub_macho_filesize64 (macho); + else + machosize = grub_macho_filesize32 (macho); + } neededspace += machosize; } else diff --git a/include/grub/macho.h b/include/grub/macho.h index 82145835f..6a98b6e12 100644 --- a/include/grub/macho.h +++ b/include/grub/macho.h @@ -68,14 +68,6 @@ struct grub_macho_header64 grub_uint32_t reserved; } __attribute__ ((packed)); -/* Convenience union. What do we need to load to identify the file type. */ -union grub_macho_filestart -{ - struct grub_macho_fat_header fat; - struct grub_macho_header32 thin32; - struct grub_macho_header64 thin64; -} __attribute__ ((packed)); - /* Common header of Mach-O commands. */ struct grub_macho_cmd { @@ -121,4 +113,28 @@ struct grub_macho_segment64 #define GRUB_MACHO_CMD_THREAD 5 +struct grub_macho_lzss_header +{ + char magic[8]; +#define GRUB_MACHO_LZSS_MAGIC "complzss" + grub_uint32_t unused; + grub_uint32_t uncompressed_size; + grub_uint32_t compressed_size; +}; + +/* Convenience union. What do we need to load to identify the file type. */ +union grub_macho_filestart +{ + struct grub_macho_fat_header fat; + struct grub_macho_header32 thin32; + struct grub_macho_header64 thin64; + struct grub_macho_lzss_header lzss; +} __attribute__ ((packed)); + +#define GRUB_MACHO_LZSS_OFFSET 0x180 + +grub_size_t +grub_decompress_lzss (grub_uint8_t *dst, grub_uint8_t *dstend, + grub_uint8_t *src, grub_uint8_t *srcend); + #endif diff --git a/include/grub/machoload.h b/include/grub/machoload.h index bb0374c88..1eec118f1 100644 --- a/include/grub/machoload.h +++ b/include/grub/machoload.h @@ -33,27 +33,38 @@ struct grub_macho_file int ncmds32; grub_size_t cmdsize32; grub_uint8_t *cmds32; + grub_uint8_t *uncompressed32; + int compressed32; + grub_size_t compressed_size32; + grub_size_t uncompressed_size32; grub_ssize_t offset64; grub_ssize_t end64; int ncmds64; grub_size_t cmdsize64; grub_uint8_t *cmds64; + grub_uint8_t *uncompressed64; + int compressed64; + grub_size_t compressed_size64; + grub_size_t uncompressed_size64; }; typedef struct grub_macho_file *grub_macho_t; -grub_macho_t grub_macho_open (const char *); -grub_macho_t grub_macho_file (grub_file_t file, const char *filename); +grub_macho_t grub_macho_open (const char *, int is_64bit); +grub_macho_t grub_macho_file (grub_file_t file, const char *filename, + int is_64bit); grub_err_t grub_macho_close (grub_macho_t); -int grub_macho_contains_macho32 (grub_macho_t); grub_err_t grub_macho_size32 (grub_macho_t macho, grub_uint32_t *segments_start, - grub_uint32_t *segments_end, int flags); -grub_uint32_t grub_macho_get_entry_point32 (grub_macho_t macho); + grub_uint32_t *segments_end, int flags, + const char *filename); +grub_uint32_t grub_macho_get_entry_point32 (grub_macho_t macho, + const char *filename); -int grub_macho_contains_macho64 (grub_macho_t); grub_err_t grub_macho_size64 (grub_macho_t macho, grub_uint64_t *segments_start, - grub_uint64_t *segments_end, int flags); -grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho); + grub_uint64_t *segments_end, int flags, + const char *filename); +grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho, + const char *filename); /* Ignore BSS segments when loading. */ #define GRUB_MACHO_NOBSS 0x1 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index 63800c10b..3ba2458b6 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -66,8 +66,11 @@ EOF if [ -f /Extra/DSDT.aml ]; then acpi -e /Extra/DSDT.aml fi - $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid - if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then + if [ /kernelcache -nt /System/Library/Extensions ]; then + $1 /kernelcache boot-uuid=\${uuid} rd=*uuid + else + $1 /mach_kernel boot-uuid=\${uuid} rd=*uuid + elif [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then xnu_mkext /System/Library/Extensions.mkext else xnu_kextdir /System/Library/Extensions