public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Michael Trimarchi <michael@amarulasolutions.com>
To: Han Xu <han.xu@nxp.com>, U-Boot-Denx <u-boot@lists.denx.de>
Cc: Ye Li <ye.li@nxp.com>, Stefano Babic <sbabic@denx.de>,
	Miquel Raynal <miquel.raynal@bootlin.com>,
	Fabio Estevam <festevam@denx.de>,
	Dario Binacchi <dario.binacchi@amarulasolutions.com>,
	Sean Anderson <sean.anderson@seco.com>,
	linux-amarula@amarulasolutions.com,
	Jagan Teki <jagan@amarulasolutions.com>,
	Ariel D'Alessandro <ariel.dalessandro@collabora.com>,
	Tom Rini <trini@konsulko.com>, Fabio Estevam <festevam@gmail.com>,
	Tim Harvey <tharvey@gateworks.com>
Subject: [PATCH V4 2/5] mtd: nand: mxs_nand_spl: Fix bad block skipping
Date: Sun, 15 May 2022 11:35:31 +0200	[thread overview]
Message-ID: <20220515093534.1737172-3-michael@amarulasolutions.com> (raw)
In-Reply-To: <20220515093534.1737172-1-michael@amarulasolutions.com>

The specific implementation was having bug. Those bugs are since
the beginning of the implementation. Some manufactures can already
experience this bug in their SPL code. This bug can be more visible on
architecture that has complicated boot process like imx8mn. Older
version of uboot can be affected if the bad block
appear in correspoding of the beginning of u-boot image. In order to
adjust the function we scan from the first erase block.

The problematic part of old code was in this part:

while (is_badblock(mtd, offs, 1)) {
           page = page + nand_page_per_block;
          /* Check i we've reached the end of flash. */
          if (page >= mtd->size >> chip->page_shift) {
                      free(page_buf);
                      return -ENOMEM;
         }
}

Even we fix it adding increment of the offset of one erase block size
, we don't fix the problem, because the first erase block where the
image start is not checked. The code was tested on an imx8mn where
the boot rom api was not able to skip it. This code is used by other
architecures like imx6 and imx8mm

Cc: Han Xu <han.xu@nxp.com>
Cc: Fabio Estevam <festevam@gmail.com>
Acked-by: Han Xu <han.xu@nxp.com>
Tested-By: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---
V3->V4:
	- none
V2->V3:
	- Add tested-by from Tim
	- Add ack from Han Xu
	- Rework english of commit message
V1->V2:
	- Adjust the commit message
	- Add Cc Han Xu and Fabio
	- fix size >= 0 to > 0
