Reenable XNU

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-11 13:43:44 +01:00
parent 669a1c01fb
commit cb1b2ad7e0
6 changed files with 148 additions and 150 deletions

View file

@ -179,7 +179,7 @@ linux_mod_SOURCES = loader/i386/linux.c
linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_CFLAGS = $(COMMON_CFLAGS)
linux_mod_LDFLAGS = $(COMMON_LDFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
#pkglib_MODULES += xnu.mod pkglib_MODULES += xnu.mod
xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c loader/i386/pc/xnu.c \ xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c loader/i386/pc/xnu.c \
loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c
xnu_mod_CFLAGS = $(COMMON_CFLAGS) xnu_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -117,5 +117,4 @@ grub_err_t grub_xnu_boot (void);
grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *bootparams_relloc); grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *bootparams_relloc);
grub_err_t grub_err_t
grub_cpu_xnu_fill_devicetree (void); grub_cpu_xnu_fill_devicetree (void);
extern grub_uint32_t grub_xnu_heap_will_be_at;
#endif #endif

View file

@ -87,7 +87,7 @@ extern struct grub_xnu_devtree_key *grub_xnu_devtree_root;
void grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur); void grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur);
grub_err_t grub_xnu_writetree_toheap (void **start, grub_size_t *size); grub_err_t grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size);
struct grub_xnu_devtree_key *grub_xnu_create_value (struct grub_xnu_devtree_key **parent, struct grub_xnu_devtree_key *grub_xnu_create_value (struct grub_xnu_devtree_key **parent,
char *name); char *name);
@ -102,11 +102,12 @@ grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired,
int maxrecursion); int maxrecursion);
grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired,
int maxrecursion); int maxrecursion);
void *grub_xnu_heap_malloc (int size); grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target);
grub_err_t grub_xnu_fill_devicetree (void); grub_err_t grub_xnu_fill_devicetree (void);
extern grub_uint32_t grub_xnu_heap_real_start; extern struct grub_relocator *grub_xnu_relocator;
extern grub_size_t grub_xnu_heap_size; extern grub_size_t grub_xnu_heap_size;
extern void *grub_xnu_heap_start;
extern struct grub_video_bitmap *grub_xnu_bitmap; extern struct grub_video_bitmap *grub_xnu_bitmap;
extern int grub_xnu_is_64bit; extern int grub_xnu_is_64bit;
extern grub_addr_t grub_xnu_heap_target_start;
#endif #endif

View file

