]> git.proxmox.com Git - grub2.git/commitdiff
Support Apple FAT binaries on non-Apple platforms.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 10 Jan 2013 11:50:01 +0000 (12:50 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 10 Jan 2013 11:50:01 +0000 (12:50 +0100)
* include/grub/macho.h (GRUB_MACHO_FAT_EFI_MAGIC): New define.
* include/grub/i386/macho.h (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT):
Likewise.
* grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Parse
Apple FAT binaries.

ChangeLog
grub-core/loader/efi/chainloader.c
include/grub/i386/macho.h
include/grub/macho.h

index 48d297d8b87e9676b994cf58136dcc5e39c14458..4567cae0c9e3fd7e2d696ba950baefa642081645 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-01-10  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Support Apple FAT binaries on non-Apple platforms.
+
+       * include/grub/macho.h (GRUB_MACHO_FAT_EFI_MAGIC): New define.
+       * include/grub/i386/macho.h (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT):
+       Likewise.
+       * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Parse
+       Apple FAT binaries.
+
 2013-01-10  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/kern/disk.c (grub_disk_write): Fix sector number on 4K
index 3f3e6e3817f120d9ea96438cc8571308b5b5d8e1..c0fed8068bcf3b71c74b28c945a16ec54197dcd3 100644 (file)
 #include <grub/command.h>
 #include <grub/i18n.h>
 #include <grub/net.h>
+#if defined (__i386__) || defined (__x86_64__)
+#include <grub/macho.h>
+#include <grub/i386/macho.h>
+#endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -198,6 +202,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
   grub_efi_device_path_t *dp = 0;
   grub_efi_loaded_image_t *loaded_image;
   char *filename;
+  void *boot_image = 0;
   grub_efi_handle_t dev_handle = 0;
 
   if (argc == 0)
@@ -278,7 +283,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
-  if (grub_file_read (file, (void *) ((grub_addr_t) address), size) != size)
+  boot_image = (void *) ((grub_addr_t) address);
+  if (grub_file_read (file, boot_image, size) != size)
     {
       if (grub_errno == GRUB_ERR_NONE)
        grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -287,9 +293,45 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
+#if defined (__i386__) || defined (__x86_64__)
+  if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
+    {
+      struct grub_macho_fat_header *head = boot_image;
+      if (head->magic
+         == grub_cpu_to_le32_compile_time (GRUB_MACHO_FAT_EFI_MAGIC))
+       {
+         grub_uint32_t i;
+         struct grub_macho_fat_arch *archs
+           = (struct grub_macho_fat_arch *) (head + 1);
+         for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++)
+           {
+             if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype))
+               break;
+           }
+         if (i == grub_cpu_to_le32 (head->nfat_arch))
+           {
+             grub_error (GRUB_ERR_BAD_OS, "no compatible arch found");
+             goto fail;
+           }
+         if (grub_cpu_to_le32 (archs[i].offset)
+             > ~grub_cpu_to_le32 (archs[i].size)
+             || grub_cpu_to_le32 (archs[i].offset)
+             + grub_cpu_to_le32 (archs[i].size)
+             > (grub_size_t) size)
+           {
+             grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+                         filename);
+             goto fail;
+           }
+         boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
+         size = grub_cpu_to_le32 (archs[i].size);
+       }
+    }
+#endif
+
   status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
-                         (void *) ((grub_addr_t) address), size,
-                         &image_handle);
+                      boot_image, size,
+                      &image_handle);
   if (status != GRUB_EFI_SUCCESS)
     {
       if (status == GRUB_EFI_OUT_OF_RESOURCES)
index f22c21190139f1803735ecec707e2a6b258ac91b..5ee9f9e70e76cfeaf5bfbf8e6e5baad347d3dcc8 100644 (file)
 
 #define GRUB_MACHO_CPUTYPE_IS_HOST32(x) ((x)==0x00000007)
 #define GRUB_MACHO_CPUTYPE_IS_HOST64(x) ((x)==0x01000007)
+#ifdef __x86_64__
+#define GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT(x) ((x)==0x01000007)
+#else
+#define GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT(x) ((x)==0x00000007)
+#endif
 
 struct grub_macho_thread32
 {
index 6a98b6e127b7bd5ad0b5085a1a394195ae68b893..21f0714e0c00778ce3499beb29ab853c870df0d3 100644 (file)
@@ -27,6 +27,7 @@ struct grub_macho_fat_header
   grub_uint32_t nfat_arch;
 } __attribute__ ((packed));
 #define GRUB_MACHO_FAT_MAGIC 0xcafebabe
+#define GRUB_MACHO_FAT_EFI_MAGIC 0x0ef1fab9
 
 typedef grub_uint32_t grub_macho_cpu_type_t;
 typedef grub_uint32_t grub_macho_cpu_subtype_t;