---
 drivers/mtd/nand/raw/mxs_nand_spl.c | 90 ++++++++++++++++-------------
 1 file changed, 49 insertions(+), 41 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index 59a67ee414..2bfb181007 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -218,14 +218,14 @@ void nand_init(void)
 	mxs_nand_setup_ecc(mtd);
 }
 
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
 {
-	struct nand_chip *chip;
-	unsigned int page;
+	unsigned int sz;
+	unsigned int block, lastblock;
+	unsigned int page, page_offset;
 	unsigned int nand_page_per_block;
-	unsigned int sz = 0;
+	struct nand_chip *chip;
 	u8 *page_buf = NULL;
-	u32 page_off;
 
 	chip = mtd_to_nand(mtd);
 	if (!chip->numchips)
@@ -235,47 +235,42 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
 	if (!page_buf)
 		return -ENOMEM;
 
-	page = offs >> chip->page_shift;
-	page_off = offs & (mtd->writesize - 1);
+	/* offs has to be aligned to a page address! */
+	block = offs / mtd->erasesize;
+	lastblock = (offs + size - 1) / mtd->erasesize;
+	page = (offs % mtd->erasesize) / mtd->writesize;
+	page_offset = offs % mtd->writesize;
 	nand_page_per_block = mtd->erasesize / mtd->writesize;
 
-	debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
-
-	while (size) {
-		if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
-			return -1;
-
-		if (size > (mtd->writesize - page_off))
-			sz = (mtd->writesize - page_off);
-		else
-			sz = size;
-
-		memcpy(buf, page_buf + page_off, sz);
-
-		offs += mtd->writesize;
-		page++;
-		buf += (mtd->writesize - page_off);
-		page_off = 0;
-		size -= sz;
-
-		/*
-		 * Check if we have crossed a block boundary, and if so
-		 * check for bad block.
-		 */
-		if (!(page % nand_page_per_block)) {
-			/*
-			 * Yes, new block. See if this block is good. If not,
-			 * loop until we find a good block.
-			 */
-			while (is_badblock(mtd, offs, 1)) {
-				page = page + nand_page_per_block;
-				/* Check i we've reached the end of flash. */
-				if (page >= mtd->size >> chip->page_shift) {
+	while (block <= lastblock && size > 0) {
+		if (!is_badblock(mtd, mtd->erasesize * block, 1)) {
+			/* Skip bad blocks */
+			while (page < nand_page_per_block) {
+				int curr_page = nand_page_per_block * block + page;
+
+				if (mxs_read_page_ecc(mtd, page_buf, curr_page) < 0) {
 					free(page_buf);
-					return -ENOMEM;
+					return -EIO;
 				}
+
+				if (size > (mtd->writesize - page_offset))
+					sz = (mtd->writesize - page_offset);
+				else
+					sz = size;
+
+				memcpy(dst, page_buf + page_offset, sz);
+				dst += sz;
+				size -= sz;
+				page_offset = 0;
+				page++;
 			}
+
+			page = 0;
+		} else {
+			lastblock++;
 		}
+
+		block++;
 	}
 
 	free(page_buf);
@@ -294,6 +289,19 @@ void nand_deselect(void)
 
 u32 nand_spl_adjust_offset(u32 sector, u32 offs)
 {
-	/* Handle the offset adjust in nand_spl_load_image,*/
+	unsigned int block, lastblock;
+
+	block = sector / mtd->erasesize;
+	lastblock = (sector + offs) / mtd->erasesize;
+
+	while (block <= lastblock) {
+		if (is_badblock(mtd, block * mtd->erasesize, 1)) {
+			offs += mtd->erasesize;
+			lastblock++;
+		}
+
+		block++;
+	}
+
 	return offs;
 }
-- 
2.25.1


  parent reply	other threads:[~2022-05-15  9:36 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-15  9:35 [PATCH V4 0/5] MXS nand fixes in SPL Michael Trimarchi
2022-05-15  9:35 ` [PATCH V4 1/5] nand: raw: mxs_nand: Fix specific hook registration Michael Trimarchi
2022-05-20 13:42   ` sbabic
2022-05-15  9:35 ` Michael Trimarchi [this message]
2022-05-20 13:43   ` [PATCH V4 2/5] mtd: nand: mxs_nand_spl: Fix bad block skipping sbabic
2022-05-15  9:35 ` [PATCH V4 3/5] arm: mach-imx: cmd_nandbcb fix bad block handling Michael Trimarchi
2022-05-20 13:42   ` sbabic
2022-05-15  9:35 ` [PATCH V4 4/5] spl: spl_nand: Fix bad block handling in fitImage Michael Trimarchi
2022-05-20 13:41   ` sbabic
2022-05-15  9:35 ` [PATCH V4 5/5] board: bsh: Switch to nand spl load instead of romapi Michael Trimarchi
2022-05-18 10:17   ` Michael Nazzareno Trimarchi
2022-05-18 11:53     ` Stefano Babic
2022-05-15 12:54 ` [PATCH V4 0/5] MXS nand fixes in SPL Fabio Estevam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220515093534.1737172-3-michael@amarulasolutions.com \
    --to=michael@amarulasolutions.com \
    --cc=ariel.dalessandro@collabora.com \
    --cc=dario.binacchi@amarulasolutions.com \
    --cc=festevam@denx.de \
    --cc=festevam@gmail.com \
    --cc=han.xu@nxp.com \
    --cc=jagan@amarulasolutions.com \
    --cc=linux-amarula@amarulasolutions.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=sbabic@denx.de \
    --cc=sean.anderson@seco.com \
    --cc=tharvey@gateworks.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=ye.li@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox