]> git.ipfire.org Git - u-boot.git/blame - env/env.c
env: Pass additional parameters to the env lookup function
[u-boot.git] / env / env.c
CommitLineData
c9d728dd
SG
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
11DECLARE_GLOBAL_DATA_PTR;
12
52746c43 13static struct env_driver *_env_driver_lookup(enum env_location loc)
c9d728dd
SG
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
8a3a7e22
MR
29/**
30 * env_get_location() - Returns the best env location for a board
31 * @op: operations performed on the environment
32 * @prio: priority between the multiple environments, 0 being the
33 * highest priority
34 *
35 * This will return the preferred environment for the given priority.
36 *
37 * All implementations are free to use the operation, the priority and
38 * any other data relevant to their choice, but must take into account
39 * the fact that the lowest prority (0) is the most important location
40 * in the system. The following locations should be returned by order
41 * of descending priorities, from the highest to the lowest priority.
42 *
43 * Returns:
44 * an enum env_location value on success, a negative error code otherwise
45 */
46static enum env_location env_get_location(enum env_operation op, int prio)
c9d728dd 47{
8a3a7e22
MR
48 /*
49 * We support a single environment, so any environment asked
50 * with a priority that is not zero is out of our supported
51 * bounds.
52 */
53 if (prio >= 1)
54 return ENVL_UNKNOWN;
55
7b7341d7 56 if IS_ENABLED(CONFIG_ENV_IS_IN_EEPROM)
c9d728dd
SG
57 return ENVL_EEPROM;
58 else if IS_ENABLED(CONFIG_ENV_IS_IN_FAT)
59 return ENVL_FAT;
1087a794
JRO
60 else if IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)
61 return ENVL_EXT4;
c9d728dd
SG
62 else if IS_ENABLED(CONFIG_ENV_IS_IN_FLASH)
63 return ENVL_FLASH;
64 else if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
65 return ENVL_MMC;
66 else if IS_ENABLED(CONFIG_ENV_IS_IN_NAND)
67 return ENVL_NAND;
68 else if IS_ENABLED(CONFIG_ENV_IS_IN_NVRAM)
69 return ENVL_NVRAM;
70 else if IS_ENABLED(CONFIG_ENV_IS_IN_REMOTE)
71 return ENVL_REMOTE;
72 else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)
73 return ENVL_SPI_FLASH;
74 else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
75 return ENVL_UBI;
76 else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
77 return ENVL_NOWHERE;
78 else
79 return ENVL_UNKNOWN;
80}
81
8a3a7e22
MR
82
83/**
84 * env_driver_lookup() - Finds the most suited environment location
85 * @op: operations performed on the environment
86 * @prio: priority between the multiple environments, 0 being the
87 * highest priority
88 *
89 * This will try to find the available environment with the highest
90 * priority in the system.
91 *
92 * Returns:
93 * NULL on error, a pointer to a struct env_driver otherwise
94 */
95static struct env_driver *env_driver_lookup(enum env_operation op, int prio)
c9d728dd 96{
8a3a7e22 97 enum env_location loc = env_get_location(op, prio);
c9d728dd
SG
98 struct env_driver *drv;
99
8a3a7e22
MR
100 if (loc == ENVL_UNKNOWN)
101 return NULL;
102
52746c43 103 drv = _env_driver_lookup(loc);
c9d728dd
SG
104 if (!drv) {
105 debug("%s: No environment driver for location %d\n", __func__,
106 loc);
107 return NULL;
108 }
109
110 return drv;
111}
112
a69d0f60 113int env_get_char(int index)
c9d728dd 114{
8a3a7e22
MR
115 struct env_driver *drv;
116 int prio;
c9d728dd 117
2d7cb5b4 118 if (gd->env_valid == ENV_INVALID)
a69d0f60 119 return default_environment[index];
8a3a7e22
MR
120
121 for (prio = 0; (drv = env_driver_lookup(ENVOP_GET_CHAR, prio)); prio++) {
122 int ret;
123
124 if (!drv->get_char)
125 continue;
126
127 ret = drv->get_char(index);
128 if (!ret)
129 return 0;
130
131 debug("%s: Environment %s failed to load (err=%d)\n", __func__,
132 drv->name, ret);
c9d728dd
SG
133 }
134
8a3a7e22 135 return -ENODEV;
c9d728dd
SG
136}
137
138int env_load(void)
139{
8a3a7e22
MR
140 struct env_driver *drv;
141 int prio;
c9d728dd 142
8a3a7e22
MR
143 for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) {
144 int ret;
145
146 if (!drv->load)
147 continue;
148
149 ret = drv->load();
150 if (!ret)
151 return 0;
152
153 debug("%s: Environment %s failed to load (err=%d)\n", __func__,
154 drv->name, ret);
c9d728dd
SG
155 }
156
8a3a7e22 157 return -ENODEV;
c9d728dd
SG
158}
159
160int env_save(void)
161{
8a3a7e22
MR
162 struct env_driver *drv;
163 int prio;
c9d728dd 164
8a3a7e22
MR
165 for (prio = 0; (drv = env_driver_lookup(ENVOP_SAVE, prio)); prio++) {
166 int ret;
167
168 if (!drv->save)
169 continue;
170
171 printf("Saving Environment to %s...\n", drv->name);
172 ret = drv->save();
173 if (!ret)
174 return 0;
175
176 debug("%s: Environment %s failed to save (err=%d)\n", __func__,
177 drv->name, ret);
c9d728dd
SG
178 }
179
8a3a7e22 180 return -ENODEV;
c9d728dd
SG
181}
182
6eeae424 183int env_init(void)
c9d728dd 184{
8a3a7e22 185 struct env_driver *drv;
7938822a 186 int ret = -ENOENT;
8a3a7e22
MR
187 int prio;
188
189 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
190 if (!drv->init)
191 continue;
c9d728dd 192
7938822a 193 ret = drv->init();
8a3a7e22
MR
194 if (!ret)
195 return 0;
196
197 debug("%s: Environment %s failed to init (err=%d)\n", __func__,
198 drv->name, ret);
199 }
200
201 if (!prio)
202 return -ENODEV;
203
7938822a
SG
204 if (ret == -ENOENT) {
205 gd->env_addr = (ulong)&default_environment[0];
eeba55cb 206 gd->env_valid = ENV_VALID;
7938822a
SG
207
208 return 0;
c9d728dd
SG
209 }
210
8a3a7e22 211 return ret;
c9d728dd 212}