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