Exemplo n.º 1
0
static int scan_pool(struct ubi_scan_info *ubi, __be32 *pebs, int pool_size)
{
	struct ubi_vid_hdr *vh;
	u32 pnum;
	int i;

	ubi_dbg("Scanning pool size: %d", pool_size);

	for (i = 0; i < pool_size; i++) {
		pnum = be32_to_cpu(pebs[i]);

		if (ubi_io_is_bad(ubi, pnum)) {
			ubi_err("FM: Bad PEB in fastmap pool! %u", pnum);
			return UBI_BAD_FASTMAP;
		}

		vh = ubi->blockinfo + pnum;
		/*
		 * We allow the scan to fail here. The loader will notice
		 * and look for a replacement.
		 */
		ubi_scan_vid_hdr(ubi, vh, pnum);
	}
	return 0;
}
Exemplo n.º 2
0
static int ubi_scan_vid_hdr(struct ubi_scan_info *ubi, struct ubi_vid_hdr *vh,
			    u32 pnum)
{
	u32 vol_id, lnum;
	int res;

	if (ubi_io_is_bad(ubi, pnum))
		return -EINVAL;

	res = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
	if (res)
		return res;

	/* Get volume id */
	vol_id = be32_to_cpu(vh->vol_id);

	/* If this is the fastmap anchor, return right away */
	if (vol_id == UBI_FM_SB_VOLUME_ID)
		return ubi->fm_enabled ? UBI_FASTMAP_ANCHOR : 0;

	/* We only care about static volumes with an id < UBI_SPL_VOL_IDS */
	if (vol_id >= UBI_SPL_VOL_IDS || vh->vol_type != UBI_VID_STATIC)
		return 0;

	/* We are only interested in the volumes to load */
	if (!test_bit(vol_id, ubi->toload))
		return 0;

	lnum = be32_to_cpu(vh->lnum);
	return ubi_add_peb_to_vol(ubi, vh, vol_id, pnum, lnum);
}
Exemplo n.º 3
0
/**
 * paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
 * @ubi: UBI device description object
 * @pnum: physical eraseblock number to check
 *
 * This function returns zero if the physical eraseblock is good, %-EINVAL if
 * it is bad and a negative error code if an error occurred.
 */
static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
{
	int err;

	err = ubi_io_is_bad(ubi, pnum);
	if (!err)
		return err;

	ubi_err("paranoid check failed for PEB %d", pnum);
	ubi_dbg_dump_stack();
	return err > 0 ? -EINVAL : err;
}
Exemplo n.º 4
0
Arquivo: io.c Projeto: 383530895/linux
/**
 * self_check_not_bad - ensure that a physical eraseblock is not bad.
 * @ubi: UBI device description object
 * @pnum: physical eraseblock number to check
 *
 * This function returns zero if the physical eraseblock is good, %-EINVAL if
 * it is bad and a negative error code if an error occurred.
 */
