]> Git Repo - J-u-boot.git/blob - boot/bootstd-uclass.c
Merge branch '2022-01-16-bootstd-updates'
[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 <common.h>
10 #include <bootflow.h>
11 #include <bootstd.h>
12 #include <dm.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 {
77         struct bootstd_priv *std = dev_get_priv(dev);
78
79         return std->bootdev_order;
80 }
81
82 const char *const *const bootstd_get_prefixes(struct udevice *dev)
83 {
84         struct bootstd_priv *std = dev_get_priv(dev);
85
86         return std->prefixes ? std->prefixes : default_prefixes;
87 }
88
89 int bootstd_get_priv(struct bootstd_priv **stdp)
90 {
91         struct udevice *dev;
92         int ret;
93
94         ret = uclass_first_device_err(UCLASS_BOOTSTD, &dev);
95         if (ret)
96                 return ret;
97         *stdp = dev_get_priv(dev);
98
99         return 0;
100 }
101
102 static int bootstd_probe(struct udevice *dev)
103 {
104         struct bootstd_priv *std = dev_get_priv(dev);
105
106         INIT_LIST_HEAD(&std->glob_head);
107
108         return 0;
109 }
110
111 /* For now, bind the boormethod device if none are found in the devicetree */
112 int dm_scan_other(bool pre_reloc_only)
113 {
114         struct driver *drv = ll_entry_start(struct driver, driver);
115         const int n_ents = ll_entry_count(struct driver, driver);
116         struct udevice *dev, *bootstd;
117         int i, ret;
118
119         /* These are not needed before relocation */
120         if (!(gd->flags & GD_FLG_RELOC))
121                 return 0;
122
123         /* Create a bootstd device if needed */
124         uclass_find_first_device(UCLASS_BOOTSTD, &bootstd);
125         if (!bootstd) {
126                 ret = device_bind_driver(gd->dm_root, "bootstd_drv", "bootstd",
127                                          &bootstd);
128                 if (ret)
129                         return log_msg_ret("bootstd", ret);
130         }
131
132         /* If there are no bootmeth devices, create them */
133         uclass_find_first_device(UCLASS_BOOTMETH, &dev);
134         if (dev)
135                 return 0;
136
137         for (i = 0; i < n_ents; i++, drv++) {
138                 if (drv->id == UCLASS_BOOTMETH) {
139                         const char *name = drv->name;
140
141                         if (!strncmp("bootmeth_", name, 9))
142                                 name += 9;
143                         ret = device_bind(bootstd, drv, name, 0, ofnode_null(),
144                                           &dev);
145                         if (ret)
146                                 return log_msg_ret("meth", ret);
147                 }
148         }
149
150         return 0;
151 }
152
153 static const struct udevice_id bootstd_ids[] = {
154         { .compatible = "u-boot,boot-std" },
155         { }
156 };
157
158 U_BOOT_DRIVER(bootstd_drv) = {
159         .id             = UCLASS_BOOTSTD,
160         .name           = "bootstd_drv",
161         .of_to_plat     = bootstd_of_to_plat,
162         .probe          = bootstd_probe,
163         .remove         = bootstd_remove,
164         .of_match       = bootstd_ids,
165         .priv_auto      = sizeof(struct bootstd_priv),
166 };
167
168 UCLASS_DRIVER(bootstd) = {
169         .id             = UCLASS_BOOTSTD,
170         .name           = "bootstd",
171 #if CONFIG_IS_ENABLED(OF_REAL)
172         .post_bind      = dm_scan_fdt_dev,
173 #endif
174 };
This page took 0.034819 seconds and 4 git commands to generate.