xnu_resume.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2009 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/normal.h>
  19. #include <grub/dl.h>
  20. #include <grub/file.h>
  21. #include <grub/disk.h>
  22. #include <grub/misc.h>
  23. #include <grub/xnu.h>
  24. #include <grub/cpu/xnu.h>
  25. #include <grub/mm.h>
  26. #include <grub/loader.h>
  27. static void *grub_xnu_hibernate_image;
  28. static grub_err_t
  29. grub_xnu_resume_unload (void)
  30. {
  31. /* Free loaded image */
  32. if (grub_xnu_hibernate_image)
  33. grub_free (grub_xnu_hibernate_image);
  34. grub_xnu_hibernate_image = 0;
  35. grub_xnu_unlock ();
  36. return GRUB_ERR_NONE;
  37. }
  38. grub_err_t
  39. grub_xnu_resume (char *imagename)
  40. {
  41. grub_file_t file;
  42. grub_size_t total_header_size;
  43. struct grub_xnu_hibernate_header hibhead;
  44. grub_uint8_t *buf;
  45. grub_uint32_t codedest;
  46. grub_uint32_t codesize;
  47. file = grub_file_open (imagename);
  48. if (! file)
  49. return 0;
  50. /* Read the header. */
  51. if (grub_file_read (file, &hibhead, sizeof (hibhead))
  52. !=sizeof (hibhead))
  53. {
  54. grub_file_close (file);
  55. return grub_error (GRUB_ERR_READ_ERROR,
  56. "cannot read the hibernate header");
  57. }
  58. /* Check the header. */
  59. if (hibhead.magic != GRUB_XNU_HIBERNATE_MAGIC)
  60. {
  61. grub_file_close (file);
  62. return grub_error (GRUB_ERR_BAD_OS,
  63. "hibernate header has incorrect magic number");
  64. }
  65. if (hibhead.encoffset)
  66. {
  67. grub_file_close (file);
  68. return grub_error (GRUB_ERR_BAD_OS,
  69. "encrypted images aren't supported yet");
  70. }
  71. codedest = hibhead.launchcode_target_page;
  72. codedest *= GRUB_XNU_PAGESIZE;
  73. codesize = hibhead.launchcode_numpages;
  74. codesize *= GRUB_XNU_PAGESIZE;
  75. /* FIXME: check that codedest..codedest+codesize is available. */
  76. /* Calculate total size before pages to copy. */
  77. total_header_size = hibhead.extmapsize + sizeof (hibhead);
  78. /* Unload image if any. */
  79. if (grub_xnu_hibernate_image)
  80. grub_free (grub_xnu_hibernate_image);
  81. /* Try to allocate necessary space.
  82. FIXME: mm isn't good enough yet to handle huge allocations.
  83. */
  84. grub_xnu_hibernate_image = buf = XNU_RELOCATOR (alloc) (hibhead.image_size
  85. + codesize
  86. + GRUB_XNU_PAGESIZE);
  87. if (! buf)
  88. {
  89. grub_file_close (file);
  90. return grub_errno;
  91. }
  92. /* Read code part. */
  93. if (grub_file_seek (file, total_header_size) == (grub_off_t) -1
  94. || grub_file_read (file, buf, codesize)
  95. != (grub_ssize_t) codesize)
  96. {
  97. grub_file_close (file);
  98. return grub_error (GRUB_ERR_READ_ERROR, "cannot read resume image");
  99. }
  100. /* Read image. */
  101. if (grub_file_seek (file, 0) == (grub_off_t) -1
  102. || grub_file_read (file, buf + codesize + GRUB_XNU_PAGESIZE,
  103. hibhead.image_size)
  104. != (grub_ssize_t) hibhead.image_size)
  105. {
  106. grub_file_close (file);
  107. return grub_error (GRUB_ERR_READ_ERROR, "cannot read resume image");
  108. }
  109. grub_file_close (file);
  110. /* Setup variables needed by asm helper. */
  111. grub_xnu_heap_will_be_at = codedest;
  112. grub_xnu_heap_start = buf;
  113. grub_xnu_heap_size = codesize + GRUB_XNU_PAGESIZE + hibhead.image_size;
  114. grub_xnu_stack = (codedest + hibhead.stack);
  115. grub_xnu_entry_point = (codedest + hibhead.entry_point);
  116. grub_xnu_arg1 = codedest + codesize + GRUB_XNU_PAGESIZE;
  117. grub_dprintf ("xnu", "entry point 0x%x\n", codedest + hibhead.entry_point);
  118. grub_dprintf ("xnu", "image at 0x%x\n",
  119. codedest + codesize + GRUB_XNU_PAGESIZE);
  120. /* We're ready now. */
  121. grub_loader_set (grub_xnu_boot_resume,
  122. grub_xnu_resume_unload, 0);
  123. /* Prevent module from unloading. */
  124. grub_xnu_lock ();
  125. return GRUB_ERR_NONE;
  126. }