From mboxrd@z Thu Jan 1 00:00:00 1970 From: Harry Waschkeit Date: Thu, 8 Oct 2020 19:27:48 +0200 Subject: [PATCH] env: sf: add support for env erase Message-ID: <66c89baf-b52a-81cb-2846-112a7925a256@men.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Command "env erase" didn't work even though CONFIG_CMD_ERASEENV was defined, because serial flash environment routines didn't implement erase method. Signed-off-by: Waschkeit, Harry --- env/sf.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/env/sf.c b/env/sf.c index 937778aa37..9cda192a73 100644 --- a/env/sf.c +++ b/env/sf.c @@ -146,6 +146,78 @@ static int env_sf_save(void) return ret; } +#ifdef CONFIG_CMD_ERASEENV +static int env_sf_erase(void) +{ + char *saved_buffer = NULL; + u32 saved_size, saved_offset, sector; + ulong offset; + ulong offsets[2] = { CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET_REDUND }; + int i; + int ret; + + ret = setup_flash_device(); + if (ret) + return ret; + + /* get temporary storage if sector is larger than env (i.e. embedded) */ + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size); + if (!saved_buffer) { + ret = -ENOMEM; + goto done; + } + } + + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + + /* simply erase both environments, retaining non-env data (if any) */ + for (i = 0; i < ARRAY_SIZE(offsets); i++) { + offset = offsets[i]; + + if (saved_buffer) { + saved_offset = offset + CONFIG_ENV_SIZE; + ret = spi_flash_read(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + if (i) + puts("Redund:"); + + puts("Erasing SPI flash..."); + ret = spi_flash_erase(env_flash, offset, + sector * CONFIG_ENV_SECT_SIZE); + if (ret) + goto done; + + if (saved_buffer) { + puts("Writing non-environment data to SPI flash..."); + ret = spi_flash_write(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + puts("done\n"); + } + + /* here we know that both env sections are cleared */ + env_new_offset = CONFIG_ENV_OFFSET; + env_offset = CONFIG_ENV_OFFSET_REDUND; + + gd->env_valid = ENV_INVALID; + + done: + if (saved_buffer) + free(saved_buffer); + + return ret; +} +#endif /* CONFIG_CMD_ERASEENV */ + static int env_sf_load(void) { int ret; @@ -182,7 +254,7 @@ out: return ret; } -#else +#else /* #if defined(CONFIG_ENV_OFFSET_REDUND) */ static int env_sf_save(void) { u32 saved_size, saved_offset, sector; @@ -243,6 +315,57 @@ static int env_sf_save(void) return ret; } +#ifdef CONFIG_CMD_ERASEENV +static int env_sf_erase(void) +{ + u32 saved_size, saved_offset, sector; + char *saved_buffer = NULL; + int ret = 1; + + ret = setup_flash_device(); + if (ret) + return ret; + + /* Is the sector larger than the env (i.e. embedded) */ + if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; + saved_buffer = malloc(saved_size); + if (!saved_buffer) + goto done; + + ret = spi_flash_read(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + + puts("Erasing SPI flash..."); + ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, + sector * CONFIG_ENV_SECT_SIZE); + if (ret) + goto done; + + if (saved_buffer) { + puts("Writing non-environment data to SPI flash..."); + ret = spi_flash_write(env_flash, saved_offset, + saved_size, saved_buffer); + if (ret) + goto done; + } + + puts("done\n"); + + done: + if (saved_buffer) + free(saved_buffer); + + return ret; +} +#endif /* CONFIG_CMD_ERASEENV */ + static int env_sf_load(void) { int ret; @@ -277,7 +400,7 @@ out: return ret; } -#endif +#endif /* #if defined(CONFIG_ENV_OFFSET_REDUND) #else */ #if CONFIG_ENV_ADDR != 0x0 __weak void *env_sf_get_env_addr(void) @@ -311,4 +434,7 @@ U_BOOT_ENV_LOCATION(sf) = { #if defined(INITENV) && (CONFIG_ENV_ADDR != 0x0) .init = env_sf_init, #endif +#if defined(CONFIG_CMD_ERASEENV) && defined(CONFIG_ENV_ADDR) + .erase = env_sf_erase, +#endif }; -- 2.28.0 -- Harry Waschkeit - Software Engineer