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/>.
20 #include <grub/file.h>
21 #include <grub/disk.h>
23 #include <grub/cpu/xnu.h>
25 #include <grub/loader.h>
26 #include <grub/autoefi.h>
27 #include <grub/i386/tsc.h>
28 #include <grub/efi/api.h>
29 #include <grub/i386/pit.h>
30 #include <grub/misc.h>
31 #include <grub/charset.h>
32 #include <grub/term.h>
33 #include <grub/command.h>
34 #include <grub/gzio.h>
35 #include <grub/i18n.h>
37 char grub_xnu_cmdline
[1024];
38 grub_uint32_t grub_xnu_heap_will_be_at
;
39 grub_uint32_t grub_xnu_entry_point
, grub_xnu_arg1
, grub_xnu_stack
;
41 /* Aliases set for some tables. */
48 struct tbl_alias table_aliases
[] =
50 {GRUB_EFI_ACPI_20_TABLE_GUID
, "ACPI_20"},
51 {GRUB_EFI_ACPI_TABLE_GUID
, "ACPI"},
54 struct grub_xnu_devprop_device_descriptor
56 struct grub_xnu_devprop_device_descriptor
*next
;
57 struct property_descriptor
*properties
;
58 struct grub_efi_device_path
*path
;
63 utf16_strlen (grub_uint16_t
*in
)
66 for (i
= 0; in
[i
]; i
++);
70 /* Read frequency from a string in MHz and return it in Hz. */
72 readfrequency (const char *str
)
74 grub_uint64_t num
= 0;
82 digit
= grub_tolower (*str
) - '0';
88 num
= num
* 10 + digit
;
99 digit
= grub_tolower (*str
) - '0';
106 num
= num
+ mul
* digit
;
116 /* Thanks to Kabyl for precious information about Intel architecture. */
120 const grub_uint64_t sane_value
= 100000000;
121 grub_uint32_t manufacturer
[3], max_cpuid
, capabilities
, msrlow
;
122 grub_uint64_t start_tsc
;
123 grub_uint64_t end_tsc
;
124 grub_uint64_t tsc_ticks_per_ms
;
126 if (! grub_cpu_is_cpuid_supported ())
130 asm volatile ("movl $0, %%eax\n"
143 "=d" (manufacturer
[1]), "=c" (manufacturer
[2]));
145 /* Only Intel for now is done. */
146 if (grub_memcmp (manufacturer
+ 1, "ineIntel", 12) != 0)
150 asm volatile ("movl $0, %%eax\n"
152 : "=a" (max_cpuid
), "=b" (manufacturer
[0]),
153 "=d" (manufacturer
[1]), "=c" (manufacturer
[2]));
155 /* Only Intel for now is done. */
156 if (grub_memcmp (manufacturer
, "GenuineIntel", 12) != 0)
160 /* Check Speedstep. */
165 asm volatile ("movl $1, %%eax\n"
177 : "=c" (capabilities
):
180 asm volatile ("movl $1, %%eax\n"
182 : "=c" (capabilities
):
183 : "%rax", "%rbx", "%rdx");
186 if (! (capabilities
& (1 << 7)))
189 /* Calibrate the TSC rate. */
191 start_tsc
= grub_get_tsc ();
192 grub_pit_wait (0xffff);
193 end_tsc
= grub_get_tsc ();
195 tsc_ticks_per_ms
= grub_divmod64 (end_tsc
- start_tsc
, 55, 0);
197 /* Read the multiplier. */
198 asm volatile ("movl $0x198, %%ecx\n"
204 return grub_divmod64 (2000 * tsc_ticks_per_ms
,
205 ((msrlow
>> 7) & 0x3e) + ((msrlow
>> 14) & 1), 0);
208 struct property_descriptor
210 struct property_descriptor
*next
;
212 grub_uint16_t
*name16
;
218 struct grub_xnu_devprop_device_descriptor
*devices
= 0;
221 grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor
*dev
,
224 struct property_descriptor
*prop
;
225 prop
= grub_named_list_find (GRUB_AS_NAMED_LIST_P (&dev
->properties
), name
);
227 return GRUB_ERR_NONE
;
229 grub_free (prop
->name
);
230 grub_free (prop
->name16
);
231 grub_free (prop
->data
);
233 grub_list_remove (GRUB_AS_LIST_P (&dev
->properties
), GRUB_AS_LIST (prop
));
235 return GRUB_ERR_NONE
;
239 grub_xnu_devprop_remove_device (struct grub_xnu_devprop_device_descriptor
*dev
)
242 struct property_descriptor
*prop
;
244 grub_list_remove (GRUB_AS_LIST_P (&devices
), GRUB_AS_LIST (dev
));
246 for (prop
= dev
->properties
; prop
; )
248 grub_free (prop
->name
);
249 grub_free (prop
->name16
);
250 grub_free (prop
->data
);
256 grub_free (dev
->path
);
259 return GRUB_ERR_NONE
;
262 struct grub_xnu_devprop_device_descriptor
*
263 grub_xnu_devprop_add_device (struct grub_efi_device_path
*path
, int length
)
265 struct grub_xnu_devprop_device_descriptor
*ret
;
267 ret
= grub_zalloc (sizeof (*ret
));
271 ret
->path
= grub_malloc (length
);
277 ret
->pathlen
= length
;
278 grub_memcpy (ret
->path
, path
, length
);
280 grub_list_push (GRUB_AS_LIST_P (&devices
), GRUB_AS_LIST (ret
));
286 grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor
*dev
,
287 grub_uint8_t
*utf8
, grub_uint16_t
*utf16
,
288 int utf16len
, void *data
, int datalen
)
290 struct property_descriptor
*prop
;
292 prop
= grub_malloc (sizeof (*prop
));
297 prop
->name16
= utf16
;
298 prop
->name16len
= utf16len
;
300 prop
->length
= datalen
;
301 prop
->data
= grub_malloc (prop
->length
);
305 grub_free (prop
->name
);
306 grub_free (prop
->name16
);
309 grub_memcpy (prop
->data
, data
, prop
->length
);
310 grub_list_push (GRUB_AS_LIST_P (&dev
->properties
),
311 GRUB_AS_LIST (prop
));
312 return GRUB_ERR_NONE
;
316 grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor
*dev
,
317 char *name
, void *data
, int datalen
)
320 grub_uint16_t
*utf16
;
324 utf8
= (grub_uint8_t
*) grub_strdup (name
);
328 len
= grub_strlen (name
);
329 utf16
= grub_malloc (sizeof (grub_uint16_t
) * len
);
336 utf16len
= grub_utf8_to_utf16 (utf16
, len
, utf8
, len
, NULL
);
344 err
= grub_xnu_devprop_add_property (dev
, utf8
, utf16
,
345 utf16len
, data
, datalen
);
353 return GRUB_ERR_NONE
;
357 grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor
*dev
,
358 grub_uint16_t
*name
, int namelen
,
359 void *data
, int datalen
)
362 grub_uint16_t
*utf16
;
365 utf16
= grub_malloc (sizeof (grub_uint16_t
) * namelen
);
368 grub_memcpy (utf16
, name
, sizeof (grub_uint16_t
) * namelen
);
370 utf8
= grub_malloc (namelen
* 4 + 1);
377 *grub_utf16_to_utf8 ((grub_uint8_t
*) utf8
, name
, namelen
) = '\0';
379 err
= grub_xnu_devprop_add_property (dev
, utf8
, utf16
,
380 namelen
, data
, datalen
);
388 return GRUB_ERR_NONE
;
394 if (c
>= '0' && c
<= '9')
396 if (c
>= 'a' && c
<= 'z')
398 if (c
>= 'A' && c
<= 'Z')
404 grub_cpu_xnu_unload (void)
406 struct grub_xnu_devprop_device_descriptor
*dev1
, *dev2
;
408 for (dev1
= devices
; dev1
; )
411 grub_xnu_devprop_remove_device (dev1
);
417 grub_cpu_xnu_fill_devprop (void)
419 struct grub_xnu_devtree_key
*efikey
;
420 int total_length
= sizeof (struct grub_xnu_devprop_header
);
421 struct grub_xnu_devtree_key
*devprop
;
422 struct grub_xnu_devprop_device_descriptor
*device
;
424 struct grub_xnu_devprop_header
*head
;
429 efikey
= grub_xnu_create_key (&grub_xnu_devtree_root
, "efi");
433 for (device
= devices
; device
; device
= device
->next
)
435 struct property_descriptor
*propdesc
;
436 total_length
+= sizeof (struct grub_xnu_devprop_device_header
);
437 total_length
+= device
->pathlen
;
439 for (propdesc
= device
->properties
; propdesc
; propdesc
= propdesc
->next
)
441 total_length
+= sizeof (grub_uint32_t
);
442 total_length
+= sizeof (grub_uint16_t
)
443 * (propdesc
->name16len
+ 1);
444 total_length
+= sizeof (grub_uint32_t
);
445 total_length
+= propdesc
->length
;
450 devprop
= grub_xnu_create_value (&(efikey
->first_child
), "device-properties");
453 devprop
->data
= grub_malloc (total_length
);
454 devprop
->datasize
= total_length
;
460 head
->length
= total_length
;
462 head
->num_devices
= numdevs
;
463 for (device
= devices
; device
; )
465 struct grub_xnu_devprop_device_header
*devhead
;
466 struct property_descriptor
*propdesc
;
468 devhead
->num_values
= 0;
471 grub_memcpy (ptr
, device
->path
, device
->pathlen
);
472 ptr
= (char *) ptr
+ device
->pathlen
;
474 for (propdesc
= device
->properties
; propdesc
; )
481 *len
= 2 * propdesc
->name16len
+ sizeof (grub_uint16_t
)
482 + sizeof (grub_uint32_t
);
486 grub_memcpy (name
, propdesc
->name16
, 2 * propdesc
->name16len
);
487 name
+= propdesc
->name16len
;
489 /* NUL terminator. */
494 *len
= propdesc
->length
+ sizeof (grub_uint32_t
);
497 grub_memcpy (ptr
, propdesc
->data
, propdesc
->length
);
498 ptr
= (char *) ptr
+ propdesc
->length
;
500 grub_free (propdesc
->name
);
501 grub_free (propdesc
->name16
);
502 grub_free (propdesc
->data
);
504 propdesc
= propdesc
->next
;
506 devhead
->num_values
++;
509 devhead
->length
= (char *) ptr
- (char *) devhead
;
511 device
= device
->next
;
517 return GRUB_ERR_NONE
;
521 grub_cmd_devprop_load (grub_command_t cmd
__attribute__ ((unused
)),
522 int argc
, char *args
[])
525 void *buf
, *bufstart
, *bufend
;
526 struct grub_xnu_devprop_header
*head
;
531 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "file name required");
533 file
= grub_gzfile_open (args
[0], 1);
535 return grub_error (GRUB_ERR_FILE_NOT_FOUND
,
536 "couldn't load device-propertie dump");
537 size
= grub_file_size (file
);
538 buf
= grub_malloc (size
);
541 grub_file_close (file
);
544 if (grub_file_read (file
, buf
, size
) != (grub_ssize_t
) size
)
546 grub_file_close (file
);
549 grub_file_close (file
);
552 bufend
= (char *) buf
+ size
;
555 for (i
= 0; i
< grub_le_to_cpu32 (head
->num_devices
) && buf
< bufend
; i
++)
557 struct grub_efi_device_path
*dp
, *dpstart
;
558 struct grub_xnu_devprop_device_descriptor
*dev
;
559 struct grub_xnu_devprop_device_header
*devhead
;
568 buf
= (char *) buf
+ GRUB_EFI_DEVICE_PATH_LENGTH (dp
);
570 while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp
) && buf
< bufend
);
572 dev
= grub_xnu_devprop_add_device (dpstart
, (char *) buf
575 for (j
= 0; j
< grub_le_to_cpu32 (devhead
->num_values
) && buf
< bufend
;
578 grub_uint32_t
*namelen
;
579 grub_uint32_t
*datalen
;
580 grub_uint16_t
*utf16
;
590 buf
= (char *) buf
+ *namelen
- sizeof (grub_uint32_t
);
600 buf
= (char *) buf
+ *datalen
- sizeof (grub_uint32_t
);
603 err
= grub_xnu_devprop_add_property_utf16
604 (dev
, utf16
, (*namelen
- sizeof (grub_uint32_t
)
605 - sizeof (grub_uint16_t
)) / sizeof (grub_uint16_t
),
606 data
, *datalen
- sizeof (grub_uint32_t
));
609 grub_free (bufstart
);
615 grub_free (bufstart
);
616 return GRUB_ERR_NONE
;
619 /* Fill device tree. */
620 /* FIXME: some entries may be platform-agnostic. Move them to loader/xnu.c. */
622 grub_cpu_xnu_fill_devicetree (void)
624 struct grub_xnu_devtree_key
*efikey
;
625 struct grub_xnu_devtree_key
*cfgtablekey
;
626 struct grub_xnu_devtree_key
*curval
;
627 struct grub_xnu_devtree_key
*runtimesrvkey
;
628 struct grub_xnu_devtree_key
*platformkey
;
631 /* The value "model". */
632 /* FIXME: may this value be sometimes different? */
633 curval
= grub_xnu_create_value (&grub_xnu_devtree_root
, "model");
636 curval
->datasize
= sizeof ("ACPI");
637 curval
->data
= grub_strdup ("ACPI");
638 curval
= grub_xnu_create_value (&grub_xnu_devtree_root
, "compatible");
641 curval
->datasize
= sizeof ("ACPI");
642 curval
->data
= grub_strdup ("ACPI");
645 efikey
= grub_xnu_create_key (&grub_xnu_devtree_root
, "efi");
649 /* Information about firmware. */
650 curval
= grub_xnu_create_value (&(efikey
->first_child
), "firmware-revision");
653 curval
->datasize
= (SYSTEM_TABLE_SIZEOF (firmware_revision
));
654 curval
->data
= grub_malloc (curval
->datasize
);
657 grub_memcpy (curval
->data
, (SYSTEM_TABLE_VAR(firmware_revision
)),
660 curval
= grub_xnu_create_value (&(efikey
->first_child
), "firmware-vendor");
664 2 * (utf16_strlen (SYSTEM_TABLE_PTR (firmware_vendor
)) + 1);
665 curval
->data
= grub_malloc (curval
->datasize
);
668 grub_memcpy (curval
->data
, SYSTEM_TABLE_PTR (firmware_vendor
),
671 curval
= grub_xnu_create_value (&(efikey
->first_child
), "firmware-abi");
674 curval
->datasize
= sizeof ("EFI32");
675 curval
->data
= grub_malloc (curval
->datasize
);
678 if (SIZEOF_OF_UINTN
== 4)
679 grub_memcpy (curval
->data
, "EFI32", curval
->datasize
);
681 grub_memcpy (curval
->data
, "EFI64", curval
->datasize
);
683 /* The key "platform". */
684 platformkey
= grub_xnu_create_key (&(efikey
->first_child
),
689 /* Pass FSB frequency to the kernel. */
690 curval
= grub_xnu_create_value (&(platformkey
->first_child
), "FSBFrequency");
693 curval
->datasize
= sizeof (grub_uint64_t
);
694 curval
->data
= grub_malloc (curval
->datasize
);
698 /* First see if user supplies the value. */
699 char *fsbvar
= grub_env_get ("fsb");
701 *((grub_uint64_t
*) curval
->data
) = 0;
703 *((grub_uint64_t
*) curval
->data
) = readfrequency (fsbvar
);
704 /* Try autodetect. */
705 if (! *((grub_uint64_t
*) curval
->data
))
706 *((grub_uint64_t
*) curval
->data
) = guessfsb ();
707 grub_dprintf ("xnu", "fsb autodetected as %llu\n",
708 (unsigned long long) *((grub_uint64_t
*) curval
->data
));
710 cfgtablekey
= grub_xnu_create_key (&(efikey
->first_child
),
711 "configuration-table");
715 /* Fill "configuration-table" key. */
716 for (i
= 0; i
< SYSTEM_TABLE (num_table_entries
); i
++)
719 struct grub_xnu_devtree_key
*curkey
;
720 grub_efi_guid_t guid
;
723 /* Retrieve current key. */
724 #ifdef GRUB_MACHINE_EFI
727 grub_efi_system_table
->configuration_table
[i
].vendor_table
;
728 guid
= grub_efi_system_table
->configuration_table
[i
].vendor_guid
;
731 if (SIZEOF_OF_UINTN
== 4)
733 ptr
= UINT_TO_PTR (((grub_efiemu_configuration_table32_t
*)
734 SYSTEM_TABLE_PTR (configuration_table
))[i
]
737 ((grub_efiemu_configuration_table32_t
*)
738 SYSTEM_TABLE_PTR (configuration_table
))[i
].vendor_guid
;
742 ptr
= UINT_TO_PTR (((grub_efiemu_configuration_table64_t
*)
743 SYSTEM_TABLE_PTR (configuration_table
))[i
]
746 ((grub_efiemu_configuration_table64_t
*)
747 SYSTEM_TABLE_PTR (configuration_table
))[i
].vendor_guid
;
751 /* The name of key for new table. */
752 grub_snprintf (guidbuf
, sizeof (guidbuf
), "%08x-%04x-%04x-%02x%02x-",
753 guid
.data1
, guid
.data2
, guid
.data3
, guid
.data4
[0],
755 for (j
= 2; j
< 8; j
++)
756 grub_snprintf (guidbuf
+ grub_strlen (guidbuf
),
757 sizeof (guidbuf
) - grub_strlen (guidbuf
),
758 "%02x", guid
.data4
[j
]);
759 /* For some reason GUID has to be in uppercase. */
760 for (j
= 0; guidbuf
[j
] ; j
++)
761 if (guidbuf
[j
] >= 'a' && guidbuf
[j
] <= 'f')
762 guidbuf
[j
] += 'A' - 'a';
763 curkey
= grub_xnu_create_key (&(cfgtablekey
->first_child
), guidbuf
);
767 curval
= grub_xnu_create_value (&(curkey
->first_child
), "guid");
770 curval
->datasize
= sizeof (guid
);
771 curval
->data
= grub_malloc (curval
->datasize
);
774 grub_memcpy (curval
->data
, &guid
, curval
->datasize
);
776 /* The value "table". */
777 curval
= grub_xnu_create_value (&(curkey
->first_child
), "table");
780 curval
->datasize
= SIZEOF_OF_UINTN
;
781 curval
->data
= grub_malloc (curval
->datasize
);
784 if (SIZEOF_OF_UINTN
== 4)
785 *((grub_uint32_t
*)curval
->data
) = PTR_TO_UINT32 (ptr
);
787 *((grub_uint64_t
*)curval
->data
) = PTR_TO_UINT64 (ptr
);
790 for (j
= 0; j
< sizeof (table_aliases
) / sizeof (table_aliases
[0]); j
++)
791 if (grub_memcmp (&table_aliases
[j
].guid
, &guid
, sizeof (guid
)) == 0)
793 if (j
!= sizeof (table_aliases
) / sizeof (table_aliases
[0]))
795 curval
= grub_xnu_create_value (&(curkey
->first_child
), "alias");
798 curval
->datasize
= grub_strlen (table_aliases
[j
].name
) + 1;
799 curval
->data
= grub_malloc (curval
->datasize
);
802 grub_memcpy (curval
->data
, table_aliases
[j
].name
, curval
->datasize
);
806 /* Create and fill "runtime-services" key. */
807 runtimesrvkey
= grub_xnu_create_key (&(efikey
->first_child
),
811 curval
= grub_xnu_create_value (&(runtimesrvkey
->first_child
), "table");
814 curval
->datasize
= SIZEOF_OF_UINTN
;
815 curval
->data
= grub_malloc (curval
->datasize
);
818 if (SIZEOF_OF_UINTN
== 4)
819 *((grub_uint32_t
*) curval
->data
)
820 = PTR_TO_UINT32 (SYSTEM_TABLE_PTR (runtime_services
));
822 *((grub_uint64_t
*) curval
->data
)
823 = PTR_TO_UINT64 (SYSTEM_TABLE_PTR (runtime_services
));
825 return GRUB_ERR_NONE
;
829 grub_xnu_boot_resume (void)
831 struct grub_relocator32_state state
;
833 state
.esp
= grub_xnu_stack
;
834 state
.eip
= grub_xnu_entry_point
;
835 state
.eax
= grub_xnu_arg1
;
837 return grub_relocator32_boot (grub_xnu_heap_start
, grub_xnu_heap_will_be_at
,
845 struct grub_xnu_boot_params
*bootparams_relloc
;
846 grub_off_t bootparams_relloc_off
;
847 grub_off_t mmap_relloc_off
;
849 grub_efi_uintn_t memory_map_size
= 0;
850 grub_efi_memory_descriptor_t
*memory_map
;
851 grub_efi_uintn_t map_key
= 0;
852 grub_efi_uintn_t descriptor_size
= 0;
853 grub_efi_uint32_t descriptor_version
= 0;
854 grub_uint64_t firstruntimepage
, lastruntimepage
;
855 grub_uint64_t curruntimepage
;
857 grub_size_t devtreelen
;
859 struct grub_relocator32_state state
;
861 err
= grub_autoefi_prepare ();
865 err
= grub_cpu_xnu_fill_devprop ();
869 err
= grub_cpu_xnu_fill_devicetree ();
873 err
= grub_xnu_fill_devicetree ();
877 /* Page-align to avoid following parts to be inadvertently freed. */
878 err
= grub_xnu_align_heap (GRUB_XNU_PAGESIZE
);
882 /* Pass memory map to kernel. */
887 descriptor_version
= 0;
889 grub_dprintf ("xnu", "eip=%x\n", grub_xnu_entry_point
);
891 const char *debug
= grub_env_get ("debug");
893 if (debug
&& (grub_strword (debug
, "all") || grub_strword (debug
, "xnu")))
895 grub_printf ("Press any key to launch xnu\n");
899 /* Relocate the boot parameters to heap. */
900 bootparams_relloc
= grub_xnu_heap_malloc (sizeof (*bootparams_relloc
));
901 if (! bootparams_relloc
)
903 bootparams_relloc_off
= (grub_uint8_t
*) bootparams_relloc
904 - (grub_uint8_t
*) grub_xnu_heap_start
;
907 err
= grub_xnu_set_video (bootparams_relloc
);
908 if (err
!= GRUB_ERR_NONE
)
911 grub_errno
= GRUB_ERR_NONE
;
912 grub_printf ("Booting in blind mode\n");
914 bootparams_relloc
->lfb_mode
= 0;
915 bootparams_relloc
->lfb_width
= 0;
916 bootparams_relloc
->lfb_height
= 0;
917 bootparams_relloc
->lfb_depth
= 0;
918 bootparams_relloc
->lfb_line_len
= 0;
919 bootparams_relloc
->lfb_base
= 0;
922 if (grub_autoefi_get_memory_map (&memory_map_size
, memory_map
,
923 &map_key
, &descriptor_size
,
924 &descriptor_version
) < 0)
927 /* We will do few allocations later. Reserve some space for possible
928 memory map growth. */
929 memory_map_size
+= 20 * descriptor_size
;
930 memory_map
= grub_xnu_heap_malloc (memory_map_size
);
933 mmap_relloc_off
= (grub_uint8_t
*) memory_map
934 - (grub_uint8_t
*) grub_xnu_heap_start
;
936 err
= grub_xnu_writetree_toheap (&devtree
, &devtreelen
);
939 bootparams_relloc
= (struct grub_xnu_boot_params
*)
940 (bootparams_relloc_off
+ (grub_uint8_t
*) grub_xnu_heap_start
);
942 grub_memcpy (bootparams_relloc
->cmdline
, grub_xnu_cmdline
,
943 sizeof (bootparams_relloc
->cmdline
));
945 bootparams_relloc
->devtree
946 = ((grub_uint8_t
*) devtree
- (grub_uint8_t
*) grub_xnu_heap_start
)
947 + grub_xnu_heap_will_be_at
;
948 bootparams_relloc
->devtreelen
= devtreelen
;
950 memory_map
= (grub_efi_memory_descriptor_t
*)
951 ((grub_uint8_t
*) grub_xnu_heap_start
+ mmap_relloc_off
);
953 if (grub_autoefi_get_memory_map (&memory_map_size
, memory_map
,
954 &map_key
, &descriptor_size
,
955 &descriptor_version
) <= 0)
958 bootparams_relloc
->efi_system_table
959 = PTR_TO_UINT32 (grub_autoefi_system_table
);
961 firstruntimepage
= (((grub_addr_t
) grub_xnu_heap_will_be_at
962 + grub_xnu_heap_size
+ GRUB_XNU_PAGESIZE
- 1)
963 / GRUB_XNU_PAGESIZE
) + 20;
964 curruntimepage
= firstruntimepage
;
966 for (i
= 0; (unsigned) i
< memory_map_size
/ descriptor_size
; i
++)
968 grub_efi_memory_descriptor_t
*curdesc
= (grub_efi_memory_descriptor_t
*)
969 ((char *) memory_map
+ descriptor_size
* i
);
971 curdesc
->virtual_start
= curdesc
->physical_start
;
973 if (curdesc
->type
== GRUB_EFI_RUNTIME_SERVICES_DATA
974 || curdesc
->type
== GRUB_EFI_RUNTIME_SERVICES_CODE
)
976 curdesc
->virtual_start
= curruntimepage
<< 12;
977 curruntimepage
+= curdesc
->num_pages
;
978 if (curdesc
->physical_start
979 <= PTR_TO_UINT64 (grub_autoefi_system_table
)
980 && curdesc
->physical_start
+ (curdesc
->num_pages
<< 12)
981 > PTR_TO_UINT64 (grub_autoefi_system_table
))
982 bootparams_relloc
->efi_system_table
983 = PTR_TO_UINT64 (grub_autoefi_system_table
)
984 - curdesc
->physical_start
+ curdesc
->virtual_start
;
985 if (SIZEOF_OF_UINTN
== 8 && grub_xnu_is_64bit
)
986 curdesc
->virtual_start
|= 0xffffff8000000000ULL
;
990 lastruntimepage
= curruntimepage
;
992 bootparams_relloc
->efi_mmap
= grub_xnu_heap_will_be_at
+ mmap_relloc_off
;
993 bootparams_relloc
->efi_mmap_size
= memory_map_size
;
994 bootparams_relloc
->efi_mem_desc_size
= descriptor_size
;
995 bootparams_relloc
->efi_mem_desc_version
= descriptor_version
;
997 bootparams_relloc
->heap_start
= grub_xnu_heap_will_be_at
;
998 bootparams_relloc
->heap_size
= grub_xnu_heap_size
;
999 bootparams_relloc
->efi_runtime_first_page
= firstruntimepage
;
1001 bootparams_relloc
->efi_runtime_npages
= lastruntimepage
- firstruntimepage
;
1002 bootparams_relloc
->efi_uintnbits
= SIZEOF_OF_UINTN
* 8;
1004 bootparams_relloc
->verminor
= GRUB_XNU_BOOTARGS_VERMINOR
;
1005 bootparams_relloc
->vermajor
= GRUB_XNU_BOOTARGS_VERMAJOR
;
1007 /* Parameters for asm helper. */
1008 grub_xnu_stack
= bootparams_relloc
->heap_start
1009 + bootparams_relloc
->heap_size
+ GRUB_XNU_PAGESIZE
;
1010 grub_xnu_arg1
= bootparams_relloc_off
+ grub_xnu_heap_will_be_at
;
1012 if (! grub_autoefi_exit_boot_services (map_key
))
1013 return grub_error (GRUB_ERR_IO
, "can't exit boot services");
1015 grub_autoefi_set_virtual_address_map (memory_map_size
, descriptor_size
,
1016 descriptor_version
,memory_map
);
1018 state
.eip
= grub_xnu_entry_point
;
1019 state
.eax
= grub_xnu_arg1
;
1020 state
.esp
= grub_xnu_stack
;
1021 return grub_relocator32_boot (grub_xnu_heap_start
, grub_xnu_heap_will_be_at
,
1025 static grub_command_t cmd_devprop_load
;
1028 grub_cpu_xnu_init (void)
1030 cmd_devprop_load
= grub_register_command ("xnu_devprop_load",
1031 grub_cmd_devprop_load
,
1032 0, N_("Load device-properties dump."));
1036 grub_cpu_xnu_fini (void)
1038 grub_unregister_command (cmd_devprop_load
);