コード例 #1
0
ファイル: udp.c プロジェクト: pendor/grub-zfs
grub_err_t
grub_net_recv_udp_packet (struct grub_net_buff * nb,
			  struct grub_net_network_level_interface * inf)
{
  struct udphdr *udph;
  grub_net_socket_t sock;
  grub_err_t err;
  udph = (struct udphdr *) nb->data;
  err = grub_netbuff_pull (nb, sizeof (*udph));
  if (err)
    return err;

  FOR_NET_SOCKETS (sock)
  {
    if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port
	&& inf == sock->x_inf && sock->recv_hook)
      {
	if (sock->x_status == GRUB_NET_SOCKET_START)
	  {
	    sock->x_out_port = grub_be_to_cpu16 (udph->src);
	    sock->x_status = GRUB_NET_SOCKET_ESTABLISHED;
	  }

	/* App protocol remove its own reader.  */
	sock->recv_hook (sock, nb, sock->recv_hook_data);
	return GRUB_ERR_NONE;
      }
  }
  grub_netbuff_free (nb);
  return GRUB_ERR_NONE;
}
コード例 #2
0
ファイル: hfspluscomp.c プロジェクト: radsaggi/grub-clone
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;
}
コード例 #3
0
ファイル: sun.c プロジェクト: GrandTyRant/grub2
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;
}
コード例 #4
0
ファイル: tftp.c プロジェクト: 376473984/TrustedGRUB2
static int
cmp (const void *a__, const void *b__)
{
    struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
    struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
    struct tftphdr *a = (struct tftphdr *) a_->data;
    struct tftphdr *b = (struct tftphdr *) b_->data;
    /* We want the first elements to be on top.  */
    return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
}
コード例 #5
0
ファイル: hfs.c プロジェクト: P4N74/radare2
/* 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;
}
コード例 #6
0
ファイル: hfsplus.c プロジェクト: Arvian/GRUB2
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;
    }
コード例 #7
0
ファイル: ext2.c プロジェクト: TemmeR/grub2
static grub_err_t
grub_ext2_uuid (grub_device_t device, char **uuid)
{
  struct grub_ext2_data *data;
  grub_disk_t disk = device->disk;

  grub_dl_ref (my_mod);

  data = grub_ext2_mount (disk);
  if (data)
    {
      *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
			     grub_be_to_cpu16 (data->sblock.uuid[0]),
			     grub_be_to_cpu16 (data->sblock.uuid[1]),
			     grub_be_to_cpu16 (data->sblock.uuid[2]),
			     grub_be_to_cpu16 (data->sblock.uuid[3]),
			     grub_be_to_cpu16 (data->sblock.uuid[4]),
			     grub_be_to_cpu16 (data->sblock.uuid[5]),
			     grub_be_to_cpu16 (data->sblock.uuid[6]),
			     grub_be_to_cpu16 (data->sblock.uuid[7]));
    }
  else
    *uuid = NULL;

  grub_dl_unref (my_mod);

  grub_free (data);

  return grub_errno;
}
コード例 #8
0
ファイル: sun.c プロジェクト: kissthink/os-grub2
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;
}
コード例 #9
0
ファイル: font.c プロジェクト: Der-Jan/grub-zfs
/* Read a 16-bit big-endian integer from FILE, convert it to native byte
   order, and store it in *VALUE.
   Returns 0 on success, 1 on failure.  */
static int
read_be_uint16 (grub_file_t file, grub_uint16_t * value)
{
  if (grub_file_read (file, value, 2) != 2)
    return 1;
  *value = grub_be_to_cpu16 (*value);
  return 0;
}
コード例 #10
0
ファイル: hfsplus.c プロジェクト: Arvian/GRUB2
/* Return the offset of the record with the index INDEX, in the node
   NODE which is part of the B+ tree BTREE.  */
static inline grub_off_t
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
			   struct grub_hfsplus_btnode *node, int index)
{
  char *cnode = (char *) node;
  void *recptr;
  recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]);
  return grub_be_to_cpu16 (grub_get_unaligned16 (recptr));
}
コード例 #11
0
ファイル: hfsplus.c プロジェクト: AlfredArouna/grub2
/* Return the offset of the record with the index INDEX, in the node
   NODE which is part of the B+ tree BTREE.  */
