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_new(int index) 73 { 74 struct env_driver *drv = env_driver_lookup_default(); 75 int ret; 76 77 if (!drv) 78 return -ENODEV; 79 if (!drv->get_char) 80 return *(uchar *)(gd->env_addr + index); 81 ret = drv->get_char(index); 82 if (ret < 0) { 83 debug("%s: Environment failed to load (err=%d)\n", 84 __func__, ret); 85 } 86 87 return ret; 88 } 89 90 int env_load(void) 91 { 92 struct env_driver *drv = env_driver_lookup_default(); 93 int ret = 0; 94 95 if (!drv) 96 return -ENODEV; 97 if (!drv->load) 98 return 0; 99 drv->load(); /* TODO(sjg@chromium.org): Make this return an error */ 100 if (ret) { 101 debug("%s: Environment failed to load (err=%d)\n", __func__, 102 ret); 103 return ret; 104 } 105 106 return 0; 107 } 108 109 int env_save(void) 110 { 111 struct env_driver *drv = env_driver_lookup_default(); 112 int ret; 113 114 if (!drv) 115 return -ENODEV; 116 if (!drv->save) 117 return -ENOSYS; 118 ret = drv->save(); 119 if (ret) { 120 debug("%s: Environment failed to save (err=%d)\n", __func__, 121 ret); 122 return ret; 123 } 124 125 return 0; 126 } 127 128 int env_init_new(void) 129 { 130 struct env_driver *drv = env_driver_lookup_default(); 131 int ret = -ENOENT; 132 133 if (!drv) 134 return -ENODEV; 135 if (drv->init) 136 ret = drv->init(); 137 if (ret == -ENOENT) { 138 gd->env_addr = (ulong)&default_environment[0]; 139 gd->env_valid = 0; 140 141 return 0; 142 } else if (ret) { 143 debug("%s: Environment failed to init (err=%d)\n", __func__, 144 ret); 145 return ret; 146 } 147 148 return 0; 149 } 150 151 unsigned char env_get_char_spec(int index) 152 { 153 return *(uchar *)(gd->env_addr + index); 154 } 155 156 void env_relocate_spec(void) 157 { 158 env_load(); 159 } 160 161 int saveenv(void) 162 { 163 return env_save(); 164 } 165 166 int env_init(void) 167 { 168 return env_init_new(); 169 } 170