Support v2 xnu boot arguments.
* grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devicetree): New argument fsbfreq_out. (grub_xnu_set_video): Receive an argument grub_xnu_boot_params_common. (grub_xnu_boot): Support v2 arguments. Disable PIC so that APIC can be used. * grub-core/loader/machoXX.c (grub_macho_load): New argument darwin_version. * grub-core/loader/xnu.c (grub_xnu_darwin_version): New variable. * include/grub/i386/xnu.h (grub_xnu_boot_params_common): New struct. (grub_xnu_boot_params): Rename to ... (grub_xnu_boot_params_v1): ...this. Use grub_xnu_boot_params_common. (grub_xnu_boot_params_v2): New struct.
This commit is contained in:
parent
dc693fe67c
commit
83ddae2333
7 changed files with 154 additions and 52 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2012-02-27 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Support v2 xnu boot arguments.
|
||||
|
||||
* grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devicetree):
|
||||
New argument fsbfreq_out.
|
||||
(grub_xnu_set_video): Receive an argument grub_xnu_boot_params_common.
|
||||
(grub_xnu_boot): Support v2 arguments. Disable PIC so that APIC can
|
||||
be used.
|
||||
* grub-core/loader/machoXX.c (grub_macho_load): New argument
|
||||
darwin_version.
|
||||
* grub-core/loader/xnu.c (grub_xnu_darwin_version): New variable.
|
||||
* include/grub/i386/xnu.h (grub_xnu_boot_params_common): New struct.
|
||||
(grub_xnu_boot_params): Rename to ...
|
||||
(grub_xnu_boot_params_v1): ...this. Use grub_xnu_boot_params_common.
|
||||
(grub_xnu_boot_params_v2): New struct.
|
||||
|
||||
2012-02-27 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* grub-core/efiemu/prepare.c (grub_efiemu_crc): Add missing
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
@ -623,8 +624,8 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
/* Fill device tree. */
|
||||
/* FIXME: some entries may be platform-agnostic. Move them to loader/xnu.c. */
|
||||
grub_err_t
|
||||
grub_cpu_xnu_fill_devicetree (void)
|
||||
static grub_err_t
|
||||
grub_cpu_xnu_fill_devicetree (grub_uint64_t *fsbfreq_out)
|
||||
{
|
||||
struct grub_xnu_devtree_key *efikey;
|
||||
struct grub_xnu_devtree_key *cfgtablekey;
|
||||
|
@ -702,13 +703,14 @@ grub_cpu_xnu_fill_devicetree (void)
|
|||
|
||||
/* First see if user supplies the value. */
|
||||
const char *fsbvar = grub_env_get ("fsb");
|
||||
if (! fsbvar)
|
||||
*((grub_uint64_t *) curval->data) = 0;
|
||||
else
|
||||
*((grub_uint64_t *) curval->data) = readfrequency (fsbvar);
|
||||
grub_uint64_t fsbfreq = 0;
|
||||
if (fsbvar)
|
||||
fsbfreq = readfrequency (fsbvar);
|
||||
/* Try autodetect. */
|
||||
if (! *((grub_uint64_t *) curval->data))
|
||||
*((grub_uint64_t *) curval->data) = guessfsb ();
|
||||
if (! fsbfreq)
|
||||
fsbfreq = guessfsb ();
|
||||
*((grub_uint64_t *) curval->data) = fsbfreq;
|
||||
*fsbfreq_out = fsbfreq;
|
||||
grub_dprintf ("xnu", "fsb autodetected as %llu\n",
|
||||
(unsigned long long) *((grub_uint64_t *) curval->data));
|
||||
|
||||
|
@ -845,7 +847,7 @@ grub_xnu_boot_resume (void)
|
|||
|
||||
/* Setup video for xnu. */
|
||||
static grub_err_t
|
||||
grub_xnu_set_video (struct grub_xnu_boot_params *params)
|
||||
grub_xnu_set_video (struct grub_xnu_boot_params_common *params)
|
||||
{
|
||||
struct grub_video_mode_info mode_info;
|
||||
char *tmp;
|
||||
|
@ -950,7 +952,8 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
|
|||
grub_err_t
|
||||
grub_xnu_boot (void)
|
||||
{
|
||||
struct grub_xnu_boot_params *bootparams;
|
||||
union grub_xnu_boot_params_any *bootparams;
|
||||
struct grub_xnu_boot_params_common *bootparams_common;
|
||||
void *bp_in;
|
||||
grub_addr_t bootparams_target;
|
||||
grub_err_t err;
|
||||
|
@ -966,6 +969,9 @@ grub_xnu_boot (void)
|
|||
grub_size_t devtreelen;
|
||||
int i;
|
||||
struct grub_relocator32_state state;
|
||||
grub_uint64_t fsbfreq;
|
||||
int v2 = (grub_xnu_darwin_version >= 11);
|
||||
grub_uint32_t efi_system_table = 0;
|
||||
|
||||
err = grub_autoefi_prepare ();
|
||||
if (err)
|
||||
|
@ -975,7 +981,7 @@ grub_xnu_boot (void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = grub_cpu_xnu_fill_devicetree ();
|
||||
err = grub_cpu_xnu_fill_devicetree (&fsbfreq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -995,7 +1001,8 @@ grub_xnu_boot (void)
|
|||
descriptor_size = 0;
|
||||
descriptor_version = 0;
|
||||
|
||||
grub_dprintf ("xnu", "eip=%x\n", grub_xnu_entry_point);
|
||||
grub_dprintf ("xnu", "eip=%x, efi=%x\n", grub_xnu_entry_point,
|
||||
(int) grub_autoefi_system_table);
|
||||
|
||||
const char *debug = grub_env_get ("debug");
|
||||
|
||||
|
@ -1012,20 +1019,29 @@ grub_xnu_boot (void)
|
|||
return err;
|
||||
bootparams = bp_in;
|
||||
|
||||
grub_memset (bootparams, 0, sizeof (*bootparams));
|
||||
if (v2)
|
||||
{
|
||||
bootparams_common = &bootparams->v2.common;
|
||||
bootparams->v2.fsbfreq = fsbfreq;
|
||||
}
|
||||
else
|
||||
bootparams_common = &bootparams->v1.common;
|
||||
|
||||
/* Set video. */
|
||||
err = grub_xnu_set_video (bootparams);
|
||||
err = grub_xnu_set_video (bootparams_common);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
grub_puts_ (N_("Booting in blind mode"));
|
||||
|
||||
bootparams->lfb_mode = 0;
|
||||
bootparams->lfb_width = 0;
|
||||
bootparams->lfb_height = 0;
|
||||
bootparams->lfb_depth = 0;
|
||||
bootparams->lfb_line_len = 0;
|
||||
bootparams->lfb_base = 0;
|
||||
bootparams_common->lfb_mode = 0;
|
||||
bootparams_common->lfb_width = 0;
|
||||
bootparams_common->lfb_height = 0;
|
||||
bootparams_common->lfb_depth = 0;
|
||||
bootparams_common->lfb_line_len = 0;
|
||||
bootparams_common->lfb_base = 0;
|
||||
}
|
||||
|
||||
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
|
||||
|
@ -1045,11 +1061,11 @@ grub_xnu_boot (void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
grub_memcpy (bootparams->cmdline, grub_xnu_cmdline,
|
||||
sizeof (bootparams->cmdline));
|
||||
grub_memcpy (bootparams_common->cmdline, grub_xnu_cmdline,
|
||||
sizeof (bootparams_common->cmdline));
|
||||
|
||||
bootparams->devtree = devtree_target;
|
||||
bootparams->devtreelen = devtreelen;
|
||||
bootparams_common->devtree = devtree_target;
|
||||
bootparams_common->devtreelen = devtreelen;
|
||||
|
||||
err = grub_autoefi_finish_boot_services (&memory_map_size, memory_map,
|
||||
&map_key, &descriptor_size,
|
||||
|
@ -1057,7 +1073,10 @@ grub_xnu_boot (void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
bootparams->efi_system_table = (grub_addr_t) grub_autoefi_system_table;
|
||||
if (v2)
|
||||
bootparams->v2.efi_system_table = (grub_addr_t) grub_autoefi_system_table;
|
||||
else
|
||||
bootparams->v1.efi_system_table = (grub_addr_t) grub_autoefi_system_table;
|
||||
|
||||
firstruntimepage = (((grub_addr_t) grub_xnu_heap_target_start
|
||||
+ grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1)
|
||||
|
@ -1080,7 +1099,7 @@ grub_xnu_boot (void)
|
|||
<= (grub_addr_t) grub_autoefi_system_table
|
||||
&& curdesc->physical_start + (curdesc->num_pages << 12)
|
||||
> (grub_addr_t) grub_autoefi_system_table)
|
||||
bootparams->efi_system_table
|
||||
efi_system_table
|
||||
= (grub_addr_t) grub_autoefi_system_table
|
||||
- curdesc->physical_start + curdesc->virtual_start;
|
||||
if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit)
|
||||
|
@ -1090,24 +1109,33 @@ grub_xnu_boot (void)
|
|||
|
||||
lastruntimepage = curruntimepage;
|
||||
|
||||
bootparams->efi_mmap = memory_map_target;
|
||||
bootparams->efi_mmap_size = memory_map_size;
|
||||
bootparams->efi_mem_desc_size = descriptor_size;
|
||||
bootparams->efi_mem_desc_version = descriptor_version;
|
||||
if (v2)
|
||||
{
|
||||
bootparams->v2.efi_uintnbits = SIZEOF_OF_UINTN * 8;
|
||||
bootparams->v2.verminor = GRUB_XNU_BOOTARGSV2_VERMINOR;
|
||||
bootparams->v2.vermajor = GRUB_XNU_BOOTARGSV2_VERMAJOR;
|
||||
bootparams->v2.efi_system_table = efi_system_table;
|
||||
}
|
||||
else
|
||||
{
|
||||
bootparams->v1.efi_uintnbits = SIZEOF_OF_UINTN * 8;
|
||||
bootparams->v1.verminor = GRUB_XNU_BOOTARGSV1_VERMINOR;
|
||||
bootparams->v1.vermajor = GRUB_XNU_BOOTARGSV1_VERMAJOR;
|
||||
bootparams->v1.efi_system_table = efi_system_table;
|
||||
}
|
||||
|
||||
bootparams->heap_start = grub_xnu_heap_target_start;
|
||||
bootparams->heap_size = grub_xnu_heap_size;
|
||||
bootparams->efi_runtime_first_page = firstruntimepage;
|
||||
|
||||
bootparams->efi_runtime_npages = lastruntimepage - firstruntimepage;
|
||||
bootparams->efi_uintnbits = SIZEOF_OF_UINTN * 8;
|
||||
|
||||
bootparams->verminor = GRUB_XNU_BOOTARGS_VERMINOR;
|
||||
bootparams->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR;
|
||||
bootparams_common->efi_runtime_first_page = firstruntimepage;
|
||||
bootparams_common->efi_runtime_npages = lastruntimepage - firstruntimepage;
|
||||
bootparams_common->efi_mem_desc_size = descriptor_size;
|
||||
bootparams_common->efi_mem_desc_version = descriptor_version;
|
||||
bootparams_common->efi_mmap = memory_map_target;
|
||||
bootparams_common->efi_mmap_size = memory_map_size;
|
||||
bootparams_common->heap_start = grub_xnu_heap_target_start;
|
||||
bootparams_common->heap_size = grub_xnu_heap_size;
|
||||
|
||||
/* Parameters for asm helper. */
|
||||
grub_xnu_stack = bootparams->heap_start
|
||||
+ bootparams->heap_size + GRUB_XNU_PAGESIZE;
|
||||
grub_xnu_stack = bootparams_common->heap_start
|
||||
+ bootparams_common->heap_size + GRUB_XNU_PAGESIZE;
|
||||
grub_xnu_arg1 = bootparams_target;
|
||||
|
||||
grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
|
||||
|
@ -1117,6 +1145,11 @@ grub_xnu_boot (void)
|
|||
state.eax = grub_xnu_arg1;
|
||||
state.esp = grub_xnu_stack;
|
||||
state.ebp = grub_xnu_stack;
|
||||
|
||||
/* XNU uses only APIC. Disable PIC. */
|
||||
grub_outb (0xff, 0x21);
|
||||
grub_outb (0xff, 0xa1);
|
||||
|
||||
return grub_relocator32_boot (grub_xnu_relocator, state);
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ SUFFIX (grub_macho_size) (grub_macho_t macho, grub_macho_addr_t *segments_start,
|
|||
/* Load every loadable segment into memory specified by `_load_hook'. */
|
||||
grub_err_t
|
||||
SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename,
|
||||
char *offset, int flags)
|
||||
char *offset, int flags, int *darwin_version)
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR do_load(grub_macho_t _macho,
|
||||
struct grub_macho_cmd *hdr0,
|
||||
|
@ -201,6 +201,23 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename,
|
|||
|
||||
return 1;
|
||||
}
|
||||
if (darwin_version)
|
||||
{
|
||||
const char *ptr = offset + hdr->vmaddr;
|
||||
const char *end = ptr + min (hdr->filesize, hdr->vmsize)
|
||||
- (sizeof ("Darwin Kernel Version ") - 1);
|
||||
for (; ptr < end; ptr++)
|
||||
if (grub_memcmp (ptr, "Darwin Kernel Version ",
|
||||
sizeof ("Darwin Kernel Version ") - 1) == 0)
|
||||
{
|
||||
ptr += sizeof ("Darwin Kernel Version ") - 1;
|
||||
*darwin_version = 0;
|
||||
end += (sizeof ("Darwin Kernel Version ") - 1);
|
||||
while (ptr < end && grub_isdigit (*ptr))
|
||||
*darwin_version = (*ptr++ - '0') + *darwin_version * 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr->filesize < hdr->vmsize)
|
||||
|
@ -209,6 +226,9 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (darwin_version)
|
||||
*darwin_version = 0;
|
||||
|
||||
grub_macho_cmds_iterate (macho, do_load, 0);
|
||||
|
||||
return grub_errno;
|
||||
|
|
|
@ -44,6 +44,7 @@ struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0;
|
|||
static int driverspackagenum = 0;
|
||||
static int driversnum = 0;
|
||||
int grub_xnu_is_64bit = 0;
|
||||
int grub_xnu_darwin_version = 0;
|
||||
|
||||
grub_addr_t grub_xnu_heap_target_start = 0;
|
||||
grub_size_t grub_xnu_heap_size = 0;
|
||||
|
@ -387,7 +388,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
/* Load kernel. */
|
||||
err = grub_macho_load32 (macho, args[0], (char *) loadaddr - startcode,
|
||||
GRUB_MACHO_NOBSS);
|
||||
GRUB_MACHO_NOBSS, &grub_xnu_darwin_version);
|
||||
if (err)
|
||||
{
|
||||
grub_macho_close (macho);
|
||||
|
@ -500,7 +501,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
/* Load kernel. */
|
||||
err = grub_macho_load64 (macho, args[0], (char *) loadaddr - startcode,
|
||||
GRUB_MACHO_NOBSS);
|
||||
GRUB_MACHO_NOBSS, &grub_xnu_darwin_version);
|
||||
if (err)
|
||||
{
|
||||
grub_macho_close (macho);
|
||||
|
|
|
@ -28,10 +28,8 @@
|
|||
#define GRUB_XNU_PAGESIZE 4096
|
||||
typedef grub_uint32_t grub_xnu_ptr_t;
|
||||
|
||||
struct grub_xnu_boot_params
|
||||
struct grub_xnu_boot_params_common
|
||||
{
|
||||
grub_uint16_t verminor;
|
||||
grub_uint16_t vermajor;
|
||||
/* Command line passed to xnu. */
|
||||
grub_uint8_t cmdline[1024];
|
||||
|
||||
|
@ -59,17 +57,50 @@ struct grub_xnu_boot_params
|
|||
grub_xnu_ptr_t heap_start;
|
||||
/* Last used address by kernel or boot structures minus previous value. */
|
||||
grub_uint32_t heap_size;
|
||||
|
||||
/* First memory page containing runtime code or data. */
|
||||
grub_uint32_t efi_runtime_first_page;
|
||||
/* First memory page containing runtime code or data minus previous value. */
|
||||
grub_uint32_t efi_runtime_npages;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_xnu_boot_params_v1
|
||||
{
|
||||
grub_uint16_t verminor;
|
||||
grub_uint16_t vermajor;
|
||||
struct grub_xnu_boot_params_common common;
|
||||
|
||||
grub_uint32_t efi_system_table;
|
||||
/* Size of grub_efi_uintn_t in bits. */
|
||||
grub_uint8_t efi_uintnbits;
|
||||
} __attribute__ ((packed));
|
||||
#define GRUB_XNU_BOOTARGS_VERMINOR 5
|
||||
#define GRUB_XNU_BOOTARGS_VERMAJOR 1
|
||||
#define GRUB_XNU_BOOTARGSV1_VERMINOR 5
|
||||
#define GRUB_XNU_BOOTARGSV1_VERMAJOR 1
|
||||
|
||||
struct grub_xnu_boot_params_v2
|
||||
{
|
||||
grub_uint16_t verminor;
|
||||
grub_uint16_t vermajor;
|
||||
|
||||
/* Size of grub_efi_uintn_t in bits. */
|
||||
grub_uint8_t efi_uintnbits;
|
||||
grub_uint8_t unused[3];
|
||||
|
||||
struct grub_xnu_boot_params_common common;
|
||||
|
||||
grub_uint64_t efi_runtime_first_page_virtual;
|
||||
grub_uint32_t efi_system_table;
|
||||
grub_uint32_t unused2[11];
|
||||
grub_uint64_t fsbfreq;
|
||||
grub_uint32_t unused3[734];
|
||||
} __attribute__ ((packed));
|
||||
#define GRUB_XNU_BOOTARGSV2_VERMINOR 0
|
||||
#define GRUB_XNU_BOOTARGSV2_VERMAJOR 2
|
||||
|
||||
union grub_xnu_boot_params_any
|
||||
{
|
||||
struct grub_xnu_boot_params_v1 v1;
|
||||
struct grub_xnu_boot_params_v2 v2;
|
||||
};
|
||||
|
||||
struct grub_xnu_devprop_header
|
||||
{
|
||||
|
@ -114,5 +145,4 @@ extern grub_uint32_t grub_xnu_stack;
|
|||
extern grub_uint32_t grub_xnu_arg1;
|
||||
extern char grub_xnu_cmdline[1024];
|
||||
grub_err_t grub_xnu_boot (void);
|
||||
grub_err_t grub_cpu_xnu_fill_devicetree (void);
|
||||
#endif
|
||||
|
|
|
@ -58,9 +58,9 @@ grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho);
|
|||
/* Ignore BSS segments when loading. */
|
||||
#define GRUB_MACHO_NOBSS 0x1
|
||||
grub_err_t grub_macho_load32 (grub_macho_t macho, const char *filename,
|
||||
char *offset, int flags);
|
||||
char *offset, int flags, int *darwin_version);
|
||||
grub_err_t grub_macho_load64 (grub_macho_t macho, const char *filename,
|
||||
char *offset, int flags);
|
||||
char *offset, int flags, int *darwin_version);
|
||||
|
||||
/* Like filesize and file_read but take only 32-bit part
|
||||
for current architecture. */
|
||||
|
|
|
@ -115,4 +115,5 @@ typedef enum {GRUB_XNU_BITMAP_CENTER, GRUB_XNU_BITMAP_STRETCH}
|
|||
extern grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode;
|
||||
extern int grub_xnu_is_64bit;
|
||||
extern grub_addr_t grub_xnu_heap_target_start;
|
||||
extern int grub_xnu_darwin_version;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue