/** * 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; }
/** * paranoid_check_vid_hdr - check that a volume identifier header is all right. * @ubi: UBI device description object * @pnum: physical eraseblock number the volume identifier header belongs to * @vid_hdr: the volume identifier header to check * * This function returns zero if the volume identifier header is all right, and * %-EINVAL if not. */ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_vid_hdr *vid_hdr) { int err; uint32_t magic; magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x", magic, pnum, UBI_VID_HDR_MAGIC); goto fail; } err = validate_vid_hdr(ubi, vid_hdr); if (err) { ubi_err("paranoid check failed for PEB %d", pnum); goto fail; } return err; fail: ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_stack(); return -EINVAL; }
/** * validate_vid_hdr - check volume identifier header. * @vid_hdr: the volume identifier header to check * @sv: information about the volume this logical eraseblock belongs to * @pnum: physical eraseblock number the VID header came from * * This function checks that data stored in @vid_hdr is consistent. Returns * non-zero if an inconsistency was found and zero if not. * * Note, UBI does sanity check of everything it reads from the flash media. * Most of the checks are done in the I/O sub-system. Here we check that the * information in the VID header is consistent to the information in other VID * headers of the same volume. */ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, const struct ubi_scan_volume *sv, int pnum) { int vol_type = vid_hdr->vol_type; int vol_id = be32_to_cpu(vid_hdr->vol_id); int used_ebs = be32_to_cpu(vid_hdr->used_ebs); int data_pad = be32_to_cpu(vid_hdr->data_pad); if (sv->leb_count != 0) { int sv_vol_type; /* * This is not the first logical eraseblock belonging to this * volume. Ensure that the data in its VID header is consistent * to the data in previous logical eraseblock headers. */ if (vol_id != sv->vol_id) { dbg_err("inconsistent vol_id"); goto bad; } if (sv->vol_type == UBI_STATIC_VOLUME) sv_vol_type = UBI_VID_STATIC; else sv_vol_type = UBI_VID_DYNAMIC; if (vol_type != sv_vol_type) { dbg_err("inconsistent vol_type"); goto bad; } if (used_ebs != sv->used_ebs) { dbg_err("inconsistent used_ebs"); goto bad; } if (data_pad != sv->data_pad) { dbg_err("inconsistent data_pad"); goto bad; } } return 0; bad: ubi_err("inconsistent VID header at PEB %d", pnum); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_sv(sv); return -EINVAL; }
/** * ubi_scan_add_used - add physical eraseblock to the scanning information. * @ubi: UBI device description object * @si: scanning information * @pnum: the physical eraseblock number * @ec: erase counter * @vid_hdr: the volume identifier header * @bitflips: if bit-flips were detected when this physical eraseblock was read * * This function adds information about a used physical eraseblock to the * 'used' tree of the corresponding volume. The function is rather complex * because it has to handle cases when this is not the first physical * eraseblock belonging to the same logical eraseblock, and the newer one has * to be picked, while the older one has to be dropped. This function returns * zero in case of success and a negative error code in case of failure. */ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) { int err, vol_id, lnum; unsigned long long sqnum; struct ubi_scan_volume *sv; struct ubi_scan_leb *seb; struct rb_node **p, *parent = NULL; vol_id = be32_to_cpu(vid_hdr->vol_id); lnum = be32_to_cpu(vid_hdr->lnum); sqnum = be64_to_cpu(vid_hdr->sqnum); dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d", pnum, vol_id, lnum, ec, sqnum, bitflips); sv = add_volume(si, vol_id, pnum, vid_hdr); if (IS_ERR(sv)) return PTR_ERR(sv); if (si->max_sqnum < sqnum) si->max_sqnum = sqnum; /* * Walk the RB-tree of logical eraseblocks of volume @vol_id to look * if this is the first instance of this logical eraseblock or not. */ p = &sv->root.rb_node; while (*p) { int cmp_res; parent = *p; seb = rb_entry(parent, struct ubi_scan_leb, u.rb); if (lnum != seb->lnum) { if (lnum < seb->lnum) p = &(*p)->rb_left; else p = &(*p)->rb_right; continue; } /* * There is already a physical eraseblock describing the same * logical eraseblock present. */ dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " "EC %d", seb->pnum, seb->sqnum, seb->ec); /* * Make sure that the logical eraseblocks have different * sequence numbers. Otherwise the image is bad. * * However, if the sequence number is zero, we assume it must * be an ancient UBI image from the era when UBI did not have * sequence numbers. We still can attach these images, unless * there is a need to distinguish between old and new * eraseblocks, in which case we'll refuse the image in * 'compare_lebs()'. In other words, we attach old clean * images, but refuse attaching old images with duplicated * logical eraseblocks because there was an unclean reboot. */ if (seb->sqnum == sqnum && sqnum != 0) { ubi_err("two LEBs with same sequence number %llu", sqnum); ubi_dbg_dump_seb(seb, 0); ubi_dbg_dump_vid_hdr(vid_hdr); return -EINVAL; } /* * Now we have to drop the older one and preserve the newer * one. */ cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr); if (cmp_res < 0) return cmp_res; if (cmp_res & 1) { /* * This logical eraseblock is newer than the one * found earlier. */ err = validate_vid_hdr(vid_hdr, sv, pnum); if (err) return err; err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4, &si->erase); if (err) return err; seb->ec = ec; seb->pnum = pnum; seb->scrub = ((cmp_res & 2) || bitflips); seb->copy_flag = vid_hdr->copy_flag; seb->sqnum = sqnum; if (sv->highest_lnum == lnum) sv->last_data_size = be32_to_cpu(vid_hdr->data_size); return 0; } else { /* * This logical eraseblock is older than the one found * previously. */ return add_to_list(si, pnum, ec, cmp_res & 4, &si->erase); } } /* * We've met this logical eraseblock for the first time, add it to the * scanning information. */ err = validate_vid_hdr(vid_hdr, sv, pnum); if (err) return err; seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); if (!seb) return -ENOMEM; seb->ec = ec; seb->pnum = pnum; seb->lnum = lnum; seb->scrub = bitflips; seb->copy_flag = vid_hdr->copy_flag; seb->sqnum = sqnum; if (sv->highest_lnum <= lnum) { sv->highest_lnum = lnum; sv->last_data_size = be32_to_cpu(vid_hdr->data_size); } sv->leb_count += 1; rb_link_node(&seb->u.rb, parent, p); rb_insert_color(&seb->u.rb, &sv->root); return 0; }
/** * ubi_scan_add_used - add information about a physical eraseblock to the * scanning information. * @ubi: UBI device description object * @si: scanning information * @pnum: the physical eraseblock number * @ec: erase counter * @vid_hdr: the volume identifier header * @bitflips: if bit-flips were detected when this physical eraseblock was read * * This function adds information about a used physical eraseblock to the * 'used' tree of the corresponding volume. The function is rather complex * because it has to handle cases when this is not the first physical * eraseblock belonging to the same logical eraseblock, and the newer one has * to be picked, while the older one has to be dropped. This function returns * zero in case of success and a negative error code in case of failure. */ int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si, int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) { int err, vol_id, lnum; uint32_t leb_ver; unsigned long long sqnum; struct ubi_scan_volume *sv; struct ubi_scan_leb *seb; struct rb_node **p, *parent = NULL; vol_id = be32_to_cpu(vid_hdr->vol_id); lnum = be32_to_cpu(vid_hdr->lnum); sqnum = be64_to_cpu(vid_hdr->sqnum); leb_ver = be32_to_cpu(vid_hdr->leb_ver); dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d", pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips); sv = add_volume(si, vol_id, pnum, vid_hdr); if (IS_ERR(sv) < 0) return PTR_ERR(sv); if (si->max_sqnum < sqnum) si->max_sqnum = sqnum; /* * Walk the RB-tree of logical eraseblocks of volume @vol_id to look * if this is the first instance of this logical eraseblock or not. */ p = &sv->root.rb_node; while (*p) { int cmp_res; parent = *p; seb = rb_entry(parent, struct ubi_scan_leb, u.rb); if (lnum != seb->lnum) { if (lnum < seb->lnum) p = &(*p)->rb_left; else p = &(*p)->rb_right; continue; } /* * There is already a physical eraseblock describing the same * logical eraseblock present. */ dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " "LEB ver %u, EC %d", seb->pnum, seb->sqnum, seb->leb_ver, seb->ec); /* * Make sure that the logical eraseblocks have different * versions. Otherwise the image is bad. */ if (seb->leb_ver == leb_ver && leb_ver != 0) { ubi_err("two LEBs with same version %u", leb_ver); ubi_dbg_dump_seb(seb, 0); ubi_dbg_dump_vid_hdr(vid_hdr); return -EINVAL; } /* * Make sure that the logical eraseblocks have different * sequence numbers. Otherwise the image is bad. * * FIXME: remove 'sqnum != 0' check when leb_ver is removed. */ if (seb->sqnum == sqnum && sqnum != 0) { ubi_err("two LEBs with same sequence number %llu", sqnum); ubi_dbg_dump_seb(seb, 0); ubi_dbg_dump_vid_hdr(vid_hdr); return -EINVAL; } /* * Now we have to drop the older one and preserve the newer * one. */ cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr); if (cmp_res < 0) return cmp_res; if (cmp_res & 1) { /* * This logical eraseblock is newer then the one * found earlier. */ err = validate_vid_hdr(vid_hdr, sv, pnum); if (err) return err; if (cmp_res & 4) err = add_to_list(si, seb->pnum, seb->ec, &si->corr); else err = add_to_list(si, seb->pnum, seb->ec, &si->erase); if (err) return err; seb->ec = ec; seb->pnum = pnum; seb->scrub = ((cmp_res & 2) || bitflips); seb->sqnum = sqnum; seb->leb_ver = leb_ver; if (sv->highest_lnum == lnum) sv->last_data_size = be32_to_cpu(vid_hdr->data_size); return 0; } else { /* * This logical eraseblock is older then the one found * previously. */ if (cmp_res & 4) return add_to_list(si, pnum, ec, &si->corr); else return add_to_list(si, pnum, ec, &si->erase); } } /* * We've met this logical eraseblock for the first time, add it to the * scanning information. */ err = validate_vid_hdr(vid_hdr, sv, pnum); if (err) return err; seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); if (!seb) return -ENOMEM; seb->ec = ec; seb->pnum = pnum; seb->lnum = lnum; seb->sqnum = sqnum; seb->scrub = bitflips; seb->leb_ver = leb_ver; if (sv->highest_lnum <= lnum) { sv->highest_lnum = lnum; sv->last_data_size = be32_to_cpu(vid_hdr->data_size); } sv->leb_count += 1; rb_link_node(&seb->u.rb, parent, p); rb_insert_color(&seb->u.rb, &sv->root); return 0; }
/** * ubi_io_read_vid_hdr - read and check a volume identifier header. * @ubi: UBI device description object * @pnum: physical eraseblock number to read from * @vid_hdr: &struct ubi_vid_hdr object where to store the read volume * identifier header * @verbose: be verbose if the header is corrupted or wasn't found * * This function reads the volume identifier header from physical eraseblock * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read * volume identifier header. The following codes may be returned: * * o %0 if the CRC checksum is correct and the header was successfully read; * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected * and corrected by the flash driver; this is harmless but may indicate that * this eraseblock may become bad soon; * o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC * error detected); * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID * header there); * o a negative error code in case of failure. */ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr, int verbose) { int err, read_err = 0; uint32_t crc, magic, hdr_crc; void *p; dbg_io("read VID header from PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); 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) { if (err != UBI_IO_BITFLIPS && err != -EBADMSG) return err; /* * We read all the data, but either a correctable bit-flip * occurred, or MTD reported about some data integrity error, * like an ECC error in case of NAND. The former is harmless, * the later may mean the read data is corrupted. But we have a * CRC check-sum and we will identify this. If the VID header is * still OK, we just report this as there was a bit-flip. */ read_err = err; } magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { /* * If we have read all 0xFF bytes, the VID header probably does * not exist and the physical eraseblock is assumed to be free. * * But if there was a read error, we do not test the data for * 0xFFs. Even if it does contain all 0xFFs, this error * indicates that something is still wrong with this physical * eraseblock and it cannot be regarded as free. */ if (read_err != -EBADMSG && check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { /* The physical eraseblock is supposedly free */ if (verbose) ubi_warn("no VID header found at PEB %d, " "only 0xFF bytes", pnum); else if (UBI_IO_DEBUG) dbg_msg("no VID header found at PEB %d, " "only 0xFF bytes", pnum); return UBI_IO_PEB_FREE; } /* * This is not a valid VID header, and these are not 0xFF * bytes. Report that the header is corrupted. */ if (verbose) { ubi_warn("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); ubi_dbg_dump_vid_hdr(vid_hdr); } else if (UBI_IO_DEBUG) dbg_msg("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); return UBI_IO_BAD_VID_HDR; } crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); if (hdr_crc != crc) { if (verbose) { ubi_warn("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); ubi_dbg_dump_vid_hdr(vid_hdr); } else if (UBI_IO_DEBUG) dbg_msg("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); return UBI_IO_BAD_VID_HDR; } /* Validate the VID header that we have just read */ err = validate_vid_hdr(ubi, vid_hdr); if (err) { ubi_err("validation failed for PEB %d", pnum); return -EINVAL; } return read_err ? UBI_IO_BITFLIPS : 0; }
/** * validate_vid_hdr - validate a volume identifier header. * @ubi: UBI device description object * @vid_hdr: the volume identifier header to check * * This function checks that data stored in the volume identifier header * @vid_hdr. Returns zero if the VID header is OK and %1 if not. */ static int validate_vid_hdr(const struct ubi_device *ubi, const struct ubi_vid_hdr *vid_hdr) { int vol_type = vid_hdr->vol_type; int copy_flag = vid_hdr->copy_flag; int vol_id = be32_to_cpu(vid_hdr->vol_id); int lnum = be32_to_cpu(vid_hdr->lnum); int compat = vid_hdr->compat; int data_size = be32_to_cpu(vid_hdr->data_size); int used_ebs = be32_to_cpu(vid_hdr->used_ebs); int data_pad = be32_to_cpu(vid_hdr->data_pad); int data_crc = be32_to_cpu(vid_hdr->data_crc); int usable_leb_size = ubi->leb_size - data_pad; if (copy_flag != 0 && copy_flag != 1) { dbg_err("bad copy_flag"); goto bad; } if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 || data_pad < 0) { dbg_err("negative values"); goto bad; } if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) { dbg_err("bad vol_id"); goto bad; } if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) { dbg_err("bad compat"); goto bad; } if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE && compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE && compat != UBI_COMPAT_REJECT) { dbg_err("bad compat"); goto bad; } if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { dbg_err("bad vol_type"); goto bad; } if (data_pad >= ubi->leb_size / 2) { dbg_err("bad data_pad"); goto bad; } if (vol_type == UBI_VID_STATIC) { /* * Although from high-level point of view static volumes may * contain zero bytes of data, but no VID headers can contain * zero at these fields, because they empty volumes do not have * mapped logical eraseblocks. */ if (used_ebs == 0) { dbg_err("zero used_ebs"); goto bad; } if (data_size == 0) { dbg_err("zero data_size"); goto bad; } if (lnum < used_ebs - 1) { if (data_size != usable_leb_size) { dbg_err("bad data_size"); goto bad; } } else if (lnum == used_ebs - 1) { if (data_size == 0) { dbg_err("bad data_size at last LEB"); goto bad; } } else { dbg_err("too high lnum"); goto bad; } } else { if (copy_flag == 0) { if (data_crc != 0) { dbg_err("non-zero data CRC"); goto bad; } if (data_size != 0) { dbg_err("non-zero data_size"); goto bad; } } else { if (data_size == 0) { dbg_err("zero data_size of copy"); goto bad; } } if (used_ebs != 0) { dbg_err("bad used_ebs"); goto bad; } } return 0; bad: ubi_err("bad VID header"); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_stack(); return 1; }
/** * ubi_io_read_vid_hdr - read and check a volume identifier header. * @ubi: UBI device description object * @pnum: physical eraseblock number to read from * @vid_hdr: &struct ubi_vid_hdr object where to store the read volume * identifier header * @verbose: be verbose if the header is corrupted or wasn't found * * This function reads the volume identifier header from physical eraseblock * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read * volume identifier header. The error codes are the same as in * 'ubi_io_read_ec_hdr()'. * * Note, the implementation of this function is also very similar to * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'. */ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr, int verbose) { int err, read_err; uint32_t crc, magic, hdr_crc; void *p; dbg_io("read VID header from PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); p = (char *)vid_hdr - ubi->vid_hdr_shift; read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err)) return read_err; magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { if (mtd_is_eccerr(read_err)) return UBI_IO_BAD_HDR_EBADMSG; if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { if (verbose) ubi_warn("no VID header found at PEB %d, " "only 0xFF bytes", pnum); dbg_bld("no VID header found at PEB %d, " "only 0xFF bytes", pnum); if (!read_err) return UBI_IO_FF; else return UBI_IO_FF_BITFLIPS; } if (verbose) { ubi_warn("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); ubi_dbg_dump_vid_hdr(vid_hdr); } dbg_bld("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); return UBI_IO_BAD_HDR; } crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); hdr_crc = be32_to_cpu(vid_hdr->hdr_crc); if (hdr_crc != crc) { if (verbose) { ubi_warn("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); ubi_dbg_dump_vid_hdr(vid_hdr); } dbg_bld("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); if (!read_err) return UBI_IO_BAD_HDR; else return UBI_IO_BAD_HDR_EBADMSG; } err = validate_vid_hdr(ubi, vid_hdr); if (err) { ubi_err("validation failed for PEB %d", pnum); return -EINVAL; } return read_err ? UBI_IO_BITFLIPS : 0; }