Beispiel #1
0
grub_err_t
SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest)
{
  grub_ssize_t read;
  if (! SUFFIX (grub_macho_contains_macho) (macho))
    return grub_error (GRUB_ERR_BAD_OS,
		       "couldn't read architecture-specific part");

  if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1)
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS,
			 "invalid offset in program header");
    }

  read = grub_file_read (macho->file, dest,
			 macho->endXX - macho->offsetXX);
  if (read != (grub_ssize_t) (macho->endXX - macho->offsetXX))
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_BAD_OS,
			 "couldn't read architecture-specific part");
    }
  return GRUB_ERR_NONE;
}
Beispiel #2
0
/* Load every loadable segment into memory specified by `_load_hook'.  */
grub_err_t
grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
		 grub_addr_t *base, grub_size_t *size)
{
  grub_addr_t load_base = (grub_addr_t) -1ULL;
  grub_size_t load_size = 0;
  grub_err_t err;

  auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook);
  int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook)
  {
    grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook;
    grub_addr_t load_addr;
    int do_load = 1;

    load_addr = phdr->p_paddr;
    if (load_hook && load_hook (phdr, &load_addr, &do_load))
      return 1;

    if (! do_load)
      return 0;

    if (load_addr < load_base)
      load_base = load_addr;

    grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
		  (unsigned long long) load_addr,
		  (unsigned long long) phdr->p_memsz);

    if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
      {
	grub_error_push ();
	return grub_error (GRUB_ERR_BAD_OS,
			   "invalid offset in program header");
      }

    if (phdr->p_filesz)
      {
	grub_ssize_t read;
	read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
	if (read != (grub_ssize_t) phdr->p_filesz)
	  {
	    /* XXX How can we free memory from `load_hook'? */
	    grub_error_push ();
	    return grub_error (GRUB_ERR_BAD_OS,
			       "couldn't read segment from file: "
			       "wanted 0x%lx bytes; read 0x%lx bytes",
			       phdr->p_filesz, read);
	  }
      }

    if (phdr->p_filesz < phdr->p_memsz)
      grub_memset ((void *) (long) (load_addr + phdr->p_filesz),
		   0, phdr->p_memsz - phdr->p_filesz);

    load_size += phdr->p_memsz;

    return 0;
  }
Beispiel #3
0
/* Return the current timeout. If the variable "timeout" is not set or
   invalid, return -1.  */
int
grub_menu_get_timeout (void)
{
  const char *val;
  int timeout;

  val = grub_env_get ("timeout");
  if (! val)
    return -1;

  grub_error_push ();

  timeout = (int) grub_strtoul (val, 0, 0);

  /* If the value is invalid, unset the variable.  */
  if (grub_errno != GRUB_ERR_NONE)
    {
      grub_env_unset ("timeout");
      grub_errno = GRUB_ERR_NONE;
      timeout = -1;
    }

  grub_error_pop ();

  return timeout;
}
Beispiel #4
0
grub_elf_t
grub_elf_file (grub_file_t file)
{
  grub_elf_t elf;

  elf = grub_zalloc (sizeof (*elf));
  if (! elf)
    return 0;

  elf->file = file;

  if (grub_file_seek (elf->file, 0) == (grub_off_t) -1)
    goto fail;

  if (grub_file_read (elf->file, &elf->ehdr, sizeof (elf->ehdr))
      != sizeof (elf->ehdr))
    {
      grub_error_push ();
      grub_error (GRUB_ERR_READ_ERROR, "cannot read ELF header");
      goto fail;
    }

  if (grub_elf_check_header (elf))
    goto fail;

  return elf;

fail:
  grub_free (elf->phdrs);
  grub_free (elf);
  return 0;
}
Beispiel #5
0
/* Get the first entry number from the value of the environment variable NAME,
   which is a space-separated list of non-negative integers.  The entry number
   which is returned is stripped from the value of NAME.  If no entry number
   can be found, -1 is returned.  */
