📄 io.c
字号:
} } 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 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_HRD 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); if (UBI_IO_DEBUG) verbose = 1; 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 */ /* * The below is just a paranoid check, it has to be * compiled out if paranoid checks are disabled. */ err = paranoid_check_all_ff(ubi, pnum, ubi->leb_start, ubi->leb_size); if (err) return err > 0 ? UBI_IO_BAD_VID_HDR : err; if (verbose) ubi_warn("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); } 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); } 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;}/** * ubi_io_write_vid_hdr - write a volume identifier header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to write to * @vid_hdr: the volume identifier header to write * * This function writes the volume identifier header described by @vid_hdr to * physical eraseblock @pnum. This function automatically fills the * @vid_hdr->magic and the @vid_hdr->version fields, as well as calculates * header CRC checksum and stores it at vid_hdr->hdr_crc. * * This function returns zero in case of success and a negative error code in * case of failure. If %-EIO is returned, the physical eraseblock probably went * bad. */int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr){ int err; uint32_t crc; void *p; dbg_io("write VID header to PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); err = paranoid_check_peb_ec_hdr(ubi, pnum); if (err) return err > 0 ? -EINVAL: err; vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); vid_hdr->version = UBI_VERSION; crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); vid_hdr->hdr_crc = cpu_to_be32(crc); err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); if (err) return -EINVAL; p = (char *)vid_hdr - ubi->vid_hdr_shift; err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); return err;}#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID/** * 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, a positive * number 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;}/** * paranoid_check_ec_hdr - check if an erase counter header is all right. * @ubi: UBI device description object * @pnum: physical eraseblock number the erase counter header belongs to * @ec_hdr: the erase counter header to check * * This function returns zero if the erase counter header contains valid * values, and %1 if not. */static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_ec_hdr *ec_hdr){ int err; uint32_t magic; magic = be32_to_cpu(ec_hdr->magic); if (magic != UBI_EC_HDR_MAGIC) { ubi_err("bad magic %#08x, must be %#08x", magic, UBI_EC_HDR_MAGIC); goto fail; } err = validate_ec_hdr(ubi, ec_hdr); if (err) { ubi_err("paranoid check failed for PEB %d", pnum); goto fail; } return 0;fail: ubi_dbg_dump_ec_hdr(ec_hdr); ubi_dbg_dump_stack(); return 1;}/** * paranoid_check_peb_ec_hdr - check that the erase counter header of a * physical eraseblock is in-place and is all right. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * * This function returns zero if the erase counter header is all right, %1 if * not, and a negative error code if an error occurred. */static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum){ int err; uint32_t crc, hdr_crc; struct ubi_ec_hdr *ec_hdr; ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); if (!ec_hdr) return -ENOMEM; err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) goto exit; crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); hdr_crc = be32_to_cpu(ec_hdr->hdr_crc); if (hdr_crc != crc) { ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc); ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_ec_hdr(ec_hdr); ubi_dbg_dump_stack(); err = 1; goto exit; } err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);exit: kfree(ec_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 * %1 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 1;}/** * paranoid_check_peb_vid_hdr - check that the volume identifier header of a * physical eraseblock is in-place and is all right. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * * This function returns zero if the volume identifier header is all right, * %1 if not, and a negative error code 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 = 1; goto exit; } err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);exit: ubi_free_vid_hdr(ubi, vid_hdr); return err;}/** * paranoid_check_all_ff - check that a region of flash is empty. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @offset: the starting offset within the physical eraseblock to check * @len: the length of the region to check * * This function returns zero if only 0xFF bytes are present at offset * @offset of the physical eraseblock @pnum, %1 if not, and a negative error * code if an error occurred. */static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len){ size_t read; int err; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; mutex_lock(&ubi->dbg_buf_mutex); err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); if (err && err != -EUCLEAN) { ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); goto error; } err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); if (err == 0) { ubi_err("flash region at PEB %d:%d, length %d does not " "contain all 0xFF bytes", pnum, offset, len); goto fail; } mutex_unlock(&ubi->dbg_buf_mutex); return 0;fail: ubi_err("paranoid check failed for PEB %d", pnum); dbg_msg("hex dump of the %d-%d region", offset, offset + len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, ubi->dbg_peb_buf, len, 1); err = 1;error: ubi_dbg_dump_stack(); mutex_unlock(&ubi->dbg_buf_mutex); return err;}#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -