Пример #1
0
/* Read the capacity and block size of SCSI.  */
static grub_err_t
grub_scsi_read_capacity (grub_scsi_t scsi)
{
  struct grub_scsi_read_capacity rc;
  struct grub_scsi_read_capacity_data rcd;
  grub_err_t err;
  grub_err_t err_sense;

  rc.opcode = grub_scsi_cmd_read_capacity;
  rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
  rc.logical_block_addr = 0;
  rc.reserved1 = 0;
  rc.reserved2 = 0;
  rc.PMI = 0;
  rc.control = 0;
  rc.pad = 0;
	
  err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
			 sizeof (rcd), (char *) &rcd);

  /* Each SCSI command should be followed by Request Sense.
     If not so, many devices STALLs or definitely freezes. */
  err_sense = grub_scsi_request_sense (scsi);
  if (err_sense != GRUB_ERR_NONE)
  	grub_errno = err;
/* err_sense is ignored for now and Request Sense Data also... */

  if (err)
    return err;

  scsi->size = grub_be_to_cpu32 (rcd.size);
  scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);

  return GRUB_ERR_NONE;
}
Пример #2
0
static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
				 const char *name)
{
  grub_uint32_t *prop = (void *) ((grub_addr_t) fdt
                                 + grub_fdt_get_off_dt_struct (fdt)
                                 + nodeoffset);
  grub_uint32_t *end = (void *) struct_end(fdt);
  grub_uint32_t nameoff;
  char *node_name;

  SKIP_NODE_NAME(node_name, prop, end);
  while (prop < end - 2)
  {
    if (grub_be_to_cpu32(*prop) == FDT_PROP)
      {
        nameoff = grub_be_to_cpu32(*(prop + 2));
        if ((nameoff + grub_strlen (name) < grub_fdt_get_size_dt_strings (fdt))
            && !grub_strcmp (name, (char *) fdt +
                             grub_fdt_get_off_dt_strings (fdt) + nameoff))
        {
          if (prop + prop_entry_size(grub_be_to_cpu32(*(prop + 1)))
              / sizeof (*prop) >= end)
            return NULL;
          return prop;
        }
        prop += prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop);
      }
    else if (grub_be_to_cpu32(*prop) == FDT_NOP)
      prop++;
    else
      return NULL;
  }
  return NULL;
}
Пример #3
0
static struct grub_archelp_data *
grub_cbfs_mount (grub_disk_t disk)
{
  struct cbfs_file hd;
  struct grub_archelp_data *data = NULL;
  grub_uint32_t ptr;
  grub_off_t header_off;
  struct cbfs_header head;

  if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
    goto fail;

  if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
		      GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
		      sizeof (ptr), &ptr))
    goto fail;

  ptr = grub_cpu_to_le32 (ptr);
  header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    + (grub_int32_t) ptr;

  if (grub_disk_read (disk, 0, header_off,
		      sizeof (head), &head))
    goto fail;

  if (!validate_head (&head))
    goto fail;

  data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data));
  if (!data)
    goto fail;

  data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset));
  data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    - grub_be_to_cpu32 (head.bootblocksize);
  data->cbfs_align = grub_be_to_cpu32 (head.align);

  if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
    goto fail;
  if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
    data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS);

  data->next_hofs = data->cbfs_start;

  if (grub_disk_read (disk, 0, data->cbfs_start, sizeof (hd), &hd))
    goto fail;

  if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (CBFS_FILE_MAGIC) - 1))
    goto fail;

  data->disk = disk;

  return data;

fail:
  grub_free (data);
  grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem");
  return 0;
}
Пример #4
0
static grub_disk_addr_t
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
  int links;
  grub_uint32_t pos;
  int block = node->block;
  struct grub_affs_file file;
  struct grub_affs_data *data = node->data;
  grub_uint32_t mod;

  /* Find the block that points to the fileblock we are looking up by
     following the chain until the right table is reached.  */
  for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
    {
      grub_disk_read (data->disk, block + data->blocksize - 1,
		      data->blocksize * (GRUB_DISK_SECTOR_SIZE
					 - GRUB_AFFS_FILE_LOCATION),
		      sizeof (file), &file);
      if (grub_errno)
	return 0;

      block = grub_be_to_cpu32 (file.extension);
    }

  /* Translate the fileblock to the block within the right table.  */
  fileblock = mod;
  grub_disk_read (data->disk, block,
		  GRUB_AFFS_BLOCKPTR_OFFSET
		  + (data->htsize - fileblock - 1) * sizeof (pos),
		  sizeof (pos), &pos);
  if (grub_errno)
    return 0;

  return grub_be_to_cpu32 (pos);
}
Пример #5
0
static grub_err_t
sun_partition_map_iterate (grub_disk_t disk,
                           int (*hook) (grub_disk_t disk,
					const grub_partition_t partition))
{
  grub_partition_t p;
  struct grub_disk raw;
  struct grub_sun_block block;
  int partnum;
  
  raw = *disk;
  raw.partition = 0;
  
  p = (grub_partition_t) grub_malloc (sizeof (struct grub_partition));
  if (! p)
    return grub_errno;

  p->offset = 0;
  p->data = 0;
  p->partmap = &grub_sun_partition_map;
  if (grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block),
		      (char *) &block) == GRUB_ERR_NONE)
    {
      if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic))
	grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table");
      
      if (! grub_sun_is_valid (&block))
	grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
      
      /* Maybe another error value would be better, because partition
	 table _is_ recognized but invalid.  */
      for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++)
	{
	  struct grub_sun_partition_descriptor *desc;
	  
	  if (block.infos[partnum].id == 0
	      || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
	    continue;

	  desc = &block.partitions[partnum];
	  p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder)
		      * grub_be_to_cpu16 (block.ntrks)
		      * grub_be_to_cpu16 (block.nsect));
	  p->len = grub_be_to_cpu32 (desc->num_sectors);
	  p->index = partnum;
	  if (p->len)
	    {
	      if (hook (disk, p))
		partnum = GRUB_PARTMAP_SUN_MAX_PARTS;
	    }
	}
    }
  
  grub_free (p);

  return grub_errno;
}
Пример #6
0
static struct grub_sfs_data *
grub_sfs_mount (grub_disk_t disk)
{
  struct grub_sfs_data *data;
  struct grub_sfs_objc *rootobjc;
  char *rootobjc_data = 0;
  unsigned int blk;

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

  /* Read the rootblock.  */
  grub_disk_read (disk, 0, 0, sizeof (struct grub_sfs_rblock),
		  (char *) &data->rblock);
  if (grub_errno)
    goto fail;

  /* Make sure this is a sfs filesystem.  */
  if (grub_strncmp ((char *) (data->rblock.header.magic), "SFS", 4))
    {
      grub_error (GRUB_ERR_BAD_FS, "not a sfs filesystem");
      goto fail;
    }

  data->blocksize = grub_be_to_cpu32 (data->rblock.blocksize);
  rootobjc_data = grub_malloc (data->blocksize);
  if (! rootobjc_data)
    goto fail;

  /* Read the root object container.  */
  grub_disk_read (disk, grub_be_to_cpu32 (data->rblock.rootobject), 0,
		  data->blocksize, rootobjc_data);
  if (grub_errno)
    goto fail;

  rootobjc = (struct grub_sfs_objc *) rootobjc_data;

  blk = grub_be_to_cpu32 (rootobjc->objects[0].file_dir.dir.dir_objc);
  data->diropen.size = 0;
  data->diropen.block = blk;
  data->diropen.data = data;
  data->disk = disk;
  data->label = grub_strdup ((char *) (rootobjc->objects[0].filename));

  return data;

 fail:
  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
    grub_error (GRUB_ERR_BAD_FS, "not an sfs filesystem");

  grub_free (data);
  grub_free (rootobjc_data);
  return 0;
}
Пример #7
0
/* Compare the K1 and K2 extent overflow file keys.  */
static int
grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1,
		      struct grub_hfs_extent_key *k2)
{
  int cmp = k1->forktype - k2->forktype;
  if (cmp == 0)
    cmp = grub_be_to_cpu32 (k1->fileid) - grub_be_to_cpu32 (k2->fileid);
  if (cmp == 0)
    cmp = (grub_be_to_cpu16 (k1->first_block)
	   - grub_be_to_cpu16 (k2->first_block));
  return cmp;
}
Пример #8
0
static int
grub_hfsplus_cmp_attrkey (struct grub_hfsplus_key *keya,
			  struct grub_hfsplus_key_internal *keyb)
{
  struct grub_hfsplus_attrkey *attrkey_a = &keya->attrkey;
  struct grub_hfsplus_attrkey_internal *attrkey_b = &keyb->attrkey;
  grub_uint32_t aparent = grub_be_to_cpu32 (attrkey_a->cnid);
  grub_size_t len;
  int diff;

  if (aparent > attrkey_b->cnid)
    return 1;
  if (aparent < attrkey_b->cnid)
    return -1;

  len = grub_be_to_cpu16 (attrkey_a->namelen);
  if (len > attrkey_b->namelen)
    len = attrkey_b->namelen;
  /* Since it's big-endian memcmp gives the same result as manually comparing
     uint16_t but may be faster.  */
  diff = grub_memcmp (attrkey_a->name, attrkey_b->name,
		      len * sizeof (attrkey_a->name[0]));
  if (diff == 0)
    diff = grub_be_to_cpu16 (attrkey_a->namelen) - attrkey_b->namelen;
  return diff;
}
Пример #9
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));
}
Пример #10
0
static grub_err_t
sun_partition_map_iterate (grub_disk_t disk,
                           int (*hook) (grub_disk_t disk,
					const grub_partition_t partition))
{
  struct grub_partition p;
  struct grub_sun_block block;
  int partnum;
  grub_err_t err;

  p.partmap = &grub_sun_partition_map;
  err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block),
			&block);
  if (err)
    return err;

  if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic))
    return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table");

  if (! grub_sun_is_valid (&block))
      return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
  
  /* Maybe another error value would be better, because partition
     table _is_ recognized but invalid.  */
  for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++)
    {
      struct grub_sun_partition_descriptor *desc;

      if (block.infos[partnum].id == 0
	  || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
	continue;

      desc = &block.partitions[partnum];
      p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder)
		  * grub_be_to_cpu16 (block.ntrks)
		  * grub_be_to_cpu16 (block.nsect));
      p.len = grub_be_to_cpu32 (desc->num_sectors);
      p.number = p.index = partnum;
      if (p.len)
	{
	  if (hook (disk, &p))
	    partnum = GRUB_PARTMAP_SUN_MAX_PARTS;
	}
    }

  return grub_errno;
}
Пример #11
0
/* Find a direct sub-node of a given parent node. */
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
			   const char *name)
{
  grub_uint32_t *token, *end;
  char *node_name;

  if (parentoffset & 0x3)
    return -1;
  token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
                    + parentoffset);
  end = (void *) struct_end (fdt);
  if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
    return -1;
  SKIP_NODE_NAME(node_name, token, end);
  while (token < end)
  {
    switch (grub_be_to_cpu32(*token))
    {
      case FDT_BEGIN_NODE:
        node_name = (char *) (token + 1);
        if (node_name + grub_strlen (name) >= (char *) end)
          return -1;
        if (!grub_strcmp (node_name, name))
          return (int) ((grub_addr_t) token - (grub_addr_t) fdt
                        - grub_fdt_get_off_dt_struct (fdt));
        token = get_next_node (fdt, node_name);
        if (!token)
          return -1;
        break;
      case FDT_PROP:
        /* Skip property token and following data (len, nameoff and property
           value). */
        if (token >= end - 1)
          return -1;
        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
                 / sizeof(*token);
        break;
      case FDT_NOP:
        token++;
        break;
      default:
        return -1;
    }
  }
  return -1;
}
Пример #12
0
Файл: dvh.c Проект: Arvian/GRUB2
static grub_err_t
dvh_partition_map_iterate (grub_disk_t disk,
                           int (*hook) (grub_disk_t disk,
					const grub_partition_t partition))
{
  struct grub_partition p;
  union
  {
    struct grub_dvh_block dvh;
    grub_uint32_t raw[0];
  } block;
  unsigned partnum;
  grub_err_t err;

  p.partmap = &grub_dvh_partition_map;
  err = grub_disk_read (disk, 0, 0, sizeof (struct grub_dvh_block),
			&block);
  if (err)
    return err;

  if (DVH_MAGIC != grub_be_to_cpu32 (block.dvh.magic))
    return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a dvh partition table");

  if (! grub_dvh_is_valid (block.raw))
      return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
  
  /* Maybe another error value would be better, because partition
     table _is_ recognized but invalid.  */
  for (partnum = 0; partnum < ARRAY_SIZE (block.dvh.parts); partnum++)
    {
      if (block.dvh.parts[partnum].length == 0)
	continue;

      if (partnum == 10)
	continue;

      p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start);
      p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length);
      p.number = p.index = partnum;
      if (hook (disk, &p))
	break;
    }

  return grub_errno;
}
Пример #13
0
/* Find the extent that points to FILEBLOCK.  If it is not in one of
   the 8 extents described by EXTENT, return -1.  In that case set
   FILEBLOCK to the next block.  */
