U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] arm: socfpga: crc-protect SPL on warm boot
Date: Tue, 20 Nov 2018 21:54:57 +0100	[thread overview]
Message-ID: <699ba8cd-9783-5c04-86ae-bd63484050ae@gmail.com> (raw)
In-Reply-To: <4d9df11c-6c41-15aa-b5dd-e66153038241@denx.de>

On 20.11.2018 20:33, Marek Vasut wrote:
> On 11/20/2018 08:22 PM, Simon Goldschmidt wrote:
>> From: Simon Goldschmidt <sgoldschmidt@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.goldschmidt@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 ?

No, unfortunately, it's bit-reversed. Plus it uses a table, which 
increases the SPL binary by more than 2 KByte.

Simon

  reply	other threads:[~2018-11-20 20:54 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-20 19:22 [U-Boot] [PATCH] arm: socfpga: crc-protect SPL on warm boot Simon Goldschmidt
2018-11-20 19:33 ` Marek Vasut
2018-11-20 20:54   ` Simon Goldschmidt [this message]
2018-11-20 21:55     ` Dalon L Westergreen
2018-11-20 23:12       ` Marek Vasut
2018-11-21  5:13         ` Simon Goldschmidt
2018-11-21 14:06           ` Marek Vasut
2018-11-20 23:11     ` Marek Vasut
2018-11-21  5:09       ` Simon Goldschmidt
2018-11-21 14:08         ` Marek Vasut
2018-11-21 21:07           ` Simon Goldschmidt
2018-11-21 21:14             ` Marek Vasut
2018-11-22  5:18               ` Simon Goldschmidt
2018-11-22 17:09                 ` Marek Vasut
2018-11-24 19:18           ` Simon Goldschmidt

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=699ba8cd-9783-5c04-86ae-bd63484050ae@gmail.com \
    --to=simon.k.r.goldschmidt@gmail.com \
    --cc=u-boot@lists.denx.de \
    /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