config: enable TPS65219 for am64x_evm_a53 boards
[platform/kernel/u-boot.git] / boot / bootflow.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2021 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #define LOG_CATEGORY UCLASS_BOOTSTD
8
9 #include <common.h>
10 #include <bootdev.h>
11 #include <bootflow.h>
12 #include <bootmeth.h>
13 #include <bootstd.h>
14 #include <dm.h>
15 #include <malloc.h>
16 #include <dm/device-internal.h>
17 #include <dm/uclass-internal.h>
18
19 /* error codes used to signal running out of things */
20 enum {
21         BF_NO_MORE_PARTS        = -ESHUTDOWN,
22         BF_NO_MORE_DEVICES      = -ENODEV,
23 };
24
25 /**
26  * bootflow_state - name for each state
27  *
28  * See enum bootflow_state_t for what each of these means
29  */
30 static const char *const bootflow_state[BOOTFLOWST_COUNT] = {
31         "base",
32         "media",
33         "part",
34         "fs",
35         "file",
36         "ready",
37 };
38
39 const char *bootflow_state_get_name(enum bootflow_state_t state)
40 {
41         /* This doesn't need to be a useful name, since it will never occur */
42         if (state < 0 || state >= BOOTFLOWST_COUNT)
43                 return "?";
44
45         return bootflow_state[state];
46 }
47
48 int bootflow_first_glob(struct bootflow **bflowp)
49 {
50         struct bootstd_priv *std;
51         int ret;
52
53         ret = bootstd_get_priv(&std);
54         if (ret)
55                 return ret;
56
57         if (list_empty(&std->glob_head))
58                 return -ENOENT;
59
60         *bflowp = list_first_entry(&std->glob_head, struct bootflow,
61                                    glob_node);
62
63         return 0;
64 }
65
66 int bootflow_next_glob(struct bootflow **bflowp)
67 {
68         struct bootstd_priv *std;
69         struct bootflow *bflow = *bflowp;
70         int ret;
71
72         ret = bootstd_get_priv(&std);
73         if (ret)
74                 return ret;
75
76         *bflowp = NULL;
77
78         if (list_is_last(&bflow->glob_node, &std->glob_head))
79                 return -ENOENT;
80
81         *bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node);
82
83         return 0;
84 }
85
86 void bootflow_iter_init(struct bootflow_iter *iter, int flags)
87 {
88         memset(iter, '\0', sizeof(*iter));
89         iter->flags = flags;
90 }
91
92 void bootflow_iter_uninit(struct bootflow_iter *iter)
93 {
94         free(iter->dev_order);
95         free(iter->method_order);
96 }
97
98 int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
99                                 const struct udevice *bmeth)
100 {
101         /* We only support disabling the current bootmeth */
102         if (bmeth != iter->method || iter->cur_method >= iter->num_methods ||
103             iter->method_order[iter->cur_method] != bmeth)
104                 return -EINVAL;
105
106         memmove(&iter->method_order[iter->cur_method],
107                 &iter->method_order[iter->cur_method + 1],
108                 (iter->num_methods - iter->cur_method - 1) * sizeof(void *));
109
110         iter->num_methods--;
111
112         return 0;
113 }
114
115 static void bootflow_iter_set_dev(struct bootflow_iter *iter,
116                                   struct udevice *dev)
117 {
118         iter->dev = dev;
119         if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
120             BOOTFLOWF_SHOW) {
121                 if (dev)
122                         printf("Scanning bootdev '%s':\n", dev->name);
123                 else
124                         printf("No more bootdevs\n");
125         }
126 }
127
128 /**
129  * iter_incr() - Move to the next item (method, part, bootdev)
130  *
131  * Return: 0 if OK, BF_NO_MORE_DEVICES if there are no more bootdevs
132  */
133 static int iter_incr(struct bootflow_iter *iter)
134 {
135         struct udevice *dev;
136         int ret;
137
138         if (iter->err == BF_NO_MORE_DEVICES)
139                 return BF_NO_MORE_DEVICES;
140
141         if (iter->err != BF_NO_MORE_PARTS) {
142                 /* Get the next boothmethod */
143                 if (++iter->cur_method < iter->num_methods) {
144                         iter->method = iter->method_order[iter->cur_method];
145                         return 0;
146                 }
147         }
148
149         /* No more bootmeths; start at the first one, and... */
150         iter->cur_method = 0;
151         iter->method = iter->method_order[iter->cur_method];
152
153         if (iter->err != BF_NO_MORE_PARTS) {
154                 /* ...select next partition  */
155                 if (++iter->part <= iter->max_part)
156                         return 0;
157         }
158
159         /* No more partitions; start at the first one and...*/
160         iter->part = 0;
161
162         /*
163          * Note: as far as we know, there is no partition table on the next
164          * bootdev, so set max_part to 0 until we discover otherwise. See
165          * bootdev_find_in_blk() for where this is set.
166          */
167         iter->max_part = 0;
168
169         /* ...select next bootdev */
170         if (iter->flags & BOOTFLOWF_SINGLE_DEV) {
171                 ret = -ENOENT;
172         } else if (++iter->cur_dev == iter->num_devs) {
173                 ret = -ENOENT;
174                 bootflow_iter_set_dev(iter, NULL);
175         } else {
176                 dev = iter->dev_order[iter->cur_dev];
177                 ret = device_probe(dev);
178                 if (!log_msg_ret("probe", ret))
179                         bootflow_iter_set_dev(iter, dev);
180         }
181
182         /* if there are no more bootdevs, give up */
183         if (ret)
184                 return log_msg_ret("incr", BF_NO_MORE_DEVICES);
185
186         return 0;
187 }
188
189 /**
190  * bootflow_check() - Check if a bootflow can be obtained
191  *
192  * @iter: Provides part, bootmeth to use
193  * @bflow: Bootflow to update on success
194  * Return: 0 if OK, -ENOSYS if there is no bootflow support on this device,
195  *      BF_NO_MORE_PARTS if there are no more partitions on bootdev
196  */
197 static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
198 {
199         struct udevice *dev;
200         int ret;
201
202         dev = iter->dev;
203         ret = bootdev_get_bootflow(dev, iter, bflow);
204
205         /* If we got a valid bootflow, return it */
206         if (!ret) {
207                 log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n",
208                           dev->name, iter->part, iter->method->name);
209                 return 0;
210         }
211
212         /* Unless there is nothing more to try, move to the next device */
213         else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
214                 log_debug("Bootdevice '%s' part %d method '%s': Error %d\n",
215                           dev->name, iter->part, iter->method->name, ret);
216                 /*
217                  * For 'all' we return all bootflows, even
218                  * those with errors
219                  */
220                 if (iter->flags & BOOTFLOWF_ALL)
221                         return log_msg_ret("all", ret);
222         }
223         if (ret)
224                 return log_msg_ret("check", ret);
225
226         return 0;
227 }
228
229 int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
230                           int flags, struct bootflow *bflow)
231 {
232         int ret;
233
234         bootflow_iter_init(iter, flags);
235
236         ret = bootdev_setup_iter_order(iter, &dev);
237         if (ret)
238                 return log_msg_ret("obdev", -ENODEV);
239         bootflow_iter_set_dev(iter, dev);
240
241         ret = bootmeth_setup_iter_order(iter);
242         if (ret)
243                 return log_msg_ret("obmeth", -ENODEV);
244
245         /* Find the first bootmeth (there must be at least one!) */
246         iter->method = iter->method_order[iter->cur_method];
247
248         ret = bootflow_check(iter, bflow);
249         if (ret) {
250                 if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
251                         if (iter->flags & BOOTFLOWF_ALL)
252                                 return log_msg_ret("all", ret);
253                 }
254                 iter->err = ret;
255                 ret = bootflow_scan_next(iter, bflow);
256                 if (ret)
257                         return log_msg_ret("get", ret);
258         }
259
260         return 0;
261 }
262
263 int bootflow_scan_first(struct bootflow_iter *iter, int flags,
264                         struct bootflow *bflow)
265 {
266         int ret;
267
268         ret = bootflow_scan_bootdev(NULL, iter, flags, bflow);
269         if (ret)
270                 return log_msg_ret("start", ret);
271
272         return 0;
273 }
274
275 int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow)
276 {
277         int ret;
278
279         do {
280                 ret = iter_incr(iter);
281                 if (ret == BF_NO_MORE_DEVICES)
282                         return log_msg_ret("done", ret);
283
284                 if (!ret) {
285                         ret = bootflow_check(iter, bflow);
286                         if (!ret)
287                                 return 0;
288                         iter->err = ret;
289                         if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
290                                 if (iter->flags & BOOTFLOWF_ALL)
291                                         return log_msg_ret("all", ret);
292                         }
293                 } else {
294                         iter->err = ret;
295                 }
296
297         } while (1);
298 }
299
300 void bootflow_free(struct bootflow *bflow)
301 {
302         free(bflow->name);
303         free(bflow->subdir);
304         free(bflow->fname);
305         free(bflow->buf);
306 }
307
308 void bootflow_remove(struct bootflow *bflow)
309 {
310         list_del(&bflow->bm_node);
311         list_del(&bflow->glob_node);
312
313         bootflow_free(bflow);
314         free(bflow);
315 }
316
317 int bootflow_boot(struct bootflow *bflow)
318 {
319         int ret;
320
321         if (bflow->state != BOOTFLOWST_READY)
322                 return log_msg_ret("load", -EPROTO);
323
324         ret = bootmeth_boot(bflow->method, bflow);
325         if (ret)
326                 return log_msg_ret("boot", ret);
327
328         /*
329          * internal error, should not get here since we should have booted
330          * something or returned an error
331          */
332
333         return log_msg_ret("end", -EFAULT);
334 }
335
336 int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow)
337 {
338         int ret;
339
340         printf("** Booting bootflow '%s' with %s\n", bflow->name,
341                bflow->method->name);
342         ret = bootflow_boot(bflow);
343         if (!IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
344                 printf("Boot failed (err=%d)\n", ret);
345                 return ret;
346         }
347
348         switch (ret) {
349         case -EPROTO:
350                 printf("Bootflow not loaded (state '%s')\n",
351                        bootflow_state_get_name(bflow->state));
352                 break;
353         case -ENOSYS:
354                 printf("Boot method '%s' not supported\n", bflow->method->name);
355                 break;
356         case -ENOTSUPP:
357                 /* Disable this bootflow for this iteration */
358                 if (iter) {
359                         int ret2;
360
361                         ret2 = bootflow_iter_drop_bootmeth(iter, bflow->method);
362                         if (!ret2) {
363                                 printf("Boot method '%s' failed and will not be retried\n",
364                                        bflow->method->name);
365                         }
366                 }
367
368                 break;
369         default:
370                 printf("Boot failed (err=%d)\n", ret);
371                 break;
372         }
373
374         return ret;
375 }
376
377 int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter)
378 {
379         const struct udevice *media = dev_get_parent(iter->dev);
380         enum uclass_id id = device_get_uclass_id(media);
381
382         log_debug("uclass %d: %s\n", id, uclass_get_name(id));
383         if (id != UCLASS_ETH && id != UCLASS_BOOTSTD)
384                 return 0;
385
386         return -ENOTSUPP;
387 }
388
389 int bootflow_iter_uses_network(const struct bootflow_iter *iter)
390 {
391         const struct udevice *media = dev_get_parent(iter->dev);
392         enum uclass_id id = device_get_uclass_id(media);
393
394         log_debug("uclass %d: %s\n", id, uclass_get_name(id));
395         if (id == UCLASS_ETH)
396                 return 0;
397
398         return -ENOTSUPP;
399 }
400
401 int bootflow_iter_uses_system(const struct bootflow_iter *iter)
402 {
403         const struct udevice *media = dev_get_parent(iter->dev);
404         enum uclass_id id = device_get_uclass_id(media);
405
406         log_debug("uclass %d: %s\n", id, uclass_get_name(id));
407         if (id == UCLASS_BOOTSTD)
408                 return 0;
409
410         return -ENOTSUPP;
411 }