]> git.sur5r.net Git - u-boot/blobdiff - env/env.c
env: Make it explicit where we're loading our environment from
[u-boot] / env / env.c
index a239d93156df8d7e5c184542b3b016c185311d39..14324bbdd207945a63c01f297a5feb7dfd4aea8a 100644 (file)
--- a/env/env.c
+++ b/env/env.c
@@ -10,7 +10,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct env_driver *env_driver_lookup(enum env_location loc)
+static struct env_driver *_env_driver_lookup(enum env_location loc)
 {
        struct env_driver *drv;
        const int n_ents = ll_entry_count(struct env_driver, env_driver);
@@ -26,14 +26,39 @@ static struct env_driver *env_driver_lookup(enum env_location loc)
        return NULL;
 }
 
-static enum env_location env_get_default_location(void)
+/**
+ * env_get_location() - Returns the best env location for a board
+ * @op: operations performed on the environment
+ * @prio: priority between the multiple environments, 0 being the
+ *        highest priority
+ *
+ * This will return the preferred environment for the given priority.
+ *
+ * All implementations are free to use the operation, the priority and
+ * any other data relevant to their choice, but must take into account
+ * the fact that the lowest prority (0) is the most important location
+ * in the system. The following locations should be returned by order
+ * of descending priorities, from the highest to the lowest priority.
+ *
+ * Returns:
+ * an enum env_location value on success, a negative error code otherwise
+ */
+static enum env_location env_get_location(enum env_operation op, int prio)
 {
-       if IS_ENABLED(CONFIG_ENV_IS_IN_DATAFLASH)
-               return ENVL_DATAFLASH;
-       else if IS_ENABLED(CONFIG_ENV_IS_IN_EEPROM)
+       /*
+        * We support a single environment, so any environment asked
+        * with a priority that is not zero is out of our supported
+        * bounds.
+        */
+       if (prio >= 1)
+               return ENVL_UNKNOWN;
+
+       if IS_ENABLED(CONFIG_ENV_IS_IN_EEPROM)
                return ENVL_EEPROM;
        else if IS_ENABLED(CONFIG_ENV_IS_IN_FAT)
                return ENVL_FAT;
+       else if IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)
+               return ENVL_EXT4;
        else if IS_ENABLED(CONFIG_ENV_IS_IN_FLASH)
                return ENVL_FLASH;
        else if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
@@ -54,12 +79,28 @@ static enum env_location env_get_default_location(void)
                return ENVL_UNKNOWN;
 }
 
-struct env_driver *env_driver_lookup_default(void)
+
+/**
+ * env_driver_lookup() - Finds the most suited environment location
+ * @op: operations performed on the environment
+ * @prio: priority between the multiple environments, 0 being the
+ *        highest priority
+ *
+ * This will try to find the available environment with the highest
+ * priority in the system.
+ *
+ * Returns:
+ * NULL on error, a pointer to a struct env_driver otherwise
+ */
+static struct env_driver *env_driver_lookup(enum env_operation op, int prio)
 {
-       enum env_location loc = env_get_default_location();
+       enum env_location loc = env_get_location(op, prio);
        struct env_driver *drv;
 
-       drv = env_driver_lookup(loc);
+       if (loc == ENVL_UNKNOWN)
+               return NULL;
+
+       drv = _env_driver_lookup(loc);
        if (!drv) {
                debug("%s: No environment driver for location %d\n", __func__,
                      loc);
@@ -71,92 +112,106 @@ struct env_driver *env_driver_lookup_default(void)
 
 int env_get_char(int index)
 {
-       struct env_driver *drv = env_driver_lookup_default();
-       int ret;
+       struct env_driver *drv;
+       int prio;
 
-       if (!gd->env_valid)
+       if (gd->env_valid == ENV_INVALID)
                return default_environment[index];
-       if (!drv)
-               return -ENODEV;
-       if (!drv->get_char)
-               return *(uchar *)(gd->env_addr + index);
-       ret = drv->get_char(index);
-       if (ret < 0) {
-               debug("%s: Environment failed to load (err=%d)\n",
-                     __func__, ret);
+
+       for (prio = 0; (drv = env_driver_lookup(ENVOP_GET_CHAR, prio)); prio++) {
+               int ret;
+
+               if (!drv->get_char)
+                       continue;
+
+               ret = drv->get_char(index);
+               if (!ret)
+                       return 0;
+
+               debug("%s: Environment %s failed to load (err=%d)\n", __func__,
+                     drv->name, ret);
        }
 
-       return ret;
+       return -ENODEV;
 }
 
 int env_load(void)
 {
-       struct env_driver *drv = env_driver_lookup_default();
-       int ret = 0;
+       struct env_driver *drv;
+       int prio;
 
-       if (!drv)
-               return -ENODEV;
-       if (!drv->load)
-               return 0;
-       drv->load();  /* TODO(sjg@chromium.org): Make this return an error */
-       if (ret) {
-               debug("%s: Environment failed to load (err=%d)\n", __func__,
-                     ret);
-               return ret;
+       for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) {
+               int ret;
+
+               if (!drv->load)
+                       continue;
+
+               printf("Loading Environment from %s... ", drv->name);
+               ret = drv->load();
+               if (ret)
+                       printf("Failed (%d)\n", ret);
+               else
+                       printf("OK\n");
+
+               if (!ret)
+                       return 0;
        }
 
-       return 0;
+       return -ENODEV;
 }
 
 int env_save(void)
 {
-       struct env_driver *drv = env_driver_lookup_default();
-       int ret;
+       struct env_driver *drv;
+       int prio;
 
-       if (!drv)
-               return -ENODEV;
-       if (!drv->save)
-               return -ENOSYS;
-       ret = drv->save();
-       if (ret) {
-               debug("%s: Environment failed to save (err=%d)\n", __func__,
-                     ret);
-               return ret;
+       for (prio = 0; (drv = env_driver_lookup(ENVOP_SAVE, prio)); prio++) {
+               int ret;
+
+               if (!drv->save)
+                       continue;
+
+               printf("Saving Environment to %s... ", drv->name);
+               ret = drv->save();
+               if (ret)
+                       printf("Failed (%d)\n", ret);
+               else
+                       printf("OK\n");
+
+               if (!ret)
+                       return 0;
        }
 
-       return 0;
+       return -ENODEV;
 }
 
 int env_init(void)
 {
-       struct env_driver *drv = env_driver_lookup_default();
+       struct env_driver *drv;
        int ret = -ENOENT;
+       int prio;
+
+       for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
+               if (!drv->init)
+                       continue;
 
-       if (!drv)
-               return -ENODEV;
-       if (drv->init)
                ret = drv->init();
+               if (!ret)
+                       return 0;
+
+               debug("%s: Environment %s failed to init (err=%d)\n", __func__,
+                     drv->name, ret);
+       }
+
+       if (!prio)
+               return -ENODEV;
+
        if (ret == -ENOENT) {
                gd->env_addr = (ulong)&default_environment[0];
-               gd->env_valid = 0;
+               gd->env_valid = ENV_VALID;
 
                return 0;
-       } else if (ret) {
-               debug("%s: Environment failed to init (err=%d)\n", __func__,
-                     ret);
-               return ret;
        }
 
-       return 0;
-}
-
-void env_relocate_spec(void)
-{
-       env_load();
-}
-
-int saveenv(void)
-{
-       return env_save();
+       return ret;
 }
-