]> Git Repo - J-u-boot.git/blob - boot/bootstd-uclass.c
Merge patch series "clk: mediatek: add OPs to support OF_UPSTREAM"
[J-u-boot.git] / boot / bootstd-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Uclass implementation for standard boot
4  *
5  * Copyright 2021 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #include <bootflow.h>
10 #include <bootstd.h>
11 #include <dm.h>
12 #include <env.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <dm/device-internal.h>
16 #include <dm/lists.h>
17 #include <dm/read.h>
18 #include <dm/uclass-internal.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 /* These are used if filename-prefixes is not present */
23 const char *const default_prefixes[] = {"/", "/boot/", NULL};
24
25 static int bootstd_of_to_plat(struct udevice *dev)
26 {
27         struct bootstd_priv *priv = dev_get_priv(dev);
28         int ret;
29
30         if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
31                 /* Don't check errors since livetree and flattree are different */
32                 ret = dev_read_string_list(dev, "filename-prefixes",
33                                            &priv->prefixes);
34                 dev_read_string_list(dev, "bootdev-order",
35                                      &priv->bootdev_order);
36
37                 priv->theme = ofnode_find_subnode(dev_ofnode(dev), "theme");
38         }
39
40         return 0;
41 }
42
43 static void bootstd_clear_glob_(struct bootstd_priv *priv)
44 {
45         while (!list_empty(&priv->glob_head)) {
46                 struct bootflow *bflow;
47
48                 bflow = list_first_entry(&priv->glob_head, struct bootflow,
49                                          glob_node);
50                 bootflow_remove(bflow);
51         }
52 }
53
54 void bootstd_clear_glob(void)
55 {
56         struct bootstd_priv *std;
57
58         if (bootstd_get_priv(&std))
59                 return;
60
61         bootstd_clear_glob_(std);
62 }
63
64 static int bootstd_remove(struct udevice *dev)
65 {
66         struct bootstd_priv *priv = dev_get_priv(dev);
67
68         free(priv->prefixes);
69         free(priv->bootdev_order);
70         bootstd_clear_glob_(priv);
71
72         return 0;
73 }
74
75 const char *const *const bootstd_get_bootdev_order(struct udevice *dev,
76                                                    bool *okp)
77 {
78         struct bootstd_priv *std = dev_get_priv(dev);
79         const char *targets = env_get("boot_targets");
80
81         *okp = true;
82         log_debug("- targets %s %p\n", targets, std->bootdev_order);
83         if (targets && *targets) {
84                 str_free_list(std->env_order);
85                 std->env_order = str_to_list(targets);
86                 if (!std->env_order) {
87                         *okp = false;
88                         return NULL;
89                 }
90                 return std->env_order;
91         }
92
93         return std->bootdev_order;
94 }
95
96 const char *const *const bootstd_get_prefixes(struct udevice *dev)
97 {
98         struct bootstd_priv *std = dev_get_priv(dev);
99
100         return std->prefixes ? std->prefixes : default_prefixes;
101 }
102
103 int bootstd_get_priv(struct bootstd_priv **stdp)
104 {
105         struct udevice *dev;
106         int ret;
107
108         ret = uclass_first_device_err(UCLASS_BOOTSTD, &dev);
109         if (ret)
110                 return ret;
111         *stdp = dev_get_priv(dev);
112
113         return 0;
114 }
115
116 static int bootstd_probe(struct udevice *dev)
117 {
118         struct bootstd_priv *std = dev_get_priv(dev);
119
120         INIT_LIST_HEAD(&std->glob_head);
121
122         return 0;
123 }
124
125 /* For now, bind the boormethod device if none are found in the devicetree */
126 int dm_scan_other(bool pre_reloc_only)
127 {
128         struct driver *drv = ll_entry_start(struct driver, driver);
129         const int n_ents = ll_entry_count(struct driver, driver);
130         struct udevice *dev, *bootstd;
131         int i, ret;
132
133         /* These are not needed before relocation */
134         if (!(gd->flags & GD_FLG_RELOC))
135                 return 0;
136
137         /* Create a bootstd device if needed */
138         uclass_find_first_device(UCLASS_BOOTSTD, &bootstd);
139         if (!bootstd) {
140                 ret = device_bind_driver(gd->dm_root, "bootstd_drv", "bootstd",
141                                          &bootstd);
142                 if (ret)
143                         return log_msg_ret("bootstd", ret);
144         }
145
146         /* If there are no bootmeth devices, create them */
147         uclass_find_first_device(UCLASS_BOOTMETH, &dev);
148         if (dev)
149                 return 0;
150
151         for (i = 0; i < n_ents; i++, drv++) {
152                 if (drv->id == UCLASS_BOOTMETH) {
153                         const char *name = drv->name;
154
155                         if (!strncmp("bootmeth_", name, 9))
156                                 name += 9;
157                         ret = device_bind(bootstd, drv, name, 0, ofnode_null(),
158                                           &dev);
159                         if (ret)
160                                 return log_msg_ret("meth", ret);
161                 }
162         }
163
164         return 0;
165 }
166
167 static const struct udevice_id bootstd_ids[] = {
168         { .compatible = "u-boot,boot-std" },
169         { }
170 };
171
172 U_BOOT_DRIVER(bootstd_drv) = {
173         .id             = UCLASS_BOOTSTD,
174         .name           = "bootstd_drv",
175         .of_to_plat     = bootstd_of_to_plat,
176         .probe          = bootstd_probe,
177         .remove         = bootstd_remove,
178         .of_match       = bootstd_ids,
179         .priv_auto      = sizeof(struct bootstd_priv),
180 };
181
182 UCLASS_DRIVER(bootstd) = {
183         .id             = UCLASS_BOOTSTD,
184         .name           = "bootstd",
185 #if CONFIG_IS_ENABLED(OF_REAL)
186         .post_bind      = dm_scan_fdt_dev,
187 #endif
188 };
This page took 0.036183 seconds and 4 git commands to generate.