|
@@ -0,0 +1,145 @@
|
|
|
+/*
|
|
|
+ * Copyright (C) 2017 Google, Inc
|
|
|
+ * Written by Simon Glass <sjg@chromium.org>
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: GPL-2.0+
|
|
|
+ */
|
|
|
+
|
|
|
+#include <common.h>
|
|
|
+#include <environment.h>
|
|
|
+
|
|
|
+DECLARE_GLOBAL_DATA_PTR;
|
|
|
+
|
|
|
+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);
|
|
|
+ struct env_driver *entry;
|
|
|
+
|
|
|
+ drv = ll_entry_start(struct env_driver, env_driver);
|
|
|
+ for (entry = drv; entry != drv + n_ents; entry++) {
|
|
|
+ if (loc == entry->location)
|
|
|
+ return entry;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Not found */
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static enum env_location env_get_default_location(void)
|
|
|
+{
|
|
|
+ if IS_ENABLED(CONFIG_ENV_IS_IN_DATAFLASH)
|
|
|
+ return ENVL_DATAFLASH;
|
|
|
+ else 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_FLASH)
|
|
|
+ return ENVL_FLASH;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
|
|
|
+ return ENVL_MMC;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_NAND)
|
|
|
+ return ENVL_NAND;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_NVRAM)
|
|
|
+ return ENVL_NVRAM;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_REMOTE)
|
|
|
+ return ENVL_REMOTE;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)
|
|
|
+ return ENVL_SPI_FLASH;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
|
|
|
+ return ENVL_UBI;
|
|
|
+ else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
|
|
|
+ return ENVL_NOWHERE;
|
|
|
+ else
|
|
|
+ return ENVL_UNKNOWN;
|
|
|
+}
|
|
|
+
|
|
|
+static struct env_driver *env_driver_lookup_default(void)
|
|
|
+{
|
|
|
+ enum env_location loc = env_get_default_location();
|
|
|
+ struct env_driver *drv;
|
|
|
+
|
|
|
+ drv = env_driver_lookup(loc);
|
|
|
+ if (!drv) {
|
|
|
+ debug("%s: No environment driver for location %d\n", __func__,
|
|
|
+ loc);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return drv;
|
|
|
+}
|
|
|
+
|
|
|
+int env_get_char_new(int index)
|
|
|
+{
|
|
|
+ struct env_driver *drv = env_driver_lookup_default();
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int env_load(void)
|
|
|
+{
|
|
|
+ struct env_driver *drv = env_driver_lookup_default();
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int env_save(void)
|
|
|
+{
|
|
|
+ struct env_driver *drv = env_driver_lookup_default();
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int env_init_new(void)
|
|
|
+{
|
|
|
+ struct env_driver *drv = env_driver_lookup_default();
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!drv)
|
|
|
+ return -ENODEV;
|
|
|
+ if (!drv->init)
|
|
|
+ return -ENOSYS;
|
|
|
+ ret = drv->init();
|
|
|
+ if (ret) {
|
|
|
+ debug("%s: Environment failed to init (err=%d)\n", __func__,
|
|
|
+ ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|