Exemple #1
0
void ubigen_init_vid_hdr(const struct ubigen_info *ui,
			 const struct ubigen_vol_info *vi,
			 struct ubi_vid_hdr *hdr, int lnum,
			 unsigned long long sqnum,
			 const void *data, int data_size)
{
	uint32_t crc;

	memset(hdr, 0, sizeof(struct ubi_vid_hdr));

	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
	hdr->version = ui->ubi_ver;
	hdr->vol_type = vi->type;
	hdr->vol_id = cpu_to_be32(vi->id);
	hdr->lnum = cpu_to_be32(lnum);
	hdr->data_pad = cpu_to_be32(vi->data_pad);
	hdr->compat = vi->compat;
	hdr->sqnum = cpu_to_be64(sqnum);

	if (vi->type == UBI_VID_STATIC) {
		hdr->data_size = cpu_to_be32(data_size);
		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
		crc = mtd_crc32(UBI_CRC32_INIT, data, data_size);
		hdr->data_crc = cpu_to_be32(crc);
	}

	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
	hdr->hdr_crc = cpu_to_be32(crc);
}
Exemple #2
0
static int change_ech(struct ubi_ec_hdr *hdr, uint32_t image_seq,
		      long long ec)
{
	uint32_t crc;

	/* Check the EC header */
	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
		return errmsg("bad UBI magic %#08x, should be %#08x",
			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);

	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
	if (be32_to_cpu(hdr->hdr_crc) != crc)
		return errmsg("bad CRC %#08x, should be %#08x\n",
			      crc, be32_to_cpu(hdr->hdr_crc));

	hdr->image_seq = cpu_to_be32(image_seq);
	hdr->ec = cpu_to_be64(ec);
	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
	hdr->hdr_crc = cpu_to_be32(crc);

	return 0;
}
Exemple #3
0
void ubigen_init_ec_hdr(const struct ubigen_info *ui,
		        struct ubi_ec_hdr *hdr, long long ec)
{
	uint32_t crc;

	memset(hdr, 0, sizeof(struct ubi_ec_hdr));

	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
	hdr->version = ui->ubi_ver;
	hdr->ec = cpu_to_be64(ec);
	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
	hdr->data_offset = cpu_to_be32(ui->data_offs);
	hdr->image_seq = cpu_to_be32(ui->image_seq);

	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
	hdr->hdr_crc = cpu_to_be32(crc);
}
Exemple #4
0
struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
{
	struct ubi_vtbl_record *vtbl;
	int i;

	vtbl = calloc(1, ui->vtbl_size);
	if (!vtbl) {
		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
		return NULL;
	}

	for (i = 0; i < ui->max_volumes; i++) {
		uint32_t crc = mtd_crc32(UBI_CRC32_INIT, &vtbl[i],
				     UBI_VTBL_RECORD_SIZE_CRC);
		vtbl[i].crc = cpu_to_be32(crc);
	}

	return vtbl;
}
Exemple #5
0
int ubigen_add_volume(const struct ubigen_info *ui,
		      const struct ubigen_vol_info *vi,
		      struct ubi_vtbl_record *vtbl)
{
	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
	uint32_t tmp;

	if (vi->id >= ui->max_volumes) {
		errmsg("too high volume id %d, max. volumes is %d",
		       vi->id, ui->max_volumes);
		errno = EINVAL;
		return -1;
	}

	if (vi->alignment >= ui->leb_size) {
		errmsg("too large alignment %d, max is %d (LEB size)",
		       vi->alignment, ui->leb_size);
		errno = EINVAL;
		return -1;
	}

	memset(vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
	vtbl_rec->vol_type = vi->type;
	tmp = ui->leb_size % vi->alignment;
	vtbl_rec->data_pad = cpu_to_be32(tmp);
	vtbl_rec->flags = vi->flags;

	memcpy(vtbl_rec->name, vi->name, vi->name_len);
	vtbl_rec->name[vi->name_len] = '\0';
	vtbl_rec->name_len = cpu_to_be16(vi->name_len);

	tmp = mtd_crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
	vtbl_rec->crc =	 cpu_to_be32(tmp);
	return 0;
}
Exemple #6
0
/*
 *	Convert endianess
 */
static void do_endianconvert (void)
{
	char			*p = data;
	union jffs2_node_union 	*node, newnode;
	int			fd, len;
	jint32_t		mode;
	uint32_t		crc;

	fd = open (cnvfile, O_WRONLY | O_CREAT, 0644);
	if (fd < 0) {
		fprintf (stderr, "Cannot open / create file: %s\n", cnvfile);
		return;
	}

	while ( p < (data + imglen)) {
		node = (union jffs2_node_union*) p;

		/* Skip empty space */
		if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) {
			write_nocheck (fd, p, 4);
			p += 4;
			continue;
		}

		if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK)	{
			printf ("Wrong bitmask  at  0x%08zx, 0x%04x\n", p - data, je16_to_cpu (node->u.magic));
			newnode.u.magic = cnv_e16 (node->u.magic);
			newnode.u.nodetype = cnv_e16 (node->u.nodetype);
			write_nocheck (fd, &newnode, 4);
			p += 4;
			continue;
		}

		crc = mtd_crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4);
		if (crc != je32_to_cpu (node->u.hdr_crc)) {
			printf ("Wrong hdr_crc  at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc);
		}

		switch(je16_to_cpu(node->u.nodetype)) {

			case JFFS2_NODETYPE_INODE:

				newnode.i.magic = cnv_e16 (node->i.magic);
				newnode.i.nodetype = cnv_e16 (node->i.nodetype);
				newnode.i.totlen = cnv_e32 (node->i.totlen);
				newnode.i.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
				newnode.i.ino = cnv_e32 (node->i.ino);
				newnode.i.version = cnv_e32 (node->i.version);
				mode.v32 = node->i.mode.m;
				mode = cnv_e32 (mode);
				newnode.i.mode.m = mode.v32;
				newnode.i.uid = cnv_e16 (node->i.uid);
				newnode.i.gid = cnv_e16 (node->i.gid);
				newnode.i.isize = cnv_e32 (node->i.isize);
				newnode.i.atime = cnv_e32 (node->i.atime);
				newnode.i.mtime = cnv_e32 (node->i.mtime);
				newnode.i.ctime = cnv_e32 (node->i.ctime);
				newnode.i.offset = cnv_e32 (node->i.offset);
				newnode.i.csize = cnv_e32 (node->i.csize);
				newnode.i.dsize = cnv_e32 (node->i.dsize);
				newnode.i.compr = node->i.compr;
				newnode.i.usercompr = node->i.usercompr;
				newnode.i.flags = cnv_e16 (node->i.flags);
				if (recalccrc) {
					len = je32_to_cpu(node->i.csize);
					newnode.i.data_crc = cpu_to_e32 ( mtd_crc32(0, p + sizeof (struct jffs2_raw_inode), len));
				} else
					newnode.i.data_crc = cnv_e32 (node->i.data_crc);

				newnode.i.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_inode) - 8));

				write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_inode));
				write_nocheck (fd, p + sizeof (struct jffs2_raw_inode), PAD (je32_to_cpu (node->i.totlen) -  sizeof (struct jffs2_raw_inode)));

				p += PAD(je32_to_cpu (node->i.totlen));
				break;

			case JFFS2_NODETYPE_DIRENT:
				newnode.d.magic = cnv_e16 (node->d.magic);
				newnode.d.nodetype = cnv_e16 (node->d.nodetype);
				newnode.d.totlen = cnv_e32 (node->d.totlen);
				newnode.d.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
				newnode.d.pino = cnv_e32 (node->d.pino);
				newnode.d.version = cnv_e32 (node->d.version);
				newnode.d.ino = cnv_e32 (node->d.ino);
				newnode.d.mctime = cnv_e32 (node->d.mctime);
				newnode.d.nsize = node->d.nsize;
				newnode.d.type = node->d.type;
				newnode.d.unused[0] = node->d.unused[0];
				newnode.d.unused[1] = node->d.unused[1];
				newnode.d.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_dirent) - 8));
				if (recalccrc)
					newnode.d.name_crc = cpu_to_e32 ( mtd_crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize));
				else
					newnode.d.name_crc = cnv_e32 (node->d.name_crc);

				write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_dirent));
				write_nocheck (fd, p + sizeof (struct jffs2_raw_dirent), PAD (je32_to_cpu (node->d.totlen) -  sizeof (struct jffs2_raw_dirent)));
				p += PAD(je32_to_cpu (node->d.totlen));
				break;

			case JFFS2_NODETYPE_XATTR:
				newnode.x.magic = cnv_e16 (node->x.magic);
				newnode.x.nodetype = cnv_e16 (node->x.nodetype);
				newnode.x.totlen = cnv_e32 (node->x.totlen);
				newnode.x.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
				newnode.x.xid = cnv_e32 (node->x.xid);
				newnode.x.version = cnv_e32 (node->x.version);
				newnode.x.xprefix = node->x.xprefix;
				newnode.x.name_len = node->x.name_len;
				newnode.x.value_len = cnv_e16 (node->x.value_len);
				if (recalccrc)
					newnode.x.data_crc = cpu_to_e32 (mtd_crc32 (0, p + sizeof (struct jffs2_raw_xattr), node->x.name_len + je16_to_cpu (node->x.value_len) + 1));
				else
					newnode.x.data_crc = cnv_e32 (node->x.data_crc);
				newnode.x.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_xattr) - sizeof (newnode.x.node_crc)));

				write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_xattr));
				write_nocheck (fd, p + sizeof (struct jffs2_raw_xattr), PAD (je32_to_cpu (node->d.totlen) -  sizeof (struct jffs2_raw_xattr)));
				p += PAD(je32_to_cpu (node->x.totlen));
				break;

			case JFFS2_NODETYPE_XREF:
				newnode.r.magic = cnv_e16 (node->r.magic);
				newnode.r.nodetype = cnv_e16 (node->r.nodetype);
				newnode.r.totlen = cnv_e32 (node->r.totlen);
				newnode.r.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - sizeof (newnode.r.hdr_crc)));
				newnode.r.ino = cnv_e32 (node->r.ino);
				newnode.r.xid = cnv_e32 (node->r.xid);
				newnode.r.xseqno = cnv_e32 (node->r.xseqno);
				newnode.r.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_xref) - sizeof (newnode.r.node_crc)));
				p += PAD(je32_to_cpu (node->x.totlen));
				break;

			case JFFS2_NODETYPE_CLEANMARKER:
			case JFFS2_NODETYPE_PADDING:
				newnode.u.magic = cnv_e16 (node->u.magic);
				newnode.u.nodetype = cnv_e16 (node->u.nodetype);
				newnode.u.totlen = cnv_e32 (node->u.totlen);
				newnode.u.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));

				write_nocheck (fd, &newnode, sizeof (struct jffs2_unknown_node));
				len = PAD(je32_to_cpu (node->u.totlen) - sizeof (struct jffs2_unknown_node));
				if (len > 0)
					write_nocheck (fd, p + sizeof (struct jffs2_unknown_node), len);

				p += PAD(je32_to_cpu (node->u.totlen));
				break;

			case JFFS2_NODETYPE_SUMMARY : {
											  struct jffs2_sum_marker *sm_ptr;
											  int i,sum_len;
											  int counter = 0;

											  newnode.s.magic = cnv_e16 (node->s.magic);
											  newnode.s.nodetype = cnv_e16 (node->s.nodetype);
											  newnode.s.totlen = cnv_e32 (node->s.totlen);
											  newnode.s.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
											  newnode.s.sum_num = cnv_e32 (node->s.sum_num);
											  newnode.s.cln_mkr = cnv_e32 (node->s.cln_mkr);
											  newnode.s.padded = cnv_e32 (node->s.padded);

											  newnode.s.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_summary) - 8));

											  // summary header
											  p += sizeof (struct jffs2_raw_summary);

											  // summary data
											  sum_len = je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary) - sizeof (struct jffs2_sum_marker);

											  for (i=0; i<je32_to_cpu (node->s.sum_num); i++) {
												  union jffs2_sum_flash *fl_ptr;

												  fl_ptr = (union jffs2_sum_flash *) p;

												  switch (je16_to_cpu (fl_ptr->u.nodetype)) {
													  case JFFS2_NODETYPE_INODE:

														  fl_ptr->i.nodetype = cnv_e16 (fl_ptr->i.nodetype);
														  fl_ptr->i.inode = cnv_e32 (fl_ptr->i.inode);
														  fl_ptr->i.version = cnv_e32 (fl_ptr->i.version);
														  fl_ptr->i.offset = cnv_e32 (fl_ptr->i.offset);
														  fl_ptr->i.totlen = cnv_e32 (fl_ptr->i.totlen);
														  p += sizeof (struct jffs2_sum_inode_flash);
														  counter += sizeof (struct jffs2_sum_inode_flash);
														  break;

													  case JFFS2_NODETYPE_DIRENT:
														  fl_ptr->d.nodetype = cnv_e16 (fl_ptr->d.nodetype);
														  fl_ptr->d.totlen = cnv_e32 (fl_ptr->d.totlen);
														  fl_ptr->d.offset = cnv_e32 (fl_ptr->d.offset);
														  fl_ptr->d.pino = cnv_e32 (fl_ptr->d.pino);
														  fl_ptr->d.version = cnv_e32 (fl_ptr->d.version);
														  fl_ptr->d.ino = cnv_e32 (fl_ptr->d.ino);
														  p += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize;
														  counter += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize;
														  break;

													  case JFFS2_NODETYPE_XATTR:
														  fl_ptr->x.nodetype = cnv_e16 (fl_ptr->x.nodetype);
														  fl_ptr->x.xid = cnv_e32 (fl_ptr->x.xid);
														  fl_ptr->x.version = cnv_e32 (fl_ptr->x.version);
														  fl_ptr->x.offset = cnv_e32 (fl_ptr->x.offset);
														  fl_ptr->x.totlen = cnv_e32 (fl_ptr->x.totlen);
														  p += sizeof (struct jffs2_sum_xattr_flash);
														  counter += sizeof (struct jffs2_sum_xattr_flash);
														  break;

													  case JFFS2_NODETYPE_XREF:
														  fl_ptr->r.nodetype = cnv_e16 (fl_ptr->r.nodetype);
														  fl_ptr->r.offset = cnv_e32 (fl_ptr->r.offset);
														  p += sizeof (struct jffs2_sum_xref_flash);
														  counter += sizeof (struct jffs2_sum_xref_flash);
														  break;

													  default :
														  printf("Unknown node in summary information!!! nodetype(%x)\n", je16_to_cpu (fl_ptr->u.nodetype));
														  exit(EXIT_FAILURE);
														  break;
												  }

											  }

											  //pad
											  p += sum_len - counter;

											  // summary marker
											  sm_ptr = (struct jffs2_sum_marker *) p;
											  sm_ptr->offset = cnv_e32 (sm_ptr->offset);
											  sm_ptr->magic = cnv_e32 (sm_ptr->magic);
											  p += sizeof (struct jffs2_sum_marker);

											  // generate new crc on sum data
											  newnode.s.sum_crc = cpu_to_e32 ( mtd_crc32(0, ((char *) node) + sizeof (struct jffs2_raw_summary),
														  je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary)));

											  // write out new node header
											  write_nocheck(fd, &newnode, sizeof (struct jffs2_raw_summary));
											  // write out new summary data
											  write_nocheck(fd, &node->s.sum, sum_len + sizeof (struct jffs2_sum_marker));

											  break;
										  }

			case 0xffff:
										  write_nocheck (fd, p, 4);
										  p += 4;
										  break;

			default:
										  printf ("Unknown node type: 0x%04x at 0x%08zx, totlen 0x%08x\n", je16_to_cpu (node->u.nodetype), p - data, je32_to_cpu (node->u.totlen));
										  p += PAD(je32_to_cpu (node->u.totlen));

		}
	}

	close (fd);

}
Exemple #7
0
/*
 *	Dump image contents
 */
static void do_dumpcontent (void)
{
	char			*p = data, *p_free_begin;
	union jffs2_node_union 	*node;
	int			empty = 0, dirty = 0;
	char			name[256];
	uint32_t		crc;
	uint16_t		type;
	int			bitchbitmask = 0;
	int			obsolete;

	p_free_begin = NULL;
	while ( p < (data + imglen)) {
		node = (union jffs2_node_union*) p;

		/* Skip empty space */
		if (!p_free_begin)
			p_free_begin = p;
		if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) {
			p += 4;
			empty += 4;
			continue;
		}

		if (p != p_free_begin)
			printf("Empty space found from 0x%08zx to 0x%08zx\n", p_free_begin-data, p-data);
		p_free_begin = NULL;

		if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK)	{
			if (!bitchbitmask++)
				printf ("Wrong bitmask  at  0x%08zx, 0x%04x\n", p - data, je16_to_cpu (node->u.magic));
			p += 4;
			dirty += 4;
			continue;
		}
		bitchbitmask = 0;

		type = je16_to_cpu(node->u.nodetype);
		if ((type & JFFS2_NODE_ACCURATE) != JFFS2_NODE_ACCURATE) {
			obsolete = 1;
			type |= JFFS2_NODE_ACCURATE;
		} else
			obsolete = 0;
		/* Set accurate for CRC check */
		node->u.nodetype = cpu_to_je16(type);

		crc = mtd_crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4);
		if (crc != je32_to_cpu (node->u.hdr_crc)) {
			printf ("Wrong hdr_crc  at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc);
			p += 4;
			dirty += 4;
			continue;
		}

		switch(je16_to_cpu(node->u.nodetype)) {

			case JFFS2_NODETYPE_INODE:
				printf ("%8s Inode      node at 0x%08zx, totlen 0x%08x, #ino  %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n",
						obsolete ? "Obsolete" : "",
						p - data, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino),
						je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize),
						je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset));

				crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_inode) - 8);
				if (crc != je32_to_cpu (node->i.node_crc)) {
					printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.node_crc), crc);
					p += PAD(je32_to_cpu (node->i.totlen));
					dirty += PAD(je32_to_cpu (node->i.totlen));;
					continue;
				}

				crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_inode), je32_to_cpu(node->i.csize));
				if (crc != je32_to_cpu(node->i.data_crc)) {
					printf ("Wrong data_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.data_crc), crc);
					p += PAD(je32_to_cpu (node->i.totlen));
					dirty += PAD(je32_to_cpu (node->i.totlen));;
					continue;
				}

				p += PAD(je32_to_cpu (node->i.totlen));
				break;

			case JFFS2_NODETYPE_DIRENT:
				memcpy (name, node->d.name, node->d.nsize);
				name [node->d.nsize] = 0x0;
				printf ("%8s Dirent     node at 0x%08zx, totlen 0x%08x, #pino %5d, version %5d, #ino  %8d, nsize %8d, name %s\n",
						obsolete ? "Obsolete" : "",
						p - data, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino),
						je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino),
						node->d.nsize, name);

				crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_dirent) - 8);
				if (crc != je32_to_cpu (node->d.node_crc)) {
					printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.node_crc), crc);
					p += PAD(je32_to_cpu (node->d.totlen));
					dirty += PAD(je32_to_cpu (node->d.totlen));;
					continue;
				}

				crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize);
				if (crc != je32_to_cpu(node->d.name_crc)) {
					printf ("Wrong name_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.name_crc), crc);
					p += PAD(je32_to_cpu (node->d.totlen));
					dirty += PAD(je32_to_cpu (node->d.totlen));;
					continue;
				}

				p += PAD(je32_to_cpu (node->d.totlen));
				break;

			case JFFS2_NODETYPE_XATTR:
				memcpy(name, node->x.data, node->x.name_len);
				name[node->x.name_len] = '\x00';
				printf ("%8s Xattr      node at 0x%08zx, totlen 0x%08x, xid   %5d, version %5d, name_len   %3d, name %s\n",
						obsolete ? "Obsolete" : "",
						p - data,
						je32_to_cpu (node->x.totlen),
						je32_to_cpu (node->x.xid),
						je32_to_cpu (node->x.version),
						node->x.name_len,
						name);

				crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_xattr) - sizeof (node->x.node_crc));
				if (crc != je32_to_cpu (node->x.node_crc)) {
					printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->x.node_crc), crc);
					p += PAD(je32_to_cpu (node->x.totlen));
					dirty += PAD(je32_to_cpu (node->x.totlen));
					continue;
				}

				crc = mtd_crc32 (0, p + sizeof (struct jffs2_raw_xattr), node->x.name_len + je16_to_cpu (node->x.value_len) + 1);
				if (crc != je32_to_cpu (node->x.data_crc)) {
					printf ("Wrong data_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->x.data_crc), crc);
					p += PAD(je32_to_cpu (node->x.totlen));
					dirty += PAD(je32_to_cpu (node->x.totlen));
					continue;
				}
				p += PAD(je32_to_cpu (node->x.totlen));
				break;

			case JFFS2_NODETYPE_XREF:
				printf ("%8s Xref       node at 0x%08zx, totlen 0x%08x, xid   %5d, xseqno  %5d, #ino  %8d\n",
						obsolete ? "Obsolete" : "",
						p - data,
						je32_to_cpu (node->r.totlen),
						je32_to_cpu (node->r.xid),
						je32_to_cpu (node->r.xseqno),
						je32_to_cpu (node->r.ino));
				p += PAD(je32_to_cpu (node->r.totlen));
				break;

			case JFFS2_NODETYPE_SUMMARY: {

											 int i;
											 struct jffs2_sum_marker * sm;

											 printf("%8s Inode Sum  node at 0x%08zx, totlen 0x%08x, sum_num  %5d, cleanmarker size %5d\n",
													 obsolete ? "Obsolete" : "",
													 p - data,
													 je32_to_cpu (node->s.totlen),
													 je32_to_cpu (node->s.sum_num),
													 je32_to_cpu (node->s.cln_mkr));

											 crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_summary) - 8);
											 if (crc != je32_to_cpu (node->s.node_crc)) {
												 printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.node_crc), crc);
												 p += PAD(je32_to_cpu (node->s.totlen));
												 dirty += PAD(je32_to_cpu (node->s.totlen));;
												 continue;
											 }

											 crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_summary),  je32_to_cpu (node->s.totlen) - sizeof(struct jffs2_raw_summary));
											 if (crc != je32_to_cpu(node->s.sum_crc)) {
												 printf ("Wrong data_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.sum_crc), crc);
												 p += PAD(je32_to_cpu (node->s.totlen));
												 dirty += PAD(je32_to_cpu (node->s.totlen));;
												 continue;
											 }

											 if (verbose) {
												 void *sp;
												 sp = (p + sizeof(struct jffs2_raw_summary));

												 for(i=0; i<je32_to_cpu(node->s.sum_num); i++) {

													 switch(je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
														 case JFFS2_NODETYPE_INODE : {

																						 struct jffs2_sum_inode_flash *spi;
																						 spi = sp;

																						 printf ("%14s #ino  %5d,  version %5d, offset 0x%08x, totlen 0x%08x\n",
																								 "",
																								 je32_to_cpu (spi->inode),
																								 je32_to_cpu (spi->version),
																								 je32_to_cpu (spi->offset),
																								 je32_to_cpu (spi->totlen));

																						 sp += JFFS2_SUMMARY_INODE_SIZE;
																						 break;
																					 }

														 case JFFS2_NODETYPE_DIRENT : {

																						  char name[255];
																						  struct jffs2_sum_dirent_flash *spd;
																						  spd = sp;

																						  memcpy(name,spd->name,spd->nsize);
																						  name [spd->nsize] = 0x0;

																						  printf ("%14s dirent offset 0x%08x, totlen 0x%08x, #pino  %5d,  version %5d, #ino  %8d, nsize %8d, name %s \n",
																								  "",
																								  je32_to_cpu (spd->offset),
																								  je32_to_cpu (spd->totlen),
																								  je32_to_cpu (spd->pino),
																								  je32_to_cpu (spd->version),
																								  je32_to_cpu (spd->ino),
																								  spd->nsize,
																								  name);

																						  sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
																						  break;
																					  }

														 case JFFS2_NODETYPE_XATTR : {
																						  struct jffs2_sum_xattr_flash *spx;
																						  spx = sp;
																						  printf ("%14s Xattr  offset 0x%08x, totlen 0x%08x, version %5d, #xid %8d\n",
																								  "",
																								  je32_to_cpu (spx->offset),
																								  je32_to_cpu (spx->totlen),
																								  je32_to_cpu (spx->version),
																								  je32_to_cpu (spx->xid));
																						  sp += JFFS2_SUMMARY_XATTR_SIZE;
																						  break;
																					  }

														 case JFFS2_NODETYPE_XREF : {
																						  struct jffs2_sum_xref_flash *spr;
																						  spr = sp;
																						  printf ("%14s Xref   offset 0x%08x\n",
																								  "",
																								  je32_to_cpu (spr->offset));
																						  sp += JFFS2_SUMMARY_XREF_SIZE;
																						  break;
																					  }

														 default :
																					  printf("Unknown summary node!\n");
																					  break;
													 }
												 }

												 sm = (struct jffs2_sum_marker *) ((char *)p + je32_to_cpu(node->s.totlen) - sizeof(struct jffs2_sum_marker));

												 printf("%14s Sum Node Offset  0x%08x, Magic 0x%08x, Padded size 0x%08x\n",
														 "",
														 je32_to_cpu(sm->offset),
														 je32_to_cpu(sm->magic),
														 je32_to_cpu(node->s.padded));
											 }

											 p += PAD(je32_to_cpu (node->s.totlen));
											 break;
										 }

			case JFFS2_NODETYPE_CLEANMARKER:
										 if (verbose) {
											 printf ("%8s Cleanmarker     at 0x%08zx, totlen 0x%08x\n",
													 obsolete ? "Obsolete" : "",
													 p - data, je32_to_cpu (node->u.totlen));
										 }
										 p += PAD(je32_to_cpu (node->u.totlen));
										 break;

			case JFFS2_NODETYPE_PADDING:
										 if (verbose) {
											 printf ("%8s Padding    node at 0x%08zx, totlen 0x%08x\n",
													 obsolete ? "Obsolete" : "",
													 p - data, je32_to_cpu (node->u.totlen));
										 }
										 p += PAD(je32_to_cpu (node->u.totlen));
										 break;

			case 0xffff:
										 p += 4;
										 empty += 4;
										 break;

			default:
										 if (verbose) {
											 printf ("%8s Unknown    node at 0x%08zx, totlen 0x%08x\n",
													 obsolete ? "Obsolete" : "",
													 p - data, je32_to_cpu (node->u.totlen));
										 }
										 p += PAD(je32_to_cpu (node->u.totlen));
										 dirty += PAD(je32_to_cpu (node->u.totlen));

		}
	}

	if (verbose)
		printf ("Empty space: %d, dirty space: %d\n", empty, dirty);
}
Exemple #8
0
/**
 * ubi_write_fastmap - writes a fastmap.
 * @ubi: UBI device object
 * @new_fm: the to be written fastmap
 *
 * Returns 0 on success, < 0 indicates an internal error.
 */
