int cntconftables = 0;
struct SUFFIX (grub_efiemu_configuration_table) *conftables = 0;
- struct SUFFIX (grub_efiemu_runtime_services) *runtime_services;
int i;
int handle;
grub_off_t off;
/* Switch from phase 1 (counting) to phase 2 (real job) */
grub_efiemu_alloc_syms ();
grub_efiemu_mm_do_alloc ();
+ grub_efiemu_write_sym_markers ();
grub_efiemu_system_table32 = 0;
grub_efiemu_system_table64 = 0;
= (struct SUFFIX (grub_efi_system_table) *)
((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
- /* compute CRC32 of runtime_services */
- if ((err = grub_efiemu_resolve_symbol ("efiemu_runtime_services",
- &handle, &off)))
- return err;
- runtime_services = (struct SUFFIX (grub_efiemu_runtime_services) *)
- ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
- runtime_services->hdr.crc32 = 0;
- runtime_services->hdr.crc32 = grub_getcrc32
- (0, runtime_services, runtime_services->hdr.header_size);
-
/* Put pointer to the list of configuration tables in system table */
grub_efiemu_write_value
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
conftables[i].vendor_table = PTR_TO_UINT64 (cur->data);
}
+ err = SUFFIX (grub_efiemu_crc) ();
+ if (err)
+ {
+ grub_efiemu_unload ();
+ return err;
+ }
+
+ grub_dprintf ("efiemu","system_table = %p, conftables = %p (%d entries)\n",
+ SUFFIX (grub_efiemu_system_table), conftables, cntconftables);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+SUFFIX (grub_efiemu_crc) (void)
+{
+ grub_err_t err;
+ int handle;
+ grub_off_t off;
+ struct SUFFIX (grub_efiemu_runtime_services) *runtime_services;
+
+ /* compute CRC32 of runtime_services */
+ err = grub_efiemu_resolve_symbol ("efiemu_runtime_services",
+ &handle, &off);
+ if (err)
+ return err;
+
+ runtime_services = (struct SUFFIX (grub_efiemu_runtime_services) *)
+ ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
+ runtime_services->hdr.crc32 = 0;
+ runtime_services->hdr.crc32 = grub_getcrc32
+ (0, runtime_services, runtime_services->hdr.header_size);
+
+ err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off);
+ if (err)
+ return err;
+
/* compute CRC32 of system table */
SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0;
SUFFIX (grub_efiemu_system_table)->hdr.crc32
= grub_getcrc32 (0, SUFFIX (grub_efiemu_system_table),
SUFFIX (grub_efiemu_system_table)->hdr.header_size);
- grub_dprintf ("efiemu","system_table = %p, runtime_services = %p,"
- " conftables = %p (%d entries)\n",
- SUFFIX (grub_efiemu_system_table), runtime_services,
- conftables, cntconftables);
+ grub_dprintf ("efiemu","system_table = %p, runtime_services = %p\n",
+ SUFFIX (grub_efiemu_system_table), runtime_services);
return GRUB_ERR_NONE;
}
static int logn = 9;
#define LOG(x) { if (logn<900) loge[logn++]=x; }
-static int ptv_relocated = 0;
-
/* Interface with grub */
+extern grub_uint8_t efiemu_ptv_relocated;
struct grub_efi_runtime_services efiemu_runtime_services;
struct grub_efi_system_table efiemu_system_table;
extern struct grub_efiemu_ptv_rel efiemu_ptv_relloc[];
LOG ('e');
/* Ensure that we are called only once */
- if (ptv_relocated)
+ if (efiemu_ptv_relocated)
return GRUB_EFI_UNSUPPORTED;
- ptv_relocated = 1;
+ efiemu_ptv_relocated = 1;
/* Correct addresses using information supplied by grub */
for (cur_relloc = efiemu_ptv_relloc; cur_relloc->size;cur_relloc++)
static int ptv_written = 0;
static int ptv_alloc = 0;
static int ptv_handle = 0;
+static int relocated_handle = 0;
static int ptv_requested = 0;
static struct grub_efiemu_sym *efiemu_syms = 0;
+
struct grub_efiemu_sym
{
struct grub_efiemu_sym *next;
ptv_requested = 0;
grub_efiemu_mm_return_request (ptv_handle);
ptv_handle = 0;
+ grub_efiemu_mm_return_request (relocated_handle);
+ relocated_handle = 0;
}
/* Announce that the module will need NUM allocators */
ptv_handle = grub_efiemu_request_memalign
(1, (ptv_requested + 1) * sizeof (struct grub_efiemu_ptv_rel),
GRUB_EFI_RUNTIME_SERVICES_DATA);
+ relocated_handle = grub_efiemu_request_memalign
+ (1, sizeof (grub_uint8_t), GRUB_EFI_RUNTIME_SERVICES_DATA);
+
+ grub_efiemu_register_symbol ("efiemu_ptv_relocated", relocated_handle, 0);
grub_efiemu_register_symbol ("efiemu_ptv_relloc", ptv_handle, 0);
return grub_errno;
}
+grub_err_t
+grub_efiemu_write_sym_markers (void)
+{
+ struct grub_efiemu_ptv_rel *ptv_rels
+ = grub_efiemu_mm_obtain_request (ptv_handle);
+ grub_uint8_t *relocated = grub_efiemu_mm_obtain_request (relocated_handle);
+ grub_memset (ptv_rels, 0, (ptv_requested + 1)
+ * sizeof (struct grub_efiemu_ptv_rel));
+ *relocated = 0;
+ return GRUB_ERR_NONE;
+}
+
/* Write value (pointer to memory PLUS_HANDLE)
- (pointer to memory MINUS_HANDLE) + VALUE to ADDR assuming that the
size SIZE bytes. If PTV_NEEDED is 1 then announce it to runtime that this
return GRUB_ERR_NONE;
}
+
+grub_err_t
+grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
+ grub_efi_uintn_t descriptor_size,
+ grub_efi_uint32_t descriptor_version
+ __attribute__ ((unused)),
+ grub_efi_memory_descriptor_t *virtual_map)
+{
+ grub_uint8_t *ptv_relocated;
+ struct grub_efiemu_ptv_rel *cur_relloc;
+ struct grub_efiemu_ptv_rel *ptv_rels;
+
+ ptv_relocated = grub_efiemu_mm_obtain_request (relocated_handle);
+ ptv_rels = grub_efiemu_mm_obtain_request (ptv_handle);
+
+ /* Ensure that we are called only once */
+ if (*ptv_relocated)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "EfiEmu is already relocated.");
+ *ptv_relocated = 1;
+
+ /* Correct addresses using information supplied by grub */
+ for (cur_relloc = ptv_rels; cur_relloc->size; cur_relloc++)
+ {
+ grub_int64_t corr = 0;
+ grub_efi_memory_descriptor_t *descptr;
+
+ /* Compute correction */
+ for (descptr = virtual_map;
+ (grub_size_t) ((grub_uint8_t *) descptr
+ - (grub_uint8_t *) virtual_map) < memory_map_size;
+ descptr = (grub_efi_memory_descriptor_t *)
+ ((grub_uint8_t *) descptr + descriptor_size))
+ {
+ if (descptr->type == cur_relloc->plustype)
+ corr += descptr->virtual_start - descptr->physical_start;
+ if (descptr->type == cur_relloc->minustype)
+ corr -= descptr->virtual_start - descptr->physical_start;
+ }
+
+ /* Apply correction */
+ switch (cur_relloc->size)
+ {
+ case 8:
+ *((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+ break;
+ case 4:
+ *((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+ break;
+ case 2:
+ *((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+ break;
+ case 1:
+ *((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+ break;
+ }
+ }
+
+ /* Recompute crc32 of system table and runtime services */
+
+ if (grub_efiemu_sizeof_uintn_t () == 4)
+ return grub_efiemu_crc32 ();
+ else
+ return grub_efiemu_crc64 ();
+}
# define grub_autoefi_finish_boot_services grub_efi_finish_boot_services
# define grub_autoefi_system_table grub_efi_system_table
# define grub_autoefi_mmap_iterate grub_machine_mmap_iterate
+# define grub_autoefi_set_virtual_address_map grub_efi_set_virtual_address_map
static inline grub_err_t grub_autoefi_prepare (void)
{
return GRUB_ERR_NONE;
# define grub_autoefi_system_table grub_efiemu_system_table
# define grub_autoefi_mmap_iterate grub_efiemu_mmap_iterate
# define grub_autoefi_prepare grub_efiemu_prepare
+# define grub_autoefi_set_virtual_address_map grub_efiemu_set_virtual_address_map
# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_EFIEMU_MEMORY_AVAILABLE
# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_EFIEMU_MEMORY_RESERVED
# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_EFIEMU_MEMORY_ACPI
void EXPORT_FUNC (grub_reboot) (void);
void EXPORT_FUNC (grub_halt) (void);
int EXPORT_FUNC (grub_efi_finish_boot_services) (void);
+grub_err_t EXPORT_FUNC (grub_efiemu_set_virtual_address_map) (grub_efi_uintn_t memory_map_size,
+ grub_efi_uintn_t descriptor_size,
+ grub_efi_uint32_t descriptor_version,
+ grub_efi_memory_descriptor_t *virtual_map);
void grub_efi_mm_init (void);
void grub_efi_mm_fini (void);
grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value,
int plus_handle,
int minus_handle, int ptv_needed, int size);
+grub_err_t grub_efiemu_write_sym_markers (void);
grub_err_t grub_efiemu_pnvram (void);
grub_err_t grub_efiemu_prepare (void);
char *grub_efiemu_get_default_core_name (void);
void grub_efiemu_pnvram_cmd_unregister (void);
grub_err_t grub_efiemu_autocore (void);
+grub_err_t grub_efiemu_crc32 (void);
+grub_err_t grub_efiemu_crc64 (void);
+grub_err_t
+grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
+ grub_efi_uintn_t descriptor_size,
+ grub_efi_uint32_t descriptor_version
+ __attribute__ ((unused)),
+ grub_efi_memory_descriptor_t *virtual_map);
+
#endif /* ! GRUB_EFI_EMU_HEADER */
extern grub_size_t grub_xnu_heap_size;
extern char *grub_xnu_heap_start;
extern struct grub_video_bitmap *grub_xnu_bitmap;
+extern int grub_xnu_is_64bit;
#endif
return status == GRUB_EFI_SUCCESS;
}
+grub_err_t
+grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
+ grub_efi_uintn_t descriptor_size,
+ grub_efi_uint32_t descriptor_version,
+ grub_efi_memory_descriptor_t *virtual_map)
+{
+ grub_efi_runtime_services_t *r;
+ grub_efi_status_t status;
+
+ r = grub_efi_system_table->runtime_services;
+ status = efi_call_4 (r->set_virtual_address_map, memory_map_size,
+ descriptor_size, descriptor_version, virtual_map);
+
+ if (status == GRUB_EFI_SUCCESS)
+ return GRUB_ERR_NONE;
+
+ return grub_errno (GRUB_ERR_IO, "set_virtual_address_map failed");
+}
+
grub_uint32_t
grub_get_rtc (void)
{
grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *)
((char *) memory_map + descriptor_size * i);
- /* Some EFI implementations set physical_start to 0 which
- causes XNU crash. */
curdesc->virtual_start = curdesc->physical_start;
if (curdesc->type == GRUB_EFI_RUNTIME_SERVICES_DATA
|| curdesc->type == GRUB_EFI_RUNTIME_SERVICES_CODE)
{
+ if (grub_xnu_is_64bit && (SIZEOF_OF_UINTN == 8))
+ curdesc->virtual_start |= 0xffffff8000000000ULL;
+ else
+ curdesc->virtual_start &= 0x000000007fffffffULL;
if (firstruntimeaddr > curdesc->physical_start)
firstruntimeaddr = curdesc->physical_start;
if (lastruntimeaddr < curdesc->physical_start
if (! grub_autoefi_finish_boot_services ())
return grub_error (GRUB_ERR_IO, "can't exit boot services");
+ grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
+ descriptor_version,memory_map);
+
grub_xnu_launch ();
/* Never reaches here. */
struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0;
static int driverspackagenum = 0;
static int driversnum = 0;
-static int is_64bit;
+int grub_xnu_is_64bit = 0;
/* Allocate heap by 32MB-blocks. */
#define GRUB_XNU_HEAP_ALLOC_BLOCK 0x2000000
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
- is_64bit = 0;
+ grub_xnu_is_64bit = 0;
return 0;
}
grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
grub_xnu_lock ();
- is_64bit = 1;
+ grub_xnu_is_64bit = 1;
return 0;
}
return grub_error (GRUB_ERR_BAD_OS,
"Extension doesn't contain suitable architecture");
}
- if (is_64bit)
+ if (grub_xnu_is_64bit)
machosize = grub_macho_filesize64 (macho);
else
machosize = grub_macho_filesize32 (macho);
exthead->binaryaddr = (buf - grub_xnu_heap_start)
+ grub_xnu_heap_will_be_at;
exthead->binarysize = machosize;
- if (is_64bit)
+ if (grub_xnu_is_64bit)
err = grub_macho_readfile64 (macho, buf);
else
err = grub_macho_readfile32 (macho, buf);
}
for (i = 0; i < narchs; i++)
{
- if (!is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST32
+ if (!grub_xnu_is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST32
(grub_be_to_cpu32 (archs[i].cputype)))
{
readoff = grub_be_to_cpu32 (archs[i].offset);
readlen = grub_be_to_cpu32 (archs[i].size);
}
- if (is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST64
+ if (grub_xnu_is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST64
(grub_be_to_cpu32 (archs[i].cputype)))
{
readoff = grub_be_to_cpu32 (archs[i].offset);