Useful for devices which would otherwise have to use ENV_IS_NOWHERE.
Tries to find and load uboot.env from any block device (which may be,
for example, hot-pluggable sd-card, SATA or USB disk, so the exact
location is not known at the time u-boot is compiled).

Signed-off-by: Rob Clark <robdcl...@gmail.com>
---
 cmd/bootefi.c         |   5 ++
 cmd/nvedit.c          |   6 +-
 cmd/usb.c             |   4 +-
 common/Kconfig        |  11 ++++
 common/Makefile       |   1 +
 common/board_r.c      |  11 ++++
 common/env_anywhere.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/environment.h |   5 ++
 8 files changed, 196 insertions(+), 3 deletions(-)
 create mode 100644 common/env_anywhere.c

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 765383bc95..80611e1412 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -10,6 +10,7 @@
 #include <command.h>
 #include <dm.h>
 #include <efi_loader.h>
+#include <environment.h>
 #include <errno.h>
 #include <libfdt.h>
 #include <libfdt_env.h>
@@ -318,6 +319,10 @@ void efi_set_bootdev(const char *dev, const char *devnr, 
const char *path)
                part = parse_partnum(devnr);
 
                bootefi_device_path = efi_dp_from_part(desc, part);
+
+#ifdef CONFIG_ENV_IS_ANYWHERE
+               env_set_location(desc, part);
+#endif
        } else {
 #ifdef CONFIG_NET
                bootefi_device_path = efi_dp_from_eth();
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index cd17db6409..cab7ed2565 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -53,9 +53,11 @@ DECLARE_GLOBAL_DATA_PTR;
        !defined(CONFIG_ENV_IS_IN_SPI_FLASH)    && \
        !defined(CONFIG_ENV_IS_IN_REMOTE)       && \
        !defined(CONFIG_ENV_IS_IN_UBI)          && \
-       !defined(CONFIG_ENV_IS_NOWHERE)
+       !defined(CONFIG_ENV_IS_NOWHERE)         && \
+       !defined(CONFIG_ENV_IS_ANYWHERE)
 # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|MMC|FAT|EXT4|\
-NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
+NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE or \
+CONFIG_ENV_IS_ANYWHERE
 #endif
 
 /*
diff --git a/cmd/usb.c b/cmd/usb.c
index 4fa456e318..d3347301ca 100644
--- a/cmd/usb.c
+++ b/cmd/usb.c
@@ -23,7 +23,7 @@
 #include <usb.h>
 
 #ifdef CONFIG_USB_STORAGE
-static int usb_stor_curr_dev = -1; /* current device */
+int usb_stor_curr_dev = -1; /* current device */
 #endif
 #if defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
 static int __maybe_unused usb_ether_curr_dev = -1; /* current ethernet device 
*/
@@ -567,6 +567,7 @@ static void do_usb_start(void)
 {
        bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
 
+#ifndef CONFIG_ENV_IS_ANYWHERE
        if (usb_init() < 0)
                return;
 
@@ -575,6 +576,7 @@ static void do_usb_start(void)
        /* try to recognize storage devices immediately */
        usb_stor_curr_dev = usb_stor_scan(1);
 # endif
+#endif
 #ifndef CONFIG_DM_USB
 # ifdef CONFIG_USB_KEYBOARD
        drv_usb_kbd_init();
diff --git a/common/Kconfig b/common/Kconfig
index 361346b092..e5f8b5ed3f 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -210,6 +210,17 @@ config ENV_IS_NOWHERE
          Define this if you don't want to or can't have an environment stored
          on a storage medium
 
+config ENV_IS_ANYWHERE
+       bool "Environment is on any partition"
+       depends on BLK
+       help
+         Define this if you want to store the environment on the first
+         partition found containing /uboot.env.  Environment will be saved
+         to same partition it was loaded from.  This is suitable for boards
+         which may be booting from various removable devices (ie. sd-card,
+         usb-disk, etc) and you don't know at the time u-boot is built what
+         the boot media will be.
+
 endchoice
 
 config ENV_OFFSET
diff --git a/common/Makefile b/common/Makefile
index 17a92ea2d7..dd5046b78f 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
 obj-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o
 obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
 obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+obj-$(CONFIG_ENV_IS_ANYWHERE) += env_anywhere.o
 
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_$(SPL_)OF_LIBFDT) += fdt_support.o
diff --git a/common/board_r.c b/common/board_r.c
index ecca1edb04..1a47f6cf1f 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -693,6 +693,14 @@ static int run_main_loop(void)
        return 0;
 }
 