static grub_disk_addr_t
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
			 grub_disk_addr_t *fileblock)
{
  int i;
  grub_disk_addr_t blksleft = *fileblock;

  /* First lookup the file in the given extents.  */
  for (i = 0; i < 8; i++)
    {
      if (blksleft < grub_be_to_cpu32 (extent[i].count))
	return grub_be_to_cpu32 (extent[i].start) + blksleft;
      blksleft -= grub_be_to_cpu32 (extent[i].count);
    }

  *fileblock = blksleft;
  return 0xffffffffffffffffULL;
}
Пример #14
0
static grub_uint32_t
grub_png_get_dword (struct grub_png_data *data)
{
  grub_uint32_t r;

  r = 0;
  grub_file_read (data->file, (char *) &r, sizeof (grub_uint32_t));

  return grub_be_to_cpu32 (r);
}
Пример #15
0
static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
{
  grub_uint32_t *end = (void *) struct_end (fdt);
  grub_uint32_t *token;

  if (node_name >= (char *) end)
    return NULL;
  while (*node_name++)
  {
    if (node_name >= (char *) end)
  	  return NULL;
  }
  token = (grub_uint32_t *) ALIGN_UP ((grub_addr_t) node_name, 4);
  while (token < end)
  {
    switch (grub_be_to_cpu32(*token))
    {
      case FDT_BEGIN_NODE:
        token = get_next_node (fdt, (char *) (token + 1));
        if (!token)
          return NULL;
        break;
      case FDT_END_NODE:
        token++;
        if (token >= end)
          return NULL;
        return token;
      case FDT_PROP:
        /* Skip property token and following data (len, nameoff and property
           value). */
        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
                 / sizeof(*token);
        break;
      case FDT_NOP:
        token++;
        break;
      default:
        return NULL;
    }
  }
  return NULL;
}
Пример #16
0
/* Read the capacity and block size of SCSI.  */
static grub_err_t
grub_scsi_read_capacity (grub_scsi_t scsi)
{
    struct grub_scsi_read_capacity rc;
    struct grub_scsi_read_capacity_data rcd;
    grub_err_t err;

    rc.opcode = grub_scsi_cmd_read_capacity;
    rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
    grub_memset (rc.reserved, 0, sizeof (rc.reserved));

    err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
                           sizeof (rcd), (char *) &rcd);
    if (err)
        return err;

    scsi->size = grub_be_to_cpu32 (rcd.size);
    scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);

    return GRUB_ERR_NONE;
}
Пример #17
0
/* Verify checksum (true=ok).  */
static int
grub_dvh_is_valid (grub_uint32_t *label)
{
  grub_uint32_t *pos;
  grub_uint32_t sum = 0;

  for (pos = label;
       pos < (label + sizeof (struct grub_dvh_block) / 4);
       pos++)
    sum += grub_be_to_cpu32 (*pos);

  return ! sum;
}
Пример #18
0
static struct grub_hfsplus_data *
grub_hfsplus_mount (grub_disk_t disk)
{
  struct grub_hfsplus_data *data;
  struct grub_hfsplus_btheader header;
  struct grub_hfsplus_btnode node;
  grub_uint16_t magic;
  union {
    struct grub_hfs_sblock hfs;
    struct grub_hfsplus_volheader hfsplus;
  } volheader;

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

  data->disk = disk;

  /* Read the bootblock.  */
  grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
		  &volheader);
  if (grub_errno)
    goto fail;

  data->embedded_offset = 0;
  if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
    {
      grub_disk_addr_t extent_start;
      grub_disk_addr_t ablk_size;
      grub_disk_addr_t ablk_start;

      /* See if there's an embedded HFS+ filesystem.  */
      if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
	{
	  grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
	  goto fail;
	}

      /* Calculate the offset needed to translate HFS+ sector numbers.  */
      extent_start = grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block);
      ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
      ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
      data->embedded_offset = (ablk_start
			       + extent_start
			       * (ablk_size >> GRUB_DISK_SECTOR_BITS));

      grub_disk_read (disk, data->embedded_offset + GRUB_HFSPLUS_SBLOCK, 0,
		      sizeof (volheader), &volheader);
      if (grub_errno)
	goto fail;
    }
Пример #19
0
int
grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
				    const char *property, grub_uint32_t *buf,
				    grub_size_t size, grub_ssize_t *actual)
{
  int ret;
  ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
#ifndef GRUB_CPU_WORDS_BIGENDIAN
  /* Integer properties are always in big endian.  */
  if (ret == 0)
    {
      unsigned int i;
      size /= sizeof (grub_uint32_t);
      for (i = 0; i < size; i++)
	buf[i] = grub_be_to_cpu32 (buf[i]);
    }
#endif
  return ret;
}
Пример #20
0
/* Open the next section in the file.

   On success, the section name is stored in section->name and the length in
   section->length, and 0 is returned.  On failure, 1 is returned and
   grub_errno is set appropriately with an error message.

   If 1 is returned due to being at the end of the file, then section->eof is
   set to 1; otherwise, section->eof is set to 0.  */
