[PATCH v3 3/4] spl: fit: nand: fix fit loading in case of bad blocks

Michael Nazzareno Trimarchi michael at amarulasolutions.com
Sat Jun 6 21:23:09 CEST 2020


Hi Dario

I know that is an important bug to be addressed and I would like to
add even Tom on this

On Wed, May 27, 2020 at 1:56 PM Dario Binacchi <dariobin at libero.it> wrote:
>
> The offset at which the image to be loaded from NAND is located is
> retrieved from the itb header. The presence of bad blocks in the area
> of the NAND where the itb image is located could invalidate the offset
> which must therefore be adjusted taking into account the state of the
> sectors concerned.
>
> cc: Michael Trimarchi <michael at amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dariobin at libero.it>
>
> ---
>
> Changes in v3:
> The previous versions were buggy for devices others than NAND. This
> because the 'adjust_offset' helper was properly set only for the NAND
> case but called even for devices like MMC, RAM, and so on, crashing the
> boot up by that devices. Continuing to use the adjust_offset helper
> would mean checking the helper before calling it and patching too many
> files to set it properly before calling the spl_load_simple_fit routine.
> For this reason, the adjust_offset helper has been removed from the
> spl_image_info structure and the offset fixed inside the read helper for
> the NAND device only. This solution fixes the problem for the NAND device
> without side effects for other types of devices.
>
> Changes in v2: None
>
>  common/spl/spl_nand.c                   |  5 ++++-
>  drivers/mtd/nand/raw/nand_spl_loaders.c | 28 +++++++++++++++++++++++++
>  include/nand.h                          |  1 +
>  3 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
> index 48c97549eb..1e6f2dce56 100644
> --- a/common/spl/spl_nand.c
> +++ b/common/spl/spl_nand.c
> @@ -42,8 +42,11 @@ static int spl_nand_load_image(struct spl_image_info *spl_image,
>  static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
>                                ulong size, void *dst)
>  {
> +       ulong sector;
>         int ret;
>
> +       sector = *(int *)load->priv;
> +       offs = sector + nand_spl_adjust_offset(sector, offs - sector);

Check if is needed to call adjust offset in case offs and sector are
the same. Maybe a comment is needed
on top of the function to describe a bit more why is called

>         ret = nand_spl_load_image(offs, size, dst);
>         if (!ret)
>                 return size;
> @@ -66,7 +69,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image,
>
>                 debug("Found FIT\n");
>                 load.dev = NULL;
> -               load.priv = NULL;
> +               load.priv = &offset;

It's a bit an abuse here but I don't have a better plan on my side

Reviewed-by: Michael Trimarchi <michael at amarulasolutions.com>

Michael

>                 load.filename = NULL;
>                 load.bl_len = 1;
>                 load.read = spl_nand_fit_read;
> diff --git a/drivers/mtd/nand/raw/nand_spl_loaders.c b/drivers/mtd/nand/raw/nand_spl_loaders.c
> index 177c12b581..4befc75c04 100644
> --- a/drivers/mtd/nand/raw/nand_spl_loaders.c
> +++ b/drivers/mtd/nand/raw/nand_spl_loaders.c
> @@ -41,6 +41,34 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
>         return 0;
>  }
>
> +/**
> + * nand_spl_adjust_offset - Adjust offset from a starting sector
> + * @sector:    Address of the sector
> + * @offs:      Offset starting from @sector
> + *
> + * If one or more bad blocks are in the address space between @sector
> + * and @sector + @offs, @offs is increased by the NAND block size for
> + * each bad block found.
> + */
> +u32 nand_spl_adjust_offset(u32 sector, u32 offs)
> +{
> +       unsigned int block, lastblock;
> +
> +       block = sector / CONFIG_SYS_NAND_BLOCK_SIZE;
> +       lastblock = (sector + offs) / CONFIG_SYS_NAND_BLOCK_SIZE;
> +
> +       while (block <= lastblock) {
> +               if (nand_is_bad_block(block)) {
> +                       offs += CONFIG_SYS_NAND_BLOCK_SIZE;
> +                       lastblock++;
> +               }
> +
> +               block++;
> +       }
> +
> +       return offs;
> +}
> +
>  #ifdef CONFIG_SPL_UBI
>  /*
>   * Temporary storage for non NAND page aligned and non NAND page sized
> diff --git a/include/nand.h b/include/nand.h
> index 93cbe1e25d..80dd6469bc 100644
> --- a/include/nand.h
> +++ b/include/nand.h
> @@ -120,6 +120,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
>                 int allexcept);
>  int nand_get_lock_status(struct mtd_info *mtd, loff_t offset);
>
> +u32 nand_spl_adjust_offset(u32 sector, u32 offs);
>  int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst);
>  int nand_spl_read_block(int block, int offset, int len, void *dst);
>  void nand_deselect(void);
> --
> 2.17.1
>


-- 
| Michael Nazzareno Trimarchi                     Amarula Solutions BV |
| COO  -  Founder                                      Cruquiuskade 47 |
| +31(0)851119172                                 Amsterdam 1018 AM NL |
|                  [`as] http://www.amarulasolutions.com               |


More information about the U-Boot mailing list