/** * 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; 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 err; 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; }
/** * ubi_io_write - write data to a physical eraseblock. * @ubi: UBI device description object * @buf: buffer with the data to write * @pnum: physical eraseblock number to write to * @offset: offset within the physical eraseblock where to write * @len: how many bytes to write * * This function writes @len bytes of data from buffer @buf to offset @offset * of physical eraseblock @pnum. If all the data were successfully written, * zero is returned. If an error occurred, this function returns a negative * error code. If %-EIO is returned, the physical eraseblock most probably went * bad. * * Note, in case of an error, it is possible that something was still written * to the flash media, but may be some garbage. */ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { int err; size_t written; loff_t addr; dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(offset % ubi->hdrs_min_io_size == 0); ubi_assert(len > 0 && len % ubi->hdrs_min_io_size == 0); if (ubi->ro_mode) { ubi_err("read-only mode"); return -EROFS; } /* The below has to be compiled out if paranoid checks are disabled */ err = paranoid_check_not_bad(ubi, pnum); if (err) return err; /* The area we are writing to has to contain all 0xFF bytes */ err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); if (err) return err; if (offset >= ubi->leb_start) { /* * We write to the data area of the physical eraseblock. Make * sure it has valid EC and VID headers. */ err = paranoid_check_peb_ec_hdr(ubi, pnum); if (err) return err; err = paranoid_check_peb_vid_hdr(ubi, pnum); if (err) return err; } if (ubi_dbg_is_write_failure()) { dbg_err("cannot write %d bytes to PEB %d:%d " "(emulated)", len, pnum, offset); ubi_dbg_dump_stack(); return -EIO; } addr = (loff_t)pnum * ubi->peb_size + offset; err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); if (err) { ubi_err("error %d while writing %d bytes to PEB %d:%d, written " "%zd bytes", err, len, pnum, offset, written); ubi_dbg_dump_stack(); ubi_dbg_dump_flash(ubi, pnum, offset, len); } else ubi_assert(written == len); if (!err) { err = ubi_dbg_check_write(ubi, buf, pnum, offset, len); if (err) return err; /* * Since we always write sequentially, the rest of the PEB has * to contain only 0xFF bytes. */ offset += len; len = ubi->peb_size - offset; if (len) err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); } return err; }
/** * ubi_io_write - write data to a physical eraseblock. * @ubi: UBI device description object * @buf: buffer with the data to write * @pnum: physical eraseblock number to write to * @offset: offset within the physical eraseblock where to write * @len: how many bytes to write * * This function writes @len bytes of data from buffer @buf to offset @offset * of physical eraseblock @pnum. If all the data were successfully written, * zero is returned. If an error occurred, this function returns a negative * error code. If %-EIO is returned, the physical eraseblock most probably went * bad. * * Note, in case of an error, it is possible that something was still written * to the flash media, but may be some garbage. */ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { int err; size_t written; loff_t addr; #ifdef CONFIG_MTD_MSM_NAND void *buf_new; #endif dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(offset % ubi->hdrs_min_io_size == 0); ubi_assert(len > 0 && len % ubi->hdrs_min_io_size == 0); if (ubi->ro_mode) { ubi_err("read-only mode"); return -EROFS; } /* The below has to be compiled out if paranoid checks are disabled */ err = paranoid_check_not_bad(ubi, pnum); if (err) return err > 0 ? -EINVAL : err; /* The area we are writing to has to contain all 0xFF bytes */ err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); if (err) return err > 0 ? -EINVAL : err; if (offset >= ubi->leb_start) { /* * We write to the data area of the physical eraseblock. Make * sure it has valid EC and VID headers. */ err = paranoid_check_peb_ec_hdr(ubi, pnum); if (err) return err > 0 ? -EINVAL : err; err = paranoid_check_peb_vid_hdr(ubi, pnum); if (err) return err > 0 ? -EINVAL : err; } if (ubi_dbg_is_write_failure()) { dbg_err("cannot write %d bytes to PEB %d:%d " "(emulated)", len, pnum, offset); ubi_dbg_dump_stack(); return -EIO; } addr = (loff_t)pnum * ubi->peb_size + offset; #ifdef CONFIG_MTD_MSM_NAND if(!(buf_new = kmalloc(len, GFP_KERNEL | __GFP_NOFAIL))) return -ENOMEM; memcpy(buf_new, buf, len); err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf_new); #else err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); #endif if (err) { ubi_err("error %d while writing %d bytes to PEB %d:%d, written " "%zd bytes", err, len, pnum, offset, written); ubi_dbg_dump_stack(); ubi_dbg_dump_flash(ubi, pnum, offset, len); } else ubi_assert(written == len); #ifdef CONFIG_MTD_MSM_NAND kfree(buf_new); #endif return err; }