static int
get_and_remove_first_entry_number (const char *name)
{
  const char *val;
  char *tail;
  int entry;

  val = grub_env_get (name);
  if (! val)
    return -1;

  grub_error_push ();

  entry = (int) grub_strtoul (val, &tail, 0);

  if (grub_errno == GRUB_ERR_NONE)
    {
      /* Skip whitespace to find the next digit.  */
      while (*tail && grub_isspace (*tail))
	tail++;
      grub_env_set (name, tail);
    }
  else
    {
      grub_env_unset (name);
      grub_errno = GRUB_ERR_NONE;
      entry = -1;
    }

  grub_error_pop ();

  return entry;
}
Beispiel #6
0
static int
grub_macho_load_do_load (grub_macho_t _macho,
			 struct grub_macho_cmd *hdr0,
			 void *closure)
{
  struct grub_macho_load_closure *c = closure;
  grub_macho_segment_t *hdr = (grub_macho_segment_t *) hdr0;

  if (hdr->cmd != GRUB_MACHO_CMD_SEGMENT)
    return 0;

  if (! hdr->filesize && (c->flags & GRUB_MACHO_NOBSS))
    return 0;
  if (! hdr->vmsize)
    return 0;

  if (grub_file_seek (_macho->file, hdr->fileoff
		      + _macho->offsetXX) == (grub_off_t) -1)
    {
      grub_error_push ();
      grub_error (GRUB_ERR_BAD_OS,
		  "invalid offset in program header");
      return 1;
    }

  if (hdr->filesize)
    {
      grub_ssize_t read;
      read = grub_file_read (_macho->file, c->offset + hdr->vmaddr,
			     min (hdr->filesize, hdr->vmsize));
      if (read != (grub_ssize_t) min (hdr->filesize, hdr->vmsize))
	{
	  /* XXX How can we free memory from `load_hook'? */
	  grub_error_push ();
	  c->err = grub_error (GRUB_ERR_BAD_OS,
			       "couldn't read segment from file: "
			       "wanted 0x%lx bytes; read 0x%lx bytes",
			       hdr->filesize, read);
	  return 1;
	}
    }

  if (hdr->filesize < hdr->vmsize)
    grub_memset (c->offset + hdr->vmaddr + hdr->filesize,
		 0, hdr->vmsize - hdr->filesize);
  return 0;
}
Beispiel #7
0
/* Get the entry number from the variable NAME.  */
static int
get_entry_number (grub_menu_t menu, const char *name)
{
  const char *val;
  int entry;

  val = grub_env_get (name);
  if (! val)
    return -1;

  grub_error_push ();

  entry = (int) grub_strtoul (val, 0, 0);

  if (grub_errno == GRUB_ERR_BAD_NUMBER)
    {
      /* See if the variable matches the title of a menu entry.  */
      grub_menu_entry_t e = menu->entry_list;
      int i;

      grub_errno = GRUB_ERR_NONE;

      for (i = 0; e; i++)
	{
	  if (menuentry_eq (e->title, val)
	      || menuentry_eq (e->id, val))
	    {
	      entry = i;
	      break;
	    }
	  e = e->next;
	}

      if (! e)
	entry = -1;
    }

  if (grub_errno != GRUB_ERR_NONE)
    {
      grub_errno = GRUB_ERR_NONE;
      entry = -1;
    }

  grub_error_pop ();

  return entry;
}
Beispiel #8
0
static grub_err_t
grub_mb2_tags_create (void)
{
  tag_create_t *creator;
  grub_err_t err;

  for (creator = grub_mb2_tag_creators; *creator != 0; creator++)
    {
      err = (*creator) ();
      if (err)
	goto error;
    }

  return GRUB_ERR_NONE;

error:
  grub_error_push ();
  grub_mb2_tags_free ();
  grub_error_pop ();
  return err;
}
Beispiel #9
0
static grub_err_t
scale_pixmap (grub_gfxmenu_box_t self, int i, int w, int h)
{
  struct grub_video_bitmap **scaled = &self->scaled_pixmaps[i];
  struct grub_video_bitmap *raw = self->raw_pixmaps[i];

  if (raw == 0)
    return grub_errno;

  if (w == -1)
    w = grub_video_bitmap_get_width (raw);
  if (h == -1)
    h = grub_video_bitmap_get_height (raw);

  if (*scaled == 0
      || ((int) grub_video_bitmap_get_width (*scaled) != w)
      || ((int) grub_video_bitmap_get_height (*scaled) != h))
    {
      if (*scaled)
        {
          grub_video_bitmap_destroy (*scaled);
          *scaled = 0;
        }

      /* Don't try to create a bitmap with a zero dimension.  */
      if (w != 0 && h != 0)
        grub_video_bitmap_create_scaled (scaled, w, h, raw,
                                         GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
      if (grub_errno != GRUB_ERR_NONE)
        {
          grub_error_push ();
          grub_error (grub_errno,
                      "failed to scale bitmap for styled box pixmap #%d", i);
        }
    }

  return grub_errno;
}
Beispiel #10
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);
}
Beispiel #11
0
static grub_err_t
grub_mb2_tags_finish (void)
{
  struct multiboot_tag_start *start;
  grub_err_t err;

  /* Create the `end' tag.  */
  err = grub_mb2_tag_alloc (0, MULTIBOOT2_TAG_END,
			   sizeof (struct multiboot_tag_end));
  if (err)
    goto error;

  /* We created the `start' tag first.  Update it now.  */
  start = (struct multiboot_tag_start *) grub_mb2_tags;
  start->size = grub_mb2_tags_pos - grub_mb2_tags;
  return GRUB_ERR_NONE;

error:
  grub_error_push ();
  grub_mb2_tags_free ();
  grub_error_pop ();
  return err;
}
Beispiel #12
0
static grub_err_t
grub_elf32_load_phdrs (grub_elf_t elf)
{
  grub_ssize_t phdrs_size;

  phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize;

  grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
		(unsigned long long) elf->ehdr.ehdr32.e_phoff,
		(unsigned long) phdrs_size);

  elf->phdrs = grub_malloc (phdrs_size);
  if (! elf->phdrs)
    return grub_errno;

  if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1)
      || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
    {
      grub_error_push ();
      return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers");
    }

  return GRUB_ERR_NONE;
}
Beispiel #13
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 ();
}
Beispiel #14
0
grub_fs_t
grub_fs_probe (grub_device_t device)
{
  grub_fs_t p;

  if (device->disk)
    {
      /* Make it sure not to have an infinite recursive calls.  */
      static int count = 0;

      for (p = grub_fs_list; p; p = p->next)
	{
	  grub_dprintf ("fs", "Detecting %s...\n", p->name);
	  (p->dir) (device, "/", dummy_func, 0);
	  if (grub_errno == GRUB_ERR_NONE)
	    return p;

	  grub_error_push ();
	  grub_dprintf ("fs", "%s detection failed.\n", p->name);
	  grub_error_pop ();

	  if (grub_errno != GRUB_ERR_BAD_FS)
	    return 0;

	  grub_errno = GRUB_ERR_NONE;
	}

      /* Let's load modules automatically.  */
      if (grub_fs_autoload_hook && count == 0)
	{
	  count++;

	  while (grub_fs_autoload_hook ())
	    {
	      p = grub_fs_list;

	      (p->dir) (device, "/", dummy_func, 0);
	      if (grub_errno == GRUB_ERR_NONE)
		{
		  count--;
		  return p;
		}

	      if (grub_errno != GRUB_ERR_BAD_FS)
		{
		  count--;
		  return 0;
		}

	      grub_errno = GRUB_ERR_NONE;
	    }

	  count--;
	}
    }
  else if (device->net->fs)
    return device->net->fs;

  grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
  return 0;
}
Beispiel #15
0
static const char *
grub_gettext_translate (const char *orig)
{
  char *current_string;
  const char *ret;

  int min, max, current;
  int found = 0;

  struct grub_gettext_msg *cur;

  /* Make sure we can use grub_gettext_translate for error messages.  Push
     active error message to error stack and reset error message.  */
  grub_error_push ();

  cur = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_gettext_msg_list),
			      orig);

  if (cur)
    {
      grub_error_pop ();
      return cur->translated;
    }

  if (fd_mo == 0)
    {
      grub_error_pop ();
      return orig;
    }

  min = 0;
  max = grub_gettext_max;

  current = (max + min) / 2;

  while (current != min && current != max && found == 0)
    {
      current_string = grub_gettext_getstring_from_position (current);

      /* Search by bisection.  */
      if (grub_strcmp (current_string, orig) < 0)
	{
	  grub_free (current_string);
	  min = current;
	}
      else if (grub_strcmp (current_string, orig) > 0)
	{
	  grub_free (current_string);
	  max = current;
	}
      else if (grub_strcmp (current_string, orig) == 0)
	{
	  grub_free (current_string);
	  found = 1;
	}
      current = (max + min) / 2;
    }

  ret = found ? grub_gettext_gettranslation_from_position (current) : orig;

  if (found)
    {
      cur = grub_zalloc (sizeof (*cur));

      if (cur)
	{
	  cur->name = grub_strdup (orig);
	  if (cur->name)
	    {
	      cur->translated = ret;
	      grub_list_push (GRUB_AS_LIST_P (&grub_gettext_msg_list),
			      GRUB_AS_LIST (cur));
	    }
	}
      else
	grub_errno = GRUB_ERR_NONE;
    }

  grub_error_pop ();
  return ret;
}
Beispiel #16
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;
}
Beispiel #17
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);
}
Beispiel #18
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);
}
Beispiel #19
0
/* FIXME: Previously 't' changed to text menu is it necessary?  */
static grub_err_t
grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
{
  grub_gfxmenu_view_t view = NULL;
  const char *theme_path;
  struct grub_menu_viewer *instance;
  grub_err_t err;
  struct grub_video_mode_info mode_info;

  theme_path = grub_env_get ("theme");
  if (! theme_path)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified");
    }

  instance = grub_zalloc (sizeof (*instance));
  if (!instance)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_errno;
    }

  err = grub_video_get_info (&mode_info);
  if (err)
    {
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return err;
    }

  if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0
      || cached_view->screen.width != mode_info.width
      || cached_view->screen.height != mode_info.height)
    {
      grub_free (cached_view);
      /* Create the view.  */
      cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width,
					   mode_info.height);
    }

  if (! cached_view)
    {
      grub_free (instance);
      grub_error_push ();
      grub_gfxterm_fullscreen ();
      grub_error_pop ();
      return grub_errno;
    }

  view = cached_view;

  view->double_repaint = (mode_info.mode_type
			  & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)
    && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
  view->selected = entry;
  view->menu = menu;
  view->nested = nested;
  view->first_timeout = -1;

  grub_gfxmenu_view_draw (view);

  instance->data = view;
  instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry;
  instance->fini = grub_gfxmenu_viewer_fini;
  instance->print_timeout = grub_gfxmenu_print_timeout;
  instance->clear_timeout = grub_gfxmenu_clear_timeout;

  grub_menu_register_viewer (instance);

  return GRUB_ERR_NONE;
}
Beispiel #20
0
/* Get a glyph corresponding to the codepoint CODE.  Always fill glyph
   information with something, even if no glyph is found.  */