static inline unsigned int
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
			   struct grub_hfsplus_btnode *node, int index)
{
  char *cnode = (char *) node;
  grub_uint16_t *recptr;
  recptr = (grub_uint16_t *) (&cnode[btree->nodesize
				     - index * sizeof (grub_uint16_t) - 2]);
  return grub_be_to_cpu16 (*recptr);
}
コード例 #12
0
ファイル: cpio.c プロジェクト: kphillisjr/burg
static inline unsigned long long
read_number (const grub_uint16_t *arr, grub_size_t size)
{
  long long ret = 0;
#ifdef MODE_BIGENDIAN
  while (size--)
    ret = (ret << 16) | grub_be_to_cpu16 (*arr++);
#else
  while (size--)
    ret = (ret << 16) | grub_le_to_cpu16 (*arr++);
#endif
  return ret;
}
コード例 #13
0
ファイル: iso9660.c プロジェクト: JungleGenius/TrustedGRUB2
static char *
grub_iso9660_convert_string (grub_uint8_t *us, int len)
{
  char *p;
  int i;
  grub_uint16_t t[MAX_NAMELEN / 2 + 1];

  p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
  if (! p)
    return NULL;

  for (i=0; i<len; i++)
    t[i] = grub_be_to_cpu16 (grub_get_unaligned16 (us + 2 * i));

  *grub_utf16_to_utf8 ((grub_uint8_t *) p, t, len) = '\0';

  return p;
}
コード例 #14
0
ファイル: font.c プロジェクト: Der-Jan/grub-zfs
/* Read the contents of the current section as a 16-bit integer value,
   which is stored into *VALUE.
   Returns 0 upon success, nonzero upon failure.  */
static int
read_section_as_short (struct font_file_section *section,
		       grub_int16_t * value)
{
  grub_uint16_t raw_value;

  if (section->length != 2)
    {
      grub_error (GRUB_ERR_BAD_FONT,
		  "font file format error: section %c%c%c%c length "
		  "is %d but should be 2",
		  section->name[0], section->name[1],
		  section->name[2], section->name[3], section->length);
      return 1;
    }
  if (grub_file_read (section->file, &raw_value, 2) != 2)
    return 1;

  *value = grub_be_to_cpu16 (raw_value);
  return 0;
}
コード例 #15
0
ファイル: sfs.c プロジェクト: DarkPostal/grub2
/* Lookup the extent starting with BLOCK in the filesystem described
   by DATA.  Return the extent size in SIZE and the following extent
   in NEXTEXT.  */
static grub_err_t
grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
		      int *size, int *nextext)
{
  char *treeblock;
  struct grub_sfs_btree *tree;
  int i;
  int next;
  int prev;

  treeblock = grub_malloc (data->blocksize);
  if (!block)
    return 0;

  next = grub_be_to_cpu32 (data->rblock.btree);
  tree = (struct grub_sfs_btree *) treeblock;

  /* Handle this level in the btree.  */
  do
    {
      prev = 0;

      grub_disk_read (data->disk, next, 0, data->blocksize, treeblock);
      if (grub_errno)
	{
	  grub_free (treeblock);
	  return grub_errno;
	}

      for (i = 0; i < grub_be_to_cpu16 (tree->nodes); i++)
	{

#define EXTNODE(tree, index)						\
	((struct grub_sfs_btree_node *) (((char *) &(tree)->node[0])	\
					 + (index) * (tree)->nodesize))

	  /* Follow the tree down to the leaf level.  */
	  if ((grub_be_to_cpu32 (EXTNODE(tree, i)->key) >= block)
	      && !tree->leaf)
	    {
	      next = grub_be_to_cpu32 (EXTNODE (tree, i - 1)->data);
	      break;
	    }

	  /* In case the last node is reached just use that one, it is
	     the right match.  */
	  if (i + 1 == grub_be_to_cpu16 (tree->nodes) && !tree->leaf)
	    {
	      next = grub_be_to_cpu32 (EXTNODE (tree, i)->data);
	      break;
	    }

	  /* If the leaf level is reached, just find the correct extent.  */
	  if (grub_be_to_cpu32 (EXTNODE (tree, i)->key) == block && tree->leaf)
	    {
	      struct grub_sfs_btree_extent *extent;
	      extent = (struct grub_sfs_btree_extent *) EXTNODE (tree, i);

	      /* We found a correct leaf.  */
	      *size = grub_be_to_cpu16 (extent->size);
	      *nextext = grub_be_to_cpu32 (extent->next);
	      
	      grub_free (treeblock);
	      return 0;
	    }

#undef EXTNODE

	}
    } while (!tree->leaf);

  grub_free (treeblock);

  return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found");
}
コード例 #16
0
ファイル: hfs.c プロジェクト: P4N74/radare2
/* 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;
}
コード例 #17
0
ファイル: hfs.c プロジェクト: P4N74/radare2
/* Find block BLOCK of the file FILE in the mounted UFS filesystem
   DATA.  The first 3 extents are described by DAT.  If cache is set,
   using caching to improve non-random reads.  */