static int self_check_not_bad(const struct ubi_device *ubi, int pnum)
{
	int err;

	if (!ubi_dbg_chk_io(ubi))
		return 0;

	err = ubi_io_is_bad(ubi, pnum);
	if (!err)
		return err;

	ubi_err(ubi, "self-check failed for PEB %d", pnum);
	dump_stack();
	return err > 0 ? -EINVAL : err;
}
Exemplo n.º 5
0
static int assign_aeb_to_av(struct ubi_scan_info *ubi, u32 pnum, u32 lnum,
			     u32 vol_id, u32 vol_type, u32 used)
{
	struct ubi_vid_hdr *vh;

	if (ubi_io_is_bad(ubi, pnum))
		return -EINVAL;

	ubi->fastmap_pebs++;

	if (vol_id >= UBI_SPL_VOL_IDS || vol_type != UBI_STATIC_VOLUME)
		return 0;

	/* We are only interested in the volumes to load */
	if (!test_bit(vol_id, ubi->toload))
		return 0;

	vh = ubi->blockinfo + pnum;

	return ubi_scan_vid_hdr(ubi, vh, pnum);
}
Exemplo n.º 6
0
static int ubi_rescan_fm_vid_hdr(struct ubi_scan_info *ubi,
				 struct ubi_vid_hdr *vh,
				 u32 fm_pnum, u32 fm_vol_id, u32 fm_lnum)
{
	int res;

	if (ubi_io_is_bad(ubi, fm_pnum))
		return -EINVAL;

	res = ubi_io_read_vid_hdr(ubi, fm_pnum, vh, 0);
	if (!res) {
		/* Check volume id, volume type and lnum */
		if (be32_to_cpu(vh->vol_id) == fm_vol_id &&
		    vh->vol_type == UBI_VID_STATIC &&
		    be32_to_cpu(vh->lnum) == fm_lnum)
			return 0;
		ubi_dbg("RS: PEB %u vol: %u : %u typ %u lnum %u %u",
			fm_pnum, fm_vol_id, vh->vol_type,
			be32_to_cpu(vh->vol_id),
			fm_lnum, be32_to_cpu(vh->lnum));
	}
	return res;
}
Exemplo n.º 7
0
/*
 * Load a logical block of a volume into memory
 */
