| /* |
| * 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; |
| } |
| |
| 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(int index) |
| { |
| struct env_driver *drv = env_driver_lookup_default(); |
| int ret; |
| |
| 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); |
| } |
| |
| 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; |
| ret = drv->load(); |
| 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(void) |
| { |
| struct env_driver *drv = env_driver_lookup_default(); |
| int ret = -ENOENT; |
| |
| if (!drv) |
| return -ENODEV; |
| if (drv->init) |
| ret = drv->init(); |
| if (ret == -ENOENT) { |
| gd->env_addr = (ulong)&default_environment[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; |
| } |