static unsigned int
grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat,
		int file, int block, int cache)
{
  grub_hfs_datarecord_t dr;
  int pos = 0;
  struct grub_hfs_extent_key key;

  int tree = 0;
  static int cache_file = 0;
  static int cache_pos = 0;
  static grub_hfs_datarecord_t cache_dr;

  grub_memcpy (dr, dat, sizeof (dr));

  key.forktype = 0;
  key.fileid = grub_cpu_to_be32 (file);

  if (cache && cache_file == file  && block > cache_pos)
    {
      pos = cache_pos;
      key.first_block = grub_cpu_to_be16 (pos);
      grub_memcpy (dr, cache_dr, sizeof (cache_dr));
    }

  for (;;)
    {
      int i;

      /* Try all 3 extents.  */
      for (i = 0; i < 3; i++)
	{
	  /* Check if the block is stored in this extent.  */
	  if (grub_be_to_cpu16 (dr[i].count) + pos > block)
	    {
	      int first = grub_be_to_cpu16 (dr[i].first_block);

	      /* If the cache is enabled, store the current position
		 in the tree.  */
	      if (tree && cache)
		{
		  cache_file = file;
		  cache_pos = pos;
		  grub_memcpy (cache_dr, dr, sizeof (cache_dr));
		}

	      return (grub_be_to_cpu16 (data->sblock.first_block)
		      + (first + block - pos) * GRUB_HFS_BLKS);
	    }

	  /* Try the next extent.  */
	  pos += grub_be_to_cpu16 (dr[i].count);
	}

      /* Lookup the block in the extent overflow file.  */
      key.first_block = grub_cpu_to_be16 (pos);
      tree = 1;
      grub_hfs_find_node (data, (char *) &key, data->ext_root,
			  1, (char *) &dr, sizeof (dr));
      if (grub_errno)
	return 0;
    }
}
コード例 #18
0
ファイル: arp.c プロジェクト: Arvian/GRUB2
grub_err_t
grub_net_arp_receive (struct grub_net_buff *nb,
		      struct grub_net_card *card)
{
  struct arphdr *arp_header = (struct arphdr *) nb->data;
  grub_uint8_t *sender_hardware_address;
  grub_uint8_t *target_hardware_address;
  grub_net_network_level_address_t sender_addr, target_addr;
  grub_net_link_level_address_t sender_hw_addr;
  struct grub_net_network_level_interface *inf;
  grub_uint8_t *sender_protocol_address, *target_protocol_address;

