]> git.ipfire.org Git - people/ms/u-boot.git/blame - env/env.c
env: Make it explicit where we're loading our environment from
[people/ms/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
3574ba01 149 printf("Loading Environment from %s... ", drv->name);
8a3a7e22 150 ret = drv->load();
3574ba01
MR
151 if (ret)
152 printf("Failed (%d)\n", ret);
153 else
154 printf("OK\n");
155
8a3a7e22
MR
156 if (!ret)
157 return 0;
c9d728dd
SG
158 }
159
8a3a7e22 160 return -ENODEV;
c9d728dd
SG
161}
162
163int env_save(void)
164{
8a3a7e22
MR
165 struct env_driver *drv;
166 int prio;
c9d728dd 167
8a3a7e22
MR
168 for (prio = 0; (drv = env_driver_lookup(ENVOP_SAVE, prio)); prio++) {
169 int ret;
170
171 if (!drv->save)
172 continue;
173
9efac3c8 174 printf("Saving Environment to %s... ", drv->name);
8a3a7e22 175 ret = drv->save();
3574ba01
MR
176 if (ret)
177 printf("Failed (%d)\n", ret);
178 else
179 printf("OK\n");
180
8a3a7e22
MR
181 if (!ret)
182 return 0;
c9d728dd
SG
183 }
184
8a3a7e22 185 return -ENODEV;
c9d728dd
SG
186}
187
6eeae424 188int env_init(void)
c9d728dd 189{
8a3a7e22 190 struct env_driver *drv;
7938822a 191 int ret = -ENOENT;
8a3a7e22
MR
192 int prio;
193
194 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
195 if (!drv->init)
196 continue;
c9d728dd 197
7938822a 198 ret = drv->init();
8a3a7e22
MR
199 if (!ret)
200 return 0;
201
202 debug("%s: Environment %s failed to init (err=%d)\n", __func__,
203 drv->name, ret);
204 }
205
206 if (!prio)
207 return -ENODEV;
208
7938822a
SG
209 if (ret == -ENOENT) {
210 gd->env_addr = (ulong)&default_environment[0];
eeba55cb 211 gd->env_valid = ENV_VALID;
7938822a
SG
212
213 return 0;
c9d728dd
SG
214 }
215
8a3a7e22 216 return ret;
c9d728dd 217}