blob: e3ee778c29d20b7fab46a81c813bbefd8b357096 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass6eef6ea2016-05-01 11:36:03 -06002/*
3 * Copyright (C) 2016 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass6eef6ea2016-05-01 11:36:03 -06005 */
6
7#include <common.h>
Simon Glasse6f6f9e2020-05-10 11:39:58 -06008#include <blk.h>
9#include <part.h>
Simon Glass6eef6ea2016-05-01 11:36:03 -060010#include <linux/err.h>
11
12struct blk_driver *blk_driver_lookup_type(int if_type)
13{
14 struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
15 const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
16 struct blk_driver *entry;
17
18 for (entry = drv; entry != drv + n_ents; entry++) {
19 if (if_type == entry->if_type)
20 return entry;
21 }
22
23 /* Not found */
24 return NULL;
25}
26
27static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
28{
29 struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
30 const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
31 struct blk_driver *entry;
32
33 for (entry = drv; entry != drv + n_ents; entry++) {
34 if (!strcmp(if_typename, entry->if_typename))
35 return entry;
36 }
37
38 /* Not found */
39 return NULL;
40}
41
Simon Glass6faa4ed2017-07-29 11:34:53 -060042const char *blk_get_if_type_name(enum if_type if_type)
43{
44 struct blk_driver *drv = blk_driver_lookup_type(if_type);
45
46 return drv ? drv->if_typename : NULL;
47}
48
Simon Glass6eef6ea2016-05-01 11:36:03 -060049/**
50 * get_desc() - Get the block device descriptor for the given device number
51 *
52 * @drv: Legacy block driver
53 * @devnum: Device number (0 = first)
54 * @descp: Returns block device descriptor on success
55 * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the
56 * driver does not provide a way to find a device, or other -ve on other
57 * error.
58 */
59static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
60{
61 if (drv->desc) {
62 if (devnum < 0 || devnum >= drv->max_devs)
63 return -ENODEV;
64 *descp = &drv->desc[devnum];
65 return 0;
66 }
67 if (!drv->get_dev)
68 return -ENOSYS;
69
70 return drv->get_dev(devnum, descp);
71}
72
Adam Ford1811a922018-02-06 12:43:56 -060073#ifdef CONFIG_HAVE_BLOCK_DEVICE
Simon Glass6eef6ea2016-05-01 11:36:03 -060074int blk_list_part(enum if_type if_type)
75{
76 struct blk_driver *drv;
77 struct blk_desc *desc;
78 int devnum, ok;
79 bool first = true;
80
81 drv = blk_driver_lookup_type(if_type);
82 if (!drv)
83 return -ENOSYS;
84 for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
85 if (get_desc(drv, devnum, &desc))
86 continue;
87 if (desc->part_type != PART_TYPE_UNKNOWN) {
88 ++ok;
89 if (!first)
90 putc('\n');
91 part_print(desc);
92 first = false;
93 }
94 }
95 if (!ok)
96 return -ENODEV;
97
98 return 0;
99}
100
101int blk_print_part_devnum(enum if_type if_type, int devnum)
102{
103 struct blk_driver *drv = blk_driver_lookup_type(if_type);
104 struct blk_desc *desc;
105 int ret;
106
107 if (!drv)
108 return -ENOSYS;
109 ret = get_desc(drv, devnum, &desc);
110 if (ret)
111 return ret;
112 if (desc->type == DEV_TYPE_UNKNOWN)
113 return -ENOENT;
114 part_print(desc);
115
116 return 0;
117}
118
119void blk_list_devices(enum if_type if_type)
120{
121 struct blk_driver *drv = blk_driver_lookup_type(if_type);
122 struct blk_desc *desc;
123 int i;
124
125 if (!drv)
126 return;
127 for (i = 0; i < drv->max_devs; ++i) {
128 if (get_desc(drv, i, &desc))
129 continue;
130 if (desc->type == DEV_TYPE_UNKNOWN)
131 continue; /* list only known devices */
132 printf("Device %d: ", i);
133 dev_print(desc);
134 }
135}
136
137int blk_print_device_num(enum if_type if_type, int devnum)
138{
139 struct blk_driver *drv = blk_driver_lookup_type(if_type);
140 struct blk_desc *desc;
141 int ret;
142
143 if (!drv)
144 return -ENOSYS;
145 ret = get_desc(drv, devnum, &desc);
146 if (ret)
147 return ret;
148 printf("\n%s device %d: ", drv->if_typename, devnum);
149 dev_print(desc);
150
151 return 0;
152}
153
154int blk_show_device(enum if_type if_type, int devnum)
155{
156 struct blk_driver *drv = blk_driver_lookup_type(if_type);
157 struct blk_desc *desc;
158 int ret;
159
160 if (!drv)
161 return -ENOSYS;
162 printf("\nDevice %d: ", devnum);
163 if (devnum >= drv->max_devs) {
164 puts("unknown device\n");
165 return -ENODEV;
166 }
167 ret = get_desc(drv, devnum, &desc);
168 if (ret)
169 return ret;
170 dev_print(desc);
171
172 if (desc->type == DEV_TYPE_UNKNOWN)
173 return -ENOENT;
174
175 return 0;
176}
Adam Ford1811a922018-02-06 12:43:56 -0600177#endif /* CONFIG_HAVE_BLOCK_DEVICE */
Simon Glass6eef6ea2016-05-01 11:36:03 -0600178
179struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
180{
181 struct blk_driver *drv = blk_driver_lookup_type(if_type);
182 struct blk_desc *desc;
183
184 if (!drv)
185 return NULL;
186
187 if (get_desc(drv, devnum, &desc))
188 return NULL;
189
190 return desc;
191}
192
193int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
194{
195 struct blk_driver *drv = blk_driver_lookup_type(desc->if_type);
196
197 if (!drv)
198 return -ENOSYS;
199 if (drv->select_hwpart)
200 return drv->select_hwpart(desc, hwpart);
201
202 return 0;
203}
204
205struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
206{
207 struct blk_driver *drv = blk_driver_lookup_typename(if_typename);
208 struct blk_desc *desc;
209
210 if (!drv)
211 return NULL;
212
213 if (get_desc(drv, devnum, &desc))
214 return NULL;
215
216 return desc;
217}
218
219ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
220 lbaint_t blkcnt, void *buffer)
221{
222 struct blk_driver *drv = blk_driver_lookup_type(if_type);
223 struct blk_desc *desc;
224 ulong n;
225 int ret;
226
227 if (!drv)
228 return -ENOSYS;
229 ret = get_desc(drv, devnum, &desc);
230 if (ret)
231 return ret;
232 n = desc->block_read(desc, start, blkcnt, buffer);
233 if (IS_ERR_VALUE(n))
234 return n;
235
Simon Glass6eef6ea2016-05-01 11:36:03 -0600236 return n;
237}
238
239ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
240 lbaint_t blkcnt, const void *buffer)
241{
242 struct blk_driver *drv = blk_driver_lookup_type(if_type);
243 struct blk_desc *desc;
244 int ret;
245
246 if (!drv)
247 return -ENOSYS;
248 ret = get_desc(drv, devnum, &desc);
249 if (ret)
250 return ret;
251 return desc->block_write(desc, start, blkcnt, buffer);
252}
253
254int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
255{
256 struct blk_driver *drv = blk_driver_lookup_type(if_type);
257 struct blk_desc *desc;
258 int ret;
259
260 if (!drv)
261 return -ENOSYS;
262 ret = get_desc(drv, devnum, &desc);
263 if (ret)
264 return ret;
265 return drv->select_hwpart(desc, hwpart);
266}