  sender_hardware_address =
    (grub_uint8_t *) arp_header + sizeof (*arp_header);
  sender_protocol_address = sender_hardware_address + arp_header->hln;
  target_hardware_address = sender_protocol_address + arp_header->pln;
  target_protocol_address = target_hardware_address + arp_header->hln;
  if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP
      && arp_header->pln == 4)
    {
      sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
      target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
      grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4);
      grub_memcpy (&target_addr.ipv4, target_protocol_address, 4);
      if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0)
	have_pending = 1;
    }
  else
    return GRUB_ERR_NONE;

  sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
  grub_memcpy (sender_hw_addr.mac, sender_hardware_address,
	       sizeof (sender_hw_addr.mac));
  grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1);

  FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
  {
    /* Am I the protocol address target? */
    if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
	&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
      {
	grub_net_link_level_address_t target;
	/* We've already checked that pln is either 4 or 16.  */
	char tmp[arp_header->pln];

	target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
	grub_memcpy (target.mac, sender_hardware_address, 6);
	grub_memcpy (target_hardware_address, target.mac, 6);
	grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);

	grub_memcpy (tmp, sender_protocol_address, arp_header->pln);
	grub_memcpy (sender_protocol_address, target_protocol_address,
		     arp_header->pln);
	grub_memcpy (target_protocol_address, tmp, arp_header->pln);

	/* Change operation to REPLY and send packet */
	arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
	send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP);
      }
  }
  return GRUB_ERR_NONE;
}
コード例 #19
0
ファイル: apple.c プロジェクト: GrandTyRant/grub2
static grub_err_t
apple_partition_map_iterate (grub_disk_t disk,
			     int (*hook) (grub_disk_t disk,
					  const grub_partition_t partition))
{
  struct grub_partition part;
  struct grub_apple_header aheader;
  struct grub_apple_part apart;
  struct grub_disk raw;
  int partno = 0;
  unsigned pos = GRUB_DISK_SECTOR_SIZE;

  /* Enforce raw disk access.  */
  raw = *disk;
  raw.partition = 0;

  part.partmap = &grub_apple_partition_map;

  if (grub_disk_read (&raw, 0, 0, sizeof (aheader), (char *) &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;
    }

  for (;;)
    {
      if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE,
			  pos % GRUB_DISK_SECTOR_SIZE,
			  sizeof (struct grub_apple_part),  (char *) &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;
	}

      part.start = grub_be_to_cpu32 (apart.first_phys_block);
      part.len = grub_be_to_cpu32 (apart.blockcnt);
      part.offset = pos;
      part.index = 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))
	return grub_errno;

      if (grub_be_to_cpu32 (apart.first_phys_block)
	  == GRUB_DISK_SECTOR_SIZE * 2)
	return 0;

      pos += sizeof (struct grub_apple_part);
      partno++;
    }

  if (pos != GRUB_DISK_SECTOR_SIZE)
    return 0;

 fail:
  return grub_error (GRUB_ERR_BAD_PART_TABLE,
		     "Apple partition map not found.");
}
コード例 #20
0
ファイル: apple.c プロジェクト: 376473984/TrustedGRUB2
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");
}
コード例 #21
0
ファイル: hfsplus.c プロジェクト: Arvian/GRUB2
      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;
    }

  /* Make sure this is an HFS+ filesystem.  XXX: Do we really support
     HFX?  */
  magic = grub_be_to_cpu16 (volheader.hfsplus.magic);
  if (((magic != GRUB_HFSPLUS_MAGIC) && (magic != GRUB_HFSPLUSX_MAGIC))
      || volheader.hfsplus.blksize == 0
      || ((volheader.hfsplus.blksize & (volheader.hfsplus.blksize - 1)) != 0)
      || grub_be_to_cpu32 (volheader.hfsplus.blksize) < GRUB_DISK_SECTOR_SIZE)
    {
      grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
      goto fail;
    }

  grub_memcpy (&data->volheader, &volheader.hfsplus,
	       sizeof (volheader.hfsplus));

  for (data->log2blksize = 0;
       (1U << data->log2blksize) < grub_be_to_cpu32 (data->volheader.blksize);
       data->log2blksize++);
