2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>.
19 #include <grub/normal.h>
21 #include <grub/file.h>
22 #include <grub/disk.h>
23 #include <grub/misc.h>
25 #include <grub/cpu/xnu.h>
27 #include <grub/loader.h>
28 #include <grub/i18n.h>
30 static void *grub_xnu_hibernate_image
;
33 grub_xnu_resume_unload (void)
35 /* Free loaded image */
36 if (grub_xnu_hibernate_image
)
37 grub_free (grub_xnu_hibernate_image
);
38 grub_xnu_hibernate_image
= 0;
44 grub_xnu_resume (char *imagename
)
47 grub_size_t total_header_size
;
48 struct grub_xnu_hibernate_header hibhead
;
51 grub_uint32_t codedest
;
52 grub_uint32_t codesize
;
53 grub_addr_t target_image
;
56 grub_file_filter_disable_compression ();
57 file
= grub_file_open (imagename
);
61 /* Read the header. */
62 if (grub_file_read (file
, &hibhead
, sizeof (hibhead
))
65 grub_file_close (file
);
67 grub_error (GRUB_ERR_READ_ERROR
,
68 N_("premature end of file %s"), imagename
);
72 /* Check the header. */
73 if (hibhead
.magic
!= GRUB_XNU_HIBERNATE_MAGIC
)
75 grub_file_close (file
);
76 return grub_error (GRUB_ERR_BAD_OS
,
77 "hibernate header has incorrect magic number");
79 if (hibhead
.encoffset
)
81 grub_file_close (file
);
82 return grub_error (GRUB_ERR_BAD_OS
,
83 "encrypted images aren't supported yet");
86 if (hibhead
.image_size
== 0)
88 grub_file_close (file
);
89 return grub_error (GRUB_ERR_BAD_OS
,
90 "hibernate image is empty");
93 codedest
= hibhead
.launchcode_target_page
;
94 codedest
*= GRUB_XNU_PAGESIZE
;
95 codesize
= hibhead
.launchcode_numpages
;
96 codesize
*= GRUB_XNU_PAGESIZE
;
98 /* FIXME: check that codedest..codedest+codesize is available. */
100 /* Calculate total size before pages to copy. */
101 total_header_size
= hibhead
.extmapsize
+ sizeof (hibhead
);
103 /* Unload image if any. */
104 if (grub_xnu_hibernate_image
)
105 grub_free (grub_xnu_hibernate_image
);
107 /* Try to allocate necessary space.
108 FIXME: mm isn't good enough yet to handle huge allocations.
110 grub_xnu_relocator
= grub_relocator_new ();
111 if (!grub_xnu_relocator
)
113 grub_file_close (file
);
118 grub_relocator_chunk_t ch
;
119 err
= grub_relocator_alloc_chunk_addr (grub_xnu_relocator
, &ch
, codedest
,
120 codesize
+ GRUB_XNU_PAGESIZE
);
123 grub_file_close (file
);
126 code
= get_virtual_current_address (ch
);
130 grub_relocator_chunk_t ch
;
131 err
= grub_relocator_alloc_chunk_align (grub_xnu_relocator
, &ch
, 0,
132 (0xffffffff - hibhead
.image_size
) + 1,
135 GRUB_RELOCATOR_PREFERENCE_NONE
, 0);
138 grub_file_close (file
);
141 image
= get_virtual_current_address (ch
);
142 target_image
= get_physical_target_address (ch
);
145 /* Read code part. */
146 if (grub_file_seek (file
, total_header_size
) == (grub_off_t
) -1
147 || grub_file_read (file
, code
, codesize
)
148 != (grub_ssize_t
) codesize
)
150 grub_file_close (file
);
152 grub_error (GRUB_ERR_READ_ERROR
,
153 N_("premature end of file %s"), imagename
);
158 if (grub_file_seek (file
, 0) == (grub_off_t
) -1
159 || grub_file_read (file
, image
, hibhead
.image_size
)
160 != (grub_ssize_t
) hibhead
.image_size
)
162 grub_file_close (file
);
164 grub_error (GRUB_ERR_READ_ERROR
,
165 N_("premature end of file %s"), imagename
);
168 grub_file_close (file
);
170 /* Setup variables needed by asm helper. */
171 grub_xnu_heap_target_start
= codedest
;
172 grub_xnu_heap_size
= target_image
+ hibhead
.image_size
- codedest
;
173 grub_xnu_stack
= (codedest
+ hibhead
.stack
);
174 grub_xnu_entry_point
= (codedest
+ hibhead
.entry_point
);
175 grub_xnu_arg1
= target_image
;
177 grub_dprintf ("xnu", "entry point 0x%x\n", codedest
+ hibhead
.entry_point
);
178 grub_dprintf ("xnu", "image at 0x%x\n",
179 codedest
+ codesize
+ GRUB_XNU_PAGESIZE
);
181 /* We're ready now. */
182 grub_loader_set (grub_xnu_boot_resume
,
183 grub_xnu_resume_unload
, 0);
185 /* Prevent module from unloading. */
187 return GRUB_ERR_NONE
;