diff options
Diffstat (limited to 'drivers/mtd/peb.c')
-rw-r--r-- | drivers/mtd/peb.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/drivers/mtd/peb.c b/drivers/mtd/peb.c index 03d96c2a5a..a17d42885e 100644 --- a/drivers/mtd/peb.c +++ b/drivers/mtd/peb.c @@ -1,13 +1,4 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0-only #include <common.h> #include <malloc.h> @@ -214,10 +205,12 @@ int mtd_peb_read(struct mtd_info *mtd, void *buf, int pnum, int offset, return -EINVAL; if (offset < 0 || offset + len > mtd->erasesize) return -EINVAL; - if (len <= 0) + if (len < 0) return -EINVAL; if (mtd_peb_is_bad(mtd, pnum)) return -EINVAL; + if (!len) + return 0; /* Deliberately corrupt the buffer */ *((uint8_t *)buf) ^= 0xFF; @@ -397,12 +390,14 @@ int mtd_peb_write(struct mtd_info *mtd, const void *buf, int pnum, int offset, return -EINVAL; if (offset < 0 || offset + len > mtd->erasesize) return -EINVAL; - if (len <= 0) + if (len < 0) return -EINVAL; if (len % (mtd->writesize >> mtd->subpage_sft)) return -EINVAL; if (mtd_peb_is_bad(mtd, pnum)) return -EINVAL; + if (!len) + return 0; if (mtd_peb_emulate_write_failure()) { dev_err(&mtd->dev, "Cannot write %d bytes to PEB %d:%d (emulated)\n", @@ -518,6 +513,51 @@ out: } /** + * mtd_peb_read_file - read data from a mtd device + * @mtd: mtd device + * @peb_start: The first PEB where to start reading + * @peb_last: last PEB where to read from + * @buf: buffer to read to + * @len: how many bytes to read + * + * This function reads @len bytes of data to buffer @buf from the mtd device + * @mtd starting at @peb_start. Reading will stop at @peb_last. This function + * skips all bad blocks and returns 0 on success or a negative error code + * otherwise. + */ +int mtd_peb_read_file(struct mtd_info *mtd, unsigned int peb_start, + unsigned int peb_last, void *buf, size_t len) +{ + int ret, pnum; + + pnum = peb_start; + + while (len) { + size_t now = min_t(size_t, mtd->erasesize, len); + + if (pnum > peb_last) + return -EIO; + + if (mtd_peb_is_bad(mtd, pnum)) { + pnum++; + continue; + } + + ret = mtd_peb_read(mtd, buf, pnum, 0, now); + if (ret) + goto out; + + len -= now; + pnum++; + buf += now; + } + + ret = 0; +out: + return ret; +} + +/** * mtd_peb_erase - erase a physical eraseblock. * @mtd: mtd device * @pnum: physical eraseblock number to erase |