[11/11] env: store information about each environment in gd

Message ID bc807953c828df1019e9f228b2c0a3b783739660.1513975247.git-series.quentin.schulz@free-electrons.com
State New
Headers show
Series
  • Introduce variables whitelisting in environment
Related show

Commit Message

Quentin Schulz Dec. 22, 2017, 9:13 p.m.
To store the "validity" (redund or main), the env_addr (different when
redund or main env is used) and the init status of the environment for
each environment, an array of env_info structure is created in the
global data pointer.

Move all calls to env_addr, env_valid and env_has_init to the new model
in the different env drivers.

Note that env_addr and env_valid defined in board file are intentionally
left untouched and thus, will break compilation for a few boards.
The question is: why do we need to set env_addr and env_valid in board
files? In addition, env_addr is never used (only when using redundant
env and it's set before being used).

Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
 common/board_r.c                  |  8 ++++-
 env/common.c                      | 25 ++++++++++-------
 env/eeprom.c                      | 34 +++++++++++------------
 env/env.c                         | 13 +++++----
 env/flash.c                       | 48 ++++++++++++++++----------------
 env/mmc.c                         |  8 ++---
 env/nand.c                        | 36 ++++++++++++------------
 env/nowhere.c                     |  4 +--
 env/nvram.c                       | 10 +++----
 env/onenand.c                     |  2 +-
 env/remote.c                      |  4 +--
 env/sf.c                          | 26 ++++++++---------
 env/ubi.c                         |  4 +--
 include/asm-generic/global_data.h |  5 +--
 14 files changed, 121 insertions(+), 106 deletions(-)

Patch

diff --git a/common/board_r.c b/common/board_r.c
index a3b9bfb..512e109 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -125,6 +125,10 @@  __weak int fixup_cpu(void)
 
 static int initr_reloc_global_data(void)
 {
+#ifdef CONFIG_SYS_EXTRA_ENV_RELOC
+	int i;
+#endif
+
 #ifdef __ARM__
 	monitor_flash_len = _end - __image_copy_start;
 #elif defined(CONFIG_NDS32)
@@ -154,7 +158,9 @@  static int initr_reloc_global_data(void)
 	 * in SRAM mode and initialize that cache from SRAM mode back to being
 	 * a cache in cpu_init_r.
 	 */
-	gd->env_addr += gd->relocaddr - CONFIG_SYS_MONITOR_BASE;
+	for (i = 0; i < ENVL_COUNT; i++)
+		gd->env_infos[i].env_addr += gd->relocaddr -
+			CONFIG_SYS_MONITOR_BASE;
 #endif
 #ifdef CONFIG_OF_EMBED
 	/*
diff --git a/env/common.c b/env/common.c
index 24cf41b..72359fe 100644
--- a/env/common.c
+++ b/env/common.c
@@ -214,24 +214,24 @@  int env_import_redund(struct env_driver *drv, const char *buf1, const char *buf2
 		set_default_env("!bad CRC");
 		return 0;
 	} else if (crc1_ok && !crc2_ok) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (!crc1_ok && crc2_ok) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else {
 		/* both ok - check serial */
 		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else if (tmp_env1->flags > tmp_env2->flags)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else if (tmp_env2->flags > tmp_env1->flags)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else /* flags are equal - almost impossible */
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 
-	if (gd->env_valid == ENV_VALID)
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID)
 		ep = tmp_env1;
 	else
 		ep = tmp_env2;
@@ -271,11 +271,18 @@  int env_export(env_t *env_out)
 
 void env_relocate(void)
 {
+	int i;
+
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 	env_reloc();
 	env_htab.change_ok += gd->reloc_off;
+
 #endif
-	if (gd->env_valid == ENV_INVALID) {
+	for(i = 0; i < ENVL_COUNT; i++)
+		if (gd->env_infos[i].has_init)
+			break;
+
+	if (i == ENVL_COUNT) {
 #if defined(CONFIG_SPL_BUILD)
 		/* Environment not changable */
 		set_default_env(NULL);
diff --git a/env/eeprom.c b/env/eeprom.c
index b0ffce4..b48aa97 100644
--- a/env/eeprom.c
+++ b/env/eeprom.c
@@ -67,7 +67,7 @@  static int env_eeprom_get_char(struct env_driver *drv, int index)
 	unsigned int off = CONFIG_ENV_OFFSET;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	if (gd->env_valid == ENV_REDUND)
+	if (gd->env_infos[drv->location].env_valid == ENV_REDUND)
 		off = CONFIG_ENV_OFFSET_REDUND;
 #endif
 	eeprom_bus_read(CONFIG_SYS_DEF_EEPROM_ADDR,
@@ -121,24 +121,24 @@  static int env_eeprom_load(struct env_driver *drv)
 	}
 
 	if (!crc_ok[0] && !crc_ok[1]) {
-		gd->env_addr	= 0;
-		gd->env_valid = ENV_INVALID;
+		gd->env_infos[drv->location].env_addr	= 0;
+		gd->env_infos[drv->location].env_valid = ENV_INVALID;
 	} else if (crc_ok[0] && !crc_ok[1]) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (!crc_ok[0] && crc_ok[1]) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else {
 		/* both ok - check serial */
 		if (flags[0] == ACTIVE_FLAG && flags[1] == OBSOLETE_FLAG)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else if (flags[0] == OBSOLETE_FLAG && flags[1] == ACTIVE_FLAG)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else if (flags[0] == 0xFF && flags[1] == 0)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else if (flags[1] == 0xFF && flags[0] == 0)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else /* flags are equal - almost impossible */
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 
 #else /* CONFIG_ENV_OFFSET_REDUND */
@@ -166,15 +166,15 @@  static int env_eeprom_load(struct env_driver *drv)
 	}
 
 	if (crc == new) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else {
-		gd->env_valid = ENV_INVALID;
+		gd->env_infos[drv->location].env_valid = ENV_INVALID;
 	}
 #endif /* CONFIG_ENV_OFFSET_REDUND */
 
 	off = CONFIG_ENV_OFFSET;
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	if (gd->env_valid == ENV_REDUND)
+	if (gd->env_infos[drv->location].env_valid == ENV_REDUND)
 		off = CONFIG_ENV_OFFSET_REDUND;
 #endif
 
@@ -201,7 +201,7 @@  static int env_eeprom_save(struct env_driver *drv)
 		return rc;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	if (gd->env_valid == ENV_VALID) {
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID) {
 		off	= CONFIG_ENV_OFFSET_REDUND;
 		off_red	= CONFIG_ENV_OFFSET;
 	}
@@ -218,10 +218,10 @@  static int env_eeprom_save(struct env_driver *drv)
 				 off_red + offsetof(env_t, flags),
 				 (uchar *)&flag_obsolete, 1);
 
-		if (gd->env_valid == ENV_VALID)
-			gd->env_valid = ENV_REDUND;
+		if (gd->env_infos[drv->location].env_valid == ENV_VALID)
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 #endif
 	return rc;
diff --git a/env/env.c b/env/env.c
index ccddc2a..01233ce 100644
--- a/env/env.c
+++ b/env/env.c
@@ -150,7 +150,7 @@  int env_get_char(int index)
 		if (!drv->get_char)
 			continue;
 
-		if (!(gd->env_has_init & BIT(drv->location)))
+		if (!gd->env_infos[drv->location].has_init)
 			continue;
 
 		ret = drv->get_char(drv, index);
@@ -177,7 +177,7 @@  int env_load(void)
 		if (!drv->load)
 			continue;
 
-		if (!(gd->env_has_init & BIT(drv->location)))
+		if (!gd->env_infos[drv->location].has_init)
 			continue;
 
 		printf("Loading Environment from %s... ", drv->name);
@@ -203,7 +203,10 @@  int env_load(void)
 		if (!drv->load)
 			continue;
 
-		printf("Overriding env variables with ones from %s env...",
+		if (!gd->env_infos[drv->location].has_init)
+			continue;
+
+		printf("%s: Overriding env variables with ones from %s env...",
 		      __func__, drv->name);
 		ret = drv->load(drv);
 		printf("%s\n", ret ? "Failed" : "OK");
@@ -237,7 +240,7 @@  int env_save(void)
 		if (!drv->save)
 			continue;
 
-		if (!(gd->env_has_init & BIT(drv->location)))
+		if (!gd->env_infos[drv->location].has_init)
 			continue;
 
 		printf("Saving Environment to %s... ", drv->name);
@@ -277,7 +280,7 @@  int env_init(void)
 			ret = 0;
 
 		if (!ret) {
-			gd->env_has_init |= BIT(drv->location);
+			gd->env_infos[drv->location].has_init = true;
 			init = true;
 		}
 
diff --git a/env/flash.c b/env/flash.c
index 45e58b4..1c7666a 100644
--- a/env/flash.c
+++ b/env/flash.c
@@ -87,29 +87,29 @@  static int env_flash_init(struct env_driver *drv)
 		crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc;
 
 	if (crc1_ok && !crc2_ok) {
-		gd->env_addr	= addr1;
-		gd->env_valid	= ENV_VALID;
+		gd->env_infos[drv->location].env_addr	= addr1;
+		gd->env_infos[drv->location].env_valid	= ENV_VALID;
 	} else if (!crc1_ok && crc2_ok) {
-		gd->env_addr	= addr2;
-		gd->env_valid	= ENV_VALID;
+		gd->env_infos[drv->location].env_addr	= addr2;
+		gd->env_infos[drv->location].env_valid	= ENV_VALID;
 	} else if (!crc1_ok && !crc2_ok) {
-		gd->env_addr	= addr_default;
-		gd->env_valid	= ENV_INVALID;
+		gd->env_infos[drv->location].env_addr	= addr_default;
+		gd->env_infos[drv->location].env_valid	= ENV_INVALID;
 	} else if (flag1 == ACTIVE_FLAG && flag2 == OBSOLETE_FLAG) {
-		gd->env_addr	= addr1;
-		gd->env_valid	= ENV_VALID;
+		gd->env_infos[drv->location].env_addr	= addr1;
+		gd->env_infos[drv->location].env_valid	= ENV_VALID;
 	} else if (flag1 == OBSOLETE_FLAG && flag2 == ACTIVE_FLAG) {
-		gd->env_addr	= addr2;
-		gd->env_valid	= ENV_VALID;
+		gd->env_infos[drv->location].env_addr	= addr2;
+		gd->env_infos[drv->location].env_valid	= ENV_VALID;
 	} else if (flag1 == flag2) {
-		gd->env_addr	= addr1;
-		gd->env_valid	= ENV_REDUND;
+		gd->env_infos[drv->location].env_addr	= addr1;
+		gd->env_infos[drv->location].env_valid	= ENV_REDUND;
 	} else if (flag1 == 0xFF) {
-		gd->env_addr	= addr1;
-		gd->env_valid	= ENV_REDUND;
+		gd->env_infos[drv->location].env_addr	= addr1;
+		gd->env_infos[drv->location].env_valid	= ENV_REDUND;
 	} else if (flag2 == 0xFF) {
-		gd->env_addr	= addr2;
-		gd->env_valid	= ENV_REDUND;
+		gd->env_infos[drv->location].env_addr	= addr2;
+		gd->env_infos[drv->location].env_valid	= ENV_REDUND;
 	}
 
 	return 0;
@@ -225,13 +225,13 @@  done:
 static int env_flash_init(struct env_driver *drv)
 {
 	if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
-		gd->env_addr	= (ulong)&(env_ptr->data);
-		gd->env_valid	= ENV_VALID;
+		gd->env_infos[drv->location].env_addr	= (ulong)&(env_ptr->data);
+		gd->env_infos[drv->location].env_valid	= ENV_VALID;
 		return 0;
 	}
 
-	gd->env_addr	= (ulong)&default_environment[0];
-	gd->env_valid	= ENV_INVALID;
+	gd->env_infos[drv->location].env_addr	= (ulong)&default_environment[0];
+	gd->env_infos[drv->location].env_valid	= ENV_INVALID;
 	return 0;
 }
 #endif
@@ -311,7 +311,7 @@  done:
 static int env_flash_load(struct env_driver *drv)
 {
 #ifdef CONFIG_ENV_ADDR_REDUND
-	if (gd->env_addr != (ulong)&(flash_addr->data)) {
+	if (gd->env_infos[drv->location].env_addr != (ulong)&(flash_addr->data)) {
 		env_t *etmp = flash_addr;
 		ulong ltmp = end_addr;
 
@@ -326,7 +326,7 @@  static int env_flash_load(struct env_driver *drv)
 	    crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc) {
 		char flag = OBSOLETE_FLAG;
 
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new);
 		flash_write(&flag,
 			    (ulong)&(flash_addr_new->flags),
@@ -338,7 +338,7 @@  static int env_flash_load(struct env_driver *drv)
 	    (flash_addr->flags & ACTIVE_FLAG) == ACTIVE_FLAG) {
 		char flag = ACTIVE_FLAG;
 
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		flash_sect_protect(0, (ulong)flash_addr, end_addr);
 		flash_write(&flag,
 			    (ulong)&(flash_addr->flags),
@@ -346,7 +346,7 @@  static int env_flash_load(struct env_driver *drv)
 		flash_sect_protect(1, (ulong)flash_addr, end_addr);
 	}
 
-	if (gd->env_valid == ENV_REDUND)
+	if (gd->env_infos[drv->location].env_valid == ENV_REDUND)
 		puts("*** Warning - some problems detected "
 		     "reading environment; recovered successfully\n\n");
 #endif /* CONFIG_ENV_ADDR_REDUND */
diff --git a/env/mmc.c b/env/mmc.c
index 64d1404..250108f 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -163,7 +163,7 @@  static int env_mmc_save(struct env_driver *drv)
 		goto fini;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	if (gd->env_valid == ENV_VALID)
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID)
 		copy = 1;
 #endif
 
@@ -182,7 +182,7 @@  static int env_mmc_save(struct env_driver *drv)
 	ret = 0;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
+	gd->env_infos[drv->location].env_valid = gd->env_infos[drv->location].env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
 #endif
 
 fini:
@@ -247,10 +247,10 @@  static int env_mmc_load(struct env_driver *drv)
 		ret = -EIO;
 		goto fini;
 	} else if (!read1_fail && read2_fail) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 		env_import((char *)tmp_env1, 1);
 	} else if (read1_fail && !read2_fail) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		env_import((char *)tmp_env2, 1);
 	} else {
 		env_import_redund((char *)tmp_env1, (char *)tmp_env2);
diff --git a/env/nand.c b/env/nand.c
index 49e506e..77b9ca1 100644
--- a/env/nand.c
+++ b/env/nand.c
@@ -78,42 +78,42 @@  static int env_nand_init(struct env_driver *drv)
 	crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc;
 
 	if (!crc1_ok && !crc2_ok) {
-		gd->env_addr	= 0;
-		gd->env_valid	= ENV_INVALID;
+		gd->env_infos[drv->location].env_addr	= 0;
+		gd->env_infos[drv->location].env_valid	= ENV_INVALID;
 
 		return 0;
 	} else if (crc1_ok && !crc2_ok) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	else if (!crc1_ok && crc2_ok) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else {
 		/* both ok - check serial */
 		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else if (tmp_env1->flags > tmp_env2->flags)
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 		else if (tmp_env2->flags > tmp_env1->flags)
-			gd->env_valid = ENV_REDUND;
+			gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		else /* flags are equal - almost impossible */
-			gd->env_valid = ENV_VALID;
+			gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 
-	if (gd->env_valid == ENV_REDUND)
+	if (gd->env_infos[drv->location].env_valid == ENV_REDUND)
 		env_ptr = tmp_env2;
 	else
 #endif
-	if (gd->env_valid == ENV_VALID)
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID)
 		env_ptr = tmp_env1;
 
-	gd->env_addr = (ulong)env_ptr->data;
+	gd->env_infos[drv->location].env_addr = (ulong)env_ptr->data;
 
 #else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
-	gd->env_addr	= (ulong)&default_environment[0];
-	gd->env_valid	= ENV_VALID;
+	gd->env_infos[drv->location].env_addr	= (ulong)&default_environment[0];
+	gd->env_infos[drv->location].env_valid	= ENV_VALID;
 #endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
 
 	return 0;
@@ -216,14 +216,14 @@  static int env_nand_save(struct env_driver *drv)
 		return ret;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
-	env_idx = (gd->env_valid == ENV_VALID);
+	env_idx = (gd->env_infos[drv->location].env_valid == ENV_VALID);
 #endif
 
 	ret = erase_and_write_env(&location[env_idx], (u_char *)env_new);
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	if (!ret) {
 		/* preset other copy for next write */
-		gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID :
+		gd->env_infos[drv->location].env_valid = gd->env_infos[drv->location].env_valid == ENV_REDUND ? ENV_VALID :
 				ENV_REDUND;
 		return ret;
 	}
@@ -346,10 +346,10 @@  static int env_nand_load(struct env_driver *drv)
 		set_default_env("!bad env area");
 		goto done;
 	} else if (!read1_fail && read2_fail) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 		env_import((char *)tmp_env1, 1);
 	} else if (read1_fail && !read2_fail) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 		env_import((char *)tmp_env2, 1);
 	} else {
 		env_import_redund(drv, (char *)tmp_env1, (char *)tmp_env2);
diff --git a/env/nowhere.c b/env/nowhere.c
index fb6ea9e..7d81a57 100644
--- a/env/nowhere.c
+++ b/env/nowhere.c
@@ -26,8 +26,8 @@  static int env_nowhere_load(struct env_driver *drv)
  */
 static int env_nowhere_init(struct env_driver *drv)
 {
-	gd->env_addr	= (ulong)&default_environment[0];
-	gd->env_valid	= ENV_VALID;
+	gd->env_infos[drv->location].env_addr	= (ulong)&default_environment[0];
+	gd->env_infos[drv->location].env_valid	= ENV_VALID;
 
 	return 0;
 }
diff --git a/env/nvram.c b/env/nvram.c
index aad341d..c36c1af 100644
--- a/env/nvram.c
+++ b/env/nvram.c
@@ -98,15 +98,15 @@  static int env_nvram_init(struct env_driver *drv)
 	nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE);
 
 	if (crc32(0, data, ENV_SIZE) == crc) {
-		gd->env_addr	= (ulong)CONFIG_ENV_ADDR + sizeof(long);
+		gd->env_infos[drv->location].env_addr	= (ulong)CONFIG_ENV_ADDR + sizeof(long);
 #else
 	if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
-		gd->env_addr	= (ulong)&env_ptr->data;
+		gd->env_infos[drv->location].env_addr	= (ulong)&env_ptr->data;
 #endif
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else {
-		gd->env_addr	= (ulong)&default_environment[0];
-		gd->env_valid	= ENV_INVALID;
+		gd->env_infos[drv->location].env_addr	= (ulong)&default_environment[0];
+		gd->env_infos[drv->location].env_valid	= ENV_INVALID;
 	}
 
 	return 0;
diff --git a/env/onenand.c b/env/onenand.c
index e633ebe..68790f1 100644
--- a/env/onenand.c
+++ b/env/onenand.c
@@ -58,7 +58,7 @@  static int env_onenand_load(struct env_driver *drv)
 
 	rc = env_import(buf, 1);
 	if (rc)
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 
 	return rc ? 0 : -EIO;
 }
