All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
To: Marek Vasut <marek.vasut+renesas@mailbox.org>
Cc: Jerome Forissier <jerome.forissier@linaro.org>,
	Simon Glass <sjg@chromium.org>, Tom Rini <trini@konsulko.com>,
	u-boot@lists.denx.de
Subject: Re: [PATCH v2 2/3] env: Add single to redundant environment upgrade path
Date: Tue, 23 Dec 2025 18:43:00 +0100	[thread overview]
Message-ID: <ac80d9cd-4890-4382-9ce6-2f237933d32c@gmx.de> (raw)
In-Reply-To: <20251223143130.16266-2-marek.vasut+renesas@mailbox.org>

On 12/23/25 15:31, Marek Vasut wrote:
> Add support for converting single-copy environment to redundant environment.
> In case CRC checks on both redundant environment copies fail, try one more
> CRC check on the primary environment copy and treat it as single environment.

Why would a CRC check suddenly succeed if it has failed before?

This needs some more explanation.

> If that check does pass, rewrite the single-copy environment into redundant
> environment format, indicate the environment is valid, and import that as
> usual primary copy of redundant environment. Follow up 'env save' will then
> store two environment copies and the system will continue to operate as
> regular redundant environment system.
> 
> Add test which validates this upgrade path. The test starts with spi.bin
> which is pre-populated as single-copy environment and then upgrades that
> environment to dual-copy environment.
> 
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> ---
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> Cc: Jerome Forissier <jerome.forissier@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: u-boot@lists.denx.de
> ---
> V2: - Gate the option behind ENV_REDUNDANT_UPGRADE
>      - Fix up mkenvimage path in env test
> ---
>   env/Kconfig               | 11 ++++++
>   env/common.c              | 31 +++++++++++++++-
>   test/py/tests/test_env.py | 74 +++++++++++++++++++++++++++++++++++++++
>   3 files changed, 115 insertions(+), 1 deletion(-)
> 
> diff --git a/env/Kconfig b/env/Kconfig
> index 4430669964c..b312f9b5324 100644
> --- a/env/Kconfig
> +++ b/env/Kconfig
> @@ -489,6 +489,17 @@ config ENV_REDUNDANT
>   	  which is used by env import/export commands which are independent of
>   	  storing variables to redundant location on a non volatile device.
>   
> +config ENV_REDUNDANT_UPGRADE
> +	bool "Enable single-copy to redundant environment upgrade support"
> +	depends on ENV_REDUNDANT
> +	help
> +	  Normally, redundant environment is expected to always operate on
> +	  two copies of the environment. However, hardware that may have
> +	  originally shipped with single-copy environment can be upgraded

%s/with single-copy/with a single-copy/
%s/can be/that can be/

> +	  to redundant environment without loss of existing environment
> +	  content by correctly configuring the location of the redundant
> +	  environment copy and by enabling this option.

Why do we have to make this an option?
Shouldn't we always try to restore the environment?