int
grub_font_get_glyph (grub_uint32_t code,
                     grub_font_glyph_t glyph)
{
    struct font *font;
    grub_uint8_t bitmap[32];

    /* FIXME: It is necessary to cache glyphs!  */

restart:
    for (font = font_list; font; font = font->next)
    {
        grub_uint32_t offset;

        offset = find_glyph (font, code);
        if (offset)
        {
            grub_uint32_t w;
            int len;

            /* Make sure we can find glyphs for error messages.  Push active
               error message to error stack and reset error message.  */
            grub_error_push ();

            grub_file_seek (font->file, offset);
            if ((len = grub_file_read (font->file, (char *) &w, sizeof (w)))
                    != sizeof (w))
            {
                remove_font (font);
                goto restart;
            }

            w = grub_le_to_cpu32 (w);
            if (w != 1 && w != 2)
            {
                /* grub_error (GRUB_ERR_BAD_FONT, "invalid width"); */
                remove_font (font);
                goto restart;
            }

            if (grub_file_read (font->file, (char *) bitmap, w * 16)
                    != (grub_ssize_t) w * 16)
            {
                remove_font (font);
                goto restart;
            }

            /* Fill glyph with information.  */
            grub_memcpy (glyph->bitmap, bitmap, w * 16);

            glyph->char_width = w;
            glyph->width = glyph->char_width * 8;
            glyph->height = 16;
            glyph->baseline = (16 * 3) / 4;

            /* Restore old error message.  */
            grub_error_pop ();

            return 1;
        }
    }

    /* Uggh...  No font was found.  */
    fill_with_default_glyph (glyph);
    return 0;
}
Beispiel #21
0
/* Get a glyph for the Unicode character CODE in FONT.  The glyph is loaded
   from the font file if has not been loaded yet.
   Returns a pointer to the glyph if found, or 0 if it is not found.  */
