Exemplo n.º 1
0
/* Load the kext. */
static grub_err_t
grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)),
		   int argc, char *args[])
{
  grub_file_t binfile = 0;
  if (argc == 2)
    {
      /* User explicitly specified plist and binary. */
      if (grub_strcmp (args[1], "-") != 0)
	{
	  binfile = grub_gzfile_open (args[1], 1);
	  if (! binfile)
	    {
	      grub_error (GRUB_ERR_BAD_OS, "can't open file");
	      return GRUB_ERR_NONE;
	    }
	}
      return grub_xnu_load_driver (grub_strcmp (args[0], "-") ? args[0] : 0,
				   binfile);
    }

  /* load kext normally. */
  if (argc == 1)
    return grub_xnu_load_kext_from_dir (args[0], 0, 10);

  return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
}
Exemplo n.º 2
0
/* This is similar to grub_gzfile_open. */
static grub_file_t
grub_mofile_open (const char *filename)
{
  int unsigned magic;
  int version;

  /* Using fd_mo and not another variable because
     it's needed for grub_gettext_get_info.  */

  fd_mo = grub_gzfile_open (filename, 1);
  grub_errno = GRUB_ERR_NONE;

  if (!fd_mo)
    {
      grub_dprintf ("gettext", "Cannot read %s\n", filename);
      return 0;
    }

  magic = grub_gettext_get_info (GETTEXT_MAGIC_NUMBER);

  if (magic != MO_MAGIC_NUMBER)
    {
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo file: %s",
		  filename);
      grub_file_close (fd_mo);
      fd_mo = 0;
      return 0;
    }

  version = grub_gettext_get_info (GETTEXT_FILE_FORMAT);

  if (version != 0)
    {
      grub_error (GRUB_ERR_BAD_FILE_TYPE,
		  "mo: invalid mo version in file: %s", filename);
      fd_mo = 0;
      return 0;
    }

  return fd_mo;
}
Exemplo n.º 3
0
static grub_err_t
grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)),
		      int argc, char *args[])
{
  grub_file_t file;
  void *loadto;
  grub_err_t err;
  grub_size_t size;

  if (argc != 1)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");

  if (! grub_xnu_heap_size)
    return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");

  file = grub_gzfile_open (args[0], 1);
  if (! file)
    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
		       "couldn't load ramdisk");

  err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
  if (err)
    return err;

  size = grub_file_size (file);

  loadto = grub_xnu_heap_malloc (size);
  if (! loadto)
    return grub_errno;
  if (grub_file_read (file, loadto, size)
      != (grub_ssize_t) (size))
    {
      grub_file_close (file);
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]);
    }
  return grub_xnu_register_memory ("RAMDisk", 0, loadto, size);
}
Exemplo n.º 4
0
/* Returns true if the kext should be loaded according to plist
   and osbundlereq. Also fill BINNAME. */
