All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rob Clark <robdclark@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] env: add ENV_IS_ANYWHERE
Date: Mon, 31 Jul 2017 08:42:01 -0400	[thread overview]
Message-ID: <20170731124202.9500-1-robdclark@gmail.com> (raw)

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@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@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

             reply	other threads:[~2017-07-31 12:42 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-31 12:42 Rob Clark [this message]
2017-07-31 12:42 ` [U-Boot] [PATCH] vsprintf.c: add wide string (%ls) support Rob Clark
2017-08-02  2:22   ` Heinrich Schuchardt
2017-08-02  9:38     ` Rob Clark
2017-08-02 17:05       ` Heinrich Schuchardt
2017-08-02 18:15         ` Rob Clark
2017-08-02 21:40           ` Heinrich Schuchardt
2017-08-02 22:25             ` Rob Clark
2017-08-03  0:48 ` [U-Boot] [PATCH] env: add ENV_IS_ANYWHERE 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=20170731124202.9500-1-robdclark@gmail.com \
    --to=robdclark@gmail.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.