@ -35,7 +35,6 @@
#include <grub/i18n.h> #include <grub/i18n.h>
char grub_xnu_cmdline[1024]; char grub_xnu_cmdline[1024];
grub_uint32_t grub_xnu_heap_will_be_at;
grub_uint32_t grub_xnu_entry_point, grub_xnu_arg1, grub_xnu_stack; grub_uint32_t grub_xnu_entry_point, grub_xnu_arg1, grub_xnu_stack;
/* Aliases set for some tables. */ /* Aliases set for some tables. */
@ -832,26 +831,25 @@ grub_xnu_boot_resume (void)
state.eip = grub_xnu_entry_point; state.eip = grub_xnu_entry_point;
state.eax = grub_xnu_arg1; state.eax = grub_xnu_arg1;
return grub_relocator32_boot (grub_xnu_heap_start, grub_xnu_heap_will_be_at, return grub_relocator32_boot (grub_xnu_relocator, state);
state);
} }
/* Boot xnu. */ /* Boot xnu. */
grub_err_t grub_err_t
grub_xnu_boot (void) grub_xnu_boot (void)
{ {
struct grub_xnu_boot_params *bootparams_relloc; struct grub_xnu_boot_params *bootparams;
grub_off_t bootparams_relloc_off; grub_addr_t bootparams_target;
grub_off_t mmap_relloc_off;
grub_err_t err; grub_err_t err;
grub_efi_uintn_t memory_map_size = 0; grub_efi_uintn_t memory_map_size = 0;
grub_efi_memory_descriptor_t *memory_map; grub_efi_memory_descriptor_t *memory_map;
grub_addr_t memory_map_target;
grub_efi_uintn_t map_key = 0; grub_efi_uintn_t map_key = 0;
grub_efi_uintn_t descriptor_size = 0; grub_efi_uintn_t descriptor_size = 0;
grub_efi_uint32_t descriptor_version = 0; grub_efi_uint32_t descriptor_version = 0;
grub_uint64_t firstruntimepage, lastruntimepage; grub_uint64_t firstruntimepage, lastruntimepage;
grub_uint64_t curruntimepage; grub_uint64_t curruntimepage;
void *devtree; grub_addr_t devtree_target;
grub_size_t devtreelen; grub_size_t devtreelen;
int i; int i;
struct grub_relocator32_state state; struct grub_relocator32_state state;
@ -895,26 +893,25 @@ grub_xnu_boot (void)
} }
/* Relocate the boot parameters to heap. */ /* Relocate the boot parameters to heap. */
bootparams_relloc = grub_xnu_heap_malloc (sizeof (*bootparams_relloc)); err = grub_xnu_heap_malloc (sizeof (*bootparams),
if (! bootparams_relloc) (void **) &bootparams, &bootparams_target);
return grub_errno; if (err)
bootparams_relloc_off = (grub_uint8_t *) bootparams_relloc return err;
- (grub_uint8_t *) grub_xnu_heap_start;
/* Set video. */ /* Set video. */
err = grub_xnu_set_video (bootparams_relloc); err = grub_xnu_set_video (bootparams);
if (err != GRUB_ERR_NONE) if (err != GRUB_ERR_NONE)
{ {
grub_print_error (); grub_print_error ();
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
grub_printf ("Booting in blind mode\n"); grub_printf ("Booting in blind mode\n");
bootparams_relloc->lfb_mode = 0; bootparams->lfb_mode = 0;
bootparams_relloc->lfb_width = 0; bootparams->lfb_width = 0;
bootparams_relloc->lfb_height = 0; bootparams->lfb_height = 0;
bootparams_relloc->lfb_depth = 0; bootparams->lfb_depth = 0;
bootparams_relloc->lfb_line_len = 0; bootparams->lfb_line_len = 0;
bootparams_relloc->lfb_base = 0; bootparams->lfb_base = 0;
} }
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map, if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
@ -925,38 +922,29 @@ grub_xnu_boot (void)
/* We will do few allocations later. Reserve some space for possible /* We will do few allocations later. Reserve some space for possible
memory map growth. */ memory map growth. */
memory_map_size += 20 * descriptor_size; memory_map_size += 20 * descriptor_size;
memory_map = grub_xnu_heap_malloc (memory_map_size); err = grub_xnu_heap_malloc (memory_map_size,
if (! memory_map) (void **) &memory_map, &memory_map_target);
return grub_errno;
mmap_relloc_off = (grub_uint8_t *) memory_map
- (grub_uint8_t *) grub_xnu_heap_start;
err = grub_xnu_writetree_toheap (&devtree, &devtreelen);
if (err) if (err)
return err; return err;
bootparams_relloc = (struct grub_xnu_boot_params *)
(bootparams_relloc_off + (grub_uint8_t *) grub_xnu_heap_start);
grub_memcpy (bootparams_relloc->cmdline, grub_xnu_cmdline, err = grub_xnu_writetree_toheap (&devtree_target, &devtreelen);
sizeof (bootparams_relloc->cmdline)); if (err)
return err;
bootparams_relloc->devtree grub_memcpy (bootparams->cmdline, grub_xnu_cmdline,
= ((grub_uint8_t *) devtree - (grub_uint8_t *) grub_xnu_heap_start) sizeof (bootparams->cmdline));
+ grub_xnu_heap_will_be_at;
bootparams_relloc->devtreelen = devtreelen;
memory_map = (grub_efi_memory_descriptor_t *) bootparams->devtree = devtree_target;
((grub_uint8_t *) grub_xnu_heap_start + mmap_relloc_off); bootparams->devtreelen = devtreelen;
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map, if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
&map_key, &descriptor_size, &map_key, &descriptor_size,
&descriptor_version) <= 0) &descriptor_version) <= 0)
return grub_errno; return grub_errno;
bootparams_relloc->efi_system_table bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table);
= PTR_TO_UINT32 (grub_autoefi_system_table);
firstruntimepage = (((grub_addr_t) grub_xnu_heap_will_be_at firstruntimepage = (((grub_addr_t) grub_xnu_heap_target_start
+ grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1) + grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1)
/ GRUB_XNU_PAGESIZE) + 20; / GRUB_XNU_PAGESIZE) + 20;
curruntimepage = firstruntimepage; curruntimepage = firstruntimepage;
@ -977,7 +965,7 @@ grub_xnu_boot (void)
<= PTR_TO_UINT64 (grub_autoefi_system_table) <= PTR_TO_UINT64 (grub_autoefi_system_table)
&& curdesc->physical_start + (curdesc->num_pages << 12) && curdesc->physical_start + (curdesc->num_pages << 12)
> PTR_TO_UINT64 (grub_autoefi_system_table)) > PTR_TO_UINT64 (grub_autoefi_system_table))
bootparams_relloc->efi_system_table bootparams->efi_system_table
= PTR_TO_UINT64 (grub_autoefi_system_table) = PTR_TO_UINT64 (grub_autoefi_system_table)
- curdesc->physical_start + curdesc->virtual_start; - curdesc->physical_start + curdesc->virtual_start;
if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit) if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit)
@ -987,25 +975,25 @@ grub_xnu_boot (void)
lastruntimepage = curruntimepage; lastruntimepage = curruntimepage;
bootparams_relloc->efi_mmap = grub_xnu_heap_will_be_at + mmap_relloc_off; bootparams->efi_mmap = memory_map_target;
bootparams_relloc->efi_mmap_size = memory_map_size; bootparams->efi_mmap_size = memory_map_size;
bootparams_relloc->efi_mem_desc_size = descriptor_size; bootparams->efi_mem_desc_size = descriptor_size;
bootparams_relloc->efi_mem_desc_version = descriptor_version; bootparams->efi_mem_desc_version = descriptor_version;
bootparams_relloc->heap_start = grub_xnu_heap_will_be_at; bootparams->heap_start = grub_xnu_heap_target_start;
bootparams_relloc->heap_size = grub_xnu_heap_size; bootparams->heap_size = grub_xnu_heap_size;
bootparams_relloc->efi_runtime_first_page = firstruntimepage; bootparams->efi_runtime_first_page = firstruntimepage;
bootparams_relloc->efi_runtime_npages = lastruntimepage - firstruntimepage; bootparams->efi_runtime_npages = lastruntimepage - firstruntimepage;
bootparams_relloc->efi_uintnbits = SIZEOF_OF_UINTN * 8; bootparams->efi_uintnbits = SIZEOF_OF_UINTN * 8;
bootparams_relloc->verminor = GRUB_XNU_BOOTARGS_VERMINOR; bootparams->verminor = GRUB_XNU_BOOTARGS_VERMINOR;
bootparams_relloc->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR; bootparams->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR;
/* Parameters for asm helper. */ /* Parameters for asm helper. */
grub_xnu_stack = bootparams_relloc->heap_start grub_xnu_stack = bootparams->heap_start
+ bootparams_relloc->heap_size + GRUB_XNU_PAGESIZE; + bootparams->heap_size + GRUB_XNU_PAGESIZE;
grub_xnu_arg1 = bootparams_relloc_off + grub_xnu_heap_will_be_at; grub_xnu_arg1 = bootparams_target;
if (! grub_autoefi_exit_boot_services (map_key)) if (! grub_autoefi_exit_boot_services (map_key))
return grub_error (GRUB_ERR_IO, "can't exit boot services"); return grub_error (GRUB_ERR_IO, "can't exit boot services");
@ -1016,8 +1004,7 @@ grub_xnu_boot (void)
state.eip = grub_xnu_entry_point; state.eip = grub_xnu_entry_point;
state.eax = grub_xnu_arg1; state.eax = grub_xnu_arg1;
state.esp = grub_xnu_stack; state.esp = grub_xnu_stack;
return grub_relocator32_boot (grub_xnu_heap_start, grub_xnu_heap_will_be_at, return grub_relocator32_boot (grub_xnu_relocator, state);
state);
} }
static grub_command_t cmd_devprop_load; static grub_command_t cmd_devprop_load;