static int ubi_write_fastmap(struct ubigen_info *ubi,
			     struct ubi_fastmap_layout *new_fm, 
			     struct ubigen_vol_info *vi, 
			     int vc,
			     int out_fd)
{
	size_t fm_pos = 0;
	char *fm_raw;
	struct ubi_fm_sb *fmsb;
	struct ubi_fm_hdr *fmh;
	struct ubi_fm_scan_pool *fmpl1, *fmpl2;
	struct ubi_fm_ec *fec;
	struct ubi_fm_volhdr *fvh;
	struct ubi_fm_eba *feba;
	struct ubigen_vol_info *vol;
	struct ubi_vid_hdr *vid_hdr;
	int ret, i, j, free_peb_count, used_peb_count, vol_count;
	int scrub_peb_count, erase_peb_count;
	struct ubigen_vol_info fm_vi;
	int free_start;

	memset(&fm_vi, 0, sizeof(struct ubigen_vol_info));

        fm_vi.id = UBI_FM_SB_VOLUME_ID;
        fm_vi.type = UBI_VID_DYNAMIC;
        fm_vi.compat = UBI_COMPAT_DELETE;


	fm_raw = malloc(ubi->peb_size);
	memset(fm_raw, 0, ubi->peb_size);

	ubigen_init_ec_hdr(ubi, (struct ubi_ec_hdr *)fm_raw, ubi->ec);

	vid_hdr = (struct ubi_vid_hdr *)(fm_raw + ubi->vid_hdr_offs);
	ubigen_init_vid_hdr(ubi, &fm_vi, vid_hdr, 0, 1, NULL, 0);
	fm_pos += ubi->data_offs;

	fmsb = (struct ubi_fm_sb *)(fm_raw + fm_pos);
	fm_pos += sizeof(*fmsb);

	fmh = (struct ubi_fm_hdr *)(fm_raw + fm_pos);
	fm_pos += sizeof(*fmh);

	fmsb->magic = cpu_to_be32(UBI_FM_SB_MAGIC);
	fmsb->version = UBI_FM_FMT_VERSION;
	fmsb->used_blocks = cpu_to_be32(new_fm->used_blocks);

	fmh->magic = cpu_to_be32(UBI_FM_HDR_MAGIC);
	free_peb_count = 0;
	used_peb_count = 0;
	scrub_peb_count = 0;
	erase_peb_count = 0;
	vol_count = 0;

	fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
	fm_pos += sizeof(*fmpl1);
	fmpl1->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
	fmpl1->size = cpu_to_be16(ubi->fm_pool.size);
	fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size);

	for (i = 0; i < ubi->fm_pool.size; i++)
		fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);

	fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
	fm_pos += sizeof(*fmpl2);
	fmpl2->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
	fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size);
	fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);

	for (i = 0; i < ubi->fm_wl_pool.size; i++)
		fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);

	free_start = ubi->used_peb + ubi->fm_pool.size + ubi->fm_wl_pool.size;

	fmh->free_peb_count = cpu_to_be32(free_peb_count); //0
	/* used list*/
	for (i = 0 ; i < ubi->used_peb; i++) {
		if(i == 2) //Skip PEB 2
			continue;
		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);

		fec->pnum = cpu_to_be32(i);
		fec->ec = cpu_to_be32(ubi->ec);

		used_peb_count++;
		fm_pos += sizeof(*fec);
	}
	fmh->used_peb_count = cpu_to_be32(used_peb_count);

	fmh->scrub_peb_count = cpu_to_be32(scrub_peb_count); //0
	/* empty pebs to erase*/
	for (i = free_start ; i < ubi->peb_count; i++) {
		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);

		fec->pnum = cpu_to_be32(i);
		fec->ec = cpu_to_be32(ubi->ec);

		erase_peb_count++;
		fm_pos += sizeof(*fec);
	}
	fmh->erase_peb_count = cpu_to_be32(erase_peb_count);

	for (i = 0; i < vc; i++) {
		int32_t tmp, reserved_pebs;
		vol = &vi[i];

		if (vol->bytes == 0)
			continue;

		vol_count++;

		fvh = (struct ubi_fm_volhdr *)(fm_raw + fm_pos);
		fm_pos += sizeof(*fvh);

		fvh->magic = cpu_to_be32(UBI_FM_VHDR_MAGIC);
		fvh->vol_id = cpu_to_be32(vol->id);
		fvh->vol_type = UBI_DYNAMIC_VOLUME;
		reserved_pebs = (vol->bytes + ubi->leb_size - 1) / ubi->leb_size;
		fvh->used_ebs = cpu_to_be32(reserved_pebs);
		tmp = ubi->leb_size % vol->alignment;
		fvh->data_pad = cpu_to_be32(tmp);
		fvh->last_eb_bytes = cpu_to_be32(vol->usable_leb_size);


		feba = (struct ubi_fm_eba *)(fm_raw + fm_pos);
		fm_pos += sizeof(*feba) + (sizeof(__be32) * reserved_pebs);

		printf("vol %d reserved_pebs %d\n", i, reserved_pebs);
		printf("vol %d start %d stop %d\n", i, vol->start, vol->stop);
		for (j = 0; j < reserved_pebs; j++) {
			if(vol->start > 0 && j < vol->stop - vol->start) 
				feba->pnum[j] = cpu_to_be32(vol->start+j);
			else
				feba->pnum[j] = cpu_to_be32(-1);
		}

		feba->reserved_pebs = cpu_to_be32(reserved_pebs);
		feba->magic = cpu_to_be32(UBI_FM_EBA_MAGIC);
	}
	//for vol table 
	{
		uint32_t tmp;

		vol_count++;

		fvh = (struct ubi_fm_volhdr *)(fm_raw + fm_pos);
		fm_pos += sizeof(*fvh);

		fvh->magic = cpu_to_be32(UBI_FM_VHDR_MAGIC);
		fvh->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID);
		fvh->vol_type = UBI_DYNAMIC_VOLUME;
		fvh->used_ebs = cpu_to_be32(UBI_LAYOUT_VOLUME_EBS);
		tmp = ubi->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
		fvh->data_pad = cpu_to_be32(tmp);
		fvh->last_eb_bytes = cpu_to_be32(UBI_LAYOUT_VOLUME_EBS);


		feba = (struct ubi_fm_eba *)(fm_raw + fm_pos);
		fm_pos += sizeof(*feba) + (sizeof(__be32) * UBI_LAYOUT_VOLUME_EBS);

		for (j = 0; j < UBI_LAYOUT_VOLUME_EBS; j++)
			feba->pnum[j] = cpu_to_be32(j);

		feba->reserved_pebs = cpu_to_be32(UBI_LAYOUT_VOLUME_EBS);
		feba->magic = cpu_to_be32(UBI_FM_EBA_MAGIC);
	}
	fmh->vol_count = cpu_to_be32(vol_count);
	fmh->bad_peb_count = cpu_to_be32(0);

	vid_hdr->lnum = 0;


	for (i = 0; i < new_fm->used_blocks; i++) {
		fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum);
		fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec);
	}

	fmsb->data_crc = 0;
	fmsb->data_crc = cpu_to_be32(mtd_crc32(UBI_CRC32_INIT, fmsb,
					   ubi->fm_size));

	for (i = 0; i < new_fm->used_blocks; i++) {
		off_t seek = ubi->peb_size*(2+i);
		printf("writing fastmap SB to PEB %i\n", new_fm->e[i]->pnum);
		if(lseek(out_fd, seek, SEEK_SET) != seek) {
			sys_errmsg("cannot seek output file");
			goto out_free;
		}
		ret = write(out_fd, fm_raw, ubi->peb_size);
		if (ret != ubi->peb_size) {
			sys_errmsg("cannot write %d bytes", ubi->peb_size);
			goto out_free;
		} else 
			ret = 0;
	}

	printf("fastmap written!");