> +
>   config ENV_FAT_INTERFACE
>   	string "Name of the block device for the environment"
>   	depends on ENV_IS_IN_FAT
> diff --git a/env/common.c b/env/common.c
> index 05e78d63874..b2adbe93dbe 100644
> --- a/env/common.c
> +++ b/env/common.c
> @@ -473,14 +473,24 @@ int env_import(const char *buf, int check, int flags)
>   #ifdef CONFIG_ENV_REDUNDANT
>   static unsigned char env_flags;
>   
> +#define ENV_SINGLE_HEADER_SIZE	(sizeof(uint32_t))
> +#define ENV_SINGLE_SIZE		(CONFIG_ENV_SIZE - ENV_SINGLE_HEADER_SIZE)
> +
> +typedef struct {
> +	uint32_t	crc;			/* CRC32 over data bytes */
> +	unsigned char	data[ENV_SINGLE_SIZE];	/* Environment data */
> +} env_single_t;
> +
>   int env_check_redund(const char *buf1, int buf1_read_fail,
>   		     const char *buf2, int buf2_read_fail)
>   {
> -	int crc1_ok = 0, crc2_ok = 0;
> +	int crc1_ok = 0, crc2_ok = 0, i;
>   	env_t *tmp_env1, *tmp_env2;
> +	env_single_t *tmp_envs;
>   
>   	tmp_env1 = (env_t *)buf1;
>   	tmp_env2 = (env_t *)buf2;
> +	tmp_envs = (env_single_t *)buf1;
>   
>   	if (buf1_read_fail && buf2_read_fail) {
>   		puts("*** Error - No Valid Environment Area found\n");
> @@ -498,6 +508,25 @@ int env_check_redund(const char *buf1, int buf1_read_fail,
>   				tmp_env2->crc;
>   
>   	if (!crc1_ok && !crc2_ok) {

Do we really have a third location to copy from when both store 1 and 
store 2 are defective? I would have expected that if a vendor provides a 
single copy then exactly one of crc1_ok or crc2_ok is true and the other 
is false.

Please, provide a documentation update explaining how this all works.

Best regards

Heinrich

> +		/*
> +		 * Upgrade single-copy environment to redundant environment.
> +		 * In case CRC checks on both environment copies fail, try
> +		 * one more CRC check on the primary environment copy and
> +		 * treat it as single-copy environment. If that check does
> +		 * pass, rewrite the single-copy environment into redundant
> +		 * environment format and indicate the environment is valid.
> +		 * The follow up calls will import the environment as if it
> +		 * was a redundant environment. Follow up 'env save' will
> +		 * then store two environment copies.
> +		 */
> +		if (CONFIG_IS_ENABLED(ENV_REDUNDANT_UPGRADE) && !buf1_read_fail &&
> +		    crc32(0, tmp_envs->data, ENV_SINGLE_SIZE) == tmp_envs->crc) {
> +			for (i = ENV_SIZE - 1; i >= 0; i--)
> +				tmp_env1->data[i] = tmp_envs->data[i];
> +			tmp_env1->flags = 0;
> +			gd->env_valid = ENV_VALID;
> +			return 0;
> +		}
>   		gd->env_valid = ENV_INVALID;
>   		return -ENOMSG; /* needed for env_load() */
>   	} else if (crc1_ok && !crc2_ok) {
> diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
> index 48e31f19b3c..f8713a59ba9 100644
> --- a/test/py/tests/test_env.py
> +++ b/test/py/tests/test_env.py
> @@ -477,6 +477,22 @@ def mk_env_spi_flash(state_test_env):
>       utils.run_and_log(c, ['cp',  '-f', persistent, spi_flash_img])
>       return spi_flash_img
>   
> +def mk_env_spi_flash_single(state_test_env):
> +
> +    """Create an single-copy SPI NOR image with foo=bar entry."""
> +    c = state_test_env.ubman
> +    filename = 'spi.bin'
> +    spi_flash_img = c.config.source_dir  + '/' + filename
> +
> +    try:
> +        mkenvimage = os.path.join(c.config.build_dir, 'tools/mkenvimage')
> +        call('( echo foo=bar | %s -s 8192 -p 0x00 - ; dd if=/dev/zero bs=2088960 count=1 2>/dev/null ) > %s' % ( mkenvimage , spi_flash_img ), shell=True)
> +    except CalledProcessError:
> +        call('rm -f %s' % spi_flash_img, shell=True)
> +        raise
> +
> +    return spi_flash_img
> +
>   @pytest.mark.boardspec('sandbox')
>   @pytest.mark.buildconfigspec('cmd_echo')
>   @pytest.mark.buildconfigspec('cmd_nvedit_info')
> @@ -574,6 +590,64 @@ def test_env_spi_flash(state_test_env):
>   
>       """Test ENV in SPI NOR on sandbox."""
>       c = state_test_env.ubman
> +    spi_flash_img = ''
> +    try:
> +        spi_flash_img = mk_env_spi_flash_single(state_test_env)
> +
> +        response = c.run_command('sf probe')
> +        assert 'SF: Detected m25p16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB' in response
> +
> +        # force env location: SF
> +        response = c.run_command('env select SPIFlash')
> +        assert 'Select Environment on SPIFlash: OK' in response
> +
> +        response = c.run_command('env load')
> +        assert 'Loading Environment from SPIFlash... OK' in response
> +
> +        response = c.run_command('env print foo')
> +        assert 'foo=bar' in response
> +
> +        response = c.run_command('env save')
> +        assert 'Saving Environment to SPIFlash' in response
> +
> +        response = c.run_command('env load')
> +        assert 'Loading Environment from SPIFlash... OK' in response
> +
> +        response = c.run_command('env print foo')
> +        assert 'foo=bar' in response
> +
> +        response = c.run_command('env save')
> +        assert 'Saving Environment to SPIFlash' in response
> +
> +        response = c.run_command('env save')
> +        assert 'Saving Environment to SPIFlash' in response
> +
> +        response = c.run_command('env load')
> +        assert 'Loading Environment from SPIFlash... OK' in response
> +
> +        response = c.run_command('env print foo')
> +        assert 'foo=bar' in response
> +
> +        # restore env location: NOWHERE (prio 0 in sandbox)
> +        response = c.run_command('env select nowhere')
> +        assert 'Select Environment on nowhere: OK' in response
> +
> +        response = c.run_command('env load')
> +        assert 'Loading Environment from nowhere... OK' in response
> +
> +        response = c.run_command('env info')
> +        assert 'env_valid = invalid' in response
> +        assert 'env_ready = true' in response
> +        assert 'env_use_default = true' in response
> +
> +        response = c.run_command('env info -p -d')
> +        assert 'Default environment is used' in response
> +        assert 'Environment cannot be persisted' in response
> +
> +    finally:
> +        if spi_flash_img:
> +            call('rm -f %s' % spi_flash_img, shell=True)
> +
>       spi_flash_img = ''
>       try:
>           spi_flash_img = mk_env_spi_flash(state_test_env)


  reply	other threads:[~2025-12-23 17:43 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-23 14:31 [PATCH v2 1/3] test: env: Add test for environment storage in SPI NOR Marek Vasut
2025-12-23 14:31 ` [PATCH v2 2/3] env: Add single to redundant environment upgrade path Marek Vasut
2025-12-23 17:43   ` Heinrich Schuchardt [this message]
2025-12-23 18:04     ` Tom Rini
2025-12-23 18:53     ` Marek Vasut
2025-12-23 14:31 ` [PATCH v2 3/3] configs: sandbox: Enable environment in SPI NOR support Marek Vasut
2025-12-23 17:58   ` Heinrich Schuchardt
2025-12-23 18:07     ` Tom Rini
2025-12-23 17:32 ` [PATCH v2 1/3] test: env: Add test for environment storage in SPI NOR Heinrich Schuchardt
2025-12-23 18:55   ` Marek Vasut
2025-12-23 23:32     ` Tom Rini
2025-12-31 16:07       ` Marek Vasut
2025-12-31 16:11         ` Tom Rini
2025-12-31 16:50           ` Marek Vasut
2025-12-31 17:18             ` Tom Rini
2025-12-31 17:46               ` Marek Vasut
2025-12-24  3:18     ` Heinrich Schuchardt
2026-01-07 21:06 ` Tom Rini

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=ac80d9cd-4890-4382-9ce6-2f237933d32c@gmx.de \
    --to=xypron.glpk@gmx.de \
    --cc=jerome.forissier@linaro.org \
    --cc=marek.vasut+renesas@mailbox.org \
    --cc=sjg@chromium.org \
    --cc=trini@konsulko.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.