View file

@ -39,45 +39,28 @@ static int driverspackagenum = 0;
static int driversnum = 0; static int driversnum = 0;
int grub_xnu_is_64bit = 0; int grub_xnu_is_64bit = 0;
void *grub_xnu_heap_start = 0; grub_addr_t grub_xnu_heap_target_start = 0;
grub_size_t grub_xnu_heap_size = 0; grub_size_t grub_xnu_heap_size = 0;
struct grub_relocator *grub_xnu_relocator;
/* Allocate heap by 32MB-blocks. */
#define GRUB_XNU_HEAP_ALLOC_BLOCK 0x2000000
static grub_err_t static grub_err_t
grub_xnu_register_memory (char *prefix, int *suffix, grub_xnu_register_memory (char *prefix, int *suffix,
void *addr, grub_size_t size); grub_addr_t addr, grub_size_t size);
void * grub_err_t
grub_xnu_heap_malloc (int size) grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target)
{ {
void *val; grub_err_t err;
int oldblknum, newblknum;
/* The page after the heap is used for stack. Ensure it's usable. */ err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, src,
if (grub_xnu_heap_size) grub_xnu_heap_target_start
oldblknum = (grub_xnu_heap_size + GRUB_XNU_PAGESIZE + grub_xnu_heap_size, size);
+ GRUB_XNU_HEAP_ALLOC_BLOCK - 1) / GRUB_XNU_HEAP_ALLOC_BLOCK; if (err)
else return err;
oldblknum = 0;
newblknum = (grub_xnu_heap_size + size + GRUB_XNU_PAGESIZE
+ GRUB_XNU_HEAP_ALLOC_BLOCK - 1) / GRUB_XNU_HEAP_ALLOC_BLOCK;
if (oldblknum != newblknum)
{
/* FIXME: instruct realloc to allocate at 1MB if possible once
advanced mm is ready. */
grub_xnu_heap_start
= XNU_RELOCATOR (realloc) (grub_xnu_heap_start,
newblknum
* GRUB_XNU_HEAP_ALLOC_BLOCK);
if (!grub_xnu_heap_start)
return NULL;
}
val = (grub_uint8_t *) grub_xnu_heap_start + grub_xnu_heap_size; *target = grub_xnu_heap_target_start + grub_xnu_heap_size;
grub_xnu_heap_size += size; grub_xnu_heap_size += size;
grub_dprintf ("xnu", "val=%p\n", val); grub_dprintf ("xnu", "val=%p\n", *src);
return val; return GRUB_ERR_NONE;
} }
/* Make sure next block of the heap will be aligned. /* Make sure next block of the heap will be aligned.
@ -86,11 +69,9 @@ grub_xnu_heap_malloc (int size)
grub_err_t grub_err_t
grub_xnu_align_heap (int align) grub_xnu_align_heap (int align)
{ {
int align_overhead = align - grub_xnu_heap_size % align; grub_xnu_heap_size
if (align_overhead == align) = ALIGN_UP (grub_xnu_heap_target_start+ grub_xnu_heap_size, align)
return GRUB_ERR_NONE; - grub_xnu_heap_target_start;
if (! grub_xnu_heap_malloc (align_overhead))
return grub_errno;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -206,13 +187,14 @@ grub_xnu_writetree_toheap_real (void *curptr,
} }
grub_err_t grub_err_t
grub_xnu_writetree_toheap (void **start, grub_size_t *size) grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size)
{ {
struct grub_xnu_devtree_key *chosen; struct grub_xnu_devtree_key *chosen;
struct grub_xnu_devtree_key *memorymap; struct grub_xnu_devtree_key *memorymap;
struct grub_xnu_devtree_key *driverkey; struct grub_xnu_devtree_key *driverkey;
struct grub_xnu_extdesc *extdesc; struct grub_xnu_extdesc *extdesc;
grub_err_t err; grub_err_t err;
void *src;
err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
if (err) if (err)
@ -243,16 +225,17 @@ grub_xnu_writetree_toheap (void **start, grub_size_t *size)
/* Allocate the space based on the size with dummy value. */ /* Allocate the space based on the size with dummy value. */
*size = grub_xnu_writetree_get_size (grub_xnu_devtree_root, "/"); *size = grub_xnu_writetree_get_size (grub_xnu_devtree_root, "/");
*start = grub_xnu_heap_malloc (*size + GRUB_XNU_PAGESIZE err = grub_xnu_heap_malloc (ALIGN_UP (*size + 1, GRUB_XNU_PAGESIZE),
- *size % GRUB_XNU_PAGESIZE); &src, target);
if (err)
return err;
/* Put real data in the dummy. */ /* Put real data in the dummy. */
extdesc->addr = (grub_uint8_t *) *start - (grub_uint8_t *) grub_xnu_heap_start extdesc->addr = *target;
+ grub_xnu_heap_will_be_at;
extdesc->size = (grub_uint32_t) *size; extdesc->size = (grub_uint32_t) *size;
/* Write the tree to heap. */ /* Write the tree to heap. */
grub_xnu_writetree_toheap_real (*start, grub_xnu_devtree_root, "/"); grub_xnu_writetree_toheap_real (src, grub_xnu_devtree_root, "/");
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -337,8 +320,9 @@ grub_xnu_unload (void)
/* Free loaded image. */ /* Free loaded image. */
driversnum = 0; driversnum = 0;
driverspackagenum = 0; driverspackagenum = 0;
grub_free (grub_xnu_heap_start); grub_relocator_unload (grub_xnu_relocator);
grub_xnu_heap_start = 0; grub_xnu_relocator = NULL;
grub_xnu_heap_target_start = 0;
grub_xnu_heap_size = 0; grub_xnu_heap_size = 0;
grub_xnu_unlock (); grub_xnu_unlock ();
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -353,6 +337,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
grub_uint32_t startcode, endcode; grub_uint32_t startcode, endcode;
int i; int i;
char *ptr, *loadaddr; char *ptr, *loadaddr;
grub_addr_t loadaddr_target;
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
@ -380,15 +365,18 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n", grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n",
(unsigned long) endcode, (unsigned long) startcode); (unsigned long) endcode, (unsigned long) startcode);
loadaddr = grub_xnu_heap_malloc (endcode - startcode); grub_xnu_relocator = grub_relocator_new ();
grub_xnu_heap_will_be_at = startcode; if (!grub_xnu_relocator)
return grub_errno;
grub_xnu_heap_target_start = startcode;
err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr,
&loadaddr_target);
if (! loadaddr) if (err)
{ {
grub_macho_close (macho); grub_macho_close (macho);
grub_xnu_unload (); grub_xnu_unload ();
return grub_error (GRUB_ERR_OUT_OF_MEMORY, return err;
"not enough memory to load kernel");
} }
/* Load kernel. */ /* Load kernel. */
@ -451,6 +439,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
grub_uint64_t startcode, endcode; grub_uint64_t startcode, endcode;
int i; int i;
char *ptr, *loadaddr; char *ptr, *loadaddr;
grub_addr_t loadaddr_target;
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
@ -481,15 +470,18 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n", grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n",
(unsigned long) endcode, (unsigned long) startcode); (unsigned long) endcode, (unsigned long) startcode);
loadaddr = grub_xnu_heap_malloc (endcode - startcode); grub_xnu_relocator = grub_relocator_new ();
grub_xnu_heap_will_be_at = startcode; if (!grub_xnu_relocator)
return grub_errno;
grub_xnu_heap_target_start = startcode;
err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr,
&loadaddr_target);
if (! loadaddr) if (err)
{ {
grub_macho_close (macho); grub_macho_close (macho);
grub_xnu_unload (); grub_xnu_unload ();
return grub_error (GRUB_ERR_OUT_OF_MEMORY, return err;
"not enough memory to load kernel");
} }
/* Load kernel. */ /* Load kernel. */
@ -547,7 +539,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
and increment SUFFIX. */ and increment SUFFIX. */
static grub_err_t static grub_err_t
grub_xnu_register_memory (char *prefix, int *suffix, grub_xnu_register_memory (char *prefix, int *suffix,
void *addr, grub_size_t size) grub_addr_t addr, grub_size_t size)
{ {
struct grub_xnu_devtree_key *chosen; struct grub_xnu_devtree_key *chosen;
struct grub_xnu_devtree_key *memorymap; struct grub_xnu_devtree_key *memorymap;
@ -585,8 +577,7 @@ grub_xnu_register_memory (char *prefix, int *suffix,
= (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc)); = (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc));
if (! driverkey->data) if (! driverkey->data)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register extension"); return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register extension");
extdesc->addr = grub_xnu_heap_will_be_at + extdesc->addr = addr;
((grub_uint8_t *) addr - (grub_uint8_t *) grub_xnu_heap_start);
extdesc->size = (grub_uint32_t) size; extdesc->size = (grub_uint32_t) size;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -628,7 +619,8 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
grub_file_t infoplist; grub_file_t infoplist;
struct grub_xnu_extheader *exthead; struct grub_xnu_extheader *exthead;
int neededspace = sizeof (*exthead); int neededspace = sizeof (*exthead);
grub_uint8_t *buf; grub_uint8_t *buf, *buf0;
grub_addr_t buf_target;
grub_size_t infoplistsize = 0, machosize = 0; grub_size_t infoplistsize = 0, machosize = 0;
char *name, *nameend; char *name, *nameend;
int namelen; int namelen;
@ -683,7 +675,10 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
if (err) if (err)
return err; return err;
buf = grub_xnu_heap_malloc (neededspace); err = grub_xnu_heap_malloc (neededspace, (void **) &buf0, &buf_target);
if (err)
return err;
buf = buf0;
exthead = (struct grub_xnu_extheader *) buf; exthead = (struct grub_xnu_extheader *) buf;
grub_memset (exthead, 0, sizeof (*exthead)); grub_memset (exthead, 0, sizeof (*exthead));
@ -692,8 +687,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
/* Load the binary. */ /* Load the binary. */
if (macho) if (macho)
{ {
exthead->binaryaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) exthead->binaryaddr = buf_target + (buf - buf0);
+ grub_xnu_heap_will_be_at;
exthead->binarysize = machosize; exthead->binarysize = machosize;
if (grub_xnu_is_64bit) if (grub_xnu_is_64bit)
err = grub_macho_readfile64 (macho, buf); err = grub_macho_readfile64 (macho, buf);
@ -712,8 +706,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
/* Load the plist. */ /* Load the plist. */
if (infoplist) if (infoplist)
{ {
exthead->infoplistaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) exthead->infoplistaddr = buf_target + (buf - buf0);
+ grub_xnu_heap_will_be_at;
exthead->infoplistsize = infoplistsize + 1; exthead->infoplistsize = infoplistsize + 1;
if (grub_file_read (infoplist, buf, infoplistsize) if (grub_file_read (infoplist, buf, infoplistsize)
!= (grub_ssize_t) (infoplistsize)) != (grub_ssize_t) (infoplistsize))
@ -729,15 +722,14 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
exthead->nameaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) exthead->nameaddr = (buf - buf0) + buf_target;
+ grub_xnu_heap_will_be_at;
exthead->namesize = namelen + 1; exthead->namesize = namelen + 1;
grub_memcpy (buf, name, namelen); grub_memcpy (buf, name, namelen);
buf[namelen] = 0; buf[namelen] = 0;
buf += namelen + 1; buf += namelen + 1;
/* Announce to kernel */ /* Announce to kernel */
return grub_xnu_register_memory ("Driver-", &driversnum, exthead, return grub_xnu_register_memory ("Driver-", &driversnum, buf_target,
neededspace); neededspace);
} }
@ -748,6 +740,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
{ {
grub_file_t file; grub_file_t file;
void *loadto; void *loadto;
grub_addr_t loadto_target;
grub_err_t err; grub_err_t err;
grub_off_t readoff = 0; grub_off_t readoff = 0;
grub_ssize_t readlen = -1; grub_ssize_t readlen = -1;
@ -836,11 +829,11 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
return err; return err;
} }
loadto = grub_xnu_heap_malloc (readlen); err = grub_xnu_heap_malloc (readlen, &loadto, &loadto_target);
if (! loadto) if (err)
{ {
grub_file_close (file); grub_file_close (file);
return grub_errno; return err;
} }
/* Read the file. */ /* Read the file. */
@ -855,7 +848,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
/* Pass it to kernel. */ /* Pass it to kernel. */
return grub_xnu_register_memory ("DriversPackage-", &driverspackagenum, return grub_xnu_register_memory ("DriversPackage-", &driverspackagenum,
loadto, readlen); loadto_target, readlen);
} }
static grub_err_t static grub_err_t
@ -864,6 +857,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
{ {
grub_file_t file; grub_file_t file;
void *loadto; void *loadto;
grub_addr_t loadto_target;
grub_err_t err; grub_err_t err;
grub_size_t size; grub_size_t size;
@ -884,9 +878,9 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
size = grub_file_size (file); size = grub_file_size (file);
loadto = grub_xnu_heap_malloc (size); err = grub_xnu_heap_malloc (size, &loadto, &loadto_target);
if (! loadto) if (err)
return grub_errno; return err;
if (grub_file_read (file, loadto, size) if (grub_file_read (file, loadto, size)
!= (grub_ssize_t) (size)) != (grub_ssize_t) (size))
{ {
@ -894,7 +888,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
grub_error_push (); grub_error_push ();
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]);
} }
return grub_xnu_register_memory ("RAMDisk", 0, loadto, size); return grub_xnu_register_memory ("RAMDisk", 0, loadto_target, size);
} }
/* Returns true if the kext should be loaded according to plist /* Returns true if the kext should be loaded according to plist

View file

@ -45,10 +45,12 @@ grub_xnu_resume (char *imagename)
grub_file_t file; grub_file_t file;
grub_size_t total_header_size; grub_size_t total_header_size;
struct grub_xnu_hibernate_header hibhead; struct grub_xnu_hibernate_header hibhead;
grub_uint8_t *buf; void *code;
void *image;
grub_uint32_t codedest; grub_uint32_t codedest;
grub_uint32_t codesize; grub_uint32_t codesize;
grub_addr_t target_image;
grub_err_t err;
file = grub_file_open (imagename); file = grub_file_open (imagename);
if (! file) if (! file)
@ -94,18 +96,35 @@ grub_xnu_resume (char *imagename)
/* Try to allocate necessary space. /* Try to allocate necessary space.
FIXME: mm isn't good enough yet to handle huge allocations. FIXME: mm isn't good enough yet to handle huge allocations.
*/ */
grub_xnu_hibernate_image = buf = XNU_RELOCATOR (alloc) (hibhead.image_size grub_xnu_relocator = grub_relocator_new ();
+ codesize if (!grub_xnu_relocator)
+ GRUB_XNU_PAGESIZE);
if (! buf)
{ {
grub_file_close (file); grub_file_close (file);
return grub_errno; return grub_errno;
} }
err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &code,
codedest, codesize + GRUB_XNU_PAGESIZE);
if (err)
{
grub_file_close (file);
return err;
}
err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &image,
&target_image, 0,
(0xffffffff - hibhead.image_size) + 1,
hibhead.image_size,
GRUB_XNU_PAGESIZE);
if (err)
{
grub_file_close (file);
return err;
}
/* Read code part. */ /* Read code part. */
if (grub_file_seek (file, total_header_size) == (grub_off_t) -1 if (grub_file_seek (file, total_header_size) == (grub_off_t) -1
|| grub_file_read (file, buf, codesize) || grub_file_read (file, code, codesize)
!= (grub_ssize_t) codesize) != (grub_ssize_t) codesize)
{ {
grub_file_close (file); grub_file_close (file);
@ -114,8 +133,7 @@ grub_xnu_resume (char *imagename)
/* Read image. */ /* Read image. */
if (grub_file_seek (file, 0) == (grub_off_t) -1 if (grub_file_seek (file, 0) == (grub_off_t) -1
|| grub_file_read (file, buf + codesize + GRUB_XNU_PAGESIZE, || grub_file_read (file, image, hibhead.image_size)
hibhead.image_size)
!= (grub_ssize_t) hibhead.image_size) != (grub_ssize_t) hibhead.image_size)
{ {
grub_file_close (file); grub_file_close (file);
@ -124,12 +142,11 @@ grub_xnu_resume (char *imagename)
grub_file_close (file); grub_file_close (file);
/* Setup variables needed by asm helper. */ /* Setup variables needed by asm helper. */
grub_xnu_heap_will_be_at = codedest; grub_xnu_heap_target_start = codedest;
grub_xnu_heap_start = buf; grub_xnu_heap_size = target_image + hibhead.image_size - codedest;
grub_xnu_heap_size = codesize + GRUB_XNU_PAGESIZE + hibhead.image_size;
grub_xnu_stack = (codedest + hibhead.stack); grub_xnu_stack = (codedest + hibhead.stack);
grub_xnu_entry_point = (codedest + hibhead.entry_point); grub_xnu_entry_point = (codedest + hibhead.entry_point);
grub_xnu_arg1 = codedest + codesize + GRUB_XNU_PAGESIZE; grub_xnu_arg1 = target_image;
grub_dprintf ("xnu", "entry point 0x%x\n", codedest + hibhead.entry_point); grub_dprintf ("xnu", "entry point 0x%x\n", codedest + hibhead.entry_point);
grub_dprintf ("xnu", "image at 0x%x\n", grub_dprintf ("xnu", "image at 0x%x\n",