diff --git a/env/remote.c b/env/remote.c
index b004964..895759e 100644
--- a/env/remote.c
+++ b/env/remote.c
@@ -26,8 +26,8 @@  DECLARE_GLOBAL_DATA_PTR;
 static int env_remote_init(struct env_driver *drv)
 {
 	if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
-		gd->env_addr = (ulong)&(env_ptr->data);
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_addr = (ulong)&(env_ptr->data);
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 		return 0;
 	}
 
diff --git a/env/sf.c b/env/sf.c
index e811cde..40e2671 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -98,7 +98,7 @@  static int env_sf_save(struct env_driver *drv)
 		return -EIO;
 	env_new.flags	= ACTIVE_FLAG;
 
-	if (gd->env_valid == ENV_VALID) {
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID) {
 		env_new_offset = CONFIG_ENV_OFFSET_REDUND;
 		env_offset = CONFIG_ENV_OFFSET;
 	} else {
@@ -150,9 +150,9 @@  static int env_sf_save(struct env_driver *drv)
 
 	puts("done\n");
 
-	gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
+	gd->env_infos[drv->location].env_valid = gd->env_infos[drv->location].env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
 
-	printf("Valid environment: %d\n", (int)gd->env_valid);
+	printf("Valid environment: %d\n", (int)gd->env_infos[drv->location].env_valid);
 
  done:
 	if (saved_buffer)
@@ -206,30 +206,30 @@  static int env_sf_load(struct env_driver *drv)
 		ret = -EIO;
 		goto err_read;
 	} else if (crc1_ok && !crc2_ok) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (!crc1_ok && crc2_ok) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else if (tmp_env1->flags == ACTIVE_FLAG &&
 		   tmp_env2->flags == OBSOLETE_FLAG) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (tmp_env1->flags == OBSOLETE_FLAG &&
 		   tmp_env2->flags == ACTIVE_FLAG) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else if (tmp_env1->flags == tmp_env2->flags) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (tmp_env1->flags == 0xFF) {
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	} else if (tmp_env2->flags == 0xFF) {
-		gd->env_valid = ENV_REDUND;
+		gd->env_infos[drv->location].env_valid = ENV_REDUND;
 	} else {
 		/*
 		 * this differs from code in env_flash.c, but I think a sane
 		 * default path is desirable.
 		 */
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 	}
 
-	if (gd->env_valid == ENV_VALID)
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID)
 		ep = tmp_env1;
 	else
 		ep = tmp_env2;
@@ -336,7 +336,7 @@  static int env_sf_load(struct env_driver *drv)
 
 	ret = env_import(buf, 1);
 	if (ret)
-		gd->env_valid = ENV_VALID;
+		gd->env_infos[drv->location].env_valid = ENV_VALID;
 
 err_read:
 	spi_flash_free(env_flash);
diff --git a/env/ubi.c b/env/ubi.c
index 51b61eb..bd137e9 100644
--- a/env/ubi.c
+++ b/env/ubi.c
@@ -35,7 +35,7 @@  static int env_ubi_save(struct env_driver *drv)
 		return 1;
 	}
 
-	if (gd->env_valid == ENV_VALID) {
+	if (gd->env_infos[drv->location].env_valid == ENV_VALID) {
 		puts("Writing to redundant UBI... ");
 		if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND,
 				     (void *)env_new, CONFIG_ENV_SIZE)) {
@@ -57,7 +57,7 @@  static int env_ubi_save(struct env_driver *drv)
 
 	puts("done\n");
 
-	gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
+	gd->env_infos[drv->location].env_valid = gd->env_infos[drv->location].env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
 
 	return 0;
 }
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 1d0611f..17cf1b7 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -23,6 +23,7 @@ 
 #ifndef __ASSEMBLY__
 #include <membuff.h>
 #include <linux/list.h>
+#include <environment.h>
 
 typedef struct global_data {
 	bd_t *bd;
@@ -48,9 +49,7 @@  typedef struct global_data {
 #if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
 	unsigned long precon_buf_idx;	/* Pre-Console buffer index */
 #endif
-	unsigned long env_addr;		/* Address  of Environment struct */
-	unsigned long env_valid;	/* Environment valid? enum env_valid */
-	unsigned long env_has_init;	/* Bitmask of boolean of struct env_location offsets */
+	struct env_info env_infos[ENVL_COUNT];
 
 	unsigned long ram_top;		/* Top address of RAM used by U-Boot */
 	unsigned long relocaddr;	/* Start address of U-Boot in RAM */