1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2016 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7 #define LOG_CATEGORY UCLASS_BLK
8
9 #include <common.h>
10 #include <blk.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <part.h>
15 #include <dm/device-internal.h>
16 #include <dm/lists.h>
17 #include <dm/uclass-internal.h>
18 #include <linux/err.h>
19
20 static const char *if_typename_str[IF_TYPE_COUNT] = {
21 [IF_TYPE_IDE] = "ide",
22 [IF_TYPE_SCSI] = "scsi",
23 [IF_TYPE_ATAPI] = "atapi",
24 [IF_TYPE_USB] = "usb",
25 [IF_TYPE_DOC] = "doc",
26 [IF_TYPE_MMC] = "mmc",
27 [IF_TYPE_SD] = "sd",
28 [IF_TYPE_SATA] = "sata",
29 [IF_TYPE_HOST] = "host",
30 [IF_TYPE_NVME] = "nvme",
31 [IF_TYPE_EFI] = "efi",
32 [IF_TYPE_VIRTIO] = "virtio",
33 [IF_TYPE_PVBLOCK] = "pvblock",
34 };
35
36 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
37 [IF_TYPE_IDE] = UCLASS_IDE,
38 [IF_TYPE_SCSI] = UCLASS_SCSI,
39 [IF_TYPE_ATAPI] = UCLASS_INVALID,
40 [IF_TYPE_USB] = UCLASS_MASS_STORAGE,
41 [IF_TYPE_DOC] = UCLASS_INVALID,
42 [IF_TYPE_MMC] = UCLASS_MMC,
43 [IF_TYPE_SD] = UCLASS_INVALID,
44 [IF_TYPE_SATA] = UCLASS_AHCI,
45 [IF_TYPE_HOST] = UCLASS_ROOT,
46 [IF_TYPE_NVME] = UCLASS_NVME,
47 [IF_TYPE_EFI] = UCLASS_EFI,
48 [IF_TYPE_VIRTIO] = UCLASS_VIRTIO,
49 [IF_TYPE_PVBLOCK] = UCLASS_PVBLOCK,
50 };
51
if_typename_to_iftype(const char * if_typename)52 static enum if_type if_typename_to_iftype(const char *if_typename)
53 {
54 int i;
55
56 for (i = 0; i < IF_TYPE_COUNT; i++) {
57 if (if_typename_str[i] &&
58 !strcmp(if_typename, if_typename_str[i]))
59 return i;
60 }
61
62 return IF_TYPE_UNKNOWN;
63 }
64
if_type_to_uclass_id(enum if_type if_type)65 static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
66 {
67 return if_type_uclass_id[if_type];
68 }
69
blk_get_if_type_name(enum if_type if_type)70 const char *blk_get_if_type_name(enum if_type if_type)
71 {
72 return if_typename_str[if_type];
73 }
74
blk_get_devnum_by_type(enum if_type if_type,int devnum)75 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
76 {
77 struct blk_desc *desc;
78 struct udevice *dev;
79 int ret;
80
81 ret = blk_get_device(if_type, devnum, &dev);
82 if (ret)
83 return NULL;
84 desc = dev_get_uclass_plat(dev);
85
86 return desc;
87 }
88
89 /*
90 * This function is complicated with driver model. We look up the interface
91 * name in a local table. This gives us an interface type which we can match
92 * against the uclass of the block device's parent.
93 */
blk_get_devnum_by_typename(const char * if_typename,int devnum)94 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
95 {
96 enum uclass_id uclass_id;
97 enum if_type if_type;
98 struct udevice *dev;
99 struct uclass *uc;
100 int ret;
101
102 if_type = if_typename_to_iftype(if_typename);
103 if (if_type == IF_TYPE_UNKNOWN) {
104 debug("%s: Unknown interface type '%s'\n", __func__,
105 if_typename);
106 return NULL;
107 }
108 uclass_id = if_type_to_uclass_id(if_type);
109 if (uclass_id == UCLASS_INVALID) {
110 debug("%s: Unknown uclass for interface type'\n",
111 if_typename_str[if_type]);
112 return NULL;
113 }
114
115 ret = uclass_get(UCLASS_BLK, &uc);
116 if (ret)
117 return NULL;
118 uclass_foreach_dev(dev, uc) {
119 struct blk_desc *desc = dev_get_uclass_plat(dev);
120
121 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
122 if_type, devnum, dev->name, desc->if_type, desc->devnum);
123 if (desc->devnum != devnum)
124 continue;
125
126 /* Find out the parent device uclass */
127 if (device_get_uclass_id(dev->parent) != uclass_id) {
128 debug("%s: parent uclass %d, this dev %d\n", __func__,
129 device_get_uclass_id(dev->parent), uclass_id);
130 continue;
131 }
132
133 if (device_probe(dev))
134 return NULL;
135
136 debug("%s: Device desc %p\n", __func__, desc);
137 return desc;
138 }
139 debug("%s: No device found\n", __func__);
140
141 return NULL;
142 }
143
144 /**
145 * blk_get_by_device() - Get the block device descriptor for the given device
146 * @dev: Instance of a storage device
147 *
148 * Return: With block device descriptor on success , NULL if there is no such
149 * block device.
150 */
blk_get_by_device(struct udevice * dev)151 struct blk_desc *blk_get_by_device(struct udevice *dev)
152 {
153 struct udevice *child_dev;
154
155 device_foreach_child(child_dev, dev) {
156 if (device_get_uclass_id(child_dev) != UCLASS_BLK)
157 continue;
158
159 return dev_get_uclass_plat(child_dev);
160 }
161
162 debug("%s: No block device found\n", __func__);
163
164 return NULL;
165 }
166
167 /**
168 * get_desc() - Get the block device descriptor for the given device number
169 *
170 * @if_type: Interface type
171 * @devnum: Device number (0 = first)
172 * @descp: Returns block device descriptor on success
173 * @return 0 on success, -ENODEV if there is no such device and no device
174 * with a higher device number, -ENOENT if there is no such device but there
175 * is one with a higher number, or other -ve on other error.
176 */
get_desc(enum if_type if_type,int devnum,struct blk_desc ** descp)177 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
178 {
179 bool found_more = false;
180 struct udevice *dev;
181 struct uclass *uc;
182 int ret;
183
184 *descp = NULL;
185 ret = uclass_get(UCLASS_BLK, &uc);
186 if (ret)
187 return ret;
188 uclass_foreach_dev(dev, uc) {
189 struct blk_desc *desc = dev_get_uclass_plat(dev);
190
191 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
192 if_type, devnum, dev->name, desc->if_type, desc->devnum);
193 if (desc->if_type == if_type) {
194 if (desc->devnum == devnum) {
195 ret = device_probe(dev);
196 if (ret)
197 return ret;
198
199 *descp = desc;
200 return 0;
201 } else if (desc->devnum > devnum) {
202 found_more = true;
203 }
204 }
205 }
206
207 return found_more ? -ENOENT : -ENODEV;
208 }
209
blk_select_hwpart_devnum(enum if_type if_type,int devnum,int hwpart)210 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
211 {
212 struct udevice *dev;
213 int ret;
214
215 ret = blk_get_device(if_type, devnum, &dev);
216 if (ret)
217 return ret;
218
219 return blk_select_hwpart(dev, hwpart);
220 }
221
blk_list_part(enum if_type if_type)222 int blk_list_part(enum if_type if_type)
223 {
224 struct blk_desc *desc;
225 int devnum, ok;
226 int ret;
227
228 for (ok = 0, devnum = 0;; ++devnum) {
229 ret = get_desc(if_type, devnum, &desc);
230 if (ret == -ENODEV)
231 break;
232 else if (ret)
233 continue;
234 if (desc->part_type != PART_TYPE_UNKNOWN) {
235 ++ok;
236 if (devnum)
237 putc('\n');
238 part_print(desc);
239 }
240 }
241 if (!ok)
242 return -ENODEV;
243
244 return 0;
245 }
246
blk_print_part_devnum(enum if_type if_type,int devnum)247 int blk_print_part_devnum(enum if_type if_type, int devnum)
248 {
249 struct blk_desc *desc;
250 int ret;
251
252 ret = get_desc(if_type, devnum, &desc);
253 if (ret)
254 return ret;
255 if (desc->type == DEV_TYPE_UNKNOWN)
256 return -ENOENT;
257 part_print(desc);
258
259 return 0;
260 }
261
blk_list_devices(enum if_type if_type)262 void blk_list_devices(enum if_type if_type)
263 {
264 struct blk_desc *desc;
265 int ret;
266 int i;
267
268 for (i = 0;; ++i) {
269 ret = get_desc(if_type, i, &desc);
270 if (ret == -ENODEV)
271 break;
272 else if (ret)
273 continue;
274 if (desc->type == DEV_TYPE_UNKNOWN)
275 continue; /* list only known devices */
276 printf("Device %d: ", i);
277 dev_print(desc);
278 }
279 }
280
blk_print_device_num(enum if_type if_type,int devnum)281 int blk_print_device_num(enum if_type if_type, int devnum)
282 {
283 struct blk_desc *desc;
284 int ret;
285
286 ret = get_desc(if_type, devnum, &desc);
287 if (ret)
288 return ret;
289 printf("\nIDE device %d: ", devnum);
290 dev_print(desc);
291
292 return 0;
293 }
294
blk_show_device(enum if_type if_type,int devnum)295 int blk_show_device(enum if_type if_type, int devnum)
296 {
297 struct blk_desc *desc;
298 int ret;
299
300 printf("\nDevice %d: ", devnum);
301 ret = get_desc(if_type, devnum, &desc);
302 if (ret == -ENODEV || ret == -ENOENT) {
303 printf("unknown device\n");
304 return -ENODEV;
305 }
306 if (ret)
307 return ret;
308 dev_print(desc);
309
310 if (desc->type == DEV_TYPE_UNKNOWN)
311 return -ENOENT;
312
313 return 0;
314 }
315
blk_read_devnum(enum if_type if_type,int devnum,lbaint_t start,lbaint_t blkcnt,void * buffer)316 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
317 lbaint_t blkcnt, void *buffer)
318 {
319 struct blk_desc *desc;
320 ulong n;
321 int ret;
322
323 ret = get_desc(if_type, devnum, &desc);
324 if (ret)
325 return ret;
326 n = blk_dread(desc, start, blkcnt, buffer);
327 if (IS_ERR_VALUE(n))
328 return n;
329
330 return n;
331 }
332
blk_write_devnum(enum if_type if_type,int devnum,lbaint_t start,lbaint_t blkcnt,const void * buffer)333 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
334 lbaint_t blkcnt, const void *buffer)
335 {
336 struct blk_desc *desc;
337 int ret;
338
339 ret = get_desc(if_type, devnum, &desc);
340 if (ret)
341 return ret;
342 return blk_dwrite(desc, start, blkcnt, buffer);
343 }
344
blk_select_hwpart(struct udevice * dev,int hwpart)345 int blk_select_hwpart(struct udevice *dev, int hwpart)
346 {
347 const struct blk_ops *ops = blk_get_ops(dev);
348
349 if (!ops)
350 return -ENOSYS;
351 if (!ops->select_hwpart)
352 return 0;
353
354 return ops->select_hwpart(dev, hwpart);
355 }
356
blk_dselect_hwpart(struct blk_desc * desc,int hwpart)357 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
358 {
359 return blk_select_hwpart(desc->bdev, hwpart);
360 }
361
blk_first_device(int if_type,struct udevice ** devp)362 int blk_first_device(int if_type, struct udevice **devp)
363 {
364 struct blk_desc *desc;
365 int ret;
366
367 ret = uclass_find_first_device(UCLASS_BLK, devp);
368 if (ret)
369 return ret;
370 if (!*devp)
371 return -ENODEV;
372 do {
373 desc = dev_get_uclass_plat(*devp);
374 if (desc->if_type == if_type)
375 return 0;
376 ret = uclass_find_next_device(devp);
377 if (ret)
378 return ret;
379 } while (*devp);
380
381 return -ENODEV;
382 }
383
blk_next_device(struct udevice ** devp)384 int blk_next_device(struct udevice **devp)
385 {
386 struct blk_desc *desc;
387 int ret, if_type;
388
389 desc = dev_get_uclass_plat(*devp);
390 if_type = desc->if_type;
391 do {
392 ret = uclass_find_next_device(devp);
393 if (ret)
394 return ret;
395 if (!*devp)
396 return -ENODEV;
397 desc = dev_get_uclass_plat(*devp);
398 if (desc->if_type == if_type)
399 return 0;
400 } while (1);
401 }
402
blk_find_device(int if_type,int devnum,struct udevice ** devp)403 int blk_find_device(int if_type, int devnum, struct udevice **devp)
404 {
405 struct uclass *uc;
406 struct udevice *dev;
407 int ret;
408
409 ret = uclass_get(UCLASS_BLK, &uc);
410 if (ret)
411 return ret;
412 uclass_foreach_dev(dev, uc) {
413 struct blk_desc *desc = dev_get_uclass_plat(dev);
414
415 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
416 if_type, devnum, dev->name, desc->if_type, desc->devnum);
417 if (desc->if_type == if_type && desc->devnum == devnum) {
418 *devp = dev;
419 return 0;
420 }
421 }
422
423 return -ENODEV;
424 }
425
blk_get_device(int if_type,int devnum,struct udevice ** devp)426 int blk_get_device(int if_type, int devnum, struct udevice **devp)
427 {
428 int ret;
429
430 ret = blk_find_device(if_type, devnum, devp);
431 if (ret)
432 return ret;
433
434 return device_probe(*devp);
435 }
436
blk_dread(struct blk_desc * block_dev,lbaint_t start,lbaint_t blkcnt,void * buffer)437 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
438 lbaint_t blkcnt, void *buffer)
439 {
440 struct udevice *dev = block_dev->bdev;
441 const struct blk_ops *ops = blk_get_ops(dev);
442 ulong blks_read;
443
444 if (!ops->read)
445 return -ENOSYS;
446
447 if (blkcache_read(block_dev->if_type, block_dev->devnum,
448 start, blkcnt, block_dev->blksz, buffer))
449 return blkcnt;
450 blks_read = ops->read(dev, start, blkcnt, buffer);
451 if (blks_read == blkcnt)
452 blkcache_fill(block_dev->if_type, block_dev->devnum,
453 start, blkcnt, block_dev->blksz, buffer);
454
455 return blks_read;
456 }
457
blk_dwrite(struct blk_desc * block_dev,lbaint_t start,lbaint_t blkcnt,const void * buffer)458 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
459 lbaint_t blkcnt, const void *buffer)
460 {
461 struct udevice *dev = block_dev->bdev;
462 const struct blk_ops *ops = blk_get_ops(dev);
463
464 if (!ops->write)
465 return -ENOSYS;
466
467 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
468 return ops->write(dev, start, blkcnt, buffer);
469 }
470
blk_derase(struct blk_desc * block_dev,lbaint_t start,lbaint_t blkcnt)471 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
472 lbaint_t blkcnt)
473 {
474 struct udevice *dev = block_dev->bdev;
475 const struct blk_ops *ops = blk_get_ops(dev);
476
477 if (!ops->erase)
478 return -ENOSYS;
479
480 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
481 return ops->erase(dev, start, blkcnt);
482 }
483
blk_get_from_parent(struct udevice * parent,struct udevice ** devp)484 int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
485 {
486 struct udevice *dev;
487 enum uclass_id id;
488 int ret;
489
490 device_find_first_child(parent, &dev);
491 if (!dev) {
492 debug("%s: No block device found for parent '%s'\n", __func__,
493 parent->name);
494 return -ENODEV;
495 }
496 id = device_get_uclass_id(dev);
497 if (id != UCLASS_BLK) {
498 debug("%s: Incorrect uclass %s for block device '%s'\n",
499 __func__, uclass_get_name(id), dev->name);
500 return -ENOTBLK;
501 }
502 ret = device_probe(dev);
503 if (ret)
504 return ret;
505 *devp = dev;
506
507 return 0;
508 }
509
blk_find_max_devnum(enum if_type if_type)510 int blk_find_max_devnum(enum if_type if_type)
511 {
512 struct udevice *dev;
513 int max_devnum = -ENODEV;
514 struct uclass *uc;
515 int ret;
516
517 ret = uclass_get(UCLASS_BLK, &uc);
518 if (ret)
519 return ret;
520 uclass_foreach_dev(dev, uc) {
521 struct blk_desc *desc = dev_get_uclass_plat(dev);
522
523 if (desc->if_type == if_type && desc->devnum > max_devnum)
524 max_devnum = desc->devnum;
525 }
526
527 return max_devnum;
528 }
529
blk_next_free_devnum(enum if_type if_type)530 int blk_next_free_devnum(enum if_type if_type)
531 {
532 int ret;
533
534 ret = blk_find_max_devnum(if_type);
535 if (ret == -ENODEV)
536 return 0;
537 if (ret < 0)
538 return ret;
539
540 return ret + 1;
541 }
542
blk_flags_check(struct udevice * dev,enum blk_flag_t req_flags)543 static int blk_flags_check(struct udevice *dev, enum blk_flag_t req_flags)
544 {
545 const struct blk_desc *desc = dev_get_uclass_plat(dev);
546 enum blk_flag_t flags;
547
548 flags = desc->removable ? BLKF_REMOVABLE : BLKF_FIXED;
549
550 return flags & req_flags ? 0 : 1;
551 }
552
blk_first_device_err(enum blk_flag_t flags,struct udevice ** devp)553 int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp)
554 {
555 int ret;
556
557 for (ret = uclass_first_device_err(UCLASS_BLK, devp);
558 !ret;
559 ret = uclass_next_device_err(devp)) {
560 if (!blk_flags_check(*devp, flags))
561 return 0;
562 }
563
564 return -ENODEV;
565 }
566
blk_next_device_err(enum blk_flag_t flags,struct udevice ** devp)567 int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp)
568 {
569 int ret;
570
571 for (ret = uclass_next_device_err(devp);
572 !ret;
573 ret = uclass_next_device_err(devp)) {
574 if (!blk_flags_check(*devp, flags))
575 return 0;
576 }
577
578 return -ENODEV;
579 }
580
blk_count_devices(enum blk_flag_t flag)581 int blk_count_devices(enum blk_flag_t flag)
582 {
583 struct udevice *dev;
584 int count = 0;
585
586 blk_foreach_probe(flag, dev)
587 count++;
588
589 return count;
590 }
591
blk_claim_devnum(enum if_type if_type,int devnum)592 static int blk_claim_devnum(enum if_type if_type, int devnum)
593 {
594 struct udevice *dev;
595 struct uclass *uc;
596 int ret;
597
598 ret = uclass_get(UCLASS_BLK, &uc);
599 if (ret)
600 return ret;
601 uclass_foreach_dev(dev, uc) {
602 struct blk_desc *desc = dev_get_uclass_plat(dev);
603
604 if (desc->if_type == if_type && desc->devnum == devnum) {
605 int next = blk_next_free_devnum(if_type);
606
607 if (next < 0)
608 return next;
609 desc->devnum = next;
610 return 0;
611 }
612 }
613
614 return -ENOENT;
615 }
616
blk_create_device(struct udevice * parent,const char * drv_name,const char * name,int if_type,int devnum,int blksz,lbaint_t lba,struct udevice ** devp)617 int blk_create_device(struct udevice *parent, const char *drv_name,
618 const char *name, int if_type, int devnum, int blksz,
619 lbaint_t lba, struct udevice **devp)
620 {
621 struct blk_desc *desc;
622 struct udevice *dev;
623 int ret;
624
625 if (devnum == -1) {
626 devnum = blk_next_free_devnum(if_type);
627 } else {
628 ret = blk_claim_devnum(if_type, devnum);
629 if (ret < 0 && ret != -ENOENT)
630 return ret;
631 }
632 if (devnum < 0)
633 return devnum;
634 ret = device_bind_driver(parent, drv_name, name, &dev);
635 if (ret)
636 return ret;
637 desc = dev_get_uclass_plat(dev);
638 desc->if_type = if_type;
639 desc->blksz = blksz;
640 desc->log2blksz = LOG2(desc->blksz);
641 desc->lba = lba;
642 desc->part_type = PART_TYPE_UNKNOWN;
643 desc->bdev = dev;
644 desc->devnum = devnum;
645 *devp = dev;
646
647 return 0;
648 }
649
blk_create_devicef(struct udevice * parent,const char * drv_name,const char * name,int if_type,int devnum,int blksz,lbaint_t lba,struct udevice ** devp)650 int blk_create_devicef(struct udevice *parent, const char *drv_name,
651 const char *name, int if_type, int devnum, int blksz,
652 lbaint_t lba, struct udevice **devp)
653 {
654 char dev_name[30], *str;
655 int ret;
656
657 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
658 str = strdup(dev_name);
659 if (!str)
660 return -ENOMEM;
661
662 ret = blk_create_device(parent, drv_name, str, if_type, devnum,
663 blksz, lba, devp);
664 if (ret) {
665 free(str);
666 return ret;
667 }
668 device_set_name_alloced(*devp);
669
670 return 0;
671 }
672
blk_unbind_all(int if_type)673 int blk_unbind_all(int if_type)
674 {
675 struct uclass *uc;
676 struct udevice *dev, *next;
677 int ret;
678
679 ret = uclass_get(UCLASS_BLK, &uc);
680 if (ret)
681 return ret;
682 uclass_foreach_dev_safe(dev, next, uc) {
683 struct blk_desc *desc = dev_get_uclass_plat(dev);
684
685 if (desc->if_type == if_type) {
686 ret = device_remove(dev, DM_REMOVE_NORMAL);
687 if (ret)
688 return ret;
689 ret = device_unbind(dev);
690 if (ret)
691 return ret;
692 }
693 }
694
695 return 0;
696 }
697
blk_post_probe(struct udevice * dev)698 static int blk_post_probe(struct udevice *dev)
699 {
700 if (IS_ENABLED(CONFIG_PARTITIONS) &&
701 IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) {
702 struct blk_desc *desc = dev_get_uclass_plat(dev);
703
704 part_init(desc);
705 }
706
707 return 0;
708 }
709
710 UCLASS_DRIVER(blk) = {
711 .id = UCLASS_BLK,
712 .name = "blk",
713 .post_probe = blk_post_probe,
714 .per_device_plat_auto = sizeof(struct blk_desc),
715 };
716