Automatically creating a BBT is the right thing to do if the NAND is factory new. However when migrating from a barebox older than commit v2020.03.0~28^2~1 ("mtd: nand-imx: Create BBT automatically when necessary") on a used machine, this automatism is really bad because it most likely marks the blocks containing the barebox image (and possibly more) as bad. On such a system the vendor BBMs are gone, but it was operated without that information before, so continuing to do so is a sane option. Add a light check for the NAND to be really pristine: If the first block looks like containing a barebox image or a UBI refuse to create a BBT. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> --- drivers/mtd/nand/nand_imx.c | 59 ++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c index b26889358b3f..9a7f82d59029 100644 --- a/drivers/mtd/nand/nand_imx.c +++ b/drivers/mtd/nand/nand_imx.c @@ -12,6 +12,7 @@ #include <common.h> #include <driver.h> +#include <filetype.h> #include <malloc.h> #include <init.h> #include <linux/mtd/mtd.h> @@ -1166,30 +1167,6 @@ static int __init mxcnd_probe_dt(struct imx_nand_host *host) * From this point on we can forget about the BBMs and rely completely * on the flash BBT. */ -static int checkbad(struct nand_chip *chip, loff_t ofs) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - int ret; - uint8_t buf[mtd->writesize + mtd->oobsize]; - struct mtd_oob_ops ops; - - ops.mode = MTD_OPS_RAW; - ops.ooboffs = 0; - ops.datbuf = buf; - ops.len = mtd->writesize; - ops.oobbuf = buf + mtd->writesize; - ops.ooblen = mtd->oobsize; - - ret = mtd_read_oob(mtd, ofs, &ops); - if (ret < 0) - return ret; - - if (buf[2000] != 0xff) - return 1; - - return 0; -} - static int imxnd_create_bbt(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); @@ -1209,12 +1186,40 @@ static int imxnd_create_bbt(struct nand_chip *chip) for (i = 0; i < numblocks; ++i) { loff_t ofs = i << chip->bbt_erase_shift; + uint8_t buf[mtd->writesize + mtd->oobsize]; + struct mtd_oob_ops ops = { + .mode = MTD_OPS_RAW, + .ooboffs = 0, + .datbuf = buf, + .len = mtd->writesize, + .oobbuf = buf + mtd->writesize, + .ooblen = mtd->oobsize, + }; - ret = checkbad(chip, ofs); - if (ret < 0) + ret = mtd_read_oob(mtd, ofs, &ops); + if (ret < 0) { + dev_err(mtd->dev.parent, "Failed to read page at 0x%08x\n", (unsigned int)ofs); goto out; + } - if (ret) { + /* + * Automatically adding a BBT based on factory BBTs is only + * sensible if the NAND is pristine. Abort if the first page + * looks like a bootloader or UBI block. + */ + if (ofs == 0 && is_barebox_arm_head(buf)) { + dev_err(mtd->dev.parent, "Flash seems to contain a barebox image, refusing\n"); + ret = -EINVAL; + goto out; + } + + if (ofs == 0 && !memcmp(buf, "UBI#", 4)) { + dev_err(mtd->dev.parent, "Flash seems to contain a UBI, refusing\n"); + ret = -EINVAL; + goto out; + } + + if (buf[2000] != 0xff) { bbt[i >> 2] |= 0x03 << (2 * (i & 0x3)); dev_info(mtd->dev.parent, "Bad eraseblock %d at 0x%08x\n", i, (unsigned int)ofs); -- 2.43.0