static int
grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq,
				   char **binname)
{
  grub_file_t file;
  char *buf = 0, *tagstart = 0, *ptr1 = 0, *keyptr = 0;
  char *stringptr = 0, *ptr2 = 0;
  grub_size_t size;
  int depth = 0;
  int ret;
  int osbundlekeyfound = 0, binnamekeyfound = 0;
  if (binname)
    *binname = 0;

  file = grub_gzfile_open (plistname, 1);
  if (! file)
    {
      grub_file_close (file);
      grub_error_push ();
      grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", plistname);
      return 0;
    }

  size = grub_file_size (file);
  buf = grub_malloc (size);
  if (! buf)
    {
      grub_file_close (file);
      grub_error_push ();
      grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't read file %s", plistname);
      return 0;
    }
  if (grub_file_read (file, buf, size) != (grub_ssize_t) (size))
    {
      grub_file_close (file);
      grub_error_push ();
      grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", plistname);
      return 0;
    }
  grub_file_close (file);

  /* Set the return value for the case when no OSBundleRequired tag is found. */
  if (osbundlereq)
    ret = grub_strword (osbundlereq, "all") || grub_strword (osbundlereq, "-");
  else
    ret = 1;

  /* Parse plist. It's quite dirty and inextensible but does its job. */
  for (ptr1 = buf; ptr1 < buf + size; ptr1++)
    switch (*ptr1)
      {
      case '<':
	tagstart = ptr1;
	*ptr1 = 0;
	if (keyptr && depth == 4
	    && grub_strcmp (keyptr, "OSBundleRequired") == 0)
	  osbundlekeyfound = 1;
	if (keyptr && depth == 4 &&
	    grub_strcmp (keyptr, "CFBundleExecutable") == 0)
	  binnamekeyfound = 1;
	if (stringptr && osbundlekeyfound && osbundlereq && depth == 4)
	  {
	    for (ptr2 = stringptr; *ptr2; ptr2++)
	      *ptr2 = grub_tolower (*ptr2);
	    ret = grub_strword (osbundlereq, stringptr)
	      || grub_strword (osbundlereq, "all");
	  }
	if (stringptr && binnamekeyfound && binname && depth == 4)
	  {
	    if (*binname)
	      grub_free (*binname);
	    *binname = grub_strdup (stringptr);
	  }

	*ptr1 = '<';
	keyptr = 0;
	stringptr = 0;
	break;
      case '>':
	if (! tagstart)
	  {
	    grub_free (buf);
	    grub_error (GRUB_ERR_BAD_OS, "can't parse %s", plistname);
	    return 0;
	  }
	*ptr1 = 0;
	if (tagstart[1] == '?' || ptr1[-1] == '/')
	  {
	    osbundlekeyfound = 0;
	    *ptr1 = '>';
	    break;
	  }
	if (depth == 3 && grub_strcmp (tagstart + 1, "key") == 0)
	  keyptr = ptr1 + 1;
	if (depth == 3 && grub_strcmp (tagstart + 1, "string") == 0)
	  stringptr = ptr1 + 1;
	else if (grub_strcmp (tagstart + 1, "/key") != 0)
	  {
	    osbundlekeyfound = 0;
	    binnamekeyfound = 0;
	  }
	*ptr1 = '>';

	if (tagstart[1] == '/')
	  depth--;
	else
	  depth++;
	break;
      }
  grub_free (buf);

  return ret;
}
Exemplo n.º 5
0
/* Load mkext. */
static grub_err_t
grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
		    int argc, char *args[])
{
  grub_file_t file;
  void *loadto;
  grub_err_t err;
  grub_off_t readoff = 0;
  grub_ssize_t readlen = -1;
  struct grub_macho_fat_header head;
  struct grub_macho_fat_arch *archs;
  int narchs, i;

  if (argc != 1)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");

  if (! grub_xnu_heap_size)
    return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded");

  file = grub_gzfile_open (args[0], 1);
  if (! file)
    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
		       "couldn't load driver package");

  /* Sometimes caches are fat binary. Errgh. */
  if (grub_file_read (file, &head, sizeof (head))
      != (grub_ssize_t) (sizeof (head)))
    {
      /* I don't know the internal structure of package but
	 can hardly imagine a valid package shorter than 20 bytes. */
      grub_file_close (file);
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]);
    }

  /* Find the corresponding architecture. */
  if (grub_be_to_cpu32 (head.magic) == GRUB_MACHO_FAT_MAGIC)
    {
      narchs = grub_be_to_cpu32 (head.nfat_arch);
      archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
      if (! archs)
	{
	  grub_file_close (file);
	  grub_error_push ();
	  return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			     "couldn't read file %s", args[0]);

	}
      if (grub_file_read (file, archs,
			  sizeof (struct grub_macho_fat_arch) * narchs)
	  != (grub_ssize_t) sizeof(struct grub_macho_fat_arch) * narchs)
	{
	  grub_free (archs);
	  grub_error_push ();
	  return grub_error (GRUB_ERR_READ_ERROR, "cannot read fat header");
	}
      for (i = 0; i < narchs; i++)
	{
	  if (!grub_xnu_is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST32
	      (grub_be_to_cpu32 (archs[i].cputype)))
	    {
	      readoff = grub_be_to_cpu32 (archs[i].offset);
	      readlen = grub_be_to_cpu32 (archs[i].size);
	    }
	  if (grub_xnu_is_64bit && GRUB_MACHO_CPUTYPE_IS_HOST64
	      (grub_be_to_cpu32 (archs[i].cputype)))
	    {
	      readoff = grub_be_to_cpu32 (archs[i].offset);
	      readlen = grub_be_to_cpu32 (archs[i].size);
	    }
	}
      grub_free (archs);
    }
  else
    {
      /* It's a flat file. Some sane people still exist. */
      readoff = 0;
      readlen = grub_file_size (file);
    }

  if (readlen == -1)
    {
      grub_file_close (file);
      return grub_error (GRUB_ERR_BAD_OS, "no suitable architecture is found");
    }

  /* Allocate space. */
  err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE);
  if (err)
    {
      grub_file_close (file);
      return err;
    }

  loadto = grub_xnu_heap_malloc (readlen);
  if (! loadto)
    {
      grub_file_close (file);
      return grub_errno;
    }

  /* Read the file. */
  grub_file_seek (file, readoff);
  if (grub_file_read (file, loadto, readlen) != (grub_ssize_t) (readlen))
    {
      grub_file_close (file);
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]);
    }
  grub_file_close (file);

  /* Pass it to kernel. */
  return grub_xnu_register_memory ("DriversPackage-", &driverspackagenum,
				   loadto, readlen);
}
Exemplo n.º 6
0
/* 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);
}
Exemplo n.º 7
0
/* Load extension DIRNAME. (extensions are directories in xnu) */
grub_err_t
grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired,
			     int maxrecursion)
{
  grub_device_t dev;
  char *newdirname;
  char *newpath;
  char *device_name;
  grub_fs_t fs;
  const char *path;
  char *binsuffix;
  grub_file_t binfile;

  newdirname = grub_malloc (grub_strlen (dirname) + 20);
  if (! newdirname)
    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate buffer");
  grub_strcpy (newdirname, dirname);
  newdirname[grub_strlen (dirname)] = '/';
  newdirname[grub_strlen (dirname) + 1] = 0;
  device_name = grub_file_get_device_name (dirname);
  dev = grub_device_open (device_name);
  if (dev)
    {
      struct grub_xnu_load_kext_from_dir_closure c;

      fs = grub_fs_probe (dev);
      path = grub_strchr (dirname, ')');
      if (! path)
	path = dirname;
      else
	path++;

      newpath = grub_strchr (newdirname, ')');
      if (! newpath)
	newpath = newdirname;
      else
	newpath++;

      c.dirname = dirname;
      c.osbundlerequired = osbundlerequired;
      c.maxrecursion = maxrecursion;
      c.usemacos = 0;
      c.plistname = 0;
      c.newdirname = newdirname;
      /* Look at the directory. */
      if (fs)
	(fs->dir) (dev, path, grub_xnu_load_kext_from_dir_hook, &c);

      if (c.plistname && grub_xnu_check_os_bundle_required
	  (c.plistname, osbundlerequired, &binsuffix))
	{
	  if (binsuffix)
	    {
	      /* Open the binary. */
	      char *binname = grub_malloc (grub_strlen (dirname)
					   + grub_strlen (binsuffix)
					   + sizeof ("/MacOS/"));
	      grub_strcpy (binname, dirname);
	      if (c.usemacos)
		grub_strcpy (binname + grub_strlen (binname), "/MacOS/");
	      else
		grub_strcpy (binname + grub_strlen (binname), "/");
	      grub_strcpy (binname + grub_strlen (binname), binsuffix);
	      grub_dprintf ("xnu", "%s:%s\n", c.plistname, binname);
	      binfile = grub_gzfile_open (binname, 1);
	      if (! binfile)
		grub_errno = GRUB_ERR_NONE;

	      /* Load the extension. */
	      grub_xnu_load_driver (c.plistname, binfile);
	      grub_free (binname);
	      grub_free (binsuffix);
	    }
	  else
	    {
	      grub_dprintf ("xnu", "%s:0\n", c.plistname);
	      grub_xnu_load_driver (c.plistname, 0);
	    }
	}
      grub_free (c.plistname);
      grub_device_close (dev);
    }
  grub_free (device_name);

  return GRUB_ERR_NONE;
}
Exemplo n.º 8
0
static grub_err_t
grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
	      int argc, char **args)
{
  grub_ssize_t rd1, rd2;
  grub_off_t pos;
  grub_file_t file1 = 0;
  grub_file_t file2 = 0;
  char *buf1 = 0;
  char *buf2 = 0;

  if (argc != 2)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");

  grub_printf ("Compare file `%s' with `%s':\n", args[0],
	       args[1]);

  file1 = grub_gzfile_open (args[0], 1);
  file2 = grub_gzfile_open (args[1], 1);
  if (! file1 || ! file2)
    goto cleanup;

  if (grub_file_size (file1) != grub_file_size (file2))
    grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n",
		 (unsigned long long) grub_file_size (file1), args[0],
		 (unsigned long long) grub_file_size (file2), args[1]);
  else
    {
      pos = 0;

      buf1 = grub_malloc (BUFFER_SIZE);
      buf2 = grub_malloc (BUFFER_SIZE);

      if (! buf1 || ! buf2)
        goto cleanup;

      do
	{
	  int i;

	  rd1 = grub_file_read (file1, buf1, BUFFER_SIZE);
	  rd2 = grub_file_read (file2, buf2, BUFFER_SIZE);

	  if (rd1 != rd2)
	    goto cleanup;

	  for (i = 0; i < rd2; i++)
	    {
	      if (buf1[i] != buf2[i])
		{
		  grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
			       (unsigned long long) (i + pos), buf1[i], args[0],
			       buf2[i], args[1]);
		  goto cleanup;
		}
	    }
	  pos += BUFFER_SIZE;

	}
      while (rd2);

      grub_printf ("The files are identical.\n");
    }

