diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/mtdcore.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 6eb52ed50c..78f2a08541 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -142,3 +142,52 @@ void put_mtd_device(struct mtd_info *mtd) c = --mtd->usecount; BUG_ON(c < 0); } + +#if defined(CONFIG_CMD_MTDPARTS_SPREAD) +/** + * mtd_get_len_incl_bad + * + * Check if length including bad blocks fits into device. + * + * @param mtd an MTD device + * @param offset offset in flash + * @param length image length + * @return image length including bad blocks in *len_incl_bad and whether or not + * the length returned was truncated in *truncated + */ +void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, + const uint64_t length, uint64_t *len_incl_bad, + int *truncated) +{ + *truncated = 0; + *len_incl_bad = 0; + + if (offset >= mtd->size) { + *truncated = 1; + return; + } + + if (!mtd->block_isbad) { + *len_incl_bad = length; + return; + } + + uint64_t len_excl_bad = 0; + uint64_t block_len; + + while (len_excl_bad < length) { + block_len = mtd->erasesize - (offset & (mtd->erasesize - 1)); + + if (!mtd->block_isbad(mtd, offset & ~(mtd->erasesize - 1))) + len_excl_bad += block_len; + + *len_incl_bad += block_len; + offset += block_len; + + if (offset >= mtd->size) { + *truncated = 1; + break; + } + } +} +#endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */ |