From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets Signed-off-by: Rafał Miłecki <zajec5@gmail.com> --- --- a/drivers/mtd/parsers/parser_trx.c +++ b/drivers/mtd/parsers/parser_trx.c @@ -30,6 +30,33 @@ struct trx_header { uint32_t offset[3]; } __packed; +/* + * Calculate real end offset (address) for a given amount of data. It checks + * all blocks skipping bad ones. + */ +static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes) +{ + size_t real_offset = 0; + + if (mtd_block_isbad(mtd, real_offset)) + pr_warn("Base offset shouldn't be at bad block"); + + while (bytes >= mtd->erasesize) { + bytes -= mtd->erasesize; + real_offset += mtd->erasesize; + while (mtd_block_isbad(mtd, real_offset)) { + real_offset += mtd->erasesize; + + if (real_offset >= mtd->size) + return real_offset - mtd->erasesize; + } + } + + real_offset += bytes; + + return real_offset; +} + static const char *parser_trx_data_part_name(struct mtd_info *master, size_t offset) { @@ -84,21 +111,21 @@ static int parser_trx_parse(struct mtd_i if (trx.offset[2]) { part = &parts[curr_part++]; part->name = "loader"; - part->offset = trx.offset[i]; + part->offset = parser_trx_real_offset(mtd, trx.offset[i]); i++; } if (trx.offset[i]) { part = &parts[curr_part++]; part->name = "linux"; - part->offset = trx.offset[i]; + part->offset = parser_trx_real_offset(mtd, trx.offset[i]); i++; } if (trx.offset[i]) { part = &parts[curr_part++]; - part->name = parser_trx_data_part_name(mtd, trx.offset[i]); - part->offset = trx.offset[i]; + part->offset = parser_trx_real_offset(mtd, trx.offset[i]); + part->name = parser_trx_data_part_name(mtd, part->offset); i++; }