Ejemplo n.º 1
0
int
grub_fdt_create_empty_tree (void *fdt, unsigned int size)
{
  struct grub_fdt_empty_tree *et;

  if (size < GRUB_FDT_EMPTY_TREE_SZ)
    return -1;

  grub_memset (fdt, 0, size);
  et = fdt;

  et->empty_node.tree_end = grub_cpu_to_be32_compile_time (FDT_END);
  et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE);
  et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE);
  ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap =
    grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8));

  grub_fdt_set_off_dt_strings (fdt, sizeof (*et));
  grub_fdt_set_off_dt_struct (fdt,
			      sizeof (et->header) + sizeof (et->empty_rsvmap));
  grub_fdt_set_version (fdt, FDT_SUPPORTED_VERSION);
  grub_fdt_set_last_comp_version (fdt, FDT_SUPPORTED_VERSION);
  grub_fdt_set_size_dt_struct (fdt, sizeof (et->empty_node));
  grub_fdt_set_totalsize (fdt, size);
  grub_fdt_set_magic (fdt, FDT_MAGIC);

  return 0;
}
Ejemplo n.º 2
0
static int add_subnode (void *fdt, int parentoffset, const char *name)
{
  grub_uint32_t *token = (void *) ((grub_addr_t) fdt
                                   + grub_fdt_get_off_dt_struct(fdt)
                                   + parentoffset);
  grub_uint32_t *end = (void *) struct_end (fdt);
  unsigned int entry_size = node_entry_size (name);
  unsigned int struct_size = grub_fdt_get_size_dt_struct(fdt);
  char *node_name;

  SKIP_NODE_NAME(node_name, token, end);

  /* Insert the new subnode just after the properties of the parent node (if
     any).*/
  while (1)
  {
    if (token >= end)
      return -1;
    switch (grub_be_to_cpu32(*token))
    {
      case FDT_PROP:
        /* Skip len, nameoff and property value. */
        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
                 / sizeof(*token);
        break;
      case FDT_BEGIN_NODE:
      case FDT_END_NODE:
        goto insert;
      case FDT_NOP:
        token++;
        break;
      default:
        /* invalid token */
        return -1;
    }
  }
insert:
  grub_memmove (token + entry_size / sizeof(*token), token,
                (grub_addr_t) end - (grub_addr_t) token);
  *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE);
  token[entry_size / sizeof(*token) - 2] = 0;	/* padding bytes */
  grub_strcpy((char *) (token + 1), name);
  token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE);
  grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size);
  return ((grub_addr_t) token - (grub_addr_t) fdt
          - grub_fdt_get_off_dt_struct(fdt));
}
Ejemplo n.º 3
0
static int
validate_head (struct cbfs_header *head)
{
  return (head->magic == grub_cpu_to_be32_compile_time (CBFS_HEADER_MAGIC)
	  && (head->version
	      == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION1)
	      || head->version
	      == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION2))
	  && (grub_be_to_cpu32 (head->bootblocksize)
	      < grub_be_to_cpu32 (head->romsize))
	  && (grub_be_to_cpu32 (head->offset)
	      < grub_be_to_cpu32 (head->romsize))
	  && (grub_be_to_cpu32 (head->offset)
	      + grub_be_to_cpu32 (head->bootblocksize)
	      < grub_be_to_cpu32 (head->romsize))
	  && head->align != 0
	  && (head->align & (head->align - 1)) == 0
	  && head->romsize != 0);
}
Ejemplo n.º 4
0
/* Mount the filesystem on the disk DISK.  */
static struct grub_hfs_data *
grub_hfs_mount (grub_disk_t disk)
{
  struct grub_hfs_data *data;
  struct grub_hfs_catalog_key key;
  struct grub_hfs_dirrec dir;
  int first_block;

  struct
  {
    struct grub_hfs_node node;
    struct grub_hfs_treeheader head;
  } treehead;

  data = grub_malloc (sizeof (struct grub_hfs_data));
  if (!data)
    return 0;

  /* Read the superblock.  */
  if (grub_disk_read (disk, GRUB_HFS_SBLOCK, 0,
		      sizeof (struct grub_hfs_sblock), &data->sblock))
    goto fail;

  /* Check if this is a HFS filesystem.  */
  if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC
      || (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff)))
    {
      grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
      goto fail;
    }

  /* Check if this is an embedded HFS+ filesystem.  */
  if (grub_be_to_cpu16 (data->sblock.embed_sig) == GRUB_HFS_EMBED_HFSPLUS_SIG)
    {
      grub_error (GRUB_ERR_BAD_FS, "embedded HFS+ filesystem");
      goto fail;
    }

  data->blksz = grub_be_to_cpu32 (data->sblock.blksz);
  data->disk = disk;

  /* Lookup the root node of the extent overflow tree.  */
  first_block = ((grub_be_to_cpu16 (data->sblock.extent_recs[0].first_block)
		  * GRUB_HFS_BLKS)
		 + grub_be_to_cpu16 (data->sblock.first_block));

  if (grub_disk_read (data->disk, first_block, 0,
		      sizeof (treehead), &treehead))
    goto fail;
  data->ext_root = grub_be_to_cpu32 (treehead.head.root_node);
  data->ext_size = grub_be_to_cpu16 (treehead.head.node_size);

  /* Lookup the root node of the catalog tree.  */
  first_block = ((grub_be_to_cpu16 (data->sblock.catalog_recs[0].first_block)
		  * GRUB_HFS_BLKS)
		 + grub_be_to_cpu16 (data->sblock.first_block));
  if (grub_disk_read (data->disk, first_block, 0,
		      sizeof (treehead), &treehead))
    goto fail;
  data->cat_root = grub_be_to_cpu32 (treehead.head.root_node);
  data->cat_size = grub_be_to_cpu16 (treehead.head.node_size);

  /* Lookup the root directory node in the catalog tree using the
     volume name.  */
  key.parent_dir = grub_cpu_to_be32 (1);
  key.strlen = data->sblock.volname[0];
  grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));

  if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
			  0, (char *) &dir, sizeof (dir)) == 0)
    {
      grub_error (GRUB_ERR_BAD_FS, "cannot find the HFS root directory");
      goto fail;
    }

  if (grub_errno)
    goto fail;

  data->rootdir = grub_be_to_cpu32 (dir.dirid);

  return data;
 fail:
  grub_free (data);

  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
    grub_error (GRUB_ERR_BAD_FS, "not a HFS filesystem");

  return 0;
}
Ejemplo n.º 5
0
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
		       const void *val, grub_uint32_t len)
{
  grub_uint32_t *prop;
  int prop_name_present = 0;
  grub_uint32_t nameoff = 0;

  if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3)
      || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt
                           + grub_fdt_get_off_dt_struct (fdt) + nodeoffset))
          != FDT_BEGIN_NODE))
    return -1;
  prop = find_prop (fdt, nodeoffset, name);
  if (prop)
    {
	  grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)),
                                        sizeof(grub_uint32_t));
	  grub_uint32_t i;

      prop_name_present = 1;
	  for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++)
        *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP);
      if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
        {
          /* Length of new property value is greater than the space allocated
             for the current value: a new entry needs to be created, so save the
             nameoff field of the current entry and replace the current entry
             with NOP tokens. */
          nameoff = grub_be_to_cpu32 (*(prop + 2));
          *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP);
          prop = NULL;
        }
    }
  if (!prop || !prop_name_present) {
    unsigned int needed_space = 0;

    if (!prop)
      needed_space = prop_entry_size(len);
    if (!prop_name_present)
      needed_space += grub_strlen (name) + 1;
    if (needed_space > get_free_space (fdt))
      return -1;
    if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0)
      return -1;
  }
  if (!prop_name_present) {
    /* Append the property name at the end of the strings block. */
    nameoff = grub_fdt_get_size_dt_strings (fdt);
    grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff,
                 name);
    grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt)
                                  + grub_strlen (name) + 1);
  }
  if (!prop) {
    char *node_name = (char *) ((grub_addr_t) fdt
                                + grub_fdt_get_off_dt_struct (fdt) + nodeoffset
                                + sizeof(grub_uint32_t));

    prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4));
    grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop,
                  struct_end(fdt) - (grub_addr_t) prop);
    grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt)
                                 + prop_entry_size(len));
    *prop = grub_cpu_to_be32_compile_time (FDT_PROP);
    *(prop + 2) = grub_cpu_to_be32 (nameoff);
  }
  *(prop + 1) = grub_cpu_to_be32 (len);

  /* Insert padding bytes at the end of the value; if they are not needed, they
     will be overwritten by the following memcpy. */
  *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;

  grub_memcpy (prop + 3, val, len);
  return 0;
}
Ejemplo n.º 6
0
static grub_err_t 
hfsplus_open_compressed_real (struct grub_hfsplus_file *node)
{
  grub_err_t err;
  struct grub_hfsplus_btnode *attr_node;
  grub_off_t attr_off;
  struct grub_hfsplus_key_internal key;
  struct grub_hfsplus_attr_header *attr_head;
  struct grub_hfsplus_compress_attr *cmp_head;
#define c grub_cpu_to_be16_compile_time
  const grub_uint16_t compress_attr_name[] =
    {
      c('c'), c('o'), c('m'), c('.'), c('a'), c('p'), c('p'), c('l'), c('e'),
      c('.'), c('d'), c('e'), c('c'), c('m'), c('p'), c('f'), c('s') };
#undef c
  if (node->size)
    return 0;

  key.attrkey.cnid = node->fileid;
  key.attrkey.namelen = sizeof (compress_attr_name) / sizeof (compress_attr_name[0]);
  key.attrkey.name = compress_attr_name;

  err = grub_hfsplus_btree_search (&node->data->attr_tree, &key,
				   grub_hfsplus_cmp_attrkey,
				   &attr_node, &attr_off);
  if (err || !attr_node)
    {
      grub_errno = 0;
      return 0;
    }

  attr_head = (struct grub_hfsplus_attr_header *)
    ((char *) grub_hfsplus_btree_recptr (&node->data->attr_tree,
					 attr_node, attr_off)
     + sizeof (struct grub_hfsplus_attrkey) + sizeof (compress_attr_name));
  if (attr_head->type != 0x10
      || !(attr_head->size & grub_cpu_to_be64_compile_time(~0xfULL)))
    {
      grub_free (attr_node);
      return 0;
    }
  cmp_head = (struct grub_hfsplus_compress_attr *) (attr_head + 1);
  if (cmp_head->magic != grub_cpu_to_be32_compile_time (0x66706d63))
    {
      grub_free (attr_node);
      return 0;
    }
  node->size = grub_le_to_cpu32 (cmp_head->uncompressed_inline_size);

  if (cmp_head->type == grub_cpu_to_le32_compile_time (HFSPLUS_COMPRESSION_RESOURCE))
    {
      grub_uint32_t index_size;
      node->compressed = 2;

      if (grub_hfsplus_read_file (node, 0, 0,
				  0x104, sizeof (index_size),
				  (char *) &index_size)
	  != 4)
	{
	  node->compressed = 0;
	  grub_free (attr_node);
	  grub_errno = 0;
	  return 0;
	}
      node->compress_index_size = grub_le_to_cpu32 (index_size);
      node->compress_index = grub_malloc (node->compress_index_size
					  * sizeof (node->compress_index[0]));
      if (!node->compress_index)
	{
	  node->compressed = 0;
	  grub_free (attr_node);
	  return grub_errno;
	}
      if (grub_hfsplus_read_file (node, 0, 0,
				  0x104 + sizeof (index_size),
				  node->compress_index_size
				  * sizeof (node->compress_index[0]),
				  (char *) node->compress_index)
	  != (grub_ssize_t) (node->compress_index_size
			     * sizeof (node->compress_index[0])))
	{
	  node->compressed = 0;
	  grub_free (attr_node);
	  grub_free (node->compress_index);
	  grub_errno = 0;
	  return 0;
	}

      node->cbuf_block = -1;

      node->cbuf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE);
      grub_free (attr_node);
      if (!node->cbuf)
	{
	  node->compressed = 0;
	  grub_free (node->compress_index);
	  return grub_errno;
	}
      return 0;
    }
  if (cmp_head->type != HFSPLUS_COMPRESSION_INLINE)
    {
      grub_free (attr_node);
      return 0;
    }

  node->cbuf = grub_malloc (node->size);
  if (!node->cbuf)
    return grub_errno;

  if (grub_zlib_decompress ((char *) (cmp_head + 1),
			    grub_cpu_to_be64 (attr_head->size)
			    - sizeof (*cmp_head), 0,
			    node->cbuf, node->size) < 0)
    return grub_errno;
  node->compressed = 1;
  return 0;
}
Ejemplo n.º 7
0
grub_macho_t
grub_macho_file (grub_file_t file, const char *filename, int is_64bit)
{
  grub_macho_t macho;
  union grub_macho_filestart filestart;

  macho = grub_malloc (sizeof (*macho));
  if (! macho)
    return 0;

  macho->file = file;
  macho->offset32 = -1;
  macho->offset64 = -1;
  macho->end32 = -1;
  macho->end64 = -1;
  macho->cmds32 = 0;
  macho->cmds64 = 0;
  macho->uncompressed32 = 0;
  macho->uncompressed64 = 0;
  macho->compressed32 = 0;
  macho->compressed64 = 0;

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

  if (grub_file_read (macho->file, &filestart, sizeof (filestart))
      != sizeof (filestart))
    {
      if (!grub_errno)
	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
		    filename);
      goto fail;
    }

  /* Is it a fat file? */
  if (filestart.fat.magic == grub_cpu_to_be32_compile_time (GRUB_MACHO_FAT_MAGIC))
    {
      struct grub_macho_fat_arch *archs;
      int i, narchs;

      /* Load architecture description. */
      narchs = grub_be_to_cpu32 (filestart.fat.nfat_arch);
      if (grub_file_seek (macho->file, sizeof (struct grub_macho_fat_header))
	  == (grub_off_t) -1)
	goto fail;
      archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
      if (!archs)
	goto fail;
      if (grub_file_read (macho->file, archs,
			  sizeof (struct grub_macho_fat_arch) * narchs)
	  != (grub_ssize_t) sizeof(struct grub_macho_fat_arch) * narchs)
	{
	  grub_free (archs);
	  if (!grub_errno)
	    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
			filename);
	  goto fail;
	}

      for (i = 0; i < narchs; i++)
	{
	  if ((archs[i].cputype
	       == grub_cpu_to_be32_compile_time (GRUB_MACHO_CPUTYPE_IA32))
	      && !is_64bit)
	    {
	      macho->offset32 = grub_be_to_cpu32 (archs[i].offset);
	      macho->end32 = grub_be_to_cpu32 (archs[i].offset)
		+ grub_be_to_cpu32 (archs[i].size);
	    }
	  if ((archs[i].cputype
	       == grub_cpu_to_be32_compile_time (GRUB_MACHO_CPUTYPE_AMD64))
	      && is_64bit)
	    {
	      macho->offset64 = grub_be_to_cpu32 (archs[i].offset);
	      macho->end64 = grub_be_to_cpu32 (archs[i].offset)
		+ grub_be_to_cpu32 (archs[i].size);
	    }
	}
      grub_free (archs);
    }

  /* Is it a thin 32-bit file? */
  if (filestart.thin32.magic == GRUB_MACHO_MAGIC32 && !is_64bit)
    {
      macho->offset32 = 0;
      macho->end32 = grub_file_size (file);
    }

  /* Is it a thin 64-bit file? */
  if (filestart.thin64.magic == GRUB_MACHO_MAGIC64 && is_64bit)
    {
      macho->offset64 = 0;
      macho->end64 = grub_file_size (file);
    }

  if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC,
		   sizeof (filestart.lzss.magic)) == 0 && !is_64bit)
    {
      macho->offset32 = 0;
      macho->end32 = grub_file_size (file);
    }

  /* Is it a thin 64-bit file? */
  if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC,
		   sizeof (filestart.lzss.magic)) == 0 && is_64bit)
    {
      macho->offset64 = 0;
      macho->end64 = grub_file_size (file);
    }

  grub_macho_parse32 (macho, filename);
  grub_macho_parse64 (macho, filename);

  if (macho->offset32 == -1 && !is_64bit)
    {
      grub_error (GRUB_ERR_BAD_OS,
		  "Mach-O doesn't contain suitable 32-bit architecture");
      goto fail;
    }

  if (macho->offset64 == -1 && is_64bit)
    {
      grub_error (GRUB_ERR_BAD_OS,
		  "Mach-O doesn't contain suitable 64-bit architecture");
      goto fail;
    }

  return macho;

fail:
  macho->file = 0;
  grub_macho_close (macho);
  return 0;
}