static int ubi_load_block(struct ubi_scan_info *ubi, uint8_t *laddr,
			  struct ubi_vol_info *vi, u32 vol_id, u32 lnum,
			  u32 last)
{
	struct ubi_vid_hdr *vh, *vrepl;
	u32 pnum, crc, dlen;

retry:
	/*
	 * If this is a fastmap run, we try to rescan full, otherwise
	 * we simply give up.
	 */
	if (!test_bit(lnum, vi->found)) {
		ubi_warn("LEB %d of %d is missing", lnum, last);
		return -EINVAL;
	}

	pnum = vi->lebs_to_pebs[lnum];

	ubi_dbg("Load vol %u LEB %u PEB %u", vol_id, lnum, pnum);

	if (ubi_io_is_bad(ubi, pnum)) {
		ubi_warn("Corrupted mapping block %d PB %d\n", lnum, pnum);
		return -EINVAL;
	}

	if (test_bit(pnum, ubi->corrupt))
		goto find_other;

	/*
	 * Lets try to read that block
	 */
	vh = ubi->blockinfo + pnum;

	if (!test_bit(pnum, ubi->scanned)) {
		ubi_warn("Vol: %u LEB %u PEB %u not yet scanned", vol_id,
			 lnum, pnum);
		if (ubi_rescan_fm_vid_hdr(ubi, vh, pnum, vol_id, lnum))
			goto find_other;
	}

	/*
	 * Check, if the total number of blocks is correct
	 */
	if (be32_to_cpu(vh->used_ebs) != last) {
		ubi_dbg("Block count missmatch.");
		ubi_dbg("vh->used_ebs: %d nrblocks: %d",
			be32_to_cpu(vh->used_ebs), last);
		generic_set_bit(pnum, ubi->corrupt);
		goto find_other;
	}

	/*
	 * Get the data length of this block.
	 */
	dlen = be32_to_cpu(vh->data_size);

	/*
	 * Read the data into RAM. We ignore the return value
	 * here as the only thing which might go wrong are
	 * bitflips. Try nevertheless.
	 */
	ubi_io_read(ubi, laddr, pnum, ubi->leb_start, dlen);

	/* Calculate CRC over the data */
	crc = crc32(UBI_CRC32_INIT, laddr, dlen);

	if (crc != be32_to_cpu(vh->data_crc)) {
		ubi_warn("Vol: %u LEB %u PEB %u data CRC failure", vol_id,
			 lnum, pnum);
		generic_set_bit(pnum, ubi->corrupt);
		goto find_other;
	}

	/* We are good. Return the data length we read */
	return dlen;

find_other:
	ubi_dbg("Find replacement for LEB %u PEB %u", lnum, pnum);
	generic_clear_bit(lnum, vi->found);
	vrepl = NULL;

	for (pnum = 0; pnum < ubi->peb_count; pnum++) {
		struct ubi_vid_hdr *tmp = ubi->blockinfo + pnum;
		u32 t_vol_id = be32_to_cpu(tmp->vol_id);
		u32 t_lnum = be32_to_cpu(tmp->lnum);

		if (test_bit(pnum, ubi->corrupt))
			continue;

		if (t_vol_id != vol_id || t_lnum != lnum)
			continue;

		if (!test_bit(pnum, ubi->scanned)) {
			ubi_warn("Vol: %u LEB %u PEB %u not yet scanned",
				 vol_id, lnum, pnum);
			if (ubi_rescan_fm_vid_hdr(ubi, tmp, pnum, vol_id, lnum))
				continue;
		}

		/*
		 * We found one. If its the first, assign it otherwise
		 * compare the sqnum
		 */
		generic_set_bit(lnum, vi->found);

		if (!vrepl) {
			vrepl = tmp;
			continue;
		}

		if (be64_to_cpu(vrepl->sqnum) < be64_to_cpu(tmp->sqnum))
			vrepl = tmp;
	}

	if (vrepl) {
		/* Update the vi table */
		pnum = vrepl - ubi->blockinfo;
		vi->lebs_to_pebs[lnum] = pnum;
		ubi_dbg("Trying PEB %u for LEB %u", pnum, lnum);
		vh = vrepl;
	}
	goto retry;
}
Exemplo n.º 8
0
static int ubi_scan_fastmap(struct ubi_scan_info *ubi,
			    struct ubi_attach_info *ai,
			    int fm_anchor)
{
	struct ubi_fm_sb *fmsb, *fmsb2;
	struct ubi_vid_hdr *vh;
	struct ubi_fastmap_layout *fm;
	int i, used_blocks, pnum, ret = 0;
	size_t fm_size;
	__be32 crc, tmp_crc;
	unsigned long long sqnum = 0;

	fmsb = &ubi->fm_sb;
	fm = &ubi->fm_layout;

	ret = ubi_io_read(ubi, fmsb, fm_anchor, ubi->leb_start, sizeof(*fmsb));
	if (ret && ret != UBI_IO_BITFLIPS)
		goto free_fm_sb;
	else if (ret == UBI_IO_BITFLIPS)
		fm->to_be_tortured[0] = 1;

	if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) {
		ubi_err("bad super block magic: 0x%x, expected: 0x%x",
			be32_to_cpu(fmsb->magic), UBI_FM_SB_MAGIC);
		ret = UBI_BAD_FASTMAP;
		goto free_fm_sb;
	}

	if (fmsb->version != UBI_FM_FMT_VERSION) {
		ubi_err("bad fastmap version: %i, expected: %i",
			fmsb->version, UBI_FM_FMT_VERSION);
		ret = UBI_BAD_FASTMAP;
		goto free_fm_sb;
	}

	used_blocks = be32_to_cpu(fmsb->used_blocks);
	if (used_blocks > UBI_FM_MAX_BLOCKS || used_blocks < 1) {
		ubi_err("number of fastmap blocks is invalid: %i", used_blocks);
		ret = UBI_BAD_FASTMAP;
		goto free_fm_sb;
	}

	fm_size = ubi->leb_size * used_blocks;
	if (fm_size != ubi->fm_size) {
		ubi_err("bad fastmap size: %zi, expected: %zi", fm_size,
			ubi->fm_size);
		ret = UBI_BAD_FASTMAP;
		goto free_fm_sb;
	}

	vh = &ubi->fm_vh;

	for (i = 0; i < used_blocks; i++) {
		pnum = be32_to_cpu(fmsb->block_loc[i]);

		if (ubi_io_is_bad(ubi, pnum)) {
			ret = UBI_BAD_FASTMAP;
			goto free_hdr;
		}

#ifdef LATER
		int image_seq;
		ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
		if (ret && ret != UBI_IO_BITFLIPS) {
			ubi_err("unable to read fastmap block# %i EC (PEB: %i)",
				i, pnum);
			if (ret > 0)
				ret = UBI_BAD_FASTMAP;
			goto free_hdr;
		} else if (ret == UBI_IO_BITFLIPS)
			fm->to_be_tortured[i] = 1;

		image_seq = be32_to_cpu(ech->image_seq);
		if (!ubi->image_seq)
			ubi->image_seq = image_seq;
		/*
		 * Older UBI implementations have image_seq set to zero, so
		 * we shouldn't fail if image_seq == 0.
		 */
		if (image_seq && (image_seq != ubi->image_seq)) {
			ubi_err("wrong image seq:%d instead of %d",
				be32_to_cpu(ech->image_seq), ubi->image_seq);
			ret = UBI_BAD_FASTMAP;
			goto free_hdr;
		}
#endif
		ret = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
		if (ret && ret != UBI_IO_BITFLIPS) {
			ubi_err("unable to read fastmap block# %i (PEB: %i)",
				i, pnum);
			goto free_hdr;
		}

		/*
		 * Mainline code rescans the anchor header. We've done
		 * that already so we merily copy it over.
		 */
		if (pnum == fm_anchor)
			memcpy(vh, ubi->blockinfo + pnum, sizeof(*fm));

		if (i == 0) {
			if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) {
				ubi_err("bad fastmap anchor vol_id: 0x%x," \
					" expected: 0x%x",
					be32_to_cpu(vh->vol_id),
					UBI_FM_SB_VOLUME_ID);
				ret = UBI_BAD_FASTMAP;
				goto free_hdr;
			}
		} else {
			if (be32_to_cpu(vh->vol_id) != UBI_FM_DATA_VOLUME_ID) {
				ubi_err("bad fastmap data vol_id: 0x%x," \
					" expected: 0x%x",
					be32_to_cpu(vh->vol_id),
					UBI_FM_DATA_VOLUME_ID);
				ret = UBI_BAD_FASTMAP;
				goto free_hdr;
			}
		}

		if (sqnum < be64_to_cpu(vh->sqnum))
			sqnum = be64_to_cpu(vh->sqnum);

		ret = ubi_io_read(ubi, ubi->fm_buf + (ubi->leb_size * i), pnum,
				  ubi->leb_start, ubi->leb_size);
		if (ret && ret != UBI_IO_BITFLIPS) {
			ubi_err("unable to read fastmap block# %i (PEB: %i, " \
				"err: %i)", i, pnum, ret);
			goto free_hdr;
		}
	}

	fmsb2 = (struct ubi_fm_sb *)(ubi->fm_buf);
	tmp_crc = be32_to_cpu(fmsb2->data_crc);
	fmsb2->data_crc = 0;
	crc = crc32(UBI_CRC32_INIT, ubi->fm_buf, fm_size);
	if (crc != tmp_crc) {
		ubi_err("fastmap data CRC is invalid");
		ubi_err("CRC should be: 0x%x, calc: 0x%x", tmp_crc, crc);
		ret = UBI_BAD_FASTMAP;
		goto free_hdr;
	}

	fmsb2->sqnum = sqnum;

	fm->used_blocks = used_blocks;

	ret = ubi_attach_fastmap(ubi, ai, fm);
	if (ret) {
		if (ret > 0)
			ret = UBI_BAD_FASTMAP;
		goto free_hdr;
	}

	ubi->fm = fm;
	ubi->fm_pool.max_size = ubi->fm->max_pool_size;
	ubi->fm_wl_pool.max_size = ubi->fm->max_wl_pool_size;
	ubi_msg("attached by fastmap %uMB %u blocks",
		ubi->fsize_mb, ubi->peb_count);
	ubi_dbg("fastmap pool size: %d", ubi->fm_pool.max_size);
	ubi_dbg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);

out:
	if (ret)
		ubi_err("Attach by fastmap failed, doing a full scan!");
	return ret;

free_hdr:
free_fm_sb:
	goto out;
}