[v1] spl: nand: allow partial nand page reads during nand_spl_load_image
Dario Binacchi
dario.binacchi at amarulasolutions.com
Fri Nov 18 13:08:38 CET 2022
Hi Colin,
On Tue, Nov 15, 2022 at 5:35 PM Colin Foster
<colin.foster at in-advantage.com> wrote:
>
> The nand_spl_load_image function was guaranteed to read an entire block
> into RAM, regardless of how many bytes were to be read. This is
> particularly problematic when spl_load_legacy_image is called, as this
> function attempts to load a struct image_header but gets surprised with
> a full flash sector.
>
> Allow partial reads to restore functionality to the code path
> spl_nand_load_element() -> spl_load_legacy_img() ->
> spl_nand_legacy_read(load, header, sizeof(hdr), header);
>
> Signed-off-by: Colin Foster <colin.foster at in-advantage.com>
> ---
> drivers/mtd/nand/raw/nand_spl_loaders.c | 36 ++++++++++++++++---------
> 1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/nand_spl_loaders.c b/drivers/mtd/nand/raw/nand_spl_loaders.c
> index 4befc75c04..84ac482c06 100644
> --- a/drivers/mtd/nand/raw/nand_spl_loaders.c
> +++ b/drivers/mtd/nand/raw/nand_spl_loaders.c
> @@ -1,9 +1,18 @@
> +/*
> + * Temporary storage for non NAND page aligned and non NAND page sized
> + * reads. Note: This does not support runtime detected FLASH yet, but
> + * that should be reasonably easy to fix by making the buffer large
> + * enough :)
> + */
> +static u8 scratch_buf[CONFIG_SYS_NAND_PAGE_SIZE];
> +
> int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
> {
> + unsigned int read_this_time = CONFIG_SYS_NAND_PAGE_SIZE;
> + unsigned int size_remaining = size;
> unsigned int block, lastblock;
> unsigned int page, page_offset;
>
> - /* offs has to be aligned to a page address! */
> block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
> lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
> page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;
> @@ -12,8 +21,18 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
> while (block <= lastblock) {
> if (!nand_is_bad_block(block)) {
> /* Skip bad blocks */
> - while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
> - nand_read_page(block, page, dst);
> + while (page < CONFIG_SYS_NAND_PAGE_COUNT &&
> + size_remaining > 0) {
> + if (size_remaining < CONFIG_SYS_NAND_PAGE_SIZE)
> + {
> + nand_read_page(block, page,
> + scratch_buf);
> + memcpy(dst, scratch_buf,
> + size_remaining);
> + read_this_time = size_remaining;
> + } else {
> + nand_read_page(block, page, dst);
> + }
> /*
> * When offs is not aligned to page address the
> * extra offset is copied to dst as well. Copy
> @@ -26,7 +45,8 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
> dst = (void *)((int)dst - page_offset);
> page_offset = 0;
> }
> - dst += CONFIG_SYS_NAND_PAGE_SIZE;
> + dst += read_this_time;
> + size_remaining -= read_this_time;
> page++;
> }
>
> @@ -70,14 +90,6 @@ u32 nand_spl_adjust_offset(u32 sector, u32 offs)
> }
>
> #ifdef CONFIG_SPL_UBI
> -/*
> - * Temporary storage for non NAND page aligned and non NAND page sized
> - * reads. Note: This does not support runtime detected FLASH yet, but
> - * that should be reasonably easy to fix by making the buffer large
> - * enough :)
> - */
> -static u8 scratch_buf[CONFIG_SYS_NAND_PAGE_SIZE];
> -
> /**
> * nand_spl_read_block - Read data from physical eraseblock into a buffer
> * @block: Number of the physical eraseblock
> --
> 2.25.1
>
Reviewed-by: Dario Binacchi <dario.binacchi at amarulasolutions.com>
Thanks and regards,
Dario
--
Dario Binacchi
Embedded Linux Developer
dario.binacchi at amarulasolutions.com
__________________________________
Amarula Solutions SRL
Via Le Canevare 30, 31100 Treviso, Veneto, IT
T. +39 042 243 5310
info at amarulasolutions.com
www.amarulasolutions.com
More information about the U-Boot
mailing list