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