spl: nand: Set bl_len to page size
authorSean Anderson <seanga2@gmail.com>
Sat, 4 Nov 2023 20:37:44 +0000 (16:37 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 16 Nov 2023 17:43:48 +0000 (12:43 -0500)
Since commit 34793598c83 ("mtd: nand: mxs_nand_spl: Remove the page aligned
access") there are no longer any users of nand_get_mtd. However, it is
still important to know what the page size is so we can allocate a
large-enough buffer. If the image size is not page-aligned, we will go off
the end of the buffer and clobber some memory.

Introduce a new function nand_page_size which returns the page size. For
most drivers it is easy to determine the page size. However, a few need to
be modified since they only keep the page size around temporarily.

It's possible that this patch could cause a regression on some platforms if
the offset is non-aligned and there is invalid address space immediately
before the load address. spl_load_legacy_img does not (except when
compressing) respect bl_len, so only boards with SPL_LOAD_FIT (8 boards) or
SPL_LOAD_IMX_CONTAINER (none in tree) would be affected.

defconfig               CONFIG_TEXT_BASE
======================= ================
am335x_evm              0x80800000
am43xx_evm              0x80800000
am43xx_evm_rtconly      0x80800000
am43xx_evm_usbhost_boot 0x80800000
am43xx_hs_evm           0x80800000
dra7xx_evm              0x80800000
gwventana_nand          0x17800000
imx8mn_bsh_smm_s2       0x40200000

All the sitara boards have DDR mapped at 0x80000000. gwventana is an i.MX6Q
which has DDR at 0x10000000. I don't have the IMX8MNRM handy, but on the
i.MX8M DDR starts at 0x40000000. Therefore all of these boards can handle a
little underflow.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
13 files changed:
common/spl/spl_nand.c
drivers/mtd/nand/raw/am335x_spl_bch.c
drivers/mtd/nand/raw/atmel_nand.c
drivers/mtd/nand/raw/denali_spl.c
drivers/mtd/nand/raw/fsl_ifc_spl.c
drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
drivers/mtd/nand/raw/mt7621_nand_spl.c
drivers/mtd/nand/raw/mxc_nand_spl.c
drivers/mtd/nand/raw/mxs_nand_spl.c
drivers/mtd/nand/raw/nand.c
drivers/mtd/nand/raw/nand_spl_simple.c
drivers/mtd/nand/raw/sunxi_nand_spl.c
include/nand.h

index 5b6932b..57a7a1a 100644 (file)
@@ -72,23 +72,18 @@ static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs,
        return size;
 }
 
-struct mtd_info * __weak nand_get_mtd(void)
-{
-       return NULL;
-}
-
 static int spl_nand_load_element(struct spl_image_info *spl_image,
                                 struct spl_boot_device *bootdev,
                                 int offset, struct legacy_img_hdr *header)
 {
-       struct mtd_info *mtd = nand_get_mtd();
-       int bl_len = mtd ? mtd->writesize : 1;
+       int bl_len;
        int err;
 
        err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
        if (err)
                return err;
 
+       bl_len = nand_page_size();
        if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
            image_get_magic(header) == FDT_MAGIC) {
                struct spl_load_info load;
@@ -118,7 +113,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image,
                load.dev = NULL;
                load.priv = NULL;
                load.filename = NULL;
-               load.bl_len = 1;
+               load.bl_len = IS_ENABLED(CONFIG_SPL_LZMA) ? bl_len : 1;
                load.read = spl_nand_legacy_read;
 
                return spl_load_legacy_img(spl_image, bootdev, &load, offset, header);
index fb9c623..6831af9 100644 (file)
@@ -218,6 +218,11 @@ void nand_init(void)
        nand_command(0, 0, 0, NAND_CMD_RESET);
 }
 
+unsigned int nand_page_size(void)
+{
+       return nand_to_mtd(&nand_chip)->writesize;
+}
+
 /* Unselect after operation */
 void nand_deselect(void)
 {
index 8332011..6d94e7a 100644 (file)
@@ -1452,6 +1452,11 @@ void nand_init(void)
                nand_chip.select_chip(mtd, 0);
 }
 
+unsigned int nand_page_size(void)
+{
+       return nand_to_mtd(&nand_chip)->writesize;
+}
+
 void nand_deselect(void)
 {
        if (nand_chip.select_chip)
index 690279c..165a233 100644 (file)
@@ -234,4 +234,9 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
        return 0;
 }
 
+unsigned int nand_page_size(void)
+{
+       return page_size;
+}
+
 void nand_deselect(void) {}
index c67065e..69d26f1 100644 (file)
@@ -106,6 +106,8 @@ static inline int bad_block(uchar *marker, int port_size)
                return __raw_readw((u16 *)marker) != 0xffff;
 }
 
