blob: f36932183d1f89ee253829f93c91ce0844b5ddea [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass3bf2ab92016-05-01 11:36:03 -06002/*
3 * Copyright (C) 2016 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass3bf2ab92016-05-01 11:36:03 -06005 */
6
Simon Glass655306c2020-05-10 11:39:58 -06007#include <blk.h>
8#include <part.h>
Simon Glass3bf2ab92016-05-01 11:36:03 -06009#include <linux/err.h>
10
Simon Glassfada3f92022-09-17 09:00:09 -060011struct blk_driver *blk_driver_lookup_type(int uclass_id)
Simon Glass3bf2ab92016-05-01 11:36:03 -060012{
13 struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
14 const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
15 struct blk_driver *entry;
16
17 for (entry = drv; entry != drv + n_ents; entry++) {
Simon Glassfada3f92022-09-17 09:00:09 -060018 if (uclass_id == entry->uclass_id)
Simon Glass3bf2ab92016-05-01 11:36:03 -060019 return entry;
20 }
21
22 /* Not found */
23 return NULL;
24}
25
Simon Glassfada3f92022-09-17 09:00:09 -060026static struct blk_driver *blk_driver_lookup_typename(const char *uclass_idname)
Simon Glass3bf2ab92016-05-01 11:36:03 -060027{
28 struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
29 const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
30 struct blk_driver *entry;
31
32 for (entry = drv; entry != drv + n_ents; entry++) {
Simon Glassfada3f92022-09-17 09:00:09 -060033 if (!strcmp(uclass_idname, entry->uclass_idname))
Simon Glass3bf2ab92016-05-01 11:36:03 -060034 return entry;
35 }
36
37 /* Not found */
38 return NULL;
39}
40
Simon Glassfada3f92022-09-17 09:00:09 -060041const char *blk_get_uclass_name(enum uclass_id uclass_id)
Simon Glass85af5a42017-07-29 11:34:53 -060042{
Simon Glassfada3f92022-09-17 09:00:09 -060043 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass85af5a42017-07-29 11:34:53 -060044
Simon Glassfada3f92022-09-17 09:00:09 -060045 return drv ? drv->uclass_idname : NULL;
Simon Glass85af5a42017-07-29 11:34:53 -060046}
47
Simon Glass3bf2ab92016-05-01 11:36:03 -060048/**
49 * get_desc() - Get the block device descriptor for the given device number
50 *
51 * @drv: Legacy block driver
52 * @devnum: Device number (0 = first)
53 * @descp: Returns block device descriptor on success
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010054 * Return: 0 on success, -ENODEV if there is no such device, -ENOSYS if the
Simon Glass3bf2ab92016-05-01 11:36:03 -060055 * driver does not provide a way to find a device, or other -ve on other
56 * error.
57 */
58static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
59{
60 if (drv->desc) {
61 if (devnum < 0 || devnum >= drv->max_devs)
62 return -ENODEV;
63 *descp = &drv->desc[devnum];
64 return 0;
65 }
66 if (!drv->get_dev)
67 return -ENOSYS;
68
69 return drv->get_dev(devnum, descp);
70}
71
Simon Glassfada3f92022-09-17 09:00:09 -060072int blk_list_part(enum uclass_id uclass_id)
Simon Glass3bf2ab92016-05-01 11:36:03 -060073{
74 struct blk_driver *drv;
75 struct blk_desc *desc;
76 int devnum, ok;
77 bool first = true;
78
Simon Glassfada3f92022-09-17 09:00:09 -060079 drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -060080 if (!drv)
81 return -ENOSYS;
82 for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
83 if (get_desc(drv, devnum, &desc))
84 continue;
85 if (desc->part_type != PART_TYPE_UNKNOWN) {
86 ++ok;
87 if (!first)
88 putc('\n');
89 part_print(desc);
90 first = false;
91 }
92 }
93 if (!ok)
94 return -ENODEV;
95
96 return 0;
97}
98
Simon Glassfada3f92022-09-17 09:00:09 -060099int blk_print_part_devnum(enum uclass_id uclass_id, int devnum)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600100{
Simon Glassfada3f92022-09-17 09:00:09 -0600101 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600102 struct blk_desc *desc;
103 int ret;
104
105 if (!drv)
106 return -ENOSYS;
107 ret = get_desc(drv, devnum, &desc);
108 if (ret)
109 return ret;
110 if (desc->type == DEV_TYPE_UNKNOWN)
111 return -ENOENT;
112 part_print(desc);
113
114 return 0;
115}
116
Simon Glassfada3f92022-09-17 09:00:09 -0600117void blk_list_devices(enum uclass_id uclass_id)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600118{
Simon Glassfada3f92022-09-17 09:00:09 -0600119 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600120 struct blk_desc *desc;
121 int i;
122
123 if (!drv)
124 return;
125 for (i = 0; i < drv->max_devs; ++i) {
126 if (get_desc(drv, i, &desc))
127 continue;
128 if (desc->type == DEV_TYPE_UNKNOWN)
129 continue; /* list only known devices */
130 printf("Device %d: ", i);
131 dev_print(desc);
132 }
133}
134
Simon Glassfada3f92022-09-17 09:00:09 -0600135int blk_print_device_num(enum uclass_id uclass_id, int devnum)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600136{
Simon Glassfada3f92022-09-17 09:00:09 -0600137 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600138 struct blk_desc *desc;
139 int ret;
140
141 if (!drv)
142 return -ENOSYS;
143 ret = get_desc(drv, devnum, &desc);
144 if (ret)
145 return ret;
Simon Glassfada3f92022-09-17 09:00:09 -0600146 printf("\n%s device %d: ", drv->uclass_idname, devnum);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600147 dev_print(desc);
148
149 return 0;
150}
151
Simon Glassfada3f92022-09-17 09:00:09 -0600152int blk_show_device(enum uclass_id uclass_id, int devnum)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600153{
Simon Glassfada3f92022-09-17 09:00:09 -0600154 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600155 struct blk_desc *desc;
156 int ret;
157
158 if (!drv)
159 return -ENOSYS;
160 printf("\nDevice %d: ", devnum);
161 if (devnum >= drv->max_devs) {
162 puts("unknown device\n");
163 return -ENODEV;
164 }
165 ret = get_desc(drv, devnum, &desc);
166 if (ret)
167 return ret;
168 dev_print(desc);
169
170 if (desc->type == DEV_TYPE_UNKNOWN)
171 return -ENOENT;
172
173 return 0;
174}
Simon Glass3bf2ab92016-05-01 11:36:03 -0600175
Simon Glassfada3f92022-09-17 09:00:09 -0600176struct blk_desc *blk_get_devnum_by_uclass_id(enum uclass_id uclass_id, int devnum)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600177{
Simon Glassfada3f92022-09-17 09:00:09 -0600178 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600179 struct blk_desc *desc;
180
181 if (!drv)
182 return NULL;
183
184 if (get_desc(drv, devnum, &desc))
185 return NULL;
186
187 return desc;
188}
189
190int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
191{
Simon Glassfada3f92022-09-17 09:00:09 -0600192 struct blk_driver *drv = blk_driver_lookup_type(desc->uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600193
194 if (!drv)
195 return -ENOSYS;
196 if (drv->select_hwpart)
197 return drv->select_hwpart(desc, hwpart);
198
199 return 0;
200}
201
Simon Glassfada3f92022-09-17 09:00:09 -0600202struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600203{
Simon Glassfada3f92022-09-17 09:00:09 -0600204 struct blk_driver *drv = blk_driver_lookup_typename(uclass_idname);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600205 struct blk_desc *desc;
206
207 if (!drv)
208 return NULL;
209
210 if (get_desc(drv, devnum, &desc))
211 return NULL;
212
213 return desc;
214}
215
Simon Glassfada3f92022-09-17 09:00:09 -0600216ulong blk_read_devnum(enum uclass_id uclass_id, int devnum, lbaint_t start,
Simon Glass3bf2ab92016-05-01 11:36:03 -0600217 lbaint_t blkcnt, void *buffer)
218{
Simon Glassfada3f92022-09-17 09:00:09 -0600219 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600220 struct blk_desc *desc;
221 ulong n;
222 int ret;
223
224 if (!drv)
225 return -ENOSYS;
226 ret = get_desc(drv, devnum, &desc);
227 if (ret)
228 return ret;
229 n = desc->block_read(desc, start, blkcnt, buffer);
230 if (IS_ERR_VALUE(n))
231 return n;
232
Simon Glass3bf2ab92016-05-01 11:36:03 -0600233 return n;
234}
235
Simon Glassfada3f92022-09-17 09:00:09 -0600236ulong blk_write_devnum(enum uclass_id uclass_id, int devnum, lbaint_t start,
Simon Glass3bf2ab92016-05-01 11:36:03 -0600237 lbaint_t blkcnt, const void *buffer)
238{
Simon Glassfada3f92022-09-17 09:00:09 -0600239 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600240 struct blk_desc *desc;
241 int ret;
242
243 if (!drv)
244 return -ENOSYS;
245 ret = get_desc(drv, devnum, &desc);
246 if (ret)
247 return ret;
248 return desc->block_write(desc, start, blkcnt, buffer);
249}
250
Simon Glassfada3f92022-09-17 09:00:09 -0600251int blk_select_hwpart_devnum(enum uclass_id uclass_id, int devnum, int hwpart)
Simon Glass3bf2ab92016-05-01 11:36:03 -0600252{
Simon Glassfada3f92022-09-17 09:00:09 -0600253 struct blk_driver *drv = blk_driver_lookup_type(uclass_id);
Simon Glass3bf2ab92016-05-01 11:36:03 -0600254 struct blk_desc *desc;
255 int ret;
256
257 if (!drv)
258 return -ENOSYS;
259 ret = get_desc(drv, devnum, &desc);
260 if (ret)
261 return ret;
262 return drv->select_hwpart(desc, hwpart);
263}