static int verify_eraseblock(int ebnum) { size_t read; int err = 0; loff_t addr = ebnum * mtd->erasesize; prandom_bytes_state(&rnd_state, writebuf, subpgsize); clear_data(readbuf, subpgsize); err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { pr_err("error: read failed at %#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { pr_err("error: verify failed at %#llx\n", (long long)addr); pr_info("------------- written----------------\n"); print_subpage(writebuf); pr_info("------------- read ------------------\n"); print_subpage(readbuf); pr_info("-------------------------------------\n"); errcnt += 1; } addr += subpgsize; prandom_bytes_state(&rnd_state, writebuf, subpgsize); clear_data(readbuf, subpgsize); err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { pr_err("error: read failed at %#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { pr_info("error: verify failed at %#llx\n", (long long)addr); pr_info("------------- written----------------\n"); print_subpage(writebuf); pr_info("------------- read ------------------\n"); print_subpage(readbuf); pr_info("-------------------------------------\n"); errcnt += 1; } return err; }
static int nvram_init(void) { #ifdef CONFIG_MTD struct mtd_info *mtd; struct nvram_header header; size_t bytes_read; int err; mtd = get_mtd_device_nm("nvram"); if (IS_ERR(mtd)) return -ENODEV; err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header); if (!err && header.magic == NVRAM_MAGIC && header.len > sizeof(header)) { nvram_len = header.len; if (nvram_len >= NVRAM_SPACE) { pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", header.len, NVRAM_SPACE); nvram_len = NVRAM_SPACE - 1; } err = mtd_read(mtd, 0, nvram_len, &nvram_len, (u8 *)nvram_buf); return err; } #endif return -ENXIO; }
int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb) { int err, i, patt_count; void *buf; normsg("run torture test for PEB %d", eb); patt_count = ARRAY_SIZE(patterns); buf = malloc(mtd->eb_size); if (!buf) { errmsg("cannot allocate %d bytes of memory", mtd->eb_size); return -1; } for (i = 0; i < patt_count; i++) { err = mtd_erase(mtd, fd, eb); if (err) goto out; /* Make sure the PEB contains only 0xFF bytes */ err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); if (err) goto out; err = check_pattern(buf, 0xFF, mtd->eb_size); if (err == 0) { errmsg("erased PEB %d, but a non-0xFF byte found", eb); errno = EIO; goto out; } /* Write a pattern and check it */ memset(buf, patterns[i], mtd->eb_size); err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size); if (err) goto out; memset(buf, ~patterns[i], mtd->eb_size); err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); if (err) goto out; err = check_pattern(buf, patterns[i], mtd->eb_size); if (err == 0) { errmsg("pattern %x checking failed for PEB %d", patterns[i], eb); errno = EIO; goto out; } } err = 0; normsg("PEB %d passed torture test, do not mark it a bad", eb); out: free(buf); return -1; }
int syscfg_setup() { int i; SCfgEntry curEntry; uint32_t cursor; mtd_t *dev = syscfg_device(); if(!dev) return -1; mtd_prepare(dev); mtd_read(dev, &header, SCFG_LOCATION, sizeof(header)); if(header.magic != SCFG_MAGIC) { mtd_finish(dev); bufferPrintf("syscfg: cannot find readable syscfg partition!\r\n"); return -1; } bufferPrintf("syscfg: found version 0x%08x with %d entries using %d of %d bytes\r\n", header.version, header.entries, header.bytes_used, header.bytes_total); entries = (OIBSyscfgEntry*) malloc(sizeof(OIBSyscfgEntry) * header.entries); cursor = SCFG_LOCATION + sizeof(header); for(i = 0; i < header.entries; ++i) { mtd_read(dev, &curEntry, cursor, sizeof(curEntry)); if(curEntry.magic != CNTB_MAGIC) { entries[i].type = curEntry.magic; entries[i].size = 16; entries[i].data = (uint8_t*) malloc(16); memcpy(entries[i].data, curEntry.data, 16); } else { entries[i].type = curEntry.cntb.type; entries[i].size = curEntry.cntb.size; entries[i].data = (uint8_t*) malloc(curEntry.cntb.size); mtd_read(dev, entries[i].data, SCFG_LOCATION + curEntry.cntb.offset, curEntry.cntb.size); } cursor += sizeof(curEntry); } mtd_finish(dev); return 0; }
static int read_eraseblock_by_page(int ebnum) { unsigned char *buf = iobuf, *oobbuf = iobuf1; uint64_t addr = ((uint64_t)ebnum) * ((uint64_t)mtd.eb_size); int i, ret; for (i = 0; i < pgcnt; ++i) { memset(buf, 0, pgsize); ret = mtd_read(&mtd, fd, ebnum, i*pgsize, buf, pgsize); if (ret) { fprintf(stderr, "Error reading block %d, page %d\n", ebnum, i); return -1; } if (mtd.oob_size) { ret = mtd_read_oob(mtd_desc, &mtd, fd, addr, mtd.oob_size, oobbuf); if (ret) { fprintf(stderr, "Error reading OOB in block %d, page %d\n", ebnum, i); return -1; } oobbuf += mtd.oob_size; } buf += pgsize; addr += pgsize; } if (flags & FLAG_VERBOSE) printf("Successfully read erase block %d\n", ebnum); return 0; }
/** * ubi_dump_flash - dump a region of flash. * @ubi: UBI device description object * @pnum: the physical eraseblock number to dump * @offset: the starting offset within the physical eraseblock to dump * @len: the length of the region to dump */ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) { int err; size_t read; void *buf; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; buf = vmalloc(len); if (!buf) return; err = mtd_read(ubi->mtd, addr, len, &read, buf); if (err && err != -EUCLEAN) { ubi_err(ubi->ubi_num, "err %d while reading %d bytes from PEB %d:%d, read %zd bytes", err, len, pnum, offset, read); goto out; } if (ubi->lookuptbl) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); ubi_msg(ubi->ubi_num, "dumping %d bytes of data from PEB %d, offset %d", len, pnum, offset); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1); out: vfree(buf); return; }
static int read_eraseblock_by_page(int ebnum) { size_t read; int i, err = 0; loff_t addr = ebnum * mtd->erasesize; void *buf = iobuf; for (i = 0; i < pgcnt; i++) { err = mtd_read(mtd, addr, pgsize, &read, buf); /* Ignore corrected ECC errors */ if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n", addr); if (!err) err = -EINVAL; break; } addr += pgsize; buf += pgsize; } return err; }
int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset, enum mtdsplit_part_type *type) { u32 magic; size_t retlen; int ret; ret = mtd_read(mtd, offset, sizeof(magic), &retlen, (unsigned char *) &magic); if (ret) return ret; if (retlen != sizeof(magic)) return -EIO; if (le32_to_cpu(magic) == SQUASHFS_MAGIC) { if (type) *type = MTDSPLIT_PART_TYPE_SQUASHFS; return 0; } else if (magic == 0x19852003) { if (type) *type = MTDSPLIT_PART_TYPE_JFFS2; return 0; } else if (be32_to_cpu(magic) == UBI_EC_MAGIC) { if (type) *type = MTDSPLIT_PART_TYPE_UBI; return 0; } return -EINVAL; }
static int qihoo_init_wmac(void) { struct mtd_info * mtd; size_t nb = 0; u8 *art; int ret; if (!qihoo_c301_board) return 0; mtd = get_mtd_device_nm("radiocfg"); if (IS_ERR(mtd)) return PTR_ERR(mtd); if (mtd->size != 0x10000) return -1; art = kzalloc(0x1000, GFP_KERNEL); if (!art) return -1; ret = mtd_read(mtd, QIHOO_C301_WMAC_CALDATA_OFFSET, 0x1000, &nb, art); if (nb != 0x1000) { kfree(art); return ret; } ath79_register_wmac(art, wlan24mac); return 0; }
int mtd_get_squashfs_len(struct mtd_info *master, size_t offset, size_t *squashfs_len) { struct squashfs_super_block sb; size_t retlen; int err; err = mtd_read(master, offset, sizeof(sb), &retlen, (void *)&sb); if (err || (retlen != sizeof(sb))) { pr_alert("error occured while reading from \"%s\"\n", master->name); return -EIO; } if (le32_to_cpu(sb.s_magic) != SQUASHFS_MAGIC) { pr_alert("no squashfs found in \"%s\"\n", master->name); return -EINVAL; } retlen = le64_to_cpu(sb.bytes_used); if (retlen <= 0) { pr_alert("squashfs is empty in \"%s\"\n", master->name); return -ENODEV; } if (offset + retlen > master->size) { pr_alert("squashfs has invalid size in \"%s\"\n", master->name); return -EINVAL; } *squashfs_len = retlen; return 0; }
void env_relocate_spec(void) { struct mtd_info *mtd = &onenand_mtd; #ifdef CONFIG_ENV_ADDR_FLEX struct onenand_chip *this = &onenand_chip; #endif int rc; size_t retlen; #ifdef ENV_IS_EMBEDDED char *buf = (char *)&environment; #else loff_t env_addr = CONFIG_ENV_ADDR; char onenand_env[ONENAND_MAX_ENV_SIZE]; char *buf = (char *)&onenand_env[0]; #endif /* ENV_IS_EMBEDDED */ #ifndef ENV_IS_EMBEDDED # ifdef CONFIG_ENV_ADDR_FLEX if (FLEXONENAND(this)) env_addr = CONFIG_ENV_ADDR_FLEX; # endif /* Check OneNAND exist */ if (mtd->writesize) /* Ignore read fail */ mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, (u_char *)buf); else mtd->writesize = MAX_ONENAND_PAGESIZE; #endif /* !ENV_IS_EMBEDDED */ rc = env_import(buf, 1); if (rc) gd->env_valid = 1; }
static int get_valid_cis_sector(struct mtd_info *mtd) { int ret, k, cis_sector; size_t retlen; loff_t offset; uint8_t *sect_buf; cis_sector = -1; sect_buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); if (!sect_buf) goto out; for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { if (mtd_block_isbad(mtd, offset)) { ret = mtd_read(mtd, offset, SECTOR_SIZE, &retlen, sect_buf); if (ret < 0 || retlen != SECTOR_SIZE) { printk(KERN_WARNING "SSFDC_RO:can't read CIS/IDI sector\n"); } else if (!memcmp(sect_buf, cis_numbers, sizeof(cis_numbers))) { cis_sector = (int)(offset >> SECTOR_SHIFT); } else { pr_debug("SSFDC_RO: CIS/IDI sector not found" " on %s (mtd%d)\n", mtd->name, mtd->index); } break; }
static int verify_eraseblock2(int ebnum) { size_t read; int err = 0, k; loff_t addr = ebnum * mtd->erasesize; for (k = 1; k < 33; ++k) { if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize) break; prandom_bytes_state(&rnd_state, writebuf, subpgsize * k); clear_data(readbuf, subpgsize * k); err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf); if (unlikely(err || read != subpgsize * k)) { if (mtd_is_bitflip(err) && read == subpgsize * k) { pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { pr_err("error: read failed at " "%#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { pr_err("error: verify failed at %#llx\n", (long long)addr); errcnt += 1; } addr += subpgsize * k; } return err; }
static int erasetest(void) { size_t read, written; int err = 0, i, ebnum, ok = 1; loff_t addr0; printk(PRINT_PREF "erasetest\n"); ebnum = 0; addr0 = 0; for (i = 0; i < ebcnt && bbt[i]; ++i) { addr0 += mtd->erasesize; ebnum += 1; } printk(PRINT_PREF "erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); set_random_data(writebuf, pgsize); err = mtd_write(mtd, addr0, pgsize, &written, writebuf); if (err || written != pgsize) { printk(PRINT_PREF "error: write failed at %#llx\n", (long long)addr0); return err ? err : -1; } printk(PRINT_PREF "erasing block %d\n", ebnum); err = erase_eraseblock(ebnum); if (err) return err; printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); err = mtd_read(mtd, addr0, pgsize, &read, twopages); if (mtd_is_bitflip(err)) err = 0; if (err || read != pgsize) { printk(PRINT_PREF "error: read failed at %#llx\n", (long long)addr0); return err ? err : -1; } printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n", ebnum); for (i = 0; i < pgsize; ++i) if (twopages[i] != 0xff) { printk(PRINT_PREF "verifying all 0xff failed at %d\n", i); errcnt += 1; ok = 0; break; } if (ok && !err) printk(PRINT_PREF "erasetest ok\n"); return err; }
int images_verify(Image* image) { uint8_t hash[0x40]; int retVal = 0; if(image == NULL) { return 1; } mtd_t *dev = images_device(); if(!dev) { return 1; } mtd_prepare(dev); if(!image->hashMatch) retVal |= 1 << 2; void* data = malloc(image->padded); mtd_read(dev, data, image->offset + sizeof(Img2Header), image->padded); calculateDataHash(data, image->padded, hash); free(data); if(memcmp(hash, image->dataHash, 0x40) != 0) retVal |= 1 << 3; mtd_finish(dev); return retVal; }
static int afs_read_iis_v1(struct mtd_info *mtd, struct image_info_v1 *iis, u_int ptr) { size_t sz; int ret, i; memset(iis, 0, sizeof(*iis)); ret = mtd_read(mtd, ptr, sizeof(*iis), &sz, (u_char *)iis); if (ret < 0) goto failed; if (sz != sizeof(*iis)) { ret = -EINVAL; goto failed; } ret = 0; /* * Validate the name - it must be NUL terminated. */ for (i = 0; i < sizeof(iis->name); i++) if (iis->name[i] == '\0') break; if (i < sizeof(iis->name)) ret = 1; return ret; failed: printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", ptr, ret); return ret; }
static int do_read(void) { size_t read; int eb = rand_eb(); int offs = rand_offs(); int len = rand_len(offs), err; loff_t addr; if (bbt[eb + 1]) { if (offs >= mtd->erasesize) offs -= mtd->erasesize; if (offs + len > mtd->erasesize) len = mtd->erasesize - offs; } addr = eb * mtd->erasesize + offs; err = mtd_read(mtd, addr, len, &read, readbuf); if (mtd_is_bitflip(err)) err = 0; if (unlikely(err || read != len)) { pr_err("error: read failed at 0x%llx\n", (long long)addr); if (!err) err = -EINVAL; return err; } return 0; }
static int verify_eraseblock_ff(int ebnum) { uint32_t j; size_t read; int err = 0; loff_t addr = ebnum * mtd->erasesize; memset(writebuf, 0xff, subpgsize); for (j = 0; j < mtd->erasesize / subpgsize; ++j) { clear_data(readbuf, subpgsize); err = mtd_read(mtd, addr, subpgsize, &read, readbuf); if (unlikely(err || read != subpgsize)) { if (mtd_is_bitflip(err) && read == subpgsize) { pr_info("ECC correction at %#llx\n", (long long)addr); err = 0; } else { pr_err("error: read failed at " "%#llx\n", (long long)addr); return err ? err : -1; } } if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { pr_err("error: verify 0xff failed at " "%#llx\n", (long long)addr); errcnt += 1; } addr += subpgsize; } return err; }
static int afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, u_int off, u_int mask) { struct footer_struct fs; u_int ptr = off + mtd->erasesize - sizeof(fs); size_t sz; int ret; ret = mtd_read(mtd, ptr, sizeof(fs), &sz, (u_char *)&fs); if (ret >= 0 && sz != sizeof(fs)) ret = -EINVAL; if (ret < 0) { printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", ptr, ret); return ret; } ret = 1; /* * Does it contain the magic number? */ if (fs.signature != 0xa0ffff9f) ret = 0; /* * Check the checksum. */ if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) ret = 0; /* * Don't touch the SIB. */ if (fs.type == 2) ret = 0; *iis_start = fs.image_info_base & mask; *img_start = fs.image_start & mask; /* * Check the image info base. This can not * be located after the footer structure. */ if (*iis_start >= ptr) ret = 0; /* * Check the start of this image. The image * data can not be located after this block. */ if (*img_start > off) ret = 0; return ret; }
static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, int len, char *buf) { struct mtd_info *mtd = mtdblk->mbd.mtd; unsigned int sect_size = mtdblk->cache_size; size_t retlen; int ret; pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", mtd->name, pos, len); if (!sect_size) return mtd_read(mtd, pos, len, &retlen, buf); while (len > 0) { unsigned long sect_start = (pos/sect_size)*sect_size; unsigned int offset = pos - sect_start; unsigned int size = sect_size - offset; if (size > len) size = len; /* * Check if the requested data is already cached * Read the requested amount of data from our internal cache if it * contains what we want, otherwise we read the data directly * from flash. */ if (mtdblk->cache_state != STATE_EMPTY && mtdblk->cache_offset == sect_start) { memcpy (buf, mtdblk->cache_data + offset, size); } else { ret = mtd_read(mtd, pos, size, &retlen, buf); if (ret) return ret; if (retlen != size) return -EIO; } buf += size; pos += size; len -= size; } return 0; }
void images_write(Image* image, void* data, unsigned int length, int encrypt) { bufferPrintf("images_write(%x, %x, %x)\r\n", image, data, length); if(image == NULL) return; mtd_t *dev = images_device(); if(!dev) return; mtd_prepare(dev); uint32_t padded = length; if((length & 0xF) != 0) { padded = (padded & ~0xF) + 0x10; } if(image->next != NULL && (image->offset + sizeof(Img2Header) + padded) >= image->next->offset) { bufferPrintf("**ABORTED** requested length greater than available space.\r\n"); return; } uint32_t totalLen = sizeof(Img2Header) + padded; uint8_t* writeBuffer = (uint8_t*) malloc(totalLen); mtd_read(dev, writeBuffer, image->offset, sizeof(Img2Header)); memcpy(writeBuffer + sizeof(Img2Header), data, length); if(encrypt) aes_838_encrypt(writeBuffer + sizeof(Img2Header), padded, NULL); Img2Header* header = (Img2Header*) writeBuffer; header->dataLen = length; header->dataLenPadded = padded; calculateDataHash(writeBuffer + sizeof(Img2Header), padded, header->dataHash); uint32_t checksum = 0; crc32(&checksum, writeBuffer, 0x64); header->header_checksum = checksum; calculateHash(header, header->hash); bufferPrintf("mtd_write(0x%p, %x, %x, %x)\r\n", dev, writeBuffer, image->offset, totalLen); mtd_write(dev, writeBuffer, image->offset, totalLen); bufferPrintf("mtd_write(0x%p, %x, %x, %x) done\r\n", dev, writeBuffer, image->offset, totalLen); free(writeBuffer); mtd_finish(dev); images_release(); images_setup(); }
static int concat_read(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) { struct mtd_concat *concat = CONCAT(mtd); int ret = 0, err; int i; #ifdef __UBOOT__ *retlen = 0; #endif for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; size_t size, retsize; if (from >= subdev->size) { /* Not destined for this subdev */ size = 0; from -= subdev->size; continue; } if (from + len > subdev->size) /* First part goes into this subdev */ size = subdev->size - from; else /* Entire transaction goes into this subdev */ size = len; err = mtd_read(subdev, from, size, &retsize, buf); /* Save information about bitflips! */ if (unlikely(err)) { if (mtd_is_eccerr(err)) { mtd->ecc_stats.failed++; ret = err; } else if (mtd_is_bitflip(err)) { mtd->ecc_stats.corrected++; /* Do not overwrite -EBADMSG !! */ if (!ret) ret = err; } else return err; } *retlen += retsize; len -= size; if (len == 0) return ret; buf += size; from = 0; } return -EINVAL; }
static void find_next_position(struct mtdoops_context *cxt) { struct mtd_info *mtd = cxt->mtd; int ret, page, maxpos = 0; u32 count[2], maxcount = 0xffffffff; size_t retlen; for (page = 0; page < cxt->oops_pages; page++) { if (mtd_can_have_bb(mtd) && mtd_block_isbad(mtd, page * record_size)) continue; /* Assume the page is used */ mark_page_used(cxt, page); ret = mtd_read(mtd, page * record_size, MTDOOPS_HEADER_SIZE, &retlen, (u_char *)&count[0]); if (retlen != MTDOOPS_HEADER_SIZE || (ret < 0 && !mtd_is_bitflip(ret))) { printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n", page * record_size, retlen, MTDOOPS_HEADER_SIZE, ret); continue; } if (count[0] == 0xffffffff && count[1] == 0xffffffff) mark_page_unused(cxt, page); if (count[0] == 0xffffffff) continue; if (maxcount == 0xffffffff) { maxcount = count[0]; maxpos = page; } else if (count[0] < 0x40000000 && maxcount > 0xc0000000) { maxcount = count[0]; maxpos = page; } else if (count[0] > maxcount && count[0] < 0xc0000000) { maxcount = count[0]; maxpos = page; } else if (count[0] > maxcount && count[0] > 0xc0000000 && maxcount > 0x80000000) { maxcount = count[0]; maxpos = page; } } if (maxcount == 0xffffffff) { cxt->nextpage = 0; cxt->nextcount = 1; schedule_work(&cxt->work_erase); return; } cxt->nextpage = maxpos; cxt->nextcount = maxcount; mtdoops_inc_counter(cxt); }
static int mt76_get_of_eeprom(struct mt76_dev *dev, int len) { #ifdef CONFIG_OF struct device_node *np = dev->dev->of_node; struct mtd_info *mtd; const __be32 *list; const char *part; phandle phandle; int offset = 0; int size; size_t retlen; int ret; if (!np) return -ENOENT; list = of_get_property(np, "mediatek,mtd-eeprom", &size); if (!list) return -ENOENT; phandle = be32_to_cpup(list++); if (!phandle) return -ENOENT; np = of_find_node_by_phandle(phandle); if (!np) return -EINVAL; part = of_get_property(np, "label", NULL); if (!part) part = np->name; mtd = get_mtd_device_nm(part); if (IS_ERR(mtd)) return PTR_ERR(mtd); if (size <= sizeof(*list)) return -EINVAL; offset = be32_to_cpup(list); ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data); put_mtd_device(mtd); if (ret) return ret; if (retlen < len) return -EINVAL; return 0; #else return -ENOENT; #endif }
/** * self_check_write - make sure write succeeded. * @ubi: UBI device description object * @buf: buffer with data which were written * @pnum: physical eraseblock number the data were written to * @offset: offset within the physical eraseblock the data were written to * @len: how many bytes were written * * This functions reads data which were recently written and compares it with * the original data buffer - the data have to match. Returns zero if the data * match and a negative error code if not or in case of failure. */ static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { int err, i; size_t read; void *buf1; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; if (!ubi_dbg_chk_io(ubi)) return 0; buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); if (!buf1) { ubi_err("cannot allocate memory to check writes"); return 0; } err = mtd_read(ubi->mtd, addr, len, &read, buf1); if (err && !mtd_is_bitflip(err)) goto out_free; for (i = 0; i < len; i++) { uint8_t c = ((uint8_t *)buf)[i]; uint8_t c1 = ((uint8_t *)buf1)[i]; #if !defined(CONFIG_UBI_SILENCE_MSG) int dump_len = max_t(int, 128, len - i); #endif if (c == c1) continue; ubi_err("self-check failed for PEB %d:%d, len %d", pnum, offset, len); ubi_msg("data differ at position %d", i); ubi_msg("hex dump of the original buffer from %d to %d", i, i + dump_len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf + i, dump_len, 1); ubi_msg("hex dump of the read buffer from %d to %d", i, i + dump_len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf1 + i, dump_len, 1); dump_stack(); err = -EINVAL; goto out_free; } vfree(buf1); return 0; out_free: vfree(buf1); return err; }
/* * Check that the contents of eraseblock number @enbum is equivalent to the * @buf buffer. */ static inline int check_eraseblock(int ebnum, unsigned char *buf) { int err, retries = 0; size_t read; loff_t addr = ebnum * mtd->erasesize; size_t len = mtd->erasesize; if (pgcnt) { addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; len = pgcnt * pgsize; } retry: err = mtd_read(mtd, addr, len, &read, check_buf); if (mtd_is_bitflip(err)) pr_err("single bit flip occurred at EB %d " "MTD reported that it was fixed.\n", ebnum); else if (err) { pr_err("error %d while reading EB %d, " "read %zd\n", err, ebnum, read); return err; } if (read != len) { pr_err("failed to read %zd bytes from EB %d, " "read only %zd, but no error reported\n", len, ebnum, read); return -EIO; } if (memcmp(buf, check_buf, len)) { pr_err("read wrong data from EB %d\n", ebnum); report_corrupt(check_buf, buf); if (retries++ < RETRIES) { /* Try read again */ yield(); pr_info("re-try reading data from EB %d\n", ebnum); goto retry; } else { pr_info("retried %d times, still errors, " "give-up\n", RETRIES); return -EINVAL; } } if (retries != 0) pr_info("only attempt number %d was OK (!!!)\n", retries); return 0; }
static void da850_evm_m25p80_notify_add(struct mtd_info *mtd) { char *mac_addr = davinci_soc_info.emac_pdata->mac_addr; size_t retlen; if (!strcmp(mtd->name, "MAC-Address")) { mtd_read(mtd, 0, ETH_ALEN, &retlen, mac_addr); if (retlen == ETH_ALEN) pr_info("Read MAC addr from SPI Flash: %pM\n", mac_addr); } }
static int mtdsplit_parse_wrgg(struct mtd_info *master, struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct wrgg03_header hdr; size_t hdr_len, retlen, kernel_ent_size; size_t rootfs_offset; struct mtd_partition *parts; enum mtdsplit_part_type type; int err; hdr_len = sizeof(hdr); err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); if (err) return err; if (retlen != hdr_len) return -EIO; /* sanity checks */ if (le32_to_cpu(hdr.magic1) != WRGG03_MAGIC) return -EINVAL; kernel_ent_size = hdr_len + be32_to_cpu(hdr.size); if (kernel_ent_size > master->size) return -EINVAL; /* * The size in the header covers the rootfs as well. * Start the search from an arbitrary offset. */ err = mtd_find_rootfs_from(master, WRGG_MIN_ROOTFS_OFFS, master->size, &rootfs_offset, &type); if (err) return err; parts = kzalloc(WRGG_NR_PARTS * sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; parts[0].name = KERNEL_PART_NAME; parts[0].offset = 0; parts[0].size = rootfs_offset; parts[1].name = ROOTFS_PART_NAME; parts[1].offset = rootfs_offset; parts[1].size = master->size - rootfs_offset; *pparts = parts; return WRGG_NR_PARTS; }
static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) { int ret = -EINVAL; #ifdef CONFIG_OF static struct firmware mtd_fw; struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; size_t retlen, len = rt2x00dev->ops->eeprom_size; int size, offset = 0; struct mtd_info *mtd; const char *part; const __be32 *list; phandle phandle; list = of_get_property(np, "ralink,mtd-eeprom", &size); if (!list) { dev_err(rt2x00dev->dev, "failed to load eeprom property\n"); return -ENOENT; } phandle = be32_to_cpup(list++); if (phandle) mtd_np = of_find_node_by_phandle(phandle); if (!mtd_np) { dev_err(rt2x00dev->dev, "failed to load mtd phandle\n"); return -EINVAL; } part = of_get_property(mtd_np, "label", NULL); if (!part) part = mtd_np->name; mtd = get_mtd_device_nm(part); if (IS_ERR(mtd)) { dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part); return PTR_ERR(mtd); } if (size > sizeof(*list)) offset = be32_to_cpup(list); ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom); put_mtd_device(mtd); if (!ret) { rt2x00dev->eeprom_file = &mtd_fw; mtd_fw.size = len; mtd_fw.data = (const u8 *) rt2x00dev->eeprom; } #endif return ret; }
static int mtdsplit_parse_lzma(struct mtd_info *master, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { struct lzma_header hdr; size_t hdr_len, retlen; size_t rootfs_offset; u32 t; struct mtd_partition *parts; int err; hdr_len = sizeof(hdr); err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); if (err) return err; if (retlen != hdr_len) return -EIO; /* verify LZMA properties */ if (hdr.props[0] >= (9 * 5 * 5)) return -EINVAL; t = get_unaligned_le32(&hdr.props[1]); if (!is_power_of_2(t)) return -EINVAL; t = get_unaligned_le32(&hdr.size_high); if (t) return -EINVAL; err = mtd_find_rootfs_from(master, master->erasesize, master->size, &rootfs_offset, NULL); if (err) return err; parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; parts[0].name = KERNEL_PART_NAME; parts[0].offset = 0; parts[0].size = rootfs_offset; parts[1].name = ROOTFS_PART_NAME; parts[1].offset = rootfs_offset; parts[1].size = master->size - rootfs_offset; *pparts = parts; return LZMA_NR_PARTS; }