/** * paranoid_check_peb_vid_hdr - check volume identifier header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * * This function returns zero if the volume identifier header is all right, * and a negative error code if not or if an error occurred. */ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) { int err; uint32_t crc, hdr_crc; struct ubi_vid_hdr *vid_hdr; void *p; vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); if (!vid_hdr) return -ENOMEM; p = (char *)vid_hdr - ubi->vid_hdr_shift; err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) goto exit; crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC); hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); if (hdr_crc != crc) { ubi_err("bad VID header CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_stack(); err = -EINVAL; goto exit; } err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); exit: ubi_free_vid_hdr(ubi, vid_hdr); return err; }
/** * compare_lebs - find out which logical eraseblock is newer. * @ubi: UBI device description object * @seb: first logical eraseblock to compare * @pnum: physical eraseblock number of the second logical eraseblock to * compare * @vid_hdr: volume identifier header of the second logical eraseblock * * This function compares 2 copies of a LEB and informs which one is newer. In * case of success this function returns a positive value, in case of failure, a * negative error code is returned. The success return codes use the following * bits: * o bit 0 is cleared: the first PEB (described by @seb) is newer than the * second PEB (described by @pnum and @vid_hdr); * o bit 0 is set: the second PEB is newer; * o bit 1 is cleared: no bit-flips were detected in the newer LEB; * o bit 1 is set: bit-flips were detected in the newer LEB; * o bit 2 is cleared: the older LEB is not corrupted; * o bit 2 is set: the older LEB is corrupted. */ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, int pnum, const struct ubi_vid_hdr *vid_hdr) { void *buf; int len, err, second_is_newer, bitflips = 0, corrupted = 0; uint32_t data_crc, crc; struct ubi_vid_hdr *vh = NULL; unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); if (sqnum2 == seb->sqnum) { /* * This must be a really ancient UBI image which has been * created before sequence numbers support has been added. At * that times we used 32-bit LEB versions stored in logical * eraseblocks. That was before UBI got into mainline. We do not * support these images anymore. Well, those images still work, * but only if no unclean reboots happened. */ ubi_err("unsupported on-flash UBI format\n"); return -EINVAL; } /* Obviously the LEB with lower sequence counter is older */ second_is_newer = !!(sqnum2 > seb->sqnum); /* * Now we know which copy is newer. If the copy flag of the PEB with * newer version is not set, then we just return, otherwise we have to * check data CRC. For the second PEB we already have the VID header, * for the first one - we'll need to re-read it from flash. * * Note: this may be optimized so that we wouldn't read twice. */ if (second_is_newer) { if (!vid_hdr->copy_flag) { /* It is not a copy, so it is newer */ dbg_bld("second PEB %d is newer, copy_flag is unset", pnum); return 1; } } else { if (!seb->copy_flag) { /* It is not a copy, so it is newer */ dbg_bld("first PEB %d is newer, copy_flag is unset", pnum); return bitflips << 1; } vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); if (!vh) return -ENOMEM; pnum = seb->pnum; err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); if (err) { if (err == UBI_IO_BITFLIPS) bitflips = 1; else { dbg_err("VID of PEB %d header is bad, but it " "was OK earlier, err %d", pnum, err); if (err > 0) err = -EIO; goto out_free_vidh; } } vid_hdr = vh; } /* Read the data of the copy and check the CRC */ len = be32_to_cpu(vid_hdr->data_size); buf = vmalloc(len); if (!buf) { err = -ENOMEM; goto out_free_vidh; } err = ubi_io_read_data(ubi, buf, pnum, 0, len); if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) goto out_free_buf; data_crc = be32_to_cpu(vid_hdr->data_crc); crc = crc32(UBI_CRC32_INIT, buf, len); if (crc != data_crc) { dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", pnum, crc, data_crc); corrupted = 1; bitflips = 0; second_is_newer = !second_is_newer; } else { dbg_bld("PEB %d CRC is OK", pnum); bitflips = !!err; } vfree(buf); ubi_free_vid_hdr(ubi, vh); if (second_is_newer) dbg_bld("second PEB %d is newer, copy_flag is set", pnum); else dbg_bld("first PEB %d is newer, copy_flag is set", pnum); return second_is_newer | (bitflips << 1) | (corrupted << 2); out_free_buf: vfree(buf); out_free_vidh: ubi_free_vid_hdr(ubi, vh); return err; }
/** * compare_lebs - find out which logical eraseblock is newer. * @ubi: UBI device description object * @seb: first logical eraseblock to compare * @pnum: physical eraseblock number of the second logical eraseblock to * compare * @vid_hdr: volume identifier header of the second logical eraseblock * * This function compares 2 copies of a LEB and informs which one is newer. In * case of success this function returns a positive value, in case of failure, a * negative error code is returned. The success return codes use the following * bits: * o bit 0 is cleared: the first PEB (described by @seb) is newer then the * second PEB (described by @pnum and @vid_hdr); * o bit 0 is set: the second PEB is newer; * o bit 1 is cleared: no bit-flips were detected in the newer LEB; * o bit 1 is set: bit-flips were detected in the newer LEB; * o bit 2 is cleared: the older LEB is not corrupted; * o bit 2 is set: the older LEB is corrupted. */ static int compare_lebs(const struct ubi_device *ubi, const struct ubi_scan_leb *seb, int pnum, const struct ubi_vid_hdr *vid_hdr) { void *buf; int len, err, second_is_newer, bitflips = 0, corrupted = 0; uint32_t data_crc, crc; struct ubi_vid_hdr *vidh = NULL; unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); if (seb->sqnum == 0 && sqnum2 == 0) { long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); /* * UBI constantly increases the logical eraseblock version * number and it can overflow. Thus, we have to bear in mind * that versions that are close to %0xFFFFFFFF are less then * versions that are close to %0. * * The UBI WL unit guarantees that the number of pending tasks * is not greater then %0x7FFFFFFF. So, if the difference * between any two versions is greater or equivalent to * %0x7FFFFFFF, there was an overflow and the logical * eraseblock with lower version is actually newer then the one * with higher version. * * FIXME: but this is anyway obsolete and will be removed at * some point. */ dbg_bld("using old crappy leb_ver stuff"); abs = v1 - v2; if (abs < 0) abs = -abs; if (abs < 0x7FFFFFFF) /* Non-overflow situation */ second_is_newer = (v2 > v1); else second_is_newer = (v2 < v1); } else /* Obviously the LEB with lower sequence counter is older */ second_is_newer = sqnum2 > seb->sqnum; /* * Now we know which copy is newer. If the copy flag of the PEB with * newer version is not set, then we just return, otherwise we have to * check data CRC. For the second PEB we already have the VID header, * for the first one - we'll need to re-read it from flash. * * FIXME: this may be optimized so that we wouldn't read twice. */ if (second_is_newer) { if (!vid_hdr->copy_flag) { /* It is not a copy, so it is newer */ dbg_bld("second PEB %d is newer, copy_flag is unset", pnum); return 1; } } else { pnum = seb->pnum; vidh = ubi_zalloc_vid_hdr(ubi); if (!vidh) return -ENOMEM; err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0); if (err) { if (err == UBI_IO_BITFLIPS) bitflips = 1; else { dbg_err("VID of PEB %d header is bad, but it " "was OK earlier", pnum); if (err > 0) err = -EIO; goto out_free_vidh; } } if (!vidh->copy_flag) { /* It is not a copy, so it is newer */ dbg_bld("first PEB %d is newer, copy_flag is unset", pnum); err = bitflips << 1; goto out_free_vidh; } vid_hdr = vidh; } /* Read the data of the copy and check the CRC */ len = be32_to_cpu(vid_hdr->data_size); buf = vmalloc(len); if (!buf) { err = -ENOMEM; goto out_free_vidh; } err = ubi_io_read_data(ubi, buf, pnum, 0, len); if (err && err != UBI_IO_BITFLIPS) goto out_free_buf; data_crc = be32_to_cpu(vid_hdr->data_crc); crc = crc32(UBI_CRC32_INIT, buf, len); if (crc != data_crc) { dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", pnum, crc, data_crc); corrupted = 1; bitflips = 0; second_is_newer = !second_is_newer; } else { dbg_bld("PEB %d CRC is OK", pnum); bitflips = !!err; } vfree(buf); ubi_free_vid_hdr(ubi, vidh); if (second_is_newer) dbg_bld("second PEB %d is newer, copy_flag is set", pnum); else dbg_bld("first PEB %d is newer, copy_flag is set", pnum); return second_is_newer | (bitflips << 1) | (corrupted << 2); out_free_buf: vfree(buf); out_free_vidh: ubi_free_vid_hdr(ubi, vidh); ubi_assert(err < 0); return err; }