[U-Boot] [PATCH] env: add ENV_IS_ANYWHERE
Rob Clark
robdclark at gmail.com
Mon Jul 31 12:42:01 UTC 2017
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 <robdclark at 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
More information about the U-Boot
mailing list