1 /* 2 * Copyright (C) 2017 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <environment.h> 10 11 DECLARE_GLOBAL_DATA_PTR; 12 13 static struct env_driver *env_driver_lookup(enum env_location loc) 14 { 15 struct env_driver *drv; 16 const int n_ents = ll_entry_count(struct env_driver, env_driver); 17 struct env_driver *entry; 18 19 drv = ll_entry_start(struct env_driver, env_driver); 20 for (entry = drv; entry != drv + n_ents; entry++) { 21 if (loc == entry->location) 22 return entry; 23 } 24 25 /* Not found */ 26 return NULL; 27 } 28 29 static enum env_location env_get_default_location(void) 30 { 31 if IS_ENABLED(CONFIG_ENV_IS_IN_DATAFLASH) 32 return ENVL_DATAFLASH; 33 else if IS_ENABLED(CONFIG_ENV_IS_IN_EEPROM) 34 return ENVL_EEPROM; 35 else if IS_ENABLED(CONFIG_ENV_IS_IN_FAT) 36 return ENVL_FAT; 37 else if IS_ENABLED(CONFIG_ENV_IS_IN_FLASH) 38 return ENVL_FLASH; 39 else if IS_ENABLED(CONFIG_ENV_IS_IN_MMC) 40 return ENVL_MMC; 41 else if IS_ENABLED(CONFIG_ENV_IS_IN_NAND) 42 return ENVL_NAND; 43 else if IS_ENABLED(CONFIG_ENV_IS_IN_NVRAM) 44 return ENVL_NVRAM; 45 else if IS_ENABLED(CONFIG_ENV_IS_IN_REMOTE) 46 return ENVL_REMOTE; 47 else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH) 48 return ENVL_SPI_FLASH; 49 else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI) 50 return ENVL_UBI; 51 else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE) 52 return ENVL_NOWHERE; 53 else 54 return ENVL_UNKNOWN; 55 } 56 57 struct env_driver *env_driver_lookup_default(void) 58 { 59 enum env_location loc = env_get_default_location(); 60 struct env_driver *drv; 61 62 drv = env_driver_lookup(loc); 63 if (!drv) { 64 debug("%s: No environment driver for location %d\n", __func__, 65 loc); 66 return NULL; 67 } 68 69 return drv; 70 } 71 72 int env_get_char(int index) 73 { 74 struct env_driver *drv = env_driver_lookup_default(); 75 int ret; 76 77 if (gd->env_valid == ENV_INVALID) 78 return default_environment[index]; 79 if (!drv) 80 return -ENODEV; 81 if (!drv->get_char) 82 return *(uchar *)(gd->env_addr + index); 83 ret = drv->get_char(index); 84 if (ret < 0) { 85 debug("%s: Environment failed to load (err=%d)\n", 86 __func__, ret); 87 } 88 89 return ret; 90 } 91 92 int env_load(void) 93 { 94 struct env_driver *drv = env_driver_lookup_default(); 95 int ret = 0; 96 97 if (!drv) 98 return -ENODEV; 99 if (!drv->load) 100 return 0; 101 ret = drv->load(); 102 if (ret) { 103 debug("%s: Environment failed to load (err=%d)\n", __func__, 104 ret); 105 return ret; 106 } 107 108 return 0; 109 } 110 111 int env_save(void) 112 { 113 struct env_driver *drv = env_driver_lookup_default(); 114 int ret; 115 116 if (!drv) 117 return -ENODEV; 118 if (!drv->save) 119 return -ENOSYS; 120 ret = drv->save(); 121 if (ret) { 122 debug("%s: Environment failed to save (err=%d)\n", __func__, 123 ret); 124 return ret; 125 } 126 127 return 0; 128 } 129 130 int env_init(void) 131 { 132 struct env_driver *drv = env_driver_lookup_default(); 133 int ret = -ENOENT; 134 135 if (!drv) 136 return -ENODEV; 137 if (drv->init) 138 ret = drv->init(); 139 if (ret == -ENOENT) { 140 gd->env_addr = (ulong)&default_environment[0]; 141 gd->env_valid = ENV_VALID; 142 143 return 0; 144 } else if (ret) { 145 debug("%s: Environment failed to init (err=%d)\n", __func__, 146 ret); 147 return ret; 148 } 149 150 return 0; 151 } 152