+static int saved_page_size;
+
 int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
 {
        struct fsl_ifc_fcm *gregs = (void *)CFG_SYS_IFC_ADDR;
@@ -150,6 +152,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
                if (port_size == 8)
                        bad_marker = 5;
        }
+       saved_page_size = page_size;
 
        ver = ifc_in32(&gregs->ifc_rev);
        if (ver >= FSL_IFC_V2_0_0)
@@ -302,6 +305,11 @@ void nand_init(void)
 {
 }
 
+unsigned int nand_page_size(void)
+{
+       return saved_page_size;
+}
+
 void nand_deselect(void)
 {
 }
index ac2e669..f8ae216 100644 (file)
@@ -765,4 +765,9 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
        return 0;
 }
 
+unsigned int nand_page_size(void)
+{
+       return BYTES_PER_PAGE;
+}
+
 #endif /* CONFIG_SPL_BUILD */
index 114fc8b..a2be9ba 100644 (file)
@@ -203,6 +203,11 @@ unsigned long nand_size(void)
        return SZ_2G;
 }
 
+unsigned int nand_page_size(void)
+{
+       return nfc_dev.nand.mtd.writesize;
+}
+
 void nand_deselect(void)
 {
 }
index 81ceb12..a855c99 100644 (file)
@@ -351,3 +351,8 @@ __used void nand_boot(void)
 
 void nand_init(void) {}
 void nand_deselect(void) {}
+
+unsigned int nand_page_size(void)
+{
+       return CONFIG_SYS_NAND_PAGE_SIZE;
+}
index 3006629..f7d3f02 100644 (file)
@@ -295,6 +295,11 @@ int nand_default_bbt(struct mtd_info *mtd)
        return 0;
 }
 
+unsigned int nand_page_size(void)
+{
+       return nand_to_mtd(&nand_chip)->writesize;
+}
+
 void nand_deselect(void)
 {
 }
index eacd99c..4da4143 100644 (file)
@@ -174,3 +174,10 @@ void nand_init(void)
 
        create_mtd_concat();
 }
+
+unsigned int nand_page_size(void)
+{
+       struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
+
+       return mtd ? mtd->writesize : 1;
+}
index bbdb76d..80d6e0e 100644 (file)
@@ -227,6 +227,11 @@ void nand_init(void)
                nand_chip.select_chip(mtd, 0);
 }
 
+unsigned int nand_page_size(void)
+{
+       return nand_to_mtd(&nand_chip)->writesize;
+}
+
 /* Unselect after operation */
 void nand_deselect(void)
 {
index 6de0b0a..c9b8c78 100644 (file)
@@ -524,9 +524,10 @@ static int nand_read_buffer(struct nfc_config *conf, uint32_t offs,
        return 0;
 }
 
+static struct nfc_config conf;
+
 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
 {
-       static struct nfc_config conf = { };
        int ret;
 
        ret = nand_detect_config(&conf, offs, dest);
@@ -536,6 +537,11 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
        return nand_read_buffer(&conf, offs, size, dest);
 }
 
+unsigned int nand_page_size(void)
+{
+       return conf.page_size;
+}
+
 void nand_deselect(void)
 {
        struct sunxi_ccm_reg *const ccm =
index 70c1286..c1d7533 100644 (file)
@@ -12,6 +12,7 @@
 
 extern void nand_init(void);
 unsigned long nand_size(void);
+unsigned int nand_page_size(void);
 
 #include <linux/compat.h>
 #include <linux/mtd/mtd.h>