static int
open_section (grub_file_t file, struct font_file_section *section)
{
  grub_ssize_t retval;
  grub_uint32_t raw_length;

  section->file = file;
  section->eof = 0;

  /* Read the FOURCC section name.  */
  retval = grub_file_read (file, section->name, 4);
  if (retval >= 0 && retval < 4)
    {
      /* EOF encountered.  */
      section->eof = 1;
      return 1;
    }
  else if (retval < 0)
    {
      /* Read error.  */
      return 1;
    }

  /* Read the big-endian 32-bit section length.  */
  retval = grub_file_read (file, &raw_length, 4);
  if (retval >= 0 && retval < 4)
    {
      /* EOF encountered.  */
      section->eof = 1;
      return 1;
    }
  else if (retval < 0)
    {
      /* Read error.  */
      return 1;
    }

  /* Convert byte-order and store in *length.  */
  section->length = grub_be_to_cpu32 (raw_length);

  return 0;
}
Пример #21
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);
}
Пример #22
0
static int
grub_affs_iterate_dir (grub_fshelp_node_t dir,
		       int NESTED_FUNC_ATTR
		       (*hook) (const char *filename,
				enum grub_fshelp_filetype filetype,
				grub_fshelp_node_t node))
{
  int i;
  struct grub_affs_file file;
  struct grub_fshelp_node *node = 0;
  struct grub_affs_data *data = dir->data;
  grub_uint32_t *hashtable;

  auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
						   int size, int type);

  int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
					      int size, int type)
    {
      node = grub_malloc (sizeof (*node));
      if (!node)
	{
	  grub_free (hashtable);
	  return 1;
	}

      node->data = data;
      node->size = size;
      node->block = block;
      node->parent = grub_be_to_cpu32 (file.parent);

      if (hook (name, type, node))
	{
	  grub_free (hashtable);
	  return 1;
	}
      return 0;
    }
Пример #23
0
static struct grub_affs_data *
grub_affs_mount (grub_disk_t disk)
{
  struct grub_affs_data *data;
  grub_uint32_t *rootblock = 0;
  struct grub_affs_rblock *rblock;

  int checksum = 0;
  int checksumr = 0;
  int blocksize = 0;

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

  /* Read the bootblock.  */
  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
		  &data->bblock);
  if (grub_errno)
    goto fail;

  /* Make sure this is an affs filesystem.  */
  if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
    {
      grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
      goto fail;
    }

  /* Test if the filesystem is a OFS filesystem.  */
  if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
    {
      grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
      goto fail;
    }

  /* Read the bootblock.  */
  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
		  &data->bblock);
  if (grub_errno)
    goto fail;

  /* No sane person uses more than 8KB for a block.  At least I hope
     for that person because in that case this won't work.  */
  rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
  if (!rootblock)
    goto fail;

  rblock = (struct grub_affs_rblock *) rootblock;

  /* Read the rootblock.  */
  grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0,
		  GRUB_DISK_SECTOR_SIZE * 16, rootblock);
  if (grub_errno)
    goto fail;

  /* The filesystem blocksize is not stored anywhere in the filesystem
     itself.  One way to determine it is reading blocks for the
     rootblock until the checksum is correct.  */
  checksumr = grub_be_to_cpu32 (rblock->checksum);
  rblock->checksum = 0;
  for (blocksize = 0; blocksize < 8; blocksize++)
    {
      grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize;
      unsigned int i;

      for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
	checksum += grub_be_to_cpu32 (currblock[i]);

      if (checksumr == -checksum)
	break;
    }
  if (-checksum != checksumr)
    {
      grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
      goto fail;
    }
  blocksize++;

  data->blocksize = blocksize;
  data->disk = disk;
  data->htsize = grub_be_to_cpu32 (rblock->htsize);
  data->diropen.data = data;
  data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);

  grub_free (rootblock);

  return data;

 fail:
  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
    grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");

  grub_free (data);
  grub_free (rootblock);
  return 0;
}
Пример #24
0
static grub_err_t
apple_partition_map_iterate (grub_disk_t disk,
			     grub_partition_iterate_hook_t hook,
			     void *hook_data)
{
  struct grub_partition part;
  struct grub_apple_header aheader;
  struct grub_apple_part apart;
  int partno = 0, partnum = 0;
  unsigned pos;

  part.partmap = &grub_apple_partition_map;

  if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader))
    return grub_errno;

  if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
    {
      grub_dprintf ("partition",
		    "bad magic (found 0x%x; wanted 0x%x)\n",
		    grub_be_to_cpu16 (aheader.magic),
		    GRUB_APPLE_HEADER_MAGIC);
      goto fail;
    }

  pos = grub_be_to_cpu16 (aheader.blocksize);

  do
    {
      part.offset = pos / GRUB_DISK_SECTOR_SIZE;
      part.index = pos % GRUB_DISK_SECTOR_SIZE;

      if (grub_disk_read (disk, part.offset, part.index,
			  sizeof (struct grub_apple_part),  &apart))
	return grub_errno;

      if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC)
	{
	  grub_dprintf ("partition",
			"partition %d: bad magic (found 0x%x; wanted 0x%x)\n",
			partno, grub_be_to_cpu16 (apart.magic),
			GRUB_APPLE_PART_MAGIC);
	  break;
	}

      if (partnum == 0)
	partnum = grub_be_to_cpu32 (apart.partmap_size);

      part.start = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.first_phys_block)
		    * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
      part.len = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.blockcnt)
		  * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
      part.offset = pos;
      part.index = partno;
      part.number = partno;

      grub_dprintf ("partition",
		    "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
		    partno, apart.partname, apart.parttype,
		    grub_be_to_cpu32 (apart.first_phys_block),
		    grub_be_to_cpu32 (apart.blockcnt));

      if (hook (disk, &part, hook_data))
	return grub_errno;

      pos += grub_be_to_cpu16 (aheader.blocksize);
      partno++;
    }
  while (partno < partnum);

  if (partno != 0)
    return 0;

 fail:
  return grub_error (GRUB_ERR_BAD_PART_TABLE,
		     "Apple partition map not found");
}
Пример #25
0
/* Compare the K1 and K2 catalog file keys using HFS character ordering.  */
static int
grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1,
		      struct grub_hfs_catalog_key *k2)
{
  /* Taken from hfsutils 3.2.6 and converted to a readable form */
  static const unsigned char hfs_charorder[256] = {
    [0x00] = 0,
    [0x01] = 1,
    [0x02] = 2,
    [0x03] = 3,
    [0x04] = 4,
    [0x05] = 5,
    [0x06] = 6,
    [0x07] = 7,
    [0x08] = 8,
    [0x09] = 9,
    [0x0A] = 10,
    [0x0B] = 11,
    [0x0C] = 12,
    [0x0D] = 13,
    [0x0E] = 14,
    [0x0F] = 15,
    [0x10] = 16,
    [0x11] = 17,
    [0x12] = 18,
    [0x13] = 19,
    [0x14] = 20,
    [0x15] = 21,
    [0x16] = 22,
    [0x17] = 23,
    [0x18] = 24,
    [0x19] = 25,
    [0x1A] = 26,
    [0x1B] = 27,
    [0x1C] = 28,
    [0x1D] = 29,
    [0x1E] = 30,
    [0x1F] = 31,
    [' '] = 32,		[0xCA] = 32,
    ['!'] = 33,
    ['"'] = 34,
    [0xD2] = 35,
    [0xD3] = 36,
    [0xC7] = 37,
    [0xC8] = 38,
    ['#'] = 39,
    ['$'] = 40,
    ['%'] = 41,
    ['&'] = 42,
    ['\''] = 43,
    [0xD4] = 44,
    [0xD5] = 45,
    ['('] = 46,
    [')'] = 47,
    ['*'] = 48,
    ['+'] = 49,
    [','] = 50,
    ['-'] = 51,
    ['.'] = 52,
    ['/'] = 53,
    ['0'] = 54,
    ['1'] = 55,
    ['2'] = 56,
    ['3'] = 57,
    ['4'] = 58,
    ['5'] = 59,
    ['6'] = 60,
    ['7'] = 61,
    ['8'] = 62,
    ['9'] = 63,
    [':'] = 64,
    [';'] = 65,
    ['<'] = 66,
    ['='] = 67,
    ['>'] = 68,
    ['?'] = 69,
    ['@'] = 70,
    ['A'] = 71,		['a'] = 71,
    [0x88] = 72,	[0xCB] = 72,
    [0x80] = 73,	[0x8A] = 73,
    [0x8B] = 74,	[0xCC] = 74,
    [0x81] = 75,	[0x8C] = 75,
    [0xAE] = 76,	[0xBE] = 76,
    ['`'] = 77,
    [0x87] = 78,
    [0x89] = 79,
    [0xBB] = 80,
    ['B'] = 81,		['b'] = 81,
    ['C'] = 82,		['c'] = 82,
    [0x82] = 83,	[0x8D] = 83,
    ['D'] = 84,		['d'] = 84,
    ['E'] = 85,		['e'] = 85,
    [0x83] = 86,	[0x8E] = 86,
    [0x8F] = 87,
    [0x90] = 88,
    [0x91] = 89,
    ['F'] = 90,		['f'] = 90,
    ['G'] = 91,		['g'] = 91,
    ['H'] = 92,		['h'] = 92,
    ['I'] = 93,		['i'] = 93,
    [0x92] = 94,
    [0x93] = 95,
    [0x94] = 96,
    [0x95] = 97,
    ['J'] = 98,		['j'] = 98,
    ['K'] = 99,		['k'] = 99,
    ['L'] = 100,	['l'] = 100,
    ['M'] = 101,	['m'] = 101,
    ['N'] = 102,	['n'] = 102,
    [0x84] = 103,	[0x96] = 103,
    ['O'] = 104,	['o'] = 104,
    [0x85] = 105,	[0x9A] = 105,
    [0x9B] = 106,	[0xCD] = 106,
    [0xAF] = 107,	[0xBF] = 107,
    [0xCE] = 108,	[0xCF] = 108,
    [0x97] = 109,
    [0x98] = 110,
    [0x99] = 111,
    [0xBC] = 112,
    ['P'] = 113,	['p'] = 113,
    ['Q'] = 114,	['q'] = 114,
    ['R'] = 115,	['r'] = 115,
    ['S'] = 116,	['s'] = 116,
    [0xA7] = 117,
    ['T'] = 118,	['t'] = 118,
    ['U'] = 119,	['u'] = 119,
    [0x86] = 120,	[0x9F] = 120,
    [0x9C] = 121,
    [0x9D] = 122,
    [0x9E] = 123,
    ['V'] = 124,	['v'] = 124,
    ['W'] = 125,	['w'] = 125,
    ['X'] = 126,	['x'] = 126,
    ['Y'] = 127,	['y'] = 127,
    [0xD8] = 128,
    ['Z'] = 129,	['z'] = 129,
    ['['] = 130,
    ['\\'] = 131,
    [']'] = 132,
    ['^'] = 133,
    ['_'] = 134,
    ['{'] = 135,
    ['|'] = 136,
    ['}'] = 137,
    ['~'] = 138,
    [0x7F] = 139,
    [0xA0] = 140,
    [0xA1] = 141,
    [0xA2] = 142,
    [0xA3] = 143,
    [0xA4] = 144,
    [0xA5] = 145,
    [0xA6] = 146,
    [0xA8] = 147,
    [0xA9] = 148,
    [0xAA] = 149,
    [0xAB] = 150,
    [0xAC] = 151,
    [0xAD] = 152,
    [0xB0] = 153,
    [0xB1] = 154,
    [0xB2] = 155,
    [0xB3] = 156,
    [0xB4] = 157,
    [0xB5] = 158,
    [0xB6] = 159,
    [0xB7] = 160,
    [0xB8] = 161,
    [0xB9] = 162,
    [0xBA] = 163,
    [0xBD] = 164,
    [0xC0] = 165,
    [0xC1] = 166,
    [0xC2] = 167,
    [0xC3] = 168,
    [0xC4] = 169,
    [0xC5] = 170,
    [0xC6] = 171,
    [0xC9] = 172,
    [0xD0] = 173,
    [0xD1] = 174,
    [0xD6] = 175,
    [0xD7] = 176,
    [0xD9] = 177,
    [0xDA] = 178,
    [0xDB] = 179,
    [0xDC] = 180,
    [0xDD] = 181,
    [0xDE] = 182,
    [0xDF] = 183,
    [0xE0] = 184,
    [0xE1] = 185,
    [0xE2] = 186,
    [0xE3] = 187,
    [0xE4] = 188,
    [0xE5] = 189,
    [0xE6] = 190,
    [0xE7] = 191,
    [0xE8] = 192,
    [0xE9] = 193,
    [0xEA] = 194,
    [0xEB] = 195,
    [0xEC] = 196,
    [0xED] = 197,
    [0xEE] = 198,
    [0xEF] = 199,
    [0xF0] = 200,
    [0xF1] = 201,
    [0xF2] = 202,
    [0xF3] = 203,
    [0xF4] = 204,
    [0xF5] = 205,
    [0xF6] = 206,
    [0xF7] = 207,
    [0xF8] = 208,
    [0xF9] = 209,
    [0xFA] = 210,
    [0xFB] = 211,
    [0xFC] = 212,
    [0xFD] = 213,
    [0xFE] = 214,
    [0xFF] = 215,
  };
  int i;
  int cmp;
  int minlen = (k1->strlen < k2->strlen) ? k1->strlen : k2->strlen;

  cmp = (grub_be_to_cpu32 (k1->parent_dir) - grub_be_to_cpu32 (k2->parent_dir));
  if (cmp != 0)
    return cmp;

  for (i = 0; i < minlen; i++)
    {
      cmp = (hfs_charorder[k1->str[i]] - hfs_charorder[k2->str[i]]);
      if (cmp != 0)
	return cmp;
    }

  /* Shorter strings precede long ones.  */
  return (k1->strlen - k2->strlen);
}
Пример #26
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)
    {
      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;
}
Пример #27
0
static grub_err_t
grub_cbfs_find_file (struct grub_archelp_data *data, char **name,
		     grub_int32_t *mtime,
		     grub_uint32_t *mode)
{
  grub_size_t offset;
  for (;;
       data->dofs = data->hofs + offset,
	 data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align))
    {
      struct cbfs_file hd;
      grub_size_t namesize;

      data->hofs = data->next_hofs;

      if (data->hofs >= data->cbfs_end)
	{
	  *mode = GRUB_ARCHELP_ATTR_END;
	  return GRUB_ERR_NONE;
	}

      if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
	return grub_errno;

      if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (hd.magic)) != 0)
	{
	  *mode = GRUB_ARCHELP_ATTR_END;
	  return GRUB_ERR_NONE;
	}
      data->size = grub_be_to_cpu32 (hd.len);
      (void) mtime;
      offset = grub_be_to_cpu32 (hd.offset);

      *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME;

      namesize = offset;
      if (namesize >= sizeof (hd))
	namesize -= sizeof (hd);
      if (namesize == 0)
	continue;
      *name = grub_malloc (namesize + 1);
      if (*name == NULL)
	return grub_errno;

      if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
			  namesize, *name))
	{
	  grub_free (*name);
	  return grub_errno;
	}

      if ((*name)[0] == '\0')
	{
	  grub_free (*name);
	  *name = NULL;
	  continue;
	}

      (*name)[namesize] = 0;

      data->dofs = data->hofs + offset;
      data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align);
      return GRUB_ERR_NONE;
    }
}
Пример #28
0
/* Load the character index (CHIX) section contents from the font file.  This
   presumes that the position of FILE is positioned immediately after the
   section length for the CHIX section (i.e., at the start of the section
   contents).  Returns 0 upon success, nonzero for failure (in which case
   grub_errno is set appropriately).  */
static int
load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
		 grub_font *font)
{
  unsigned i;
  grub_uint32_t last_code;

#if FONT_DEBUG >= 2
  grub_dprintf ("font", "load_font_index(sect_length=%d)\n", sect_length);
#endif

  /* Sanity check: ensure section length is divisible by the entry size.  */
  if ((sect_length % FONT_CHAR_INDEX_ENTRY_SIZE) != 0)
    {
      grub_error (GRUB_ERR_BAD_FONT,
		  "font file format error: character index length %d "
		  "is not a multiple of the entry size %d",
		  sect_length, FONT_CHAR_INDEX_ENTRY_SIZE);
      return 1;
    }

  /* Calculate the number of characters.  */
  font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE;

  /* Allocate the character index array.  */
  font->char_index = grub_malloc (font->num_chars
				  * sizeof (struct char_index_entry));
  if (!font->char_index)
    return 1;
  font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
  if (!font->bmp_idx)
    return 1;
  grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));


#if FONT_DEBUG >= 2
  grub_dprintf ("font", "num_chars=%d)\n", font->num_chars);
#endif

  last_code = 0;

  /* Load the character index data from the file.  */
  for (i = 0; i < font->num_chars; i++)
    {
      struct char_index_entry *entry = &font->char_index[i];

      /* Read code point value; convert to native byte order.  */
      if (grub_file_read (file, &entry->code, 4) != 4)
	return 1;
      entry->code = grub_be_to_cpu32 (entry->code);

      /* Verify that characters are in ascending order.  */
      if (i != 0 && entry->code <= last_code)
	{
	  grub_error (GRUB_ERR_BAD_FONT,
		      "font characters not in ascending order: %u <= %u",
		      entry->code, last_code);
	  return 1;
	}

      if (entry->code < 0x10000)
	font->bmp_idx[entry->code] = i;

      last_code = entry->code;

      /* Read storage flags byte.  */
      if (grub_file_read (file, &entry->storage_flags, 1) != 1)
	return 1;

      /* Read glyph data offset; convert to native byte order.  */
      if (grub_file_read (file, &entry->offset, 4) != 4)
	return 1;
      entry->offset = grub_be_to_cpu32 (entry->offset);

      /* No glyph loaded.  Will be loaded on demand and cached thereafter.  */
      entry->glyph = 0;

#if FONT_DEBUG >= 5
      /* Print the 1st 10 characters.  */
      if (i < 10)
	grub_dprintf ("font", "c=%d o=%d\n", entry->code, entry->offset);
#endif
    }

  return 0;
}
Пример #29
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);
}
Пример #30
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;
}