コード例 #22
0
ファイル: tftp.c プロジェクト: 376473984/TrustedGRUB2
static grub_err_t
tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
              struct grub_net_buff *nb,
              void *f)
{
    grub_file_t file = f;
    struct tftphdr *tftph = (void *) nb->data;
    tftp_data_t data = file->data;
    grub_err_t err;
    grub_uint8_t *ptr;

    if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode))
    {
        grub_dprintf ("tftp", "TFTP packet too small\n");
        return GRUB_ERR_NONE;
    }

    tftph = (struct tftphdr *) nb->data;
    switch (grub_be_to_cpu16 (tftph->opcode))
    {
    case TFTP_OACK:
        data->block_size = TFTP_DEFAULTSIZE_PACKET;
        data->have_oack = 1;
        for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
        {
            if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
                data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0")
                                                - 1, 0, 0);
            if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
                data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0")
                                                 - 1, 0, 0);
            while (ptr < nb->tail && *ptr)
                ptr++;
            ptr++;
        }
        data->block = 0;
        grub_netbuff_free (nb);
        err = ack (data, 0);
        grub_error_save (&data->save_err);
        return GRUB_ERR_NONE;
    case TFTP_DATA:
        if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode)
                + sizeof (tftph->u.data.block)))
        {
            grub_dprintf ("tftp", "TFTP packet too small\n");
            return GRUB_ERR_NONE;
        }

        err = grub_priority_queue_push (data->pq, &nb);
        if (err)
            return err;

        {
            struct grub_net_buff **nb_top_p, *nb_top;
            while (1)
            {
                nb_top_p = grub_priority_queue_top (data->pq);
                if (!nb_top_p)
                    return GRUB_ERR_NONE;
                nb_top = *nb_top_p;
                tftph = (struct tftphdr *) nb_top->data;
                if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
                    break;
                ack (data, grub_be_to_cpu16 (tftph->u.data.block));
                grub_netbuff_free (nb_top);
                grub_priority_queue_pop (data->pq);
            }
            while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
            {
                unsigned size;

                grub_priority_queue_pop (data->pq);

                if (file->device->net->packs.count < 50)
                    err = ack (data, data->block + 1);
                else
                {
                    file->device->net->stall = 1;
                    err = 0;
                }
                if (err)
                    return err;

                err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
                                         sizeof (tftph->u.data.block));
                if (err)
                    return err;
                size = nb_top->tail - nb_top->data;

                data->block++;
                if (size < data->block_size)
                {
                    if (data->ack_sent < data->block)
                        ack (data, data->block);
                    file->device->net->eof = 1;
                    file->device->net->stall = 1;
                    grub_net_udp_close (data->sock);
                    data->sock = NULL;
                }
                /* Prevent garbage in broken cards. Is it still necessary
                   given that IP implementation has been fixed?
                 */
                if (size > data->block_size)
                {
                    err = grub_netbuff_unput (nb_top, size - data->block_size);
                    if (err)
                        return err;
                }
                /* If there is data, puts packet in socket list. */
                if ((nb_top->tail - nb_top->data) > 0)
                    grub_net_put_packet (&file->device->net->packs, nb_top);
                else
                    grub_netbuff_free (nb_top);
            }
        }
        return GRUB_ERR_NONE;
    case TFTP_ERROR:
        data->have_oack = 1;
        grub_netbuff_free (nb);
        grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
        grub_error_save (&data->save_err);
        return GRUB_ERR_NONE;
    default:
        grub_netbuff_free (nb);
        return GRUB_ERR_NONE;
    }
}
コード例 #23
0
ファイル: ldm.c プロジェクト: flihp/grub2
static struct grub_diskfilter_vg *
make_vg (grub_disk_t disk,
	 const struct grub_ldm_label *label)
{
  grub_disk_addr_t startsec, endsec, cursec;
  struct grub_diskfilter_vg *vg;
  grub_err_t err;

  /* First time we see this volume group. We've to create the
     whole volume group structure. */
  vg = grub_malloc (sizeof (*vg));
  if (! vg)
    return NULL;
  vg->extent_size = 1;
  vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
  vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
  if (! vg->uuid || !vg->name)
    {
      grub_free (vg->uuid);
      grub_free (vg->name);
      return NULL;
    }
  grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
  grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
  vg->name[LDM_NAME_STRLEN] = 0;
  vg->uuid[LDM_GUID_STRLEN] = 0;
  vg->uuid_len = grub_strlen (vg->uuid);

  vg->lvs = NULL;
  vg->pvs = NULL;

  startsec = grub_be_to_cpu64 (label->config_start);
  endsec = startsec + grub_be_to_cpu64 (label->config_size);

  /* First find disks.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_pv *pv;
	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_DISK)
	    continue;
	  pv = grub_zalloc (sizeof (*pv));
	  if (!pv)
	    goto fail2;

	  pv->disk = 0;
	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  pv->internal_id = grub_malloc (ptr[0] + 2);
	  if (!pv->internal_id)
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
	  pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
	  
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1
	      >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (pv);
	      goto fail2;
	    }
	  pv->id.uuidlen = *ptr;
	  pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
	  grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
	  pv->id.uuid[pv->id.uuidlen] = 0;

	  pv->next = vg->pvs;
	  vg->pvs = pv;
	}
    }

  /* Then find LVs.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *lv;
	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_VOLUME)
	    continue;
	  lv = grub_zalloc (sizeof (*lv));
	  if (!lv)
	    goto fail2;

	  lv->vg = vg;
	  lv->segment_count = 1;
	  lv->segment_alloc = 1;
	  lv->visible = 1;
	  lv->segments = grub_zalloc (sizeof (*lv->segments));
	  if (!lv->segments)
	    goto fail2;
	  lv->segments->start_extent = 0;
	  lv->segments->type = GRUB_DISKFILTER_MIRROR;
	  lv->segments->node_count = 0;
	  lv->segments->node_alloc = 8;
	  lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
					     * lv->segments->node_alloc);
	  if (!lv->segments->nodes)
	    goto fail2;
	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
	  if (!lv->internal_id)
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
	  lv->internal_id[ptr[0] + 1] = 0;

	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->name = grub_malloc (*ptr + 1);
	  if (!lv->name)
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv);
	      goto fail2;
	    }
	  grub_memcpy (lv->name, ptr + 1, *ptr);
	  lv->name[*ptr] = 0;
	  lv->fullname = grub_xasprintf ("ldm/%s/%s",
					 vg->uuid, lv->name);
	  if (!lv->fullname)
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1
	      >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  /* ptr = volume type.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  /* ptr = flags.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }

	  /* Skip state, type, unknown, volume number, zeros, flags. */
	  ptr += 14 + 1 + 1 + 1 + 3 + 1;
	  /* ptr = number of children.  */
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }

	  /* Skip 2 more fields.  */
	  ptr += 8 + 8;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1>= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (lv->internal_id);
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail2;
	    }
	  lv->size = read_int (ptr + 1, *ptr);
	  lv->segments->extent_count = lv->size;

	  lv->next = vg->lvs;
	  vg->lvs = lv;
	}
    }

  /* Now the components.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *comp;
	  struct grub_diskfilter_lv *lv;
	  grub_uint8_t type;

	  grub_uint8_t *ptr;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_COMPONENT)
	    continue;
	  comp = grub_zalloc (sizeof (*comp));
	  if (!comp)
	    goto fail2;
	  comp->visible = 0;
	  comp->name = 0;
	  comp->fullname = 0;

	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
	  if (!comp->internal_id)
	    {
	      grub_free (comp);
	      goto fail2;
	    }
	  grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
	  comp->internal_id[ptr[0] + 1] = 0;

	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  /* ptr = state.  */
	  ptr += *ptr + 1;
	  type = *ptr++;
	  /* skip zeros.  */
	  ptr += 4;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }

	  /* ptr = number of children. */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  ptr += 8 + 8;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic
	      + sizeof (vblk[i].dynamic))
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      goto fail2;
	    }
	  for (lv = vg->lvs; lv; lv = lv->next)
	    {
	      if (lv->internal_id[0] == ptr[0]
		  && grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0)
		break;
	    }
	  if (!lv)
	    {
	      grub_free (comp->internal_id);
	      grub_free (comp);
	      continue;
	    }
	  comp->size = lv->size;
	  if (type == SPANNED)
	    {
	      comp->segment_alloc = 8;
	      comp->segment_count = 0;
	      comp->segments = grub_malloc (sizeof (*comp->segments)
					    * comp->segment_alloc);
	      if (!comp->segments)
		goto fail2;
	    }
	  else
	    {
	      comp->segment_alloc = 1;
	      comp->segment_count = 1;
	      comp->segments = grub_malloc (sizeof (*comp->segments));
	      if (!comp->segments)
		goto fail2;
	      comp->segments->start_extent = 0;
	      comp->segments->extent_count = lv->size;
	      comp->segments->layout = 0;
	      if (type == STRIPE)
		comp->segments->type = GRUB_DISKFILTER_STRIPED;
	      else if (type == RAID5)
		{
		  comp->segments->type = GRUB_DISKFILTER_RAID5;
		  comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK;
		}
	      else
		goto fail2;
	      ptr += *ptr + 1;
	      ptr++;
	      if (!(vblk[i].flags & 0x10))
		goto fail2;
	      if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
		  || ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  grub_free (comp->internal_id);
		  grub_free (comp);
		  goto fail2;
		}
	      comp->segments->stripe_size = read_int (ptr + 1, *ptr);
	      ptr += *ptr + 1;
	      if (ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  grub_free (comp->internal_id);
		  grub_free (comp);
		  goto fail2;
		}
	      comp->segments->node_count = read_int (ptr + 1, *ptr);
	      comp->segments->node_alloc = comp->segments->node_count;
	      comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
						   * comp->segments->node_alloc);
	      if (!lv->segments->nodes)
		goto fail2;
	    }

	  if (lv->segments->node_alloc == lv->segments->node_count)
	    {
	      void *t;
	      lv->segments->node_alloc *= 2; 
	      t = grub_realloc (lv->segments->nodes,
				sizeof (*lv->segments->nodes)
				* lv->segments->node_alloc);
	      if (!t)
		goto fail2;
	      lv->segments->nodes = t;
	    }
	  lv->segments->nodes[lv->segments->node_count].pv = 0;
	  lv->segments->nodes[lv->segments->node_count].start = 0;
	  lv->segments->nodes[lv->segments->node_count++].lv = comp;
	  comp->next = vg->lvs;
	  vg->lvs = comp;
	}
    }
  /* Partitions.  */
  for (cursec = startsec + 0x12; cursec < endsec; cursec++)
    {
      struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
				/ sizeof (struct grub_ldm_vblk)];
      unsigned i;
      err = grub_disk_read (disk, cursec, 0,
			    sizeof(vblk), &vblk);
      if (err)
	goto fail2;

      for (i = 0; i < ARRAY_SIZE (vblk); i++)
	{
	  struct grub_diskfilter_lv *comp;
	  struct grub_diskfilter_node part;
	  grub_disk_addr_t start, size;

	  grub_uint8_t *ptr;
	  part.name = 0;
	  if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
			   sizeof (vblk[i].magic)) != 0)
	    continue;
	  if (grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_CONSISTENT
	      && grub_be_to_cpu16 (vblk[i].update_status)
	      != STATUS_STILL_ACTIVE)
	    continue;
	  if (vblk[i].type != ENTRY_PARTITION)
	    continue;
	  part.lv = 0;
	  part.pv = 0;

	  ptr = vblk[i].dynamic;
	  if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  /* ID */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  /* ptr = name.  */
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }

	  /* skip zeros and logcommit id.  */
	  ptr += 4 + 8;
	  if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  part.start = read_int (ptr, 8);
	  start = read_int (ptr + 8, 8);
	  ptr += 16;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  size = read_int (ptr + 1, *ptr);
	  ptr += *ptr + 1;
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }

	  for (comp = vg->lvs; comp; comp = comp->next)
	    if (comp->internal_id[0] == ptr[0]
		&& grub_memcmp (ptr + 1, comp->internal_id + 1,
				comp->internal_id[0]) == 0)
	      goto out;
	  continue;
	out:
	  if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
	      || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
	    {
	      goto fail2;
	    }
	  ptr += *ptr + 1;
	  struct grub_diskfilter_pv *pv;
	  for (pv = vg->pvs; pv; pv = pv->next)
	    if (pv->internal_id[0] == ptr[0]
		&& grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0)
	      part.pv = pv;

	  if (comp->segment_alloc == 1)
	    {
	      unsigned node_index;
	      ptr += *ptr + 1;
	      if (ptr + *ptr + 1 >= vblk[i].dynamic
		  + sizeof (vblk[i].dynamic))
		{
		  goto fail2;
		}
	      node_index = read_int (ptr + 1, *ptr);
	      if (node_index < comp->segments->node_count)
		comp->segments->nodes[node_index] = part;
	    }
	  else
	    {
	      if (comp->segment_alloc == comp->segment_count)
		{
		  void *t;
		  comp->segment_alloc *= 2;
		  t = grub_realloc (comp->segments,
				    comp->segment_alloc
				    * sizeof (*comp->segments));
		  if (!t)
		    goto fail2;
		  comp->segments = t;
		}
	      comp->segments[comp->segment_count].start_extent = start;
	      comp->segments[comp->segment_count].extent_count = size;
	      comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED;
	      comp->segments[comp->segment_count].node_count = 1;
	      comp->segments[comp->segment_count].node_alloc = 1;
	      comp->segments[comp->segment_count].nodes
		= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
	      if (!comp->segments[comp->segment_count].nodes)
		goto fail2;
	      comp->segments[comp->segment_count].nodes[0] = part;
	      comp->segment_count++;
	    }
	}
    }
  if (grub_diskfilter_vg_register (vg))
    goto fail2;
  return vg;
 fail2:
  {
    struct grub_diskfilter_lv *lv, *next_lv;
    struct grub_diskfilter_pv *pv, *next_pv;
    for (lv = vg->lvs; lv; lv = next_lv)
      {
	unsigned i;
	for (i = 0; i < lv->segment_count; i++)
	  grub_free (lv->segments[i].nodes);

	next_lv = lv->next;
	grub_free (lv->segments);
	grub_free (lv->internal_id);
	grub_free (lv->name);
	grub_free (lv->fullname);
	grub_free (lv);
      }
    for (pv = vg->pvs; pv; pv = next_pv)
      {
	next_pv = pv->next;
	grub_free (pv->id.uuid);
	grub_free (pv);
      }
  }
  grub_free (vg->uuid);
  grub_free (vg);
  return NULL;
}
コード例 #24
0
ファイル: ldm.c プロジェクト: flihp/grub2
static struct grub_diskfilter_vg * 
grub_ldm_detect (grub_disk_t disk,
		 struct grub_diskfilter_pv_id *id,
		 grub_disk_addr_t *start_sector)
{
  grub_err_t err;
  struct grub_ldm_label label;
  struct grub_diskfilter_vg *vg;

#ifdef GRUB_UTIL
  grub_util_info ("scanning %s for LDM", disk->name);
#endif

  {
    int i;
    int has_ldm = msdos_has_ldm_partition (disk);
    for (i = 0; i < 3; i++)
      {
	grub_disk_addr_t sector = LDM_LABEL_SECTOR;
	switch (i)
	  {
	  case 0:
	    if (!has_ldm)
	      continue;
	    sector = LDM_LABEL_SECTOR;
	    break;
	  case 1:
	    /* LDM is never inside a partition.  */
	    if (!has_ldm || disk->partition)
	      continue;
	    sector = grub_disk_get_size (disk);
	    if (sector == GRUB_DISK_SIZE_UNKNOWN)
	      continue;
	    sector--;
	    break;
	    /* FIXME: try the third copy.  */
	  case 2:
	    sector = gpt_ldm_sector (disk);
	    if (!sector)
	      continue;
	    break;
	  }
	err = grub_disk_read (disk, sector, 0,
			      sizeof(label), &label);
	if (err)
	  return NULL;
	if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0
	    && grub_be_to_cpu16 (label.ver_major) == 0x02
	    && grub_be_to_cpu16 (label.ver_minor) >= 0x0b
	    && grub_be_to_cpu16 (label.ver_minor) <= 0x0c)
	  break;
      }

    /* Return if we didn't find a label. */
    if (i == 3)
      {
#ifdef GRUB_UTIL
	grub_util_info ("no LDM signature found");
#endif
	return NULL;
      }
  }

  id->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
  if (!id->uuid)
    return NULL;
  grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN);
  id->uuid[LDM_GUID_STRLEN] = 0;
  id->uuidlen = grub_strlen ((char *) id->uuid);
  *start_sector = grub_be_to_cpu64 (label.pv_start);

  {
    grub_size_t s;
    for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++);
    vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid);
    if (! vg)
      vg = make_vg (disk, &label);
  }

  if (!vg)
    {
      grub_free (id->uuid);
      return NULL;
    }
  return vg;
}