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.
This commit is contained in:
parent
ebd17d6f51
commit
99ce1597a4
11 changed files with 339 additions and 80 deletions
34
ChangeLog
34
ChangeLog
|
@ -1,3 +1,37 @@
|
||||||
|
2012-02-29 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
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 <phcoder@gmail.com>
|
2012-02-29 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/disk/pata.c (grub_pata_readwrite): Fix ATAPI protocol error.
|
* grub-core/disk/pata.c (grub_pata_readwrite): Fix ATAPI protocol error.
|
||||||
|
|
|
@ -1378,6 +1378,7 @@ module = {
|
||||||
x86 = loader/macho64.c;
|
x86 = loader/macho64.c;
|
||||||
x86 = loader/macho.c;
|
x86 = loader/macho.c;
|
||||||
x86 = loader/xnu.c;
|
x86 = loader/xnu.c;
|
||||||
|
x86 = loader/lzss.c;
|
||||||
|
|
||||||
extra_dist = loader/machoXX.c;
|
extra_dist = loader/machoXX.c;
|
||||||
enable = x86;
|
enable = x86;
|
||||||
|
|
56
grub-core/loader/lzss.c
Normal file
56
grub-core/loader/lzss.c
Normal file
|
@ -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 <grub/types.h>
|
||||||
|
#include <grub/macho.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -35,8 +35,12 @@ grub_macho_close (grub_macho_t macho)
|
||||||
{
|
{
|
||||||
grub_file_t file = macho->file;
|
grub_file_t file = macho->file;
|
||||||
|
|
||||||
grub_free (macho->cmds32);
|
if (!macho->uncompressed32)
|
||||||
grub_free (macho->cmds64);
|
grub_free (macho->cmds32);
|
||||||
|
grub_free (macho->uncompressed32);
|
||||||
|
if (!macho->uncompressed64)
|
||||||
|
grub_free (macho->cmds64);
|
||||||
|
grub_free (macho->uncompressed64);
|
||||||
|
|
||||||
grub_free (macho);
|
grub_free (macho);
|
||||||
|
|
||||||
|
@ -47,7 +51,7 @@ grub_macho_close (grub_macho_t macho)
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_macho_t
|
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;
|
grub_macho_t macho;
|
||||||
union grub_macho_filestart filestart;
|
union grub_macho_filestart filestart;
|
||||||
|
@ -63,6 +67,10 @@ grub_macho_file (grub_file_t file, const char *filename)
|
||||||
macho->end64 = -1;
|
macho->end64 = -1;
|
||||||
macho->cmds32 = 0;
|
macho->cmds32 = 0;
|
||||||
macho->cmds64 = 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)
|
if (grub_file_seek (macho->file, 0) == (grub_off_t) -1)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -104,14 +112,14 @@ grub_macho_file (grub_file_t file, const char *filename)
|
||||||
for (i = 0; i < narchs; i++)
|
for (i = 0; i < narchs; i++)
|
||||||
{
|
{
|
||||||
if (GRUB_MACHO_CPUTYPE_IS_HOST32
|
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->offset32 = grub_be_to_cpu32 (archs[i].offset);
|
||||||
macho->end32 = grub_be_to_cpu32 (archs[i].offset)
|
macho->end32 = grub_be_to_cpu32 (archs[i].offset)
|
||||||
+ grub_be_to_cpu32 (archs[i].size);
|
+ grub_be_to_cpu32 (archs[i].size);
|
||||||
}
|
}
|
||||||
if (GRUB_MACHO_CPUTYPE_IS_HOST64
|
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->offset64 = grub_be_to_cpu32 (archs[i].offset);
|
||||||
macho->end64 = 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? */
|
/* 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->offset32 = 0;
|
||||||
macho->end32 = grub_file_size (file);
|
macho->end32 = grub_file_size (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is it a thin 64-bit 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->offset64 = 0;
|
||||||
macho->end64 = grub_file_size (file);
|
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_parse32 (macho, filename);
|
||||||
grub_macho_parse64 (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;
|
return macho;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
macho->file = 0;
|
||||||
grub_macho_close (macho);
|
grub_macho_close (macho);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_macho_t
|
grub_macho_t
|
||||||
grub_macho_open (const char *name)
|
grub_macho_open (const char *name, int is_64bit)
|
||||||
{
|
{
|
||||||
grub_file_t file;
|
grub_file_t file;
|
||||||
grub_macho_t macho;
|
grub_macho_t macho;
|
||||||
|
@ -155,7 +193,7 @@ grub_macho_open (const char *name)
|
||||||
if (! file)
|
if (! file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
macho = grub_macho_file (file, name);
|
macho = grub_macho_file (file, name, is_64bit);
|
||||||
if (! macho)
|
if (! macho)
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ typedef struct grub_macho_thread32 grub_macho_thread_t;
|
||||||
#define cmdsizeXX cmdsize32
|
#define cmdsizeXX cmdsize32
|
||||||
#define cmdsXX cmds32
|
#define cmdsXX cmds32
|
||||||
#define endXX end32
|
#define endXX end32
|
||||||
|
#define uncompressedXX uncompressed32
|
||||||
|
#define compressedXX compressed32
|
||||||
|
#define uncompressed_sizeXX uncompressed_size32
|
||||||
|
#define compressed_sizeXX compressed_size32
|
||||||
#define XX "32"
|
#define XX "32"
|
||||||
#define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC32
|
#define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC32
|
||||||
#define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT32
|
#define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT32
|
||||||
|
|
|
@ -11,6 +11,10 @@ typedef struct grub_macho_thread64 grub_macho_thread_t;
|
||||||
#define cmdsizeXX cmdsize64
|
#define cmdsizeXX cmdsize64
|
||||||
#define cmdsXX cmds64
|
#define cmdsXX cmds64
|
||||||
#define endXX end64
|
#define endXX end64
|
||||||
|
#define uncompressedXX uncompressed64
|
||||||
|
#define compressedXX compressed64
|
||||||
|
#define uncompressed_sizeXX uncompressed_size64
|
||||||
|
#define compressed_sizeXX compressed_size64
|
||||||
#define XX "64"
|
#define XX "64"
|
||||||
#define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC64
|
#define GRUB_MACHO_MAGIC GRUB_MACHO_MAGIC64
|
||||||
#define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT64
|
#define GRUB_MACHO_CMD_SEGMENT GRUB_MACHO_CMD_SEGMENT64
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
int
|
static int
|
||||||
SUFFIX (grub_macho_contains_macho) (grub_macho_t macho)
|
SUFFIX (grub_macho_contains_macho) (grub_macho_t macho)
|
||||||
{
|
{
|
||||||
return macho->offsetXX != -1;
|
return macho->offsetXX != -1;
|
||||||
|
@ -15,16 +15,19 @@ SUFFIX (grub_macho_contains_macho) (grub_macho_t macho)
|
||||||
void
|
void
|
||||||
SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename)
|
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? */
|
/* Is there any candidate at all? */
|
||||||
if (macho->offsetXX == -1)
|
if (macho->offsetXX == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Read header and check magic*/
|
/* Read header and check magic. */
|
||||||
if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1
|
if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1
|
||||||
|| grub_file_read (macho->file, &head, sizeof (head))
|
|| grub_file_read (macho->file, &head, sizeof (head))
|
||||||
!= sizeof(head))
|
!= sizeof (head))
|
||||||
{
|
{
|
||||||
if (!grub_errno)
|
if (!grub_errno)
|
||||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
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;
|
macho->offsetXX = -1;
|
||||||
return;
|
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");
|
grub_error (GRUB_ERR_BAD_OS, "invalid Mach-O " XX "-bit header");
|
||||||
macho->offsetXX = -1;
|
macho->offsetXX = -1;
|
||||||
|
@ -40,12 +61,14 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read commands. */
|
/* Read commands. */
|
||||||
macho->ncmdsXX = head.ncmds;
|
macho->ncmdsXX = head.macho.ncmds;
|
||||||
macho->cmdsizeXX = head.sizeofcmds;
|
macho->cmdsizeXX = head.macho.sizeofcmds;
|
||||||
macho->cmdsXX = grub_malloc(macho->cmdsizeXX);
|
macho->cmdsXX = grub_malloc (macho->cmdsizeXX);
|
||||||
if (! macho->cmdsXX)
|
if (! macho->cmdsXX)
|
||||||
return;
|
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_size_t) macho->cmdsizeXX)
|
||||||
!= (grub_ssize_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
|
static grub_err_t
|
||||||
grub_macho_cmds_iterate (grub_macho_t macho,
|
grub_macho_cmds_iterate (grub_macho_t macho,
|
||||||
grub_macho_iter_hook_t hook,
|
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;
|
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)
|
if (! macho->cmdsXX)
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't find " XX "-bit Mach-O");
|
return grub_error (GRUB_ERR_BAD_OS, "couldn't find " XX "-bit Mach-O");
|
||||||
|
hdrs = macho->cmdsXX;
|
||||||
for (i = 0; i < macho->ncmdsXX; i++)
|
for (i = 0; i < macho->ncmdsXX; i++)
|
||||||
{
|
{
|
||||||
struct grub_macho_cmd *hdr = (struct grub_macho_cmd *) hdrs;
|
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. */
|
/* Calculate the amount of memory spanned by the segments. */
|
||||||
grub_err_t
|
grub_err_t
|
||||||
SUFFIX (grub_macho_size) (grub_macho_t macho, grub_macho_addr_t *segments_start,
|
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;
|
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_start = (grub_macho_addr_t) -1;
|
||||||
*segments_end = 0;
|
*segments_end = 0;
|
||||||
|
|
||||||
grub_macho_cmds_iterate (macho, calcsize, 0);
|
grub_macho_cmds_iterate (macho, calcsize, 0, filename);
|
||||||
|
|
||||||
if (nr_phdrs == 0)
|
if (nr_phdrs == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "no program headers present");
|
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)
|
if (! hdr->vmsize)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (grub_file_seek (_macho->file, hdr->fileoff
|
|
||||||
+ _macho->offsetXX) == (grub_off_t) -1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (hdr->filesize)
|
if (hdr->filesize)
|
||||||
{
|
{
|
||||||
grub_ssize_t read;
|
grub_ssize_t read, toread = min (hdr->filesize, hdr->vmsize);
|
||||||
read = grub_file_read (_macho->file, offset + hdr->vmaddr,
|
if (macho->uncompressedXX)
|
||||||
min (hdr->filesize, hdr->vmsize));
|
{
|
||||||
if (read != (grub_ssize_t) min (hdr->filesize, hdr->vmsize))
|
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'? */
|
/* XXX How can we free memory from `load_hook'? */
|
||||||
if (!grub_errno)
|
if (!grub_errno)
|
||||||
|
@ -229,13 +332,13 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename,
|
||||||
if (darwin_version)
|
if (darwin_version)
|
||||||
*darwin_version = 0;
|
*darwin_version = 0;
|
||||||
|
|
||||||
grub_macho_cmds_iterate (macho, do_load, 0);
|
grub_macho_cmds_iterate (macho, do_load, 0, filename);
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_macho_addr_t
|
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;
|
grub_macho_addr_t entry_point = 0;
|
||||||
auto int NESTED_FUNC_ATTR hook(grub_macho_t _macho,
|
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;
|
entry_point = ((grub_macho_thread_t *) hdr)->entry_point;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
grub_macho_cmds_iterate (macho, hook, 0);
|
grub_macho_cmds_iterate (macho, hook, 0, filename);
|
||||||
return entry_point;
|
return entry_point;
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,17 +351,12 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
grub_xnu_unload ();
|
grub_xnu_unload ();
|
||||||
|
|
||||||
macho = grub_macho_open (args[0]);
|
macho = grub_macho_open (args[0], 0);
|
||||||
if (! macho)
|
if (! macho)
|
||||||
return grub_errno;
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_macho_close (macho);
|
grub_macho_close (macho);
|
||||||
|
@ -396,7 +391,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
|
||||||
return err;
|
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)
|
if (! grub_xnu_entry_point)
|
||||||
{
|
{
|
||||||
grub_macho_close (macho);
|
grub_macho_close (macho);
|
||||||
|
@ -461,17 +456,12 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
grub_xnu_unload ();
|
grub_xnu_unload ();
|
||||||
|
|
||||||
macho = grub_macho_open (args[0]);
|
macho = grub_macho_open (args[0], 1);
|
||||||
if (! macho)
|
if (! macho)
|
||||||
return grub_errno;
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_macho_close (macho);
|
grub_macho_close (macho);
|
||||||
|
@ -509,7 +499,8 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
|
||||||
return err;
|
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)
|
if (! grub_xnu_entry_point)
|
||||||
{
|
{
|
||||||
grub_macho_close (macho);
|
grub_macho_close (macho);
|
||||||
|
@ -667,18 +658,16 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
|
||||||
/* Compute the needed space. */
|
/* Compute the needed space. */
|
||||||
if (binaryfile)
|
if (binaryfile)
|
||||||
{
|
{
|
||||||
macho = grub_macho_file (binaryfile, filename);
|
macho = grub_macho_file (binaryfile, filename, grub_xnu_is_64bit);
|
||||||
if (! macho || ! grub_macho_contains_macho32 (macho))
|
if (!macho)
|
||||||
{
|
grub_file_close (binaryfile);
|
||||||
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);
|
|
||||||
else
|
else
|
||||||
machosize = grub_macho_filesize32 (macho);
|
{
|
||||||
|
if (grub_xnu_is_64bit)
|
||||||
|
machosize = grub_macho_filesize64 (macho);
|
||||||
|
else
|
||||||
|
machosize = grub_macho_filesize32 (macho);
|
||||||
|
}
|
||||||
neededspace += machosize;
|
neededspace += machosize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -68,14 +68,6 @@ struct grub_macho_header64
|
||||||
grub_uint32_t reserved;
|
grub_uint32_t reserved;
|
||||||
} __attribute__ ((packed));
|
} __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. */
|
/* Common header of Mach-O commands. */
|
||||||
struct grub_macho_cmd
|
struct grub_macho_cmd
|
||||||
{
|
{
|
||||||
|
@ -121,4 +113,28 @@ struct grub_macho_segment64
|
||||||
|
|
||||||
#define GRUB_MACHO_CMD_THREAD 5
|
#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
|
#endif
|
||||||
|
|
|
@ -33,27 +33,38 @@ struct grub_macho_file
|
||||||
int ncmds32;
|
int ncmds32;
|
||||||
grub_size_t cmdsize32;
|
grub_size_t cmdsize32;
|
||||||
grub_uint8_t *cmds32;
|
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 offset64;
|
||||||
grub_ssize_t end64;
|
grub_ssize_t end64;
|
||||||
int ncmds64;
|
int ncmds64;
|
||||||
grub_size_t cmdsize64;
|
grub_size_t cmdsize64;
|
||||||
grub_uint8_t *cmds64;
|
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;
|
typedef struct grub_macho_file *grub_macho_t;
|
||||||
|
|
||||||
grub_macho_t grub_macho_open (const char *);
|
grub_macho_t grub_macho_open (const char *, int is_64bit);
|
||||||
grub_macho_t grub_macho_file (grub_file_t file, const char *filename);
|
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);
|
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_err_t grub_macho_size32 (grub_macho_t macho, grub_uint32_t *segments_start,
|
||||||
grub_uint32_t *segments_end, int flags);
|
grub_uint32_t *segments_end, int flags,
|
||||||
grub_uint32_t grub_macho_get_entry_point32 (grub_macho_t macho);
|
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_err_t grub_macho_size64 (grub_macho_t macho, grub_uint64_t *segments_start,
|
||||||
grub_uint64_t *segments_end, int flags);
|
grub_uint64_t *segments_end, int flags,
|
||||||
grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho);
|
const char *filename);
|
||||||
|
grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho,
|
||||||
|
const char *filename);
|
||||||
|
|
||||||
/* Ignore BSS segments when loading. */
|
/* Ignore BSS segments when loading. */
|
||||||
#define GRUB_MACHO_NOBSS 0x1
|
#define GRUB_MACHO_NOBSS 0x1
|
||||||
|
|
|
@ -66,8 +66,11 @@ EOF
|
||||||
if [ -f /Extra/DSDT.aml ]; then
|
if [ -f /Extra/DSDT.aml ]; then
|
||||||
acpi -e /Extra/DSDT.aml
|
acpi -e /Extra/DSDT.aml
|
||||||
fi
|
fi
|
||||||
$1 /mach_kernel boot-uuid=\${uuid} rd=*uuid
|
if [ /kernelcache -nt /System/Library/Extensions ]; then
|
||||||
if [ /System/Library/Extensions.mkext -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
|
xnu_mkext /System/Library/Extensions.mkext
|
||||||
else
|
else
|
||||||
xnu_kextdir /System/Library/Extensions
|
xnu_kextdir /System/Library/Extensions
|
||||||
|
|
Loading…
Reference in a new issue