static struct grub_font_glyph *
grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
{
  struct char_index_entry *index_entry;

  index_entry = find_glyph (font, code);
  if (index_entry)
    {
      struct grub_font_glyph *glyph = 0;
      grub_uint16_t width;
      grub_uint16_t height;
      grub_int16_t xoff;
      grub_int16_t yoff;
      grub_int16_t dwidth;
      int len;

      if (index_entry->glyph)
	/* Return cached glyph.  */
	return index_entry->glyph;

      if (!font->file)
	/* No open file, can't load any glyphs.  */
	return 0;

      /* Make sure we can find glyphs for error messages.  Push active
         error message to error stack and reset error message.  */
      grub_error_push ();

      grub_file_seek (font->file, index_entry->offset);

      /* Read the glyph width, height, and baseline.  */
      if (read_be_uint16 (font->file, &width) != 0
	  || read_be_uint16 (font->file, &height) != 0
	  || read_be_int16 (font->file, &xoff) != 0
	  || read_be_int16 (font->file, &yoff) != 0
	  || read_be_int16 (font->file, &dwidth) != 0)
	{
	  remove_font (font);
	  return 0;
	}

      len = (width * height + 7) / 8;
      glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
      if (!glyph)
	{
	  remove_font (font);
	  return 0;
	}

      glyph->font = font;
      glyph->width = width;
      glyph->height = height;
      glyph->offset_x = xoff;
      glyph->offset_y = yoff;
      glyph->device_width = dwidth;

      /* Don't try to read empty bitmaps (e.g., space characters).  */
      if (len != 0)
	{
	  if (grub_file_read (font->file, glyph->bitmap, len) != len)
	    {
	      remove_font (font);
	      return 0;
	    }
	}

      /* Restore old error message.  */
      grub_error_pop ();

      /* Cache the glyph.  */
      index_entry->glyph = glyph;

      return glyph;
    }

  return 0;
}
Beispiel #22
0
static const char *
grub_gettext_translate_real (struct grub_gettext_context *ctx,
			     const char *orig)
{
  grub_size_t current = 0;
  int i;
  const char *current_string;
  static int depth = 0;

  if (!ctx->grub_gettext_msg_list || !ctx->fd_mo)
    return NULL;

  /* Shouldn't happen. Just a precaution if our own code
     calls gettext somehow.  */
  if (depth > 2)
    return NULL;
  depth++;

  /* Make sure we can use grub_gettext_translate for error messages.  Push
     active error message to error stack and reset error message.  */
  grub_error_push ();

  for (i = ctx->grub_gettext_max_log; i >= 0; i--)
    {
      grub_size_t test;
      int cmp;

      test = current | (1 << i);
      if (test >= ctx->grub_gettext_max)
	continue;

      current_string = grub_gettext_getstring_from_position (ctx, test);

      if (!current_string)
	{
	  grub_errno = GRUB_ERR_NONE;
	  grub_error_pop ();
	  depth--;
	  return NULL;
	}

      /* Search by bisection.  */
      cmp = grub_strcmp (current_string, orig);
      if (cmp <= 0)
	current = test;
      if (cmp == 0)
	{
	  const char *ret = 0;
	  ret = grub_gettext_gettranslation_from_position (ctx, current);
	  if (!ret)
	    {
	      grub_errno = GRUB_ERR_NONE;
	      grub_error_pop ();
	      depth--;
	      return NULL;
	    }
	  grub_error_pop ();
	  depth--;
	  return ret;      
	}
    }

  if (current == 0 && ctx->grub_gettext_max != 0)
    {
      current_string = grub_gettext_getstring_from_position (ctx, 0);

      if (!current_string)
	{
	  grub_errno = GRUB_ERR_NONE;
	  grub_error_pop ();
	  depth--;
	  return NULL;
	}

      if (grub_strcmp (current_string, orig) == 0)
	{
	  const char *ret = 0;
	  ret = grub_gettext_gettranslation_from_position (ctx, current);
	  if (!ret)
	    {
	      grub_errno = GRUB_ERR_NONE;
	      grub_error_pop ();
	      depth--;
	      return NULL;
	    }
	  grub_error_pop ();
	  depth--;
	  return ret;      
	}
    }

  grub_error_pop ();
  depth--;
  return NULL;
}