u-boot: remove driver lookup loop from env_save()
PATCH v3 1/1 u-boot: remove driver lookup loop from env_save()
When called with ENVOP_SAVE, env_get_location() only returns the gd->env_load_location variable without actually checking for the environment location and priority.
This behaviour causes env_save() to fall into an infinite loop when the low-level drv->save() call fails.
The env_save() function should not loop through the environment location list but it should save the environment into the location stored in gd->env_load_location by the last env_load() call.
---
Changes in v3:
- Add comment when env_load() fails and the env location is restored
- Introduce env_load_prio into gd struct. It stores the current priority of the environment location. Refactor of env_get_location() which acts the same on all the 'env_operation'
Changes in v2:
- Restore gd->env_load_location to the highest priority location when env_load() fails
env/env.c | 35 +++++++++++++++++------------------ include/asm-generic/global_data.h | 1 + 2 files changed, 18 insertions(+), 18 deletions(-)
env/env.c +17 -18
@@ -119,21 +119,13 @@ static void env_set_inited(enum env_location location)*/ __weak enum env_location env_get_location (enum env_operation op,int prio) { -switch (op) { -case ENVOP_GET_CHAR : -case ENVOP_INIT : -case ENVOP_LOAD : -if (prio >=ARRAY_SIZE (env_locations)) -return ENVL_UNKNOWN ; - - gd->env_load_location = env_locations[prio]; -return gd->env_load_location; - -case ENVOP_SAVE : -return gd->env_load_location; - } +if (prio >=ARRAY_SIZE (env_locations)) +return ENVL_UNKNOWN ; + + gd->env_load_location = env_locations[prio]; + gd->env_load_prio = prio; -return ENVL_UNKNOWN ; +return gd->env_load_location; }
@@ -205,22 +197,29 @@ int env_load(void)return 0 ; } +/* +* In case of invalid environment, we set the 'default' env location +* to the highest priority. In this way, next calls to env_save() +* will restore the environment at the right place. +*/ +env_get_location (ENVOP_LOAD ,0 ); +return -ENODEV ; }int env_save (void ) {struct env_driver *drv; -int prio; -for (prio =0 ; (drv =env_driver_lookup (ENVOP_SAVE , prio)); prio++) { + drv =env_driver_lookup (ENVOP_SAVE , gd->env_load_prio); +if (drv) {int ret;if (!drv->save) -continue ; +return -ENODEV ;if (!env_has_inited (drv->location)) -continue ; +return -ENODEV ;printf ("Saving Environment to %s... " , drv->name); ret = drv->save ();
include/asm-generic/global_data.h +1 -0
@@ -51,6 +51,7 @@ typedef struct global_data {unsigned long env_valid;/* Environment valid? enum env_valid */ unsigned long env_has_init;/* Bitmask of boolean of struct env_location offsets */ int env_load_location; +int env_load_prio;unsigned long ram_top;/* Top address of RAM used by U-Boot */ unsigned long relocaddr;/* Start address of U-Boot in RAM */
Signature · 1 line
2.7.4
PATCH v3 1/1 u-boot: remove driver lookup loop from env_save()
Quoted 47 lines · Nicholas Faustini
When called with
ENVOP_SAVE,env_get_location()only returns thegd->env_load_locationvariable without actually checking for the environment location and priority.This behaviour causes
env_save()to fall into an infinite loop when the low-leveldrv->save()call fails.The
env_save()function should not loop through the environment location list but it should save the environment into the location stored ingd->env_load_locationby the lastenv_load()call.Signed-off-by Nicholas Faustini <[email protected]>---
Changes in v3:
- Add comment whenenv_load()fails and the env location is restored
- Introduceenv_load_priointo gd struct. It stores the current priority of the environment location. Refactor ofenv_get_location()which acts the same on all the 'env_operation'Changes in v2:
- Restoregd->env_load_locationto the highest priority location whenenv_load()failsenv/env.c | 35 +++++++++++++++++------------------ include/asm-generic/global_data.h | 1 + 2 files changed, 18 insertions(+), 18 deletions(-)env/env.c +0
-11@@ -119,21 +119,13 @@ static void env_set_inited(enum env_location location)*/ __weak enum env_location env_get_location (enum env_operation op,int prio) { -switch (op) { -case ENVOP_GET_CHAR : -case ENVOP_INIT : -case ENVOP_LOAD : -if (prio >=ARRAY_SIZE (env_locations)) -return ENVL_UNKNOWN ; - - gd->env_load_location = env_locations[prio]; -return gd->env_load_location; - -case ENVOP_SAVE :
env/env.c static void env_set_inited(enum env_location location) · line 128
Quoted 10 lines
env/env.c +6
-3-return gd->env_load_location; - } +if (prio >=ARRAY_SIZE (env_locations)) +return ENVL_UNKNOWN ; + + gd->env_load_location = env_locations[prio]; + gd->env_load_prio = prio; -return ENVL_UNKNOWN ; +return gd->env_load_location;
Ehrm, I just saw gd->env_load_location is now unused... Other than that:
Quoted 50 lines
env/env.c +11
-4}@@ -205,22 +197,29 @@ int env_load(void)return 0 ; } +/* +* In case of invalid environment, we set the 'default' env location +* to the highest priority. In this way, next calls to env_save() +* will restore the environment at the right place. +*/ +env_get_location (ENVOP_LOAD ,0 ); +return -ENODEV ; }int env_save (void ) {struct env_driver *drv; -int prio; -for (prio =0 ; (drv =env_driver_lookup (ENVOP_SAVE , prio)); prio++) { + drv =env_driver_lookup (ENVOP_SAVE , gd->env_load_prio); +if (drv) {int ret;if (!drv->save) -continue ; +return -ENODEV ;if (!env_has_inited (drv->location)) -continue ; +return -ENODEV ;printf ("Saving Environment to %s... " , drv->name); ret = drv->save ();include/asm-generic/global_data.h +1
-0@@ -51,6 +51,7 @@ typedef struct global_data {unsigned long env_valid;/* Environment valid? enum env_valid */ unsigned long env_has_init;/* Bitmask of boolean of struct env_location offsets */ int env_load_location; +int env_load_prio;unsigned long ram_top;/* Top address of RAM used by U-Boot */ unsigned long relocaddr;/* Start address of U-Boot in RAM */
PATCH v3 1/1 u-boot: remove driver lookup loop from env_save()
Quoted 69 lines · Simon Goldschmidt
Quoted 62 lines · Nicholas Faustini
When called with
ENVOP_SAVE,env_get_location()only returns thegd->env_load_locationvariable without actually checking for the environment location and priority.This behaviour causes
env_save()to fall into an infinite loop when the low-leveldrv->save()call fails.The
env_save()function should not loop through the environment location list but it should save the environment into the location stored ingd->env_load_locationby the lastenv_load()call.Signed-off-by Nicholas Faustini <[email protected]>---
Changes in v3:
- Add comment whenenv_load()fails and the env location is restored
- Introduceenv_load_priointo gd struct. It stores the current priority of the environment location. Refactor ofenv_get_location()
which acts the same on all the 'env_operation'Changes in v2:
- Restoregd->env_load_locationto the highest priority location when
env_load() failsenv/env.c | 35 +++++++++++++++++---------
---------
include/asm-generic/global_data.h| 1 +2 files changed, 18 insertions(+), 18 deletions(-)env/env.c +5
-13@@ -119,21 +119,13 @@ static void env_set_inited(enum env_locationlocation) */ __weak enum env_location env_get_location(enum env_operation op,int prio) { -switch (op) { -case ENVOP_GET_CHAR : -case ENVOP_INIT : -case ENVOP_LOAD : -if (prio >=ARRAY_SIZE (env_locations)) -return ENVL_UNKNOWN ; - - gd->env_load_location = env_locations[prio]; -return gd->env_load_location; - -case ENVOP_SAVE : -return gd->env_load_location; - } +if (prio >=ARRAY_SIZE (env_locations)) +return ENVL_UNKNOWN ; + + gd->env_load_location = env_locations[prio]; + gd->env_load_prio = prio;env/env.c
Quoted 2 lines
env/env.c +1
-1-return ENVL_UNKNOWN ; +return gd->env_load_location;Ehrm, I just saw
gd->env_load_locationis now unused... Other than that:
Quoted 1 line
Reviewed-by Simon Goldschmidt <[email protected]>
I didn't notice that.. :blush:
I remove it from gd.env_load_prio is actually enough to get the information about the location if someone will need it.
Quoted 61 lines
Quoted 61 lines
}
env/env.c +0
-0@@ -205,22 +197,29 @@ int env_load(void) return 0; }env/env.c +2
-0+/* +* In case of invalid environment, we set the 'default' env location
env/env.c +1
-0+ * to the highest priority. In this way, next calls to
env_save()env/env.c +4
-0+* will restore the environment at the right place. +*/ +env_get_location (ENVOP_LOAD ,0 ); +return
-ENODEV;
}
intenv_save(void)
{
structenv_driver*drv;env/env.c +0
-1-int prio;env/env.c +0
-1- for (prio = 0; (drv = env_driver_lookup(ENVOP_SAVE,prio)); prio++) {
env/env.c +2
-0+ drv =env_driver_lookup (ENVOP_SAVE , gd->env_load_prio); +if (drv) {int ret;
if (!drv->save)env/env.c +1
-1-continue ; +return -ENODEV ;
if (!env_has_inited(drv->location))env/env.c +1
-1-continue ; +return -ENODEV ;
printf("Saving Environment to %s... ", drv-Quoted 1 line
name);
ret =
drv->save();include/asm- renamed from include/asm-generic/global_data.h +0
-0
generic/global_data.h
index 2d451f8..319810a 100644include/asm-generic/global_data.h +0
-0@@ -51,6 +51,7 @@ typedef struct global_data {unsigned long
env_valid; /* Environment valid?
enumenv_valid*/
unsigned longenv_has_init; /* Bitmask of boolean
of structenv_locationoffsets */
intenv_load_location;include/asm-generic/global_data.h +1
-0+int env_load_prio;
unsigned longram_top; /* Top address of
RAM used by U-Boot */
unsigned long relocaddr; /* Start address of U-
Boot in RAM */