appleloader.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* appleloader.c - apple legacy boot loader. */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2008,2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/loader.h>
  20. #include <grub/err.h>
  21. #include <grub/mm.h>
  22. #include <grub/dl.h>
  23. #include <grub/misc.h>
  24. #include <grub/efi/api.h>
  25. #include <grub/efi/efi.h>
  26. #include <grub/command.h>
  27. #include <grub/i18n.h>
  28. GRUB_MOD_LICENSE ("GPLv3+");
  29. static grub_dl_t my_mod;
  30. static grub_efi_handle_t image_handle;
  31. static grub_efi_char16_t *cmdline;
  32. static grub_err_t
  33. grub_appleloader_unload (void)
  34. {
  35. grub_efi_boot_services_t *b;
  36. b = grub_efi_system_table->boot_services;
  37. efi_call_1 (b->unload_image, image_handle);
  38. grub_free (cmdline);
  39. cmdline = 0;
  40. grub_dl_unref (my_mod);
  41. return GRUB_ERR_NONE;
  42. }
  43. static grub_err_t
  44. grub_appleloader_boot (void)
  45. {
  46. grub_efi_boot_services_t *b;
  47. b = grub_efi_system_table->boot_services;
  48. efi_call_3 (b->start_image, image_handle, 0, 0);
  49. grub_appleloader_unload ();
  50. return grub_errno;
  51. }
  52. struct piwg_full_device_path
  53. {
  54. struct grub_efi_memory_mapped_device_path comp1;
  55. struct grub_efi_piwg_device_path comp2;
  56. struct grub_efi_device_path end;
  57. };
  58. #define MAKE_PIWG_PATH(st, en) \
  59. { \
  60. .comp1 = \
  61. { \
  62. .header = { \
  63. .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, \
  64. .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, \
  65. .length = sizeof (struct grub_efi_memory_mapped_device_path) \
  66. }, \
  67. .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, \
  68. .start_address = st, \
  69. .end_address = en \
  70. }, \
  71. .comp2 = \
  72. { \
  73. .header = { \
  74. .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, \
  75. .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, \
  76. .length = sizeof (struct grub_efi_piwg_device_path) \
  77. }, \
  78. .guid = GRUB_EFI_VENDOR_APPLE_GUID \
  79. }, \
  80. .end = \
  81. { \
  82. .type = GRUB_EFI_END_DEVICE_PATH_TYPE, \
  83. .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, \
  84. .length = sizeof (struct grub_efi_device_path) \
  85. } \
  86. }
  87. /* early 2006 Core Duo / Core Solo models */
  88. static struct piwg_full_device_path devpath_1 = MAKE_PIWG_PATH (0xffe00000,
  89. 0xfff9ffff);
  90. /* mid-2006 Mac Pro (and probably other Core 2 models) */
  91. static struct piwg_full_device_path devpath_2 = MAKE_PIWG_PATH (0xffe00000,
  92. 0xfff7ffff);
  93. /* mid-2007 MBP ("Santa Rosa" based models) */
  94. static struct piwg_full_device_path devpath_3 = MAKE_PIWG_PATH (0xffe00000,
  95. 0xfff8ffff);
  96. /* early-2008 MBA */
  97. static struct piwg_full_device_path devpath_4 = MAKE_PIWG_PATH (0xffc00000,
  98. 0xfff8ffff);
  99. /* late-2008 MB/MBP (NVidia chipset) */
  100. static struct piwg_full_device_path devpath_5 = MAKE_PIWG_PATH (0xffcb4000,
  101. 0xffffbfff);
  102. /* mid-2010 MB/MBP (NVidia chipset) */
  103. static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000,
  104. 0xffffbfff);
  105. static struct piwg_full_device_path devpath_7 = MAKE_PIWG_PATH (0xff981000,
  106. 0xffc8ffff);
  107. /* mid-2012 MBP retina (MacBookPro10,1) */
  108. static struct piwg_full_device_path devpath_8 = MAKE_PIWG_PATH (0xff990000,
  109. 0xffb2ffff);
  110. struct devdata
  111. {
  112. const char *model;
  113. grub_efi_device_path_t *devpath;
  114. };
  115. struct devdata devs[] =
  116. {
  117. {"Core Duo/Solo", (grub_efi_device_path_t *) &devpath_1},
  118. {"Mac Pro", (grub_efi_device_path_t *) &devpath_2},
  119. {"MBP", (grub_efi_device_path_t *) &devpath_3},
  120. {"MBA", (grub_efi_device_path_t *) &devpath_4},
  121. {"MB NV", (grub_efi_device_path_t *) &devpath_5},
  122. {"MB NV2", (grub_efi_device_path_t *) &devpath_6},
  123. {"MBP2011", (grub_efi_device_path_t *) &devpath_7},
  124. {"MBP2012", (grub_efi_device_path_t *) &devpath_8},
  125. {NULL, NULL},
  126. };
  127. static grub_err_t
  128. grub_cmd_appleloader (grub_command_t cmd __attribute__ ((unused)),
  129. int argc, char *argv[])
  130. {
  131. grub_efi_boot_services_t *b;
  132. grub_efi_loaded_image_t *loaded_image;
  133. struct devdata *pdev;
  134. grub_dl_ref (my_mod);
  135. /* Initialize some global variables. */
  136. image_handle = 0;
  137. b = grub_efi_system_table->boot_services;
  138. for (pdev = devs ; pdev->devpath ; pdev++)
  139. if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
  140. NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
  141. break;
  142. if (! pdev->devpath)
  143. {
  144. grub_error (GRUB_ERR_BAD_OS, "can't find model");
  145. goto fail;
  146. }
  147. grub_dprintf ("appleload", "Model: %s\n", pdev->model);
  148. loaded_image = grub_efi_get_loaded_image (image_handle);
  149. if (! loaded_image)
  150. {
  151. grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
  152. goto fail;
  153. }
  154. if (argc > 0)
  155. {
  156. int i, len;
  157. grub_efi_char16_t *p16;
  158. for (i = 0, len = 0; i < argc; i++)
  159. len += grub_strlen (argv[i]) + 1;
  160. len *= sizeof (grub_efi_char16_t);
  161. cmdline = p16 = grub_malloc (len);
  162. if (! cmdline)
  163. goto fail;
  164. for (i = 0; i < argc; i++)
  165. {
  166. char *p8;
  167. p8 = argv[i];
  168. while (*p8)
  169. *(p16++) = *(p8++);
  170. *(p16++) = ' ';
  171. }
  172. *(--p16) = 0;
  173. loaded_image->load_options = cmdline;
  174. loaded_image->load_options_size = len;
  175. }
  176. grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
  177. return 0;
  178. fail:
  179. grub_dl_unref (my_mod);
  180. return grub_errno;
  181. }
  182. static grub_command_t cmd;
  183. GRUB_MOD_INIT(appleloader)
  184. {
  185. cmd = grub_register_command ("appleloader", grub_cmd_appleloader,
  186. N_("[OPTS]"),
  187. /* TRANSLATORS: This command is used on EFI to
  188. switch to BIOS mode and boot the OS requiring
  189. BIOS. */
  190. N_("Boot BIOS-based system."));
  191. my_mod = mod;
  192. }
  193. GRUB_MOD_FINI(appleloader)
  194. {
  195. grub_unregister_command (cmd);
  196. }