205
204
((msrlow >> 7) & 0x3e) + ((msrlow >> 14) & 1), 0);
207
struct property_descriptor
209
struct property_descriptor *next;
211
grub_uint16_t *name16;
217
struct grub_xnu_devprop_device_descriptor *devices = 0;
220
grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev,
223
struct property_descriptor *prop;
224
prop = grub_named_list_find (GRUB_AS_NAMED_LIST_P (&dev->properties), name);
226
return GRUB_ERR_NONE;
228
grub_free (prop->name);
229
grub_free (prop->name16);
230
grub_free (prop->data);
232
grub_list_remove (GRUB_AS_LIST_P (&dev->properties), GRUB_AS_LIST (prop));
234
return GRUB_ERR_NONE;
238
grub_xnu_devprop_remove_device (struct grub_xnu_devprop_device_descriptor *dev)
241
struct property_descriptor *prop;
243
grub_list_remove (GRUB_AS_LIST_P (&devices), GRUB_AS_LIST (dev));
245
for (prop = dev->properties; prop; )
247
grub_free (prop->name);
248
grub_free (prop->name16);
249
grub_free (prop->data);
255
grub_free (dev->path);
258
return GRUB_ERR_NONE;
261
struct grub_xnu_devprop_device_descriptor *
262
grub_xnu_devprop_add_device (struct grub_efi_device_path *path, int length)
264
struct grub_xnu_devprop_device_descriptor *ret;
266
ret = grub_zalloc (sizeof (*ret));
270
ret->path = grub_malloc (length);
276
ret->pathlen = length;
277
grub_memcpy (ret->path, path, length);
279
grub_list_push (GRUB_AS_LIST_P (&devices), GRUB_AS_LIST (ret));
285
grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
286
grub_uint8_t *utf8, grub_uint16_t *utf16,
287
int utf16len, void *data, int datalen)
289
struct property_descriptor *prop;
291
prop = grub_malloc (sizeof (*prop));
296
prop->name16 = utf16;
297
prop->name16len = utf16len;
299
prop->length = datalen;
300
prop->data = grub_malloc (prop->length);
304
grub_free (prop->name);
305
grub_free (prop->name16);
308
grub_memcpy (prop->data, data, prop->length);
309
grub_list_push (GRUB_AS_LIST_P (&dev->properties),
310
GRUB_AS_LIST (prop));
311
return GRUB_ERR_NONE;
315
grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *dev,
316
char *name, void *data, int datalen)
319
grub_uint16_t *utf16;
323
utf8 = (grub_uint8_t *) grub_strdup (name);
327
len = grub_strlen (name);
328
utf16 = grub_malloc (sizeof (grub_uint16_t) * len);
335
utf16len = grub_utf8_to_utf16 (utf16, len, utf8, len, NULL);
343
err = grub_xnu_devprop_add_property (dev, utf8, utf16,
344
utf16len, data, datalen);
352
return GRUB_ERR_NONE;
356
grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *dev,
357
grub_uint16_t *name, int namelen,
358
void *data, int datalen)
361
grub_uint16_t *utf16;
364
utf16 = grub_malloc (sizeof (grub_uint16_t) * namelen);
367
grub_memcpy (utf16, name, sizeof (grub_uint16_t) * namelen);
369
utf8 = grub_malloc (namelen * 4 + 1);
376
*grub_utf16_to_utf8 ((grub_uint8_t *) utf8, name, namelen) = '\0';
378
err = grub_xnu_devprop_add_property (dev, utf8, utf16,
379
namelen, data, datalen);
387
return GRUB_ERR_NONE;
393
if (c >= '0' && c <= '9')
395
if (c >= 'a' && c <= 'z')
397
if (c >= 'A' && c <= 'Z')
403
grub_cpu_xnu_unload (void)
405
struct grub_xnu_devprop_device_descriptor *dev1, *dev2;
407
for (dev1 = devices; dev1; )
410
grub_xnu_devprop_remove_device (dev1);
416
grub_cpu_xnu_fill_devprop (void)
418
struct grub_xnu_devtree_key *efikey;
419
int total_length = sizeof (struct grub_xnu_devprop_header);
420
struct grub_xnu_devtree_key *devprop;
421
struct grub_xnu_devprop_device_descriptor *device;
423
struct grub_xnu_devprop_header *head;
428
efikey = grub_xnu_create_key (&grub_xnu_devtree_root, "efi");
432
for (device = devices; device; device = device->next)
434
struct property_descriptor *propdesc;
435
total_length += sizeof (struct grub_xnu_devprop_device_header);
436
total_length += device->pathlen;
438
for (propdesc = device->properties; propdesc; propdesc = propdesc->next)
440
total_length += sizeof (grub_uint32_t);
441
total_length += sizeof (grub_uint16_t)
442
* (propdesc->name16len + 1);
443
total_length += sizeof (grub_uint32_t);
444
total_length += propdesc->length;
449
devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties");
452
devprop->data = grub_malloc (total_length);
453
devprop->datasize = total_length;
459
head->length = total_length;
461
head->num_devices = numdevs;
462
for (device = devices; device; )
464
struct grub_xnu_devprop_device_header *devhead;
465
struct property_descriptor *propdesc;
467
devhead->num_values = 0;
470
grub_memcpy (ptr, device->path, device->pathlen);
471
ptr = (char *) ptr + device->pathlen;
473
for (propdesc = device->properties; propdesc; )
480
*len = 2 * propdesc->name16len + sizeof (grub_uint16_t)
481
+ sizeof (grub_uint32_t);
485
grub_memcpy (name, propdesc->name16, 2 * propdesc->name16len);
486
name += propdesc->name16len;
488
/* NUL terminator. */
493
*len = propdesc->length + sizeof (grub_uint32_t);
496
grub_memcpy (ptr, propdesc->data, propdesc->length);
497
ptr = (char *) ptr + propdesc->length;
499
grub_free (propdesc->name);
500
grub_free (propdesc->name16);
501
grub_free (propdesc->data);
503
propdesc = propdesc->next;
505
devhead->num_values++;
508
devhead->length = (char *) ptr - (char *) devhead;
510
device = device->next;
516
return GRUB_ERR_NONE;
520
grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
521
int argc, char *args[])
524
void *buf, *bufstart, *bufend;
525
struct grub_xnu_devprop_header *head;
530
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
532
file = grub_gzfile_open (args[0], 1);
534
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
535
"couldn't load device-propertie dump");
536
size = grub_file_size (file);
537
buf = grub_malloc (size);
540
grub_file_close (file);
543
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
545
grub_file_close (file);
548
grub_file_close (file);
551
bufend = (char *) buf + size;
554
for (i = 0; i < grub_le_to_cpu32 (head->num_devices) && buf < bufend; i++)
556
struct grub_efi_device_path *dp, *dpstart;
557
struct grub_xnu_devprop_device_descriptor *dev;
558
struct grub_xnu_devprop_device_header *devhead;
567
buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
569
while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
571
dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
574
for (j = 0; j < grub_le_to_cpu32 (devhead->num_values) && buf < bufend;
577
grub_uint32_t *namelen;
578
grub_uint32_t *datalen;
579
grub_uint16_t *utf16;
589
buf = (char *) buf + *namelen - sizeof (grub_uint32_t);
599
buf = (char *) buf + *datalen - sizeof (grub_uint32_t);
602
err = grub_xnu_devprop_add_property_utf16
603
(dev, utf16, (*namelen - sizeof (grub_uint32_t)
604
- sizeof (grub_uint16_t)) / sizeof (grub_uint16_t),
605
data, *datalen - sizeof (grub_uint32_t));
608
grub_free (bufstart);
614
grub_free (bufstart);
615
return GRUB_ERR_NONE;
208
618
/* Fill device tree. */
209
619
/* FIXME: some entries may be platform-agnostic. Move them to loader/xnu.c. */
447
883
descriptor_size = 0;
448
884
descriptor_version = 0;
886
grub_dprintf ("xnu", "eip=%x\n", grub_xnu_entry_point);
888
const char *debug = grub_env_get ("debug");
890
if (debug && (grub_strword (debug, "all") || grub_strword (debug, "xnu")))
892
grub_printf ("Press any key to launch xnu\n");
896
/* Relocate the boot parameters to heap. */
897
bootparams_relloc = grub_xnu_heap_malloc (sizeof (*bootparams_relloc));
898
if (! bootparams_relloc)
900
bootparams_relloc_off = (grub_uint8_t *) bootparams_relloc
901
- (grub_uint8_t *) grub_xnu_heap_start;
904
err = grub_xnu_set_video (bootparams_relloc);
905
if (err != GRUB_ERR_NONE)
908
grub_errno = GRUB_ERR_NONE;
909
grub_printf ("Booting in blind mode\n");
911
bootparams_relloc->lfb_mode = 0;
912
bootparams_relloc->lfb_width = 0;
913
bootparams_relloc->lfb_height = 0;
914
bootparams_relloc->lfb_depth = 0;
915
bootparams_relloc->lfb_line_len = 0;
916
bootparams_relloc->lfb_base = 0;
450
919
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
451
920
&map_key, &descriptor_size,
452
921
&descriptor_version) < 0)
453
922
return grub_errno;
924
/* We will do few allocations later. Reserve some space for possible
925
memory map growth. */
926
memory_map_size += 20 * descriptor_size;
455
927
memory_map = grub_xnu_heap_malloc (memory_map_size);
456
928
if (! memory_map)
457
929
return grub_errno;
459
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
460
&map_key, &descriptor_size,
461
&descriptor_version) <= 0)
463
930
mmap_relloc_off = (grub_uint8_t *) memory_map
464
931
- (grub_uint8_t *) grub_xnu_heap_start;
466
firstruntimeaddr = (grub_uint64_t) (-1);
468
for (i = 0; (unsigned) i < memory_map_size / descriptor_size; i++)
470
grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *)
471
((char *) memory_map + descriptor_size * i);
473
/* Some EFI implementations set physical_start to 0 which
475
curdesc->virtual_start = curdesc->physical_start;
477
if (curdesc->type == GRUB_EFI_RUNTIME_SERVICES_DATA
478
|| curdesc->type == GRUB_EFI_RUNTIME_SERVICES_CODE)
480
if (firstruntimeaddr > curdesc->physical_start)
481
firstruntimeaddr = curdesc->physical_start;
482
if (lastruntimeaddr < curdesc->physical_start
483
+ curdesc->num_pages * 4096)
484
lastruntimeaddr = curdesc->physical_start
485
+ curdesc->num_pages * 4096;
489
/* Relocate the boot parameters to heap. */
490
bootparams_relloc = grub_xnu_heap_malloc (sizeof (*bootparams_relloc));
491
if (! bootparams_relloc)
493
bootparams_relloc_off = (grub_uint8_t *) bootparams_relloc
494
- (grub_uint8_t *) grub_xnu_heap_start;
495
933
err = grub_xnu_writetree_toheap (&devtree, &devtreelen);
501
939
grub_memcpy (bootparams_relloc->cmdline, grub_xnu_cmdline,
502
940
sizeof (bootparams_relloc->cmdline));
504
bootparams_relloc->devtree = ((char *) devtree - grub_xnu_heap_start)
942
bootparams_relloc->devtree
943
= ((grub_uint8_t *) devtree - (grub_uint8_t *) grub_xnu_heap_start)
505
944
+ grub_xnu_heap_will_be_at;
506
945
bootparams_relloc->devtreelen = devtreelen;
508
bootparams_relloc->heap_start = grub_xnu_heap_will_be_at;
509
bootparams_relloc->heap_size = grub_xnu_heap_size;
947
memory_map = (grub_efi_memory_descriptor_t *)
948
((grub_uint8_t *) grub_xnu_heap_start + mmap_relloc_off);
950
if (grub_autoefi_get_memory_map (&memory_map_size, memory_map,
951
&map_key, &descriptor_size,
952
&descriptor_version) <= 0)
955
bootparams_relloc->efi_system_table
956
= PTR_TO_UINT32 (grub_autoefi_system_table);
958
firstruntimepage = (((grub_addr_t) grub_xnu_heap_will_be_at
959
+ grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1)
960
/ GRUB_XNU_PAGESIZE) + 20;
961
curruntimepage = firstruntimepage;
963
for (i = 0; (unsigned) i < memory_map_size / descriptor_size; i++)
965
grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *)
966
((char *) memory_map + descriptor_size * i);
968
curdesc->virtual_start = curdesc->physical_start;
970
if (curdesc->type == GRUB_EFI_RUNTIME_SERVICES_DATA
971
|| curdesc->type == GRUB_EFI_RUNTIME_SERVICES_CODE)
973
curdesc->virtual_start = curruntimepage << 12;
974
curruntimepage += curdesc->num_pages;
975
if (curdesc->physical_start
976
<= PTR_TO_UINT64 (grub_autoefi_system_table)
977
&& curdesc->physical_start + (curdesc->num_pages << 12)
978
> PTR_TO_UINT64 (grub_autoefi_system_table))
979
bootparams_relloc->efi_system_table
980
= PTR_TO_UINT64 (grub_autoefi_system_table)
981
- curdesc->physical_start + curdesc->virtual_start;
982
if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit)
983
curdesc->virtual_start |= 0xffffff8000000000ULL;
987
lastruntimepage = curruntimepage;
511
989
bootparams_relloc->efi_mmap = grub_xnu_heap_will_be_at + mmap_relloc_off;
512
990
bootparams_relloc->efi_mmap_size = memory_map_size;
513
991
bootparams_relloc->efi_mem_desc_size = descriptor_size;
514
992
bootparams_relloc->efi_mem_desc_version = descriptor_version;
516
bootparams_relloc->efi_runtime_first_page = firstruntimeaddr
518
bootparams_relloc->efi_runtime_npages
519
= ((lastruntimeaddr + GRUB_XNU_PAGESIZE - 1) / GRUB_XNU_PAGESIZE)
520
- (firstruntimeaddr / GRUB_XNU_PAGESIZE);
994
bootparams_relloc->heap_start = grub_xnu_heap_will_be_at;
995
bootparams_relloc->heap_size = grub_xnu_heap_size;
996
bootparams_relloc->efi_runtime_first_page = firstruntimepage;
998
bootparams_relloc->efi_runtime_npages = lastruntimepage - firstruntimepage;
521
999
bootparams_relloc->efi_uintnbits = SIZEOF_OF_UINTN * 8;
522
bootparams_relloc->efi_system_table
523
= PTR_TO_UINT32 (grub_autoefi_system_table);
525
1001
bootparams_relloc->verminor = GRUB_XNU_BOOTARGS_VERMINOR;
526
1002
bootparams_relloc->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR;
529
1005
grub_xnu_stack = bootparams_relloc->heap_start
530
1006
+ bootparams_relloc->heap_size + GRUB_XNU_PAGESIZE;
531
1007
grub_xnu_arg1 = bootparams_relloc_off + grub_xnu_heap_will_be_at;
533
grub_xnu_launch = (void (*) (void))
534
(grub_xnu_heap_start + grub_xnu_heap_size);
536
grub_dprintf ("xnu", "eip=%x\n", grub_xnu_entry_point);
537
grub_dprintf ("xnu", "launch=%p\n", grub_xnu_launch);
539
const char *debug = grub_env_get ("debug");
541
if (debug && (grub_strword (debug, "all") || grub_strword (debug, "xnu")))
543
grub_printf ("Press any key to launch xnu\n");
548
err = grub_xnu_set_video (bootparams_relloc);
549
if (err != GRUB_ERR_NONE)
552
grub_errno = GRUB_ERR_NONE;
553
grub_printf ("Booting in blind mode\n");
555
bootparams_relloc->lfb_mode = 0;
556
bootparams_relloc->lfb_width = 0;
557
bootparams_relloc->lfb_height = 0;
558
bootparams_relloc->lfb_depth = 0;
559
bootparams_relloc->lfb_line_len = 0;
560
bootparams_relloc->lfb_base = 0;
563
grub_memcpy (grub_xnu_heap_start + grub_xnu_heap_size,
564
grub_xnu_launcher_start,
565
grub_xnu_launcher_end - grub_xnu_launcher_start);
568
if (! grub_autoefi_finish_boot_services ())
1009
if (! grub_autoefi_exit_boot_services (map_key))
569
1010
return grub_error (GRUB_ERR_IO, "can't exit boot services");
573
/* Never reaches here. */
1012
grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size,
1013
descriptor_version,memory_map);
1015
state.eip = grub_xnu_entry_point;
1016
state.eax = grub_xnu_arg1;
1017
state.esp = grub_xnu_stack;
1018
return grub_relocator32_boot (grub_xnu_heap_start, grub_xnu_heap_will_be_at,
1022
static grub_command_t cmd_devprop_load;
1025
grub_cpu_xnu_init (void)
1027
cmd_devprop_load = grub_register_command ("xnu_devprop_load",
1028
grub_cmd_devprop_load,
1029
0, "Load device-properties dump.");
1033
grub_cpu_xnu_fini (void)
1035
grub_unregister_command (cmd_devprop_load);