On 11/20/2018 08:22 PM, Simon Goldschmidt wrote:
> From: Simon Goldschmidt <sgoldschm...@de.pepperl-fuchs.com>
> 
> On socfpga gen5, a warm reboot from Linux currently triggers a warm
> reset via reset manager ctrl register.
> 
> This currently leads to the boot rom just jumping to onchip ram
> executing the SPL that is supposed to still be there. This is
> because we tell the boot rom to do so by writing a magin value
> the warmramgrp_enable register in arch_early_init_r().
> 
> However, this can lead to lockups on reboot if this register still
> contains its magic value but the SPL is not intact any more (e.g.
> partly overwritten onchip ram).
> 
> To fis this, store a crc calculated over SPL in sysmgr registers to
> let the boot rom check it on next warm boot. If the crc is still
> correct, SPL can be executd from onchip ram. If the crc fails, SPL
> is loaded from original boot source.
> 
> The crc that is written to the warmramgrp_crc register is the crc
> found in the SPL sfp image but with one addiional u32 added. For
> this, we need to add a function to calculate the updated crc. This
> is done as a bitwise calculation to keep the code increase small.
> 
> This whole patch added 96 bytes to .text for SPL for
> socfpga_socrates_defconfig.
> 
> Signed-off-by: Simon Goldschmidt <simon.k.r.goldschm...@gmail.com>
> ---
> 
>  arch/arm/mach-socfpga/misc_gen5.c |  9 ----
>  arch/arm/mach-socfpga/spl_gen5.c  | 73 +++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/mach-socfpga/misc_gen5.c 
> b/arch/arm/mach-socfpga/misc_gen5.c
> index 5fa40937c4..492a3082de 100644
> --- a/arch/arm/mach-socfpga/misc_gen5.c
> +++ b/arch/arm/mach-socfpga/misc_gen5.c
> @@ -204,15 +204,6 @@ int arch_early_init_r(void)
>  {
>       int i;
>  
> -     /*
> -      * Write magic value into magic register to unlock support for
> -      * issuing warm reset. The ancient kernel code expects this
> -      * value to be written into the register by the bootloader, so
> -      * to support that old code, we write it here instead of in the
> -      * reset_cpu() function just before resetting the CPU.
> -      */
> -     writel(0xae9efebc, &sysmgr_regs->romcodegrp_warmramgrp_enable);
> -
>       for (i = 0; i < 8; i++) /* Cache initial SW setting regs */
>               iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]);
>  
> diff --git a/arch/arm/mach-socfpga/spl_gen5.c 
> b/arch/arm/mach-socfpga/spl_gen5.c
> index ccdc661d05..3416e19f79 100644
> --- a/arch/arm/mach-socfpga/spl_gen5.c
> +++ b/arch/arm/mach-socfpga/spl_gen5.c
> @@ -63,6 +63,76 @@ u32 spl_boot_mode(const u32 boot_device)
>  }
>  #endif
>  
> +/* This function calculates the CRC32 used by the Cyclone 5 SoC Boot Rom */
> +static u32 socfpga_boot_crc(u32 crc, const unsigned char *ptr, u32 length)
> +{
> +     uint i;
> +     u8 bit;
> +     unsigned char data;
> +     const u32 poly = 0x02608edb;
> +
> +     for (; length > 0; length--, ptr++) {
> +             data = *ptr;
> +             for (i = 0; i < 8; i++) {
> +                     if (data & 0x80)
> +                             bit = 1;
> +                     else
> +                             bit = 0;
> +
> +                     data = data << 1;
> +                     if (crc & 0x80000000)
> +                             bit = 1 - bit;
> +
> +                     if (bit) {
> +                             crc ^= poly;
> +                             crc = crc << 1;
> +                             crc |= 1;
> +                     } else {
> +                             crc = crc << 1;
> +                     }
> +             }
> +     }
> +     return crc;
> +}
> +
> +/*
> + * Write magic value into magic register to unlock support for the boot rom 
> to
> + * execute spl from sram on warm reset. This may be required at least on some
> + * boards that start from qspi where the flash chip might be in a state that
> + * cannot be handled by the boot rom (e.g. 4 byte mode).
> + *
> + * To prevent just jumping to corrupted memory, a crc of the spl is 
> calculated.
> + * This crc is loaded from the running image, but has to be extended by the
> + * modified contents of the "datastart" register (i.e. 0xffff0000).
> + */
> +static void spl_init_reboot_config(void)
> +{
> +     u32 spl_crc, spl_length;
> +     const u32 spl_start = (u32)__image_copy_start;
> +     const u32 spl_start_16 = spl_start & 0xffff;
> +     u32 spl_length_u32;
> +
> +     /* load image length from sfp header (includes crc) */
> +     spl_length_u32 = *(const u16 *)(spl_start + 0x46);
> +     /* subtract crc */
> +     spl_length_u32--;
> +     /* get length in bytes */
> +     spl_length = spl_length_u32 * 4;
> +     /* load crc */
> +     spl_crc = *(const u32 *)(spl_start + spl_length);
> +     /* undo xor */
> +     spl_crc ^= 0xffffffff;
> +     /* add contents of modified datastart register */
> +     spl_crc = socfpga_boot_crc(spl_crc, (const u8 *)&spl_start, 4);
> +     /* finalize */
> +     spl_crc ^= 0xffffffff;
> +
> +     writel(0xae9efebc, &sysmgr_regs->romcodegrp_warmramgrp_enable);
> +     writel(spl_start_16, &sysmgr_regs->romcodegrp_warmramgrp_datastart);
> +     writel(spl_length, &sysmgr_regs->romcodegrp_warmramgrp_length);
> +     writel(spl_crc, &sysmgr_regs->romcodegrp_warmramgrp_crc);
> +}
> +
>  void board_init_f(ulong dummy)
>  {
>       const struct cm_config *cm_default_cfg = cm_get_default_config();
> @@ -82,6 +152,9 @@ void board_init_f(ulong dummy)
>               writel(SYSMGR_ECC_OCRAM_DERR  | SYSMGR_ECC_OCRAM_EN,
>                      &sysmgr_regs->eccgrp_ocram);
>  
> +     if (!socfpga_is_booting_from_fpga())
> +             spl_init_reboot_config();
> +
>       memset(__bss_start, 0, __bss_end - __bss_start);
>  
>       socfpga_sdram_remap_zero();
> 

Can't we use the library CRC32 function instead ?

-- 
Best regards,
Marek Vasut
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to