+#ifdef CONFIG_ENV_IS_ANYWHERE
+static int env_relocate_late(void)
+{
+       env_relocate_spec_late();
+       return 0;
+}
+#endif
+
 /*
  * Over time we hope to remove these functions with code fragments and
  * stub funtcions, and instead call the relevant function directly.
@@ -898,6 +906,9 @@ static init_fnc_t init_sequence_r[] = {
 #ifdef CONFIG_PS2KBD
        initr_kbd,
 #endif
+#ifdef CONFIG_ENV_IS_ANYWHERE
+       env_relocate_late,
+#endif
        run_main_loop,
 };
 
diff --git a/common/env_anywhere.c b/common/env_anywhere.c
new file mode 100644
index 0000000000..dc2fc9e522
--- /dev/null
+++ b/common/env_anywhere.c
@@ -0,0 +1,156 @@
+/*
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <search.h>
+#include <errno.h>
+#include <part.h>
+#include <blk.h>
+#include <usb.h>
+#include <dm.h>
+#include <fs.h>
+
+#define ENV_FILE "uboot.env"
+
+static char env_name[64] = "ANYWHERE";
+char *env_name_spec = env_name;
+
+extern int usb_stor_curr_dev;
+
+env_t *env_ptr;
+
+static struct blk_desc *env_desc;
+static int env_part;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int env_init(void)
+{
+       /* use default */
+       gd->env_addr = (ulong)&default_environment[0];
+       gd->env_valid = 1;
+
+       return 0;
+}
+
+#ifdef CONFIG_CMD_SAVEENV
+int saveenv(void)
+{
+       env_t env_new;
+       loff_t size;
+       int err;
+
+       if (!env_desc)
+               return 1;
+
+       err = env_export(&env_new);
+       if (err)
+               return err;
+
+       fs_set_blk_dev2(env_desc, env_part);
+
+       err = fs_write(ENV_FILE, (ulong)&env_new, 0, sizeof(env_t), &size);
+       if (err == -1) {
+               printf("\n** Unable to write \"%s\" to %s **\n",
+                      ENV_FILE, env_name_spec);
+               return 1;
+       }
+
+       puts("done\n");
+       return 0;
+}
+#endif /* CONFIG_CMD_SAVEENV */
+
+static int env_find(void)
+{
+       struct udevice *dev;
+
+#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_DM_USB) && 
defined(CONFIG_CMD_USB)
+       int err;
+
+       err = usb_init();
+       if (!err)
+               usb_stor_curr_dev = usb_stor_scan(1);
+#endif
+
+       for (uclass_first_device_check(UCLASS_BLK, &dev);
+            dev;
+            uclass_next_device_check(&dev)) {
+               struct blk_desc *desc = dev_get_uclass_platdata(dev);
+               disk_partition_t info;
+               int part = 1;
+
+               printf("Scanning disk %s for environment...\n", dev->name);
+
+               /* check all partitions: */
+               while (!part_get_info(desc, part, &info)) {
+                       fs_set_blk_dev2(desc, part);
+
+                       if (fs_exists(ENV_FILE)) {
+                               printf("Found %s on %s:%d\n", ENV_FILE,
+                                      dev->name, part);
+
+                               snprintf(env_name, sizeof(env_name), "%s:%d",
+                                        dev->name, part);
+
+                               env_desc = desc;
+                               env_part = part;
+
+                               return 0;
+                       }
+
+                       part++;
+               }
+       }
+
+       return 1;
+}
+
+void env_set_location(struct blk_desc *desc, int part)
+{
+       /* if we already have an environment location, keep it: */
+       if (env_desc)
+               return;
+
+       env_desc = desc;
+       env_part = part;
+}
+
+void env_relocate_spec(void)
+{
+       set_default_env(NULL);
+}
+
+void env_relocate_spec_late(void)
+{
+       ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
+       loff_t size;
+       int err;
+
+       if (env_find())
+               goto err_env_relocate;
+
+       fs_set_blk_dev2(env_desc, env_part);
+
+       err = fs_read(ENV_FILE, (ulong)buf, 0, CONFIG_ENV_SIZE, &size);
+       if (err == -1) {
+               printf("\n** Unable to read \"%s\" from %s **\n",
+                      ENV_FILE, env_name_spec);
+               goto err_env_relocate;
+       }
+
+       env_import(buf, 1);
+       return;
+
+err_env_relocate:
+       set_default_env("!could not find environment");
+}
diff --git a/include/environment.h b/include/environment.h
index 6f94986c6b..57f03fe9ad 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -177,6 +177,11 @@ extern env_t *env_ptr;
 extern void env_relocate_spec(void);
 extern unsigned char env_get_char_spec(int);
 
+#ifdef CONFIG_ENV_IS_ANYWHERE
+void env_relocate_spec_late(void);
+void env_set_location(struct blk_desc *desc, int part);
+#endif
+
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 extern void env_reloc(void);
 #endif
-- 
2.13.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to