out_free:
	free(fm_raw);

	return ret;
}
Exemple #9
0
int ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
	     int verbose)
{
	int eb, v = (verbose == 2), pr = (verbose == 1);
	struct ubi_scan_info *si;
	unsigned long long sum = 0;

	si = calloc(1, sizeof(struct ubi_scan_info));
	if (!si)
		return sys_errmsg("cannot allocate %zd bytes of memory",
				  sizeof(struct ubi_scan_info));

	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
	if (!si->ec) {
		sys_errmsg("cannot allocate %zd bytes of memory",
			   sizeof(struct ubi_scan_info));
		goto out_si;
	}

	si->vid_hdr_offs = si->data_offs = -1;

	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
	for (eb = 0; eb < mtd->eb_cnt; eb++) {
		int ret;
		uint32_t crc;
		struct ubi_ec_hdr ech;
		unsigned long long ec;

		if (v) {
			normsg_cont("scanning eraseblock %d", eb);
			fflush(stdout);
		}
		if (pr) {
			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
			fflush(stdout);
		}

		ret = mtd_is_bad(mtd, fd, eb);
		if (ret == -1)
			goto out_ec;
		if (ret) {
			si->bad_cnt += 1;
			si->ec[eb] = EB_BAD;
			if (v)
				printf(": bad\n");
			continue;
		}

		ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
		if (ret < 0)
			goto out_ec;

		if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
			if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
				si->empty_cnt += 1;
				si->ec[eb] = EB_EMPTY;
				if (v)
					printf(": empty\n");
			} else {
				si->alien_cnt += 1;
				si->ec[eb] = EB_ALIEN;
				if (v)
					printf(": alien\n");
			}
			continue;
		}

		crc = mtd_crc32(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC);
		if (be32_to_cpu(ech.hdr_crc) != crc) {
			si->corrupted_cnt += 1;
			si->ec[eb] = EB_CORRUPTED;
			if (v)
				printf(": bad CRC %#08x, should be %#08x\n",
				       crc, be32_to_cpu(ech.hdr_crc));
			continue;
		}

		ec = be64_to_cpu(ech.ec);
		if (ec > EC_MAX) {
			if (pr)
				printf("\n");
			errmsg("erase counter in EB %d is %llu, while this "
			       "program expects them to be less than %u",
			       eb, ec, EC_MAX);
			goto out_ec;
		}

		if (si->vid_hdr_offs == -1) {
			si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset);
			si->data_offs = be32_to_cpu(ech.data_offset);
			if (si->data_offs % mtd->min_io_size) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("bad data offset %d at eraseblock %d (n"
					"of multiple of min. I/O unit size %d)",
					si->data_offs, eb, mtd->min_io_size);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;

			}
		} else {
			if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("inconsistent VID header offset: was "
					"%d, but is %d in eraseblock %d",
					si->vid_hdr_offs,
					be32_to_cpu(ech.vid_hdr_offset), eb);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;
			}
			if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("inconsistent data offset: was %d, but"
					" is %d in eraseblock %d",
					si->data_offs,
					be32_to_cpu(ech.data_offset), eb);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;
			}
		}

		si->ok_cnt += 1;
		si->ec[eb] = ec;
		if (v)
			printf(": OK, erase counter %u\n", si->ec[eb]);
	}

	if (si->ok_cnt != 0) {
		/* Calculate mean erase counter */
		for (eb = 0; eb < mtd->eb_cnt; eb++) {
			if (si->ec[eb] > EC_MAX)
				continue;
			sum += si->ec[eb];
		}
		si->mean_ec = sum / si->ok_cnt;
	}

	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
		si->empty_cnt, si->alien_cnt, si->bad_cnt);

	*info = si;
	if (pr)
		printf("\n");
	return 0;

out_ec:
	free(si->ec);
out_si:
	free(si);
	*info = NULL;
	return -1;
}
Exemple #10
0
int main(int argc, char **argv)
{
	struct addrinfo *ai;
	struct addrinfo hints;
	struct addrinfo *runp;
	int ret;
	int sock;
	struct image_pkt pktbuf;
	int rfd;
	struct stat st;
	int writeerrors = 0;
	uint32_t erasesize;
	unsigned char *image, *blockptr = NULL;
	uint32_t block_nr, pkt_nr;
	int nr_blocks;
	struct timeval then, now, nextpkt;
	long time_msecs;
	int pkts_per_block;
	int total_pkts_per_block;
	struct fec_parms *fec;
	unsigned char *last_block;
	uint32_t *block_crcs;
	long tosleep;
	uint32_t sequence = 0;

	if (argc == 6) {
		tx_rate = atol(argv[5]) * 1024;
		if (tx_rate < PKT_SIZE || tx_rate > 20000000) {
			fprintf(stderr, "Bogus TX rate %d KiB/s\n", tx_rate);
			exit(1);
		}
		argc = 5;
	}
	if (argc != 5) {
		fprintf(stderr, "usage: %s <host> <port> <image> <erasesize> [<tx_rate>]\n",
			PROGRAM_NAME);
		exit(1);
	}
	pkt_delay = (sizeof(pktbuf) * 1000000) / tx_rate;
	printf("Inter-packet delay (avg): %dµs\n", pkt_delay);
	printf("Transmit rate: %d KiB/s\n", tx_rate / 1024);

	erasesize = atol(argv[4]);
	if (!erasesize) {
		fprintf(stderr, "erasesize cannot be zero\n");
		exit(1);
	}

	pkts_per_block = (erasesize + PKT_SIZE - 1) / PKT_SIZE;
	total_pkts_per_block = pkts_per_block * 3 / 2;

	/* We have to pad it with zeroes, so can't use it in-place */
	last_block = malloc(pkts_per_block * PKT_SIZE);
	if (!last_block) {
		fprintf(stderr, "Failed to allocate last-block buffer\n");
		exit(1);
	}

	fec = fec_new(pkts_per_block, total_pkts_per_block);
	if (!fec) {
		fprintf(stderr, "Error initialising FEC\n");
		exit(1);
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_DGRAM;

	ret = getaddrinfo(argv[1], argv[2], &hints, &ai);
	if (ret) {
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
		exit(1);
	}
	runp = ai;
	for (runp = ai; runp; runp = runp->ai_next) {
		sock = socket(runp->ai_family, runp->ai_socktype,
			      runp->ai_protocol);
		if (sock == -1) {
			perror("socket");
			continue;
		}
		if (connect(sock, runp->ai_addr, runp->ai_addrlen) == 0)
			break;
		perror("connect");
		close(sock);
	}
	if (!runp)
		exit(1);

	rfd = open(argv[3], O_RDONLY);
	if (rfd < 0) {
		perror("open");
		exit(1);
	}

	if (fstat(rfd, &st)) {
		perror("fstat");
		exit(1);
	}

	if (st.st_size % erasesize) {
		fprintf(stderr, "Image size %" PRIu64 " bytes is not a multiple of erasesize %d bytes\n",
				st.st_size, erasesize);
		exit(1);
	}
	image = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, rfd, 0);
	if (image == MAP_FAILED) {
		perror("mmap");
		exit(1);
	}

	nr_blocks = st.st_size / erasesize;

	block_crcs = malloc(nr_blocks * sizeof(uint32_t));
	if (!block_crcs) {
		fprintf(stderr, "Failed to allocate memory for CRCs\n");
		exit(1);
	}

	memcpy(last_block, image + (nr_blocks - 1) * erasesize, erasesize);
	memset(last_block + erasesize, 0, (PKT_SIZE * pkts_per_block) - erasesize);

	printf("Checking CRC....");
	fflush(stdout);

	pktbuf.hdr.resend = 0;
	pktbuf.hdr.totcrc = htonl(mtd_crc32(-1, image, st.st_size));
	pktbuf.hdr.nr_blocks = htonl(nr_blocks);
	pktbuf.hdr.blocksize = htonl(erasesize);
	pktbuf.hdr.thislen = htonl(PKT_SIZE);
	pktbuf.hdr.nr_pkts = htons(total_pkts_per_block);

	printf("%08x\n", ntohl(pktbuf.hdr.totcrc));
	printf("Checking block CRCs....");
	fflush(stdout);
	for (block_nr=0; block_nr < nr_blocks; block_nr++) {
		printf("\rChecking block CRCS.... %d/%d",
		       block_nr + 1, nr_blocks);
		fflush(stdout);
		block_crcs[block_nr] = mtd_crc32(-1, image + (block_nr * erasesize), erasesize);
	}

	printf("\nImage size %ld KiB (0x%08lx). %d blocks at %d pkts/block\n"
	       "Estimated transmit time per cycle: %ds\n",
	       (long)st.st_size / 1024, (long) st.st_size,
	       nr_blocks, pkts_per_block,
	       nr_blocks * pkts_per_block * pkt_delay / 1000000);
	gettimeofday(&then, NULL);
	nextpkt = then;

#ifdef RANDOMDROP
	srand((unsigned)then.tv_usec);
	printf("Random seed %u\n", (unsigned)then.tv_usec);
#endif
	while (1) for (pkt_nr=0; pkt_nr < total_pkts_per_block; pkt_nr++) {

		if (blockptr && pkt_nr == 0) {
			unsigned long amt_sent = total_pkts_per_block * nr_blocks * sizeof(pktbuf);
			gettimeofday(&now, NULL);

			time_msecs = (now.tv_sec - then.tv_sec) * 1000;
			time_msecs += ((int)(now.tv_usec - then.tv_usec)) / 1000;
			printf("\n%ld KiB sent in %ldms (%ld KiB/s)\n",
			       amt_sent / 1024, time_msecs,
			       amt_sent / 1024 * 1000 / time_msecs);
			then = now;
		}

		for (block_nr = 0; block_nr < nr_blocks; block_nr++) {

			int actualpkt;

			/* Calculating the redundant FEC blocks is expensive;
			   the first $pkts_per_block are cheap enough though
			   because they're just copies. So alternate between
			   simple and complex stuff, so that we don't start
			   to choke and fail to keep up with the expected
			   bitrate in the second half of the sequence */
			if (block_nr & 1)
				actualpkt = pkt_nr;
			else
				actualpkt = total_pkts_per_block - 1 - pkt_nr;

			blockptr = image + (erasesize * block_nr);
			if (block_nr == nr_blocks - 1)
				blockptr = last_block;

			fec_encode_linear(fec, blockptr, pktbuf.data, actualpkt, PKT_SIZE);

			pktbuf.hdr.thiscrc = htonl(mtd_crc32(-1, pktbuf.data, PKT_SIZE));
			pktbuf.hdr.block_crc = htonl(block_crcs[block_nr]);
			pktbuf.hdr.block_nr = htonl(block_nr);
			pktbuf.hdr.pkt_nr = htons(actualpkt);
			pktbuf.hdr.pkt_sequence = htonl(sequence++);

			printf("\rSending data block %08x packet %3d/%d",
			       block_nr * erasesize,
			       pkt_nr, total_pkts_per_block);

			if (pkt_nr && !block_nr) {
				unsigned long amt_sent = pkt_nr * nr_blocks * sizeof(pktbuf);

				gettimeofday(&now, NULL);

				time_msecs = (now.tv_sec - then.tv_sec) * 1000;
				time_msecs += ((int)(now.tv_usec - then.tv_usec)) / 1000;
				printf("    (%ld KiB/s)    ",
				       amt_sent / 1024 * 1000 / time_msecs);
			}

			fflush(stdout);

#ifdef RANDOMDROP
			if ((rand() % 1000) < 20) {
				printf("\nDropping packet %d of block %08x\n", pkt_nr+1, block_nr * erasesize);
				continue;
			}
#endif
			gettimeofday(&now, NULL);
#if 1
			tosleep = nextpkt.tv_usec - now.tv_usec +
				(1000000 * (nextpkt.tv_sec - now.tv_sec));

			/* We need hrtimers for this to actually work */
			if (tosleep > 0) {
				struct timespec req;

				req.tv_nsec = (tosleep % 1000000) * 1000;
				req.tv_sec = tosleep / 1000000;

				nanosleep(&req, NULL);
			}
#else
			while (now.tv_sec < nextpkt.tv_sec ||
				 (now.tv_sec == nextpkt.tv_sec &&
				  now.tv_usec < nextpkt.tv_usec)) {
				gettimeofday(&now, NULL);
			}
#endif
			nextpkt.tv_usec += pkt_delay;
			if (nextpkt.tv_usec >= 1000000) {
				nextpkt.tv_sec += nextpkt.tv_usec / 1000000;
				nextpkt.tv_usec %= 1000000;
			}

			/* If the time for the next packet has already
			   passed (by some margin), then we've lost time
			   Adjust our expected timings accordingly. If
			   we're only a little way behind, don't slip yet */
			if (now.tv_usec > (now.tv_usec + (5 * pkt_delay) +
					1000000 * (nextpkt.tv_sec - now.tv_sec))) {
				nextpkt = now;
			}

			if (write(sock, &pktbuf, sizeof(pktbuf)) < 0) {
				perror("write");
				writeerrors++;
				if (writeerrors > 10) {
					fprintf(stderr, "Too many consecutive write errors\n");
					exit(1);
				}
			} else
				writeerrors = 0;



		}
	}
	munmap(image, st.st_size);
	close(rfd);
	close(sock);
	return 0;
}
Exemple #11
0
int main (int argc, char *argv[])
{
	libmtd_t mtd_desc;
	struct mtd_dev_info mtd;
	int fd, clmpos = 0, clmlen = 8, eb;
	int isNAND, bbtest = 1;
	int error = 0;
	uint64_t offset = 0;

	exe_name = argv[0];
	for (;;) {
		int option_index = 0;
		static const char *short_options = "jq";
		static const struct option long_options[] = {
			{"help", no_argument, 0, 0},
			{"version", no_argument, 0, 0},
			{"jffs2", no_argument, 0, 'j'},
			{"quiet", no_argument, 0, 'q'},
			{"silent", no_argument, 0, 'q'},

			{0, 0, 0, 0},
		};

		int c = getopt_long(argc, argv, short_options,
				long_options, &option_index);
		if (c == EOF)
			break;

		switch (c) {
		case 0:
			switch (option_index) {
			case 0:
				display_help();
				return 0;
			case 1:
				display_version();
				return 0;
			}
			break;
		case 'q':
			quiet = 1;
			break;
		case 'j':
			jffs2 = 1;
			break;
		case '?':
			error = 1;
			break;
		}
	}
	if (optind == argc) {
		fprintf(stderr, "%s: no MTD device specified\n", exe_name);
		error = 1;
	}
	if (error) {
		fprintf(stderr, "Try `%s --help' for more information.\n",
				exe_name);
		return 1;
	}
	mtd_device = argv[optind];

	mtd_desc = libmtd_open();
	if (mtd_desc == NULL) {
		fprintf(stderr, "%s: can't initialize libmtd\n", exe_name);
		return 1;
	}

	if ((fd = open(mtd_device, O_RDWR)) < 0) {
		fprintf(stderr, "%s: %s: %s\n", exe_name, mtd_device, strerror(errno));
		return 1;
	}

	if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0) {
		fprintf(stderr, "%s: mtd_get_dev_info failed\n", exe_name);
		return 1;
	}

	isNAND = mtd.type == MTD_NANDFLASH ? 1 : 0;

	if (jffs2) {
		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
		if (!isNAND)
			cleanmarker.totlen = cpu_to_je32 (sizeof (struct jffs2_unknown_node));
		else {
			struct nand_oobinfo oobinfo;

			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
				fprintf(stderr, "%s: %s: unable to get NAND oobinfo\n", exe_name, mtd_device);
				return 1;
			}

			/* Check for autoplacement */
			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
				/* Get the position of the free bytes */
				if (!oobinfo.oobfree[0][1]) {
					fprintf (stderr, " Eeep. Autoplacement selected and no empty space in oob\n");
					return 1;
				}
				clmpos = oobinfo.oobfree[0][0];
				clmlen = oobinfo.oobfree[0][1];
				if (clmlen > 8)
					clmlen = 8;
			} else {
				/* Legacy mode */
				switch (mtd.oob_size) {
					case 8:
						clmpos = 6;
						clmlen = 2;
						break;
					case 16:
						clmpos = 8;
						clmlen = 8;
						break;
					case 64:
						clmpos = 16;
						clmlen = 8;
						break;
				}
			}
			cleanmarker.totlen = cpu_to_je32(8);
		}
		cleanmarker.hdr_crc =  cpu_to_je32 (mtd_crc32 (0, &cleanmarker,  sizeof (struct jffs2_unknown_node) - 4));
	}

	for (eb = 0; eb < (mtd.size / mtd.eb_size); eb++) {
		offset = eb * mtd.eb_size;
		if (bbtest) {
			int ret = mtd_is_bad(&mtd, fd, eb);
			if (ret > 0) {
				if (!quiet)
					printf ("\nSkipping bad block at 0x%08llx\n", (unsigned long long)offset);
				continue;
			} else if (ret < 0) {
				if (errno == EOPNOTSUPP) {
					bbtest = 0;
					if (isNAND) {
						fprintf(stderr, "%s: %s: Bad block check not available\n", exe_name, mtd_device);
						return 1;
					}
				} else {
					fprintf(stderr, "\n%s: %s: MTD get bad block failed: %s\n", exe_name, mtd_device, strerror(errno));
					return 1;
				}
			}
		}

		if (!quiet)
			show_progress(&mtd, offset);

		if (mtd_erase(mtd_desc, &mtd, fd, eb) != 0) {
			fprintf(stderr, "\n%s: %s: MTD Erase failure: %s\n", exe_name, mtd_device, strerror(errno));
			continue;
		}

		/* format for JFFS2 ? */
		if (!jffs2)
			continue;

		/* write cleanmarker */
		if (isNAND) {
			if (mtd_write_oob(mtd_desc, &mtd, fd, offset + clmpos, clmlen, &cleanmarker) != 0) {
				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
				continue;
			}
		} else {
			if (lseek (fd, (loff_t)offset, SEEK_SET) < 0) {
				fprintf(stderr, "\n%s: %s: MTD lseek failure: %s\n", exe_name, mtd_device, strerror(errno));
				continue;
			}
			if (write (fd , &cleanmarker, sizeof (cleanmarker)) != sizeof (cleanmarker)) {
				fprintf(stderr, "\n%s: %s: MTD write failure: %s\n", exe_name, mtd_device, strerror(errno));
				continue;
			}
		}
		if (!quiet)
			printf (" Cleanmarker written at %llx.", (unsigned long long)offset);
	}
	if (!quiet) {
		show_progress(&mtd, offset);
		printf("\n");
	}

	return 0;
}
Exemple #12
0
int main(int argc, char *argv[])
{
	libmtd_t mtd_desc;
	struct mtd_dev_info mtd;
	int fd, clmpos = 0, clmlen = 8;
	unsigned long long start;
	unsigned int eb, eb_start, eb_cnt;
	int isNAND;
	int error = 0;
	off_t offset = 0;

	/*
	 * Process user arguments
	 */
	for (;;) {
		int option_index = 0;
		static const char *short_options = "jNqu";
		static const struct option long_options[] = {
			{"help", no_argument, 0, 0},
			{"version", no_argument, 0, 0},
			{"jffs2", no_argument, 0, 'j'},
			{"noskipbad", no_argument, 0, 'N'},
			{"quiet", no_argument, 0, 'q'},
			{"silent", no_argument, 0, 'q'},
			{"unlock", no_argument, 0, 'u'},

			{0, 0, 0, 0},
		};

		int c = getopt_long(argc, argv, short_options,
				long_options, &option_index);
		if (c == EOF)
			break;

		switch (c) {
		case 0:
			switch (option_index) {
			case 0:
				display_help();
				return 0;
			case 1:
				display_version();
				return 0;
			}
			break;
		case 'j':
			jffs2 = 1;
			break;
		case 'N':
			noskipbad = 1;
			break;
		case 'q':
			quiet = 1;
			break;
		case 'u':
			unlock = 1;
			break;
		case '?':
			error = 1;
			break;
		}
	}
	switch (argc - optind) {
	case 3:
		mtd_device = argv[optind];
		start = simple_strtoull(argv[optind + 1], &error);
		eb_cnt = simple_strtoul(argv[optind + 2], &error);
		break;
	default:
	case 0:
		errmsg("no MTD device specified");
	case 1:
		errmsg("no start erase block specified");
	case 2:
		errmsg("no erase block count specified");
		error = 1;
		break;
	}
	if (error)
		return errmsg("Try `--help' for more information");

	/*
	 * Locate MTD and prepare for erasure
	 */
	mtd_desc = libmtd_open();
	if (mtd_desc == NULL)
		return errmsg("can't initialize libmtd");

	if ((fd = open(mtd_device, O_RDWR)) < 0)
		return sys_errmsg("%s", mtd_device);

	if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0)
		return errmsg("mtd_get_dev_info failed");

	eb_start = start / mtd.eb_size;

	isNAND = mtd.type == MTD_NANDFLASH ? 1 : 0;

	if (jffs2) {
		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
		if (!isNAND)
			cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
		else {
			struct nand_oobinfo oobinfo;

			if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0)
				return sys_errmsg("%s: unable to get NAND oobinfo", mtd_device);

			/* Check for autoplacement */
			if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
				/* Get the position of the free bytes */
				if (!oobinfo.oobfree[0][1])
					return errmsg(" Eeep. Autoplacement selected and no empty space in oob");
				clmpos = oobinfo.oobfree[0][0];
				clmlen = oobinfo.oobfree[0][1];
				if (clmlen > 8)
					clmlen = 8;
			} else {
				/* Legacy mode */
				switch (mtd.oob_size) {
					case 8:
						clmpos = 6;
						clmlen = 2;
						break;
					case 16:
						clmpos = 8;
						clmlen = 8;
						break;
					case 64:
						clmpos = 16;
						clmlen = 8;
						break;
				}
			}
			cleanmarker.totlen = cpu_to_je32(8);
		}
		cleanmarker.hdr_crc = cpu_to_je32(mtd_crc32(0, &cleanmarker, sizeof(cleanmarker) - 4));
	}

	/*
	 * Now do the actual erasing of the MTD device
	 */
	if (eb_cnt == 0)
		eb_cnt = (mtd.size / mtd.eb_size) - eb_start;

	for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
		offset = (off_t)eb * mtd.eb_size;

		if (!noskipbad) {
			int ret = mtd_is_bad(&mtd, fd, eb);
			if (ret > 0) {
				verbose(!quiet, "Skipping bad block at %08"PRIxoff_t, offset);
				continue;
			} else if (ret < 0) {
				if (errno == EOPNOTSUPP) {
					noskipbad = 1;
					if (isNAND)
						return errmsg("%s: Bad block check not available", mtd_device);
				} else
					return sys_errmsg("%s: MTD get bad block failed", mtd_device);
			}
		}

		show_progress(&mtd, offset, eb, eb_start, eb_cnt);

		if (unlock) {
			if (mtd_unlock(&mtd, fd, eb) != 0) {
				sys_errmsg("%s: MTD unlock failure", mtd_device);
				continue;
			}
		}

		if (mtd_erase(mtd_desc, &mtd, fd, eb) != 0) {
			sys_errmsg("%s: MTD Erase failure", mtd_device);
			continue;
		}

		/* format for JFFS2 ? */
		if (!jffs2)
			continue;

		/* write cleanmarker */
		if (isNAND) {
			if (mtd_write_oob(mtd_desc, &mtd, fd, (uint64_t)offset + clmpos, clmlen, &cleanmarker) != 0) {
				sys_errmsg("%s: MTD writeoob failure", mtd_device);
				continue;
			}
		} else {
			if (lseek(fd, offset, SEEK_SET) < 0) {
				sys_errmsg("%s: MTD lseek failure", mtd_device);
				continue;
			}
			if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
				sys_errmsg("%s: MTD write failure", mtd_device);
				continue;
			}
		}
		verbose(!quiet, " Cleanmarker written at %"PRIxoff_t, offset);
	}
	show_progress(&mtd, offset, eb, eb_start, eb_cnt);
	bareverbose(!quiet, "\n");

	return 0;
}