[PATCH] env: sf: add support for env erase

Harry Waschkeit harry.waschkeit at men.de
Thu Oct 8 19:27:48 CEST 2020


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 <Harry.Waschkeit at men.de>
---
  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


More information about the U-Boot mailing list