예제 #1
0
파일: xnu.c 프로젝트: Firef0x/burg-original
/* Load a directory containing kexts. */
static grub_err_t
grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)),
		      int argc, char *args[])
{
  if (argc != 1 && argc != 2)
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "directory name required");

  if (argc == 1)
    return grub_xnu_scan_dir_for_kexts (args[0],
					"console,root,local-root,network-root",
					10);
  else
    {
      char *osbundlerequired = grub_strdup (args[1]), *ptr;
      grub_err_t err;
      if (! osbundlerequired)
	return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			   "couldn't allocate string temporary space");
      for (ptr = osbundlerequired; *ptr; ptr++)
	*ptr = grub_tolower (*ptr);
      err = grub_xnu_scan_dir_for_kexts (args[0], osbundlerequired, 10);
      grub_free (osbundlerequired);
      return err;
    }
}
예제 #2
0
파일: bitsutil.c 프로젝트: mfleming/bits
grub_err_t strtou64_h(const char *str, U64 * value_ret)
{
    U64 value;
    int base = 0;
    char *end;
    const char *last = str + grub_strlen(str) - 1;
    if (last < str)
        return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number");
    if (grub_tolower(*last) == 'h') {
        base = 16;
        last--;
        if (last < str)
            return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number");
    }
    value = grub_strtoull(str, &end, base);
    if (grub_errno != GRUB_ERR_NONE || end != (last + 1)) {
        return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number");
    } else {
        *value_ret = value;
        return GRUB_ERR_NONE;
    }
}
예제 #3
0
파일: xnu.c 프로젝트: Firef0x/burg-original
/* 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;
}
예제 #4
0
파일: misc.c 프로젝트: Firef0x/burg-new
unsigned long long
grub_strtoull (const char *str, char **end, int base)
{
  unsigned long long num = 0;
  int found = 0;

  /* Skip white spaces.  */
  while (*str && grub_isspace (*str))
    str++;

  /* Guess the base, if not specified. The prefix `0x' means 16, and
     the prefix `0' means 8.  */
  if (str[0] == '0')
    {
      if (str[1] == 'x')
	{
	  if (base == 0 || base == 16)
	    {
	      base = 16;
	      str += 2;
	    }
	}
      else if (base == 0 && str[1] >= '0' && str[1] <= '7')
	base = 8;
    }

  if (base == 0)
    base = 10;

  while (*str)
    {
      unsigned long digit;

      digit = grub_tolower (*str) - '0';
      if (digit > 9)
	{
	  digit += '0' - 'a' + 10;
	  if (digit >= (unsigned long) base)
	    break;
	}

      found = 1;

      /* NUM * BASE + DIGIT > ~0ULL */
      if (num > grub_divmod64 (~0ULL - digit, base, 0))
	{
	  grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
	  return ~0ULL;
	}

      num = num * base + digit;
      str++;
    }

  if (! found)
    {
      grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
      return 0;
    }

  if (end)
    *end = (char *) str;

  return num;
}
예제 #5
0
파일: acpi.c 프로젝트: jnbek/grub2-fedora
static grub_err_t
grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
{
  struct grub_arg_list *state = ctxt->state;
  struct grub_acpi_rsdp_v10 *rsdp;
  struct efiemu_acpi_table *cur, *t;
  int i, mmapregion;
  int numoftables;

  /* Default values if no RSDP is found. */
  rev1 = 1;
  rev2 = 3;

  facs_addr = 0;
  playground = playground_ptr = 0;
  playground_size = 0;

  rsdp = (struct grub_acpi_rsdp_v10 *) grub_machine_acpi_get_rsdpv2 ();

  if (! rsdp)
    rsdp = grub_machine_acpi_get_rsdpv1 ();

  if (rsdp)
    {
      grub_uint32_t *entry_ptr;
      char *exclude = 0;
      char *load_only = 0;
      char *ptr;
      /* RSDT consists of header and an array of 32-bit pointers. */
      struct grub_acpi_table_header *rsdt;

      exclude = state[0].set ? grub_strdup (state[0].arg) : 0;
      if (exclude)
	{
	  for (ptr = exclude; *ptr; ptr++)
	    *ptr = grub_tolower (*ptr);
	}

      load_only = state[1].set ? grub_strdup (state[1].arg) : 0;
      if (load_only)
	{
	  for (ptr = load_only; *ptr; ptr++)
	    *ptr = grub_tolower (*ptr);
	}

      /* Set revision variables to replicate the same version as host. */
      rev1 = ! rsdp->revision;
      rev2 = rsdp->revision;
      rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr;
      /* Load host tables. */
      for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
	   entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
					  + rsdt->length);
	   entry_ptr++)
	{
	  char signature[5];
	  struct efiemu_acpi_table *table;
	  struct grub_acpi_table_header *curtable
	    = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr;
	  signature[4] = 0;
	  for (i = 0; i < 4;i++)
	    signature[i] = grub_tolower (curtable->signature[i]);

	  /* If it's FADT it contains addresses of DSDT and FACS. */
	  if (grub_strcmp (signature, "facp") == 0)
	    {
	      struct grub_acpi_table_header *dsdt;
	      struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable;

	      /* Set root header variables to the same values
		 as FADT by default. */
	      grub_memcpy (&root_oemid, &(fadt->hdr.oemid),
			   sizeof (root_oemid));
	      grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable),
			   sizeof (root_oemtable));
	      root_oemrev = fadt->hdr.oemrev;
	      grub_memcpy (&root_creator_id, &(fadt->hdr.creator_id),
			   sizeof (root_creator_id));
	      root_creator_rev = fadt->hdr.creator_rev;

	      /* Load DSDT if not excluded. */
	      dsdt = (struct grub_acpi_table_header *)
		(grub_addr_t) fadt->dsdt_addr;
	      if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
		  && (! load_only || grub_strword (load_only, "dsdt"))
		  && dsdt->length >= sizeof (*dsdt))
		{
		  dsdt_size = dsdt->length;
		  table_dsdt = grub_malloc (dsdt->length);
		  if (! table_dsdt)
		    {
		      free_tables ();
		      grub_free (exclude);
		      grub_free (load_only);
		      return grub_errno;
		    }
		  grub_memcpy (table_dsdt, dsdt, dsdt->length);
		}

	      /* Save FACS address. FACS shouldn't be overridden. */
	      facs_addr = fadt->facs_addr;
	    }

	  /* Skip excluded tables. */
	  if (exclude && grub_strword (exclude, signature))
	    continue;
	  if (load_only && ! grub_strword (load_only, signature))
	    continue;

	  /* Sanity check. */
	  if (curtable->length < sizeof (*curtable))
	    continue;

	  table = (struct efiemu_acpi_table *) grub_malloc
	    (sizeof (struct efiemu_acpi_table));
	  if (! table)
	    {
	      free_tables ();
	      grub_free (exclude);
	      grub_free (load_only);
	      return grub_errno;
	    }
	  table->size = curtable->length;
	  table->addr = grub_malloc (table->size);
	  playground_size += table->size;
	  if (! table->addr)
	    {
	      free_tables ();
	      return grub_errno;
	    }
	  table->next = acpi_tables;
	  acpi_tables = table;
	  grub_memcpy (table->addr, curtable, table->size);
	}
      grub_free (exclude);
      grub_free (load_only);
    }

  /* Does user specify versions to generate? */
  if (state[2].set || state[3].set)
    {
      rev1 = state[2].set;
      if (state[3].set)
	rev2 = rev2 ? : 2;
      else
예제 #6
0
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
			  grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
  struct grub_iso9660_dir dirent;
  grub_off_t offset = 0;
  grub_off_t len;
  struct iterate_dir_ctx ctx;

  len = get_node_size (dir);

  for (; offset < len; offset += dirent.len)
    {
      ctx.symlink = 0;
      ctx.was_continue = 0;

      if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
	return 0;

      /* The end of the block, skip to the next one.  */
      if (!dirent.len)
	{
	  offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ;
	  continue;
	}

      {
	char name[MAX_NAMELEN + 1];
	int nameoffset = offset + sizeof (dirent);
	struct grub_fshelp_node *node;
	int sua_off = (sizeof (dirent) + dirent.namelen + 1
		       - (dirent.namelen % 2));
	int sua_size = dirent.len - sua_off;

	sua_off += offset + dir->data->susp_skip;

	ctx.filename = 0;
	ctx.filename_alloc = 0;
	ctx.type = GRUB_FSHELP_UNKNOWN;

	if (dir->data->rockridge
	    && grub_iso9660_susp_iterate (dir, sua_off, sua_size,
					  susp_iterate_dir, &ctx))
	  return 0;

	/* Read the name.  */
	if (read_node (dir, nameoffset, dirent.namelen, (char *) name))
	  return 0;

	node = grub_malloc (sizeof (struct grub_fshelp_node));
	if (!node)
	  return 0;

	node->alloc_dirents = ARRAY_SIZE (node->dirents);
	node->have_dirents = 1;

	/* Setup a new node.  */
	node->data = dir->data;
	node->have_symlink = 0;

	/* If the filetype was not stored using rockridge, use
	   whatever is stored in the iso9660 filesystem.  */
	if (ctx.type == GRUB_FSHELP_UNKNOWN)
	  {
	    if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
	      ctx.type = GRUB_FSHELP_DIR;
	    else
	      ctx.type = GRUB_FSHELP_REG;
	  }

	/* . and .. */
	if (!ctx.filename && dirent.namelen == 1 && name[0] == 0)
	  ctx.filename = (char *) ".";

	if (!ctx.filename && dirent.namelen == 1 && name[0] == 1)
	  ctx.filename = (char *) "..";

	/* The filename was not stored in a rock ridge entry.  Read it
	   from the iso9660 filesystem.  */
	if (!dir->data->joliet && !ctx.filename)
	  {
	    char *ptr;
	    name[dirent.namelen] = '\0';
	    ctx.filename = grub_strrchr (name, ';');
	    if (ctx.filename)
	      *ctx.filename = '\0';
	    /* ISO9660 names are not case-preserving.  */
	    ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE;
	    for (ptr = name; *ptr; ptr++)
	      *ptr = grub_tolower (*ptr);
	    if (ptr != name && *(ptr - 1) == '.')
	      *(ptr - 1) = 0;
	    ctx.filename = name;
	  }

        if (dir->data->joliet && !ctx.filename)
          {
            char *semicolon;

            ctx.filename = grub_iso9660_convert_string
                  ((grub_uint8_t *) name, dirent.namelen >> 1);

	    semicolon = grub_strrchr (ctx.filename, ';');
	    if (semicolon)
	      *semicolon = '\0';

            ctx.filename_alloc = 1;
          }

	node->dirents[0] = dirent;
	while (dirent.flags & FLAG_MORE_EXTENTS)
	  {
	    offset += dirent.len;
	    if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
	      {
		if (ctx.filename_alloc)
		  grub_free (ctx.filename);
		grub_free (node);
		return 0;
	      }
	    if (node->have_dirents >= node->alloc_dirents)
	      {
		struct grub_fshelp_node *new_node;
		node->alloc_dirents *= 2;
		new_node = grub_realloc (node, 
					 sizeof (struct grub_fshelp_node)
					 + ((node->alloc_dirents
					     - ARRAY_SIZE (node->dirents))
					    * sizeof (node->dirents[0])));
		if (!new_node)
		  {
		    if (ctx.filename_alloc)
		      grub_free (ctx.filename);
		    grub_free (node);
		    return 0;
		  }
		node = new_node;
	      }
	    node->dirents[node->have_dirents++] = dirent;
	  }
	if (ctx.symlink)
	  {
	    if ((node->alloc_dirents - node->have_dirents)
		* sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1)
	      {
		struct grub_fshelp_node *new_node;
		new_node = grub_realloc (node,
					 sizeof (struct grub_fshelp_node)
					 + ((node->alloc_dirents
					     - ARRAY_SIZE (node->dirents))
					    * sizeof (node->dirents[0]))
					 + grub_strlen (ctx.symlink) + 1);
		if (!new_node)
		  {
		    if (ctx.filename_alloc)
		      grub_free (ctx.filename);
		    grub_free (node);
		    return 0;
		  }
		node = new_node;
	      }
	    node->have_symlink = 1;
	    grub_strcpy (node->symlink
			 + node->have_dirents * sizeof (node->dirents[0])
			 - sizeof (node->dirents), ctx.symlink);
	    grub_free (ctx.symlink);
	    ctx.symlink = 0;
	    ctx.was_continue = 0;
	  }
	if (hook (ctx.filename, ctx.type, node, hook_data))
	  {
	    if (ctx.filename_alloc)
	      grub_free (ctx.filename);
	    return 1;
	  }
	if (ctx.filename_alloc)
	  grub_free (ctx.filename);
      }
    }
예제 #7
0
int
uefi_dir (char *dirname)
{
    grub_efi_status_t status;
    grub_efi_char16_t *file_name_w = NULL;
    grub_efi_char16_t *dir_name_w = NULL;
    grub_efi_file_info_t *fileinfo = NULL;
    grub_efi_uintn_t buffersize = 0;
    grub_efi_file_t *directory = NULL;
    int i, dirlen = 0, ret = 0;

    file_name_w = grub_malloc (2 * strlen(dirname) + 2);
    if (!file_name_w)
        goto done;

    for (i=0; i<strlen(dirname); i++) {
        file_name_w[i] = dirname[i];
        if (file_name_w[i] == '/') {
            file_name_w[i] = '\\';
            dirlen = i;
        }
    }

    file_name_w[i] = '\0';

    status = Call_Service_5 (root->open, root, &file, file_name_w,
                             GRUB_EFI_FILE_MODE_READ, 0);

    if (status != GRUB_EFI_SUCCESS)
        goto done;

    if (dirname[i-1] == '/') {
        if (print_possibilities)
            grub_printf("\n");

        while (1) {
            int filenamelen;

            status = Call_Service_3 (file->read, file, &buffersize, fileinfo);

            if (status == GRUB_EFI_BUFFER_TOO_SMALL) {
                fileinfo = grub_malloc(buffersize);
                continue;
            } else if (status) {
                goto done;
            } else if (buffersize == 0) {
                ret = 1;
                if (print_possibilities)
                    grub_printf("\n");
                goto done;
            }

            filenamelen = fileinfo->size - sizeof(*fileinfo);

            if (print_possibilities) {
                for (i=0; i<filenamelen/2; i++)
                    grub_printf("%c", (char)fileinfo->filename[i]);
            }
            grub_printf(" ");
        }
    } else {
        char *data = NULL;
        dir_name_w = grub_malloc (2 * dirlen + 2);
        if (!dir_name_w)
            goto done;

        for (i=0; i<dirlen; i++)
            dir_name_w[i] = file_name_w[i];

        dir_name_w[i] = '\0';

        status = Call_Service_5 (root->open, root, &directory, dir_name_w,
                                 GRUB_EFI_FILE_MODE_READ, 0);

        while (1) {
            int filenamelen;
            int invalid = 0;

            status = Call_Service_3 (directory->read, directory, &buffersize, fileinfo);

            if (status == GRUB_EFI_BUFFER_TOO_SMALL) {
                fileinfo = grub_malloc(buffersize);
                continue;
            } else if (status) {
                goto done;
            } else if (buffersize == 0) {
                goto done;
            }

            filenamelen = fileinfo->size - sizeof(*fileinfo);

            if (filenamelen != ((strlen(dirname) - dirlen) * 2))
                continue;

            for (i=0; i<filenamelen/2; i++) {
                if (fileinfo->filename[i] != file_name_w[i + dirlen + 1]) {
                    if (fileinfo->filename[i] > 0xff ||
                            (grub_tolower(fileinfo->filename[i]) !=
                             grub_tolower(file_name_w[i + dirlen + 1])))
                        invalid = 1;
                }
            }

            if (!invalid)
                break;
        }

        if (fileinfo->filesize < 256 && fileinfo->filesize > 3)
        {
            data = grub_malloc(fileinfo->filesize);
            filepos = 0;

            uefi_read(data, fileinfo->filesize);

            /*
             * UEFI doesn't really support symlinks. Apple's UEFI driver exposes
             * them as files containing the path of the target. This provides
             * hacky support in the absence of a real driver.
             */
            if (data[0] == '.' && data[1] == '.' && data[2] == '/')
            {
                int j;
                char *tmpdir = grub_malloc(dirlen + fileinfo->filesize);

                for (j=0; j<dirlen+1; j++)
                    tmpdir[j] = dirname[j];
                for (j=0; j<fileinfo->filesize; j++)
                    tmpdir[j+dirlen+1] = data[j];
                tmpdir[j+dirlen+1] = '\0';

                /* Open the new file */
                ret = uefi_dir(tmpdir);
                grub_free (tmpdir);
                grub_free (data);
                goto done;
            }
        }

        if (data)
            grub_free(data);
        ret = 1;
        filemax = fileinfo->filesize;
        filepos = 0;
    }

done:
    if (fileinfo)
        grub_free (fileinfo);
    if (dir_name_w)
        grub_free (dir_name_w);
    if (file_name_w)
        grub_free (file_name_w);

    return ret;
}