cleanup:

  if (buf1)
    grub_free (buf1);
  if (buf2)
    grub_free (buf2);
  if (file1)
    grub_file_close (file1);
  if (file2)
    grub_file_close (file2);

  return grub_errno;
}
Exemplo n.º 9
0
void
grub_module2 (int argc, char *argv[])
{
  grub_file_t file;
  grub_addr_t modaddr = 0;
  grub_ssize_t modsize = 0;
  grub_err_t err;

  if (argc == 0)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
      return;
    }

  if (argc == 1)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module type specified");
      return;
    }

  if (entry == 0)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT,
		  "You need to load the multiboot kernel first");
      return;
    }

  /* Load module data.  */
  file = grub_gzfile_open (argv[0], 1);
  if (! file)
    goto out;

  modsize = grub_file_size (file);
  err = grub_mb2_arch_module_alloc (modsize, &modaddr);
  if (err)
    goto out;

  grub_dprintf ("loader", "Loading module at 0x%x - 0x%x\n", modaddr,
		modaddr + modsize);
  if (grub_file_read (file, (char *) modaddr, modsize) != modsize)
    {
      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
      goto out;
    }

  /* Create the module tag.  */
  err = grub_mb2_tag_module_create (modaddr, modsize,
				   argv[1], MULTIBOOT2_TAG_MODULE,
				   argc-2, &argv[2]);
  if (err)
    goto out;

