| 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 |
| @@ -25,6 +25,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) |
| { |
| @@ -79,21 +106,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++; |
| } |
| |