grub_macho_t grub_macho_open (const char *name, int is_64bit) { grub_file_t file; grub_macho_t macho; file = grub_file_open (name); if (! file) return 0; macho = grub_macho_file (file, name, is_64bit); if (! macho) grub_file_close (file); return macho; }
/* Load .kext. */ static grub_err_t grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) { grub_macho_t macho; grub_err_t err; grub_file_t infoplist; struct grub_xnu_extheader *exthead; int neededspace = sizeof (*exthead); grub_uint8_t *buf; grub_size_t infoplistsize = 0, machosize = 0; char *name, *nameend; int namelen; name = get_name_ptr (infoplistname); nameend = grub_strchr (name, '/'); if (nameend) namelen = nameend - name; else namelen = grub_strlen (name); neededspace += namelen + 1; if (! grub_xnu_heap_size) return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); /* Compute the needed space. */ if (binaryfile) { macho = grub_macho_file (binaryfile); if (! macho || ! grub_macho_contains_macho32 (macho)) { if (macho) grub_macho_close (macho); return grub_error (GRUB_ERR_BAD_OS, "extension doesn't contain suitable architecture"); } if (grub_xnu_is_64bit) machosize = grub_macho_filesize64 (macho); else machosize = grub_macho_filesize32 (macho); neededspace += machosize; } else macho = 0; if (infoplistname) infoplist = grub_gzfile_open (infoplistname, 1); else infoplist = 0; grub_errno = GRUB_ERR_NONE; if (infoplist) { infoplistsize = grub_file_size (infoplist); neededspace += infoplistsize + 1; } else infoplistsize = 0; /* Allocate the space. */ err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); if (err) return err; buf = grub_xnu_heap_malloc (neededspace); exthead = (struct grub_xnu_extheader *) buf; grub_memset (exthead, 0, sizeof (*exthead)); buf += sizeof (*exthead); /* Load the binary. */ if (macho) { exthead->binaryaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->binarysize = machosize; if (grub_xnu_is_64bit) err = grub_macho_readfile64 (macho, buf); else err = grub_macho_readfile32 (macho, buf); if (err) { grub_macho_close (macho); return err; } grub_macho_close (macho); buf += machosize; } grub_errno = GRUB_ERR_NONE; /* Load the plist. */ if (infoplist) { exthead->infoplistaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->infoplistsize = infoplistsize + 1; if (grub_file_read (infoplist, buf, infoplistsize) != (grub_ssize_t) (infoplistsize)) { grub_file_close (infoplist); grub_error_push (); return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s: ", infoplistname); } grub_file_close (infoplist); buf[infoplistsize] = 0; buf += infoplistsize + 1; } grub_errno = GRUB_ERR_NONE; exthead->nameaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->namesize = namelen + 1; grub_memcpy (buf, name, namelen); buf[namelen] = 0; buf += namelen + 1; /* Announce to kernel */ return grub_xnu_register_memory ("Driver-", &driversnum, exthead, neededspace); }