]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
now hangs at maxDec
authorphcoder <phcoder@debian.easynote.phnet.easynote.phnet>
Wed, 2 Sep 2009 11:34:40 +0000 (13:34 +0200)
committerphcoder <phcoder@debian.easynote.phnet.easynote.phnet>
Wed, 2 Sep 2009 11:34:40 +0000 (13:34 +0200)
efiemu/prepare.c
efiemu/runtime/efiemu.c
efiemu/symbols.c
include/grub/autoefi.h
include/grub/efi/efi.h
include/grub/efiemu/efiemu.h
include/grub/xnu.h
kern/efi/efi.c
loader/i386/xnu.c
loader/xnu.c

index 9e6d46fa18e6ca904f729cd3535323ae3016099f..620260049861896286934a60da9ed5a3d61c2e4b 100644 (file)
@@ -36,7 +36,6 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
 
   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;
@@ -54,6 +53,7 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
   /* 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;
@@ -81,16 +81,6 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
     = (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,
@@ -113,16 +103,51 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
        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;
 }
index 085e75d0cd04d49c624bdba51655cf0302828e5b..73893414ab9434258ff5e7fcaf0259f673696bff 100644 (file)
@@ -111,9 +111,8 @@ static grub_uint8_t loge[1000] = "EFIEMULOG";
 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[];
@@ -343,9 +342,9 @@ grub_efi_status_t EFI_FUNC
   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++)
index ec508d97535b6f0cba95bd1ed766fb85a7166b3b..f2076156557b6fa6c3722d7fa500901c283f85e1 100644 (file)
 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;
@@ -54,6 +56,8 @@ grub_efiemu_free_syms (void)
   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 */
@@ -114,10 +118,26 @@ grub_efiemu_alloc_syms (void)
   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
@@ -186,3 +206,67 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
 
   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 ();
+}
index 4acd43965b46c1f6b36ded8775e9d61b218c5767..4f5e262f0874e1853aac4ed9037df73cf1850518 100644 (file)
@@ -29,6 +29,7 @@
 # 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;
@@ -57,6 +58,7 @@ static inline grub_err_t grub_autoefi_prepare (void)
 # 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
index 916f9d662390d48e6eb1402eaa7f3c20d8cd9940..754c4a7cbdc4cf708e3c161dace8fcd06cdefda5 100644 (file)
@@ -57,6 +57,10 @@ int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key);
 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);
index 20163dd610c3467ba0d0271b9763a84f094182eb..3980d32cdda526e0893a1d4112dccdc470e3be79 100644 (file)
@@ -268,9 +268,19 @@ void grub_efiemu_free_syms (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 */
index 67d78d92c7e5c0de22fdca061a17d3872ed08d76..29689479b6be784cfdb93f52c37b7b0a7e34acef 100644 (file)
@@ -106,4 +106,5 @@ extern grub_uint32_t grub_xnu_heap_real_start;
 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
index 8e09a90c0b5e001b7f16a5662efddbcb52606ae3..630f012b654914fd16a201f817a4811afc42afb1 100644 (file)
@@ -188,6 +188,25 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
   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)
 {
index 06e375c69ccf193ff2f7038f6320b474baa87829..2bcedebe27247ea5391a10034f25ce0d150caa0c 100644 (file)
@@ -474,13 +474,15 @@ grub_xnu_boot (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
@@ -572,6 +574,9 @@ grub_xnu_boot (void)
   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. */
index 271a746e68a9f217149113c3ed286094f5872d35..2ebca321807ea2c59ec9e2d5474e34d79a20721f 100644 (file)
@@ -35,7 +35,7 @@
 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
@@ -444,7 +444,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
   grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
 
   grub_xnu_lock ();
-  is_64bit = 0;
+  grub_xnu_is_64bit = 0;
 
   return 0;
 }
@@ -549,7 +549,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
   grub_loader_set (grub_xnu_boot, grub_xnu_unload, 0);
 
   grub_xnu_lock ();
-  is_64bit = 1;
+  grub_xnu_is_64bit = 1;
 
   return 0;
 }
@@ -668,7 +668,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
          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);
@@ -706,7 +706,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile)
       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);
@@ -810,13 +810,13 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
        }
       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);