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