out:
  grub_error_push ();

  if (file)
    grub_file_close (file);

  if (modaddr)
    grub_mb2_arch_module_free (modaddr, modsize);

  grub_error_pop ();
}
Exemplo n.º 10
0
void
grub_multiboot2 (int argc, char *argv[])
{
  char *buffer;
  grub_file_t file = 0;
  grub_elf_t elf = 0;
  struct multiboot_header *header = 0;
  char *p;
  grub_ssize_t len;
  grub_err_t err;
  int header_found = 0;

  grub_loader_unset ();

  if (argc == 0)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
      goto fail;
    }

  file = grub_gzfile_open (argv[0], 1);
  if (! file)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
      goto fail;
    }

  buffer = grub_malloc (MULTIBOOT2_HEADER_SEARCH);
  if (! buffer)
    return;

  len = grub_file_read (file, buffer, MULTIBOOT2_HEADER_SEARCH);
  if (len < 32)
    {
      grub_error (GRUB_ERR_BAD_OS, "File too small");
      goto fail;
    }

  /* Look for the multiboot header in the buffer.  The header should
     be at least 8 bytes and aligned on a 8-byte boundary.  */
  for (p = buffer; p <= buffer + len - 8; p += 8)
    {
      header = (struct multiboot_header *) p;
      if (header->magic == MULTIBOOT2_HEADER_MAGIC)
	{
	  header_found = 1;
	  break;
	}
    }

  if (! header_found)
    grub_dprintf ("loader", "No multiboot 2 header found.\n");


  /* Create the basic tags.  */
  grub_dprintf ("loader", "Creating multiboot 2 tags\n");
  grub_mb2_tags_create ();

  /* Load the kernel and create its tag.  */
  elf = grub_elf_file (file);
  if (elf)
    {
      grub_dprintf ("loader", "Loading ELF multiboot 2 file.\n");
      err = grub_mb2_load_elf (elf, argc-1, &argv[1]);
      grub_elf_close (elf);
    }
  else
    {
      grub_errno = 0;
      grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");

      if (header)
	err = grub_mb2_load_other (file, header);
      else
	err = grub_error (GRUB_ERR_BAD_OS,
			  "Need multiboot 2 header to load non-ELF files.");
      grub_file_close (file);
    }

  grub_free (buffer);

  if (err)
    goto fail;

  /* Good to go.  */
  grub_loader_set (grub_mb2_boot, grub_mb2_unload, 1);
  return;

fail:
  grub_mb2_tags_free ();
  grub_dl_unref (my_mod);
}