1 /* 2 * (C) Copyright 2001 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <command.h> 10 #include <errno.h> 11 #include <ide.h> 12 #include <malloc.h> 13 #include <part.h> 14 #include <ubifs_uboot.h> 15 16 #undef PART_DEBUG 17 18 #ifdef PART_DEBUG 19 #define PRINTF(fmt,args...) printf (fmt ,##args) 20 #else 21 #define PRINTF(fmt,args...) 22 #endif 23 24 DECLARE_GLOBAL_DATA_PTR; 25 26 #ifdef HAVE_BLOCK_DEVICE 27 static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc) 28 { 29 struct part_driver *drv = 30 ll_entry_start(struct part_driver, part_driver); 31 const int n_ents = ll_entry_count(struct part_driver, part_driver); 32 struct part_driver *entry; 33 34 if (dev_desc->part_type == PART_TYPE_UNKNOWN) { 35 for (entry = drv; entry != drv + n_ents; entry++) { 36 int ret; 37 38 ret = entry->test(dev_desc); 39 if (!ret) { 40 dev_desc->part_type = entry->part_type; 41 return entry; 42 } 43 } 44 } else { 45 for (entry = drv; entry != drv + n_ents; entry++) { 46 if (dev_desc->part_type == entry->part_type) 47 return entry; 48 } 49 } 50 51 /* Not found */ 52 return NULL; 53 } 54 55 static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) 56 { 57 struct blk_desc *dev_desc; 58 int ret; 59 60 dev_desc = blk_get_devnum_by_typename(ifname, dev); 61 if (!dev_desc) { 62 debug("%s: No device for iface '%s', dev %d\n", __func__, 63 ifname, dev); 64 return NULL; 65 } 66 ret = blk_dselect_hwpart(dev_desc, hwpart); 67 if (ret) { 68 debug("%s: Failed to select h/w partition: err-%d\n", __func__, 69 ret); 70 return NULL; 71 } 72 73 return dev_desc; 74 } 75 76 struct blk_desc *blk_get_dev(const char *ifname, int dev) 77 { 78 return get_dev_hwpart(ifname, dev, 0); 79 } 80 #else 81 struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) 82 { 83 return NULL; 84 } 85 86 struct blk_desc *blk_get_dev(const char *ifname, int dev) 87 { 88 return NULL; 89 } 90 #endif 91 92 #ifdef HAVE_BLOCK_DEVICE 93 94 /* ------------------------------------------------------------------------- */ 95 /* 96 * reports device info to the user 97 */ 98 99 #ifdef CONFIG_LBA48 100 typedef uint64_t lba512_t; 101 #else 102 typedef lbaint_t lba512_t; 103 #endif 104 105 /* 106 * Overflowless variant of (block_count * mul_by / div_by) 107 * when div_by > mul_by 108 */ 109 static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by) 110 { 111 lba512_t bc_quot, bc_rem; 112 113 /* x * m / d == x / d * m + (x % d) * m / d */ 114 bc_quot = block_count / div_by; 115 bc_rem = block_count - div_by * bc_quot; 116 return bc_quot * mul_by + (bc_rem * mul_by) / div_by; 117 } 118 119 void dev_print (struct blk_desc *dev_desc) 120 { 121 lba512_t lba512; /* number of blocks if 512bytes block size */ 122 123 if (dev_desc->type == DEV_TYPE_UNKNOWN) { 124 puts ("not available\n"); 125 return; 126 } 127 128 switch (dev_desc->if_type) { 129 case IF_TYPE_SCSI: 130 printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n", 131 dev_desc->target,dev_desc->lun, 132 dev_desc->vendor, 133 dev_desc->product, 134 dev_desc->revision); 135 break; 136 case IF_TYPE_ATAPI: 137 case IF_TYPE_IDE: 138 case IF_TYPE_SATA: 139 printf ("Model: %s Firm: %s Ser#: %s\n", 140 dev_desc->vendor, 141 dev_desc->revision, 142 dev_desc->product); 143 break; 144 case IF_TYPE_SD: 145 case IF_TYPE_MMC: 146 case IF_TYPE_MTD: 147 case IF_TYPE_USB: 148 case IF_TYPE_NVME: 149 case IF_TYPE_RKNAND: 150 case IF_TYPE_SPINAND: 151 case IF_TYPE_SPINOR: 152 printf("Vendor: %s Rev: %s Prod: %s\n", 153 dev_desc->vendor, 154 dev_desc->revision, 155 dev_desc->product); 156 break; 157 case IF_TYPE_DOC: 158 puts("device type DOC\n"); 159 return; 160 case IF_TYPE_UNKNOWN: 161 puts("device type unknown\n"); 162 return; 163 default: 164 printf("Unhandled device type: %i\n", dev_desc->if_type); 165 return; 166 } 167 puts (" Type: "); 168 if (dev_desc->removable) 169 puts ("Removable "); 170 switch (dev_desc->type & 0x1F) { 171 case DEV_TYPE_HARDDISK: 172 puts ("Hard Disk"); 173 break; 174 case DEV_TYPE_CDROM: 175 puts ("CD ROM"); 176 break; 177 case DEV_TYPE_OPDISK: 178 puts ("Optical Device"); 179 break; 180 case DEV_TYPE_TAPE: 181 puts ("Tape"); 182 break; 183 default: 184 printf ("# %02X #", dev_desc->type & 0x1F); 185 break; 186 } 187 puts ("\n"); 188 if (dev_desc->lba > 0L && dev_desc->blksz > 0L) { 189 ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem; 190 lbaint_t lba; 191 192 lba = dev_desc->lba; 193 194 lba512 = (lba * (dev_desc->blksz/512)); 195 /* round to 1 digit */ 196 /* 2048 = (1024 * 1024) / 512 MB */ 197 mb = lba512_muldiv(lba512, 10, 2048); 198 199 mb_quot = mb / 10; 200 mb_rem = mb - (10 * mb_quot); 201 202 gb = mb / 1024; 203 gb_quot = gb / 10; 204 gb_rem = gb - (10 * gb_quot); 205 #ifdef CONFIG_LBA48 206 if (dev_desc->lba48) 207 printf (" Supports 48-bit addressing\n"); 208 #endif 209 #if defined(CONFIG_SYS_64BIT_LBA) 210 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n", 211 mb_quot, mb_rem, 212 gb_quot, gb_rem, 213 lba, 214 dev_desc->blksz); 215 #else 216 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n", 217 mb_quot, mb_rem, 218 gb_quot, gb_rem, 219 (ulong)lba, 220 dev_desc->blksz); 221 #endif 222 } else { 223 puts (" Capacity: not available\n"); 224 } 225 } 226 #endif 227 228 #ifdef HAVE_BLOCK_DEVICE 229 230 void part_init(struct blk_desc *dev_desc) 231 { 232 struct part_driver *drv = 233 ll_entry_start(struct part_driver, part_driver); 234 const int n_ents = ll_entry_count(struct part_driver, part_driver); 235 struct part_driver *entry; 236 237 blkcache_invalidate(dev_desc->if_type, dev_desc->devnum); 238 239 dev_desc->part_type = PART_TYPE_UNKNOWN; 240 for (entry = drv; entry != drv + n_ents; entry++) { 241 int ret; 242 243 ret = entry->test(dev_desc); 244 debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret); 245 if (!ret) { 246 dev_desc->part_type = entry->part_type; 247 break; 248 } 249 } 250 } 251 252 static void print_part_header(const char *type, struct blk_desc *dev_desc) 253 { 254 #if CONFIG_IS_ENABLED(MAC_PARTITION) || \ 255 CONFIG_IS_ENABLED(DOS_PARTITION) || \ 256 CONFIG_IS_ENABLED(ISO_PARTITION) || \ 257 CONFIG_IS_ENABLED(AMIGA_PARTITION) || \ 258 CONFIG_IS_ENABLED(EFI_PARTITION) 259 puts ("\nPartition Map for "); 260 switch (dev_desc->if_type) { 261 case IF_TYPE_IDE: 262 puts ("IDE"); 263 break; 264 case IF_TYPE_SATA: 265 puts ("SATA"); 266 break; 267 case IF_TYPE_SCSI: 268 puts ("SCSI"); 269 break; 270 case IF_TYPE_ATAPI: 271 puts ("ATAPI"); 272 break; 273 case IF_TYPE_USB: 274 puts ("USB"); 275 break; 276 case IF_TYPE_DOC: 277 puts ("DOC"); 278 break; 279 case IF_TYPE_MMC: 280 puts ("MMC"); 281 break; 282 case IF_TYPE_MTD: 283 puts("MTD"); 284 break; 285 case IF_TYPE_HOST: 286 puts ("HOST"); 287 break; 288 case IF_TYPE_NVME: 289 puts ("NVMe"); 290 break; 291 case IF_TYPE_RKNAND: 292 puts("RKNAND"); 293 break; 294 case IF_TYPE_SPINAND: 295 puts("SPINAND"); 296 break; 297 case IF_TYPE_SPINOR: 298 puts("SPINOR"); 299 break; 300 default: 301 puts ("UNKNOWN"); 302 break; 303 } 304 printf (" device %d -- Partition Type: %s\n\n", 305 dev_desc->devnum, type); 306 #endif /* any CONFIG_..._PARTITION */ 307 } 308 309 void part_print(struct blk_desc *dev_desc) 310 { 311 struct part_driver *drv; 312 313 drv = part_driver_lookup_type(dev_desc); 314 if (!drv) { 315 printf("## Unknown partition table type %x\n", 316 dev_desc->part_type); 317 return; 318 } 319 320 PRINTF("## Testing for valid %s partition ##\n", drv->name); 321 print_part_header(drv->name, dev_desc); 322 if (drv->print) 323 drv->print(dev_desc); 324 } 325 326 const char *part_get_type(struct blk_desc *dev_desc) 327 { 328 struct part_driver *drv; 329 330 drv = part_driver_lookup_type(dev_desc); 331 if (!drv) { 332 printf("## Unknown partition table type %x\n", 333 dev_desc->part_type); 334 return NULL; 335 } 336 337 return drv->name; 338 } 339 #endif /* HAVE_BLOCK_DEVICE */ 340 341 int part_get_info(struct blk_desc *dev_desc, int part, 342 disk_partition_t *info) 343 { 344 #ifdef HAVE_BLOCK_DEVICE 345 struct part_driver *drv; 346 347 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 348 /* The common case is no UUID support */ 349 info->uuid[0] = 0; 350 #endif 351 #ifdef CONFIG_PARTITION_TYPE_GUID 352 info->type_guid[0] = 0; 353 #endif 354 355 drv = part_driver_lookup_type(dev_desc); 356 if (!drv) { 357 debug("## Unknown partition table type %x\n", 358 dev_desc->part_type); 359 return -EPROTONOSUPPORT; 360 } 361 if (!drv->get_info) { 362 PRINTF("## Driver %s does not have the get_info() method\n", 363 drv->name); 364 return -ENOSYS; 365 } 366 if (drv->get_info(dev_desc, part, info) == 0) { 367 PRINTF("## Valid %s partition found ##\n", drv->name); 368 return 0; 369 } 370 #endif /* HAVE_BLOCK_DEVICE */ 371 372 return -1; 373 } 374 375 int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) 376 { 377 info->start = 0; 378 info->size = dev_desc->lba; 379 info->blksz = dev_desc->blksz; 380 info->bootable = 0; 381 strcpy((char *)info->type, BOOT_PART_TYPE); 382 strcpy((char *)info->name, "Whole Disk"); 383 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 384 info->uuid[0] = 0; 385 #endif 386 #ifdef CONFIG_PARTITION_TYPE_GUID 387 info->type_guid[0] = 0; 388 #endif 389 390 return 0; 391 } 392 393 int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, 394 struct blk_desc **dev_desc) 395 { 396 char *ep; 397 char *dup_str = NULL; 398 const char *dev_str, *hwpart_str; 399 int dev, hwpart; 400 401 hwpart_str = strchr(dev_hwpart_str, '.'); 402 if (hwpart_str) { 403 dup_str = strdup(dev_hwpart_str); 404 dup_str[hwpart_str - dev_hwpart_str] = 0; 405 dev_str = dup_str; 406 hwpart_str++; 407 } else { 408 dev_str = dev_hwpart_str; 409 hwpart = 0; 410 } 411 412 dev = simple_strtoul(dev_str, &ep, 16); 413 if (*ep) { 414 printf("** Bad device specification %s %s **\n", 415 ifname, dev_str); 416 dev = -EINVAL; 417 goto cleanup; 418 } 419 420 if (hwpart_str) { 421 hwpart = simple_strtoul(hwpart_str, &ep, 16); 422 if (*ep) { 423 printf("** Bad HW partition specification %s %s **\n", 424 ifname, hwpart_str); 425 dev = -EINVAL; 426 goto cleanup; 427 } 428 } 429 430 *dev_desc = get_dev_hwpart(ifname, dev, hwpart); 431 if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) { 432 printf("** Bad device %s %s **\n", ifname, dev_hwpart_str); 433 dev = -ENOENT; 434 goto cleanup; 435 } 436 437 #ifdef HAVE_BLOCK_DEVICE 438 /* 439 * Updates the partition table for the specified hw partition. 440 * Does not need to be done for hwpart 0 since it is default and 441 * already loaded. 442 */ 443 if(hwpart != 0) 444 part_init(*dev_desc); 445 #endif 446 447 cleanup: 448 free(dup_str); 449 return dev; 450 } 451 452 #define PART_UNSPECIFIED -2 453 #define PART_AUTO -1 454 int blk_get_device_part_str(const char *ifname, const char *dev_part_str, 455 struct blk_desc **dev_desc, 456 disk_partition_t *info, int allow_whole_dev) 457 { 458 int ret = -1; 459 const char *part_str; 460 char *dup_str = NULL; 461 const char *dev_str; 462 int dev; 463 char *ep; 464 int p; 465 int part; 466 disk_partition_t tmpinfo; 467 468 #ifdef CONFIG_SANDBOX 469 /* 470 * Special-case a pseudo block device "hostfs", to allow access to the 471 * host's own filesystem. 472 */ 473 if (0 == strcmp(ifname, "hostfs")) { 474 *dev_desc = NULL; 475 info->start = 0; 476 info->size = 0; 477 info->blksz = 0; 478 info->bootable = 0; 479 strcpy((char *)info->type, BOOT_PART_TYPE); 480 strcpy((char *)info->name, "Sandbox host"); 481 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 482 info->uuid[0] = 0; 483 #endif 484 #ifdef CONFIG_PARTITION_TYPE_GUID 485 info->type_guid[0] = 0; 486 #endif 487 488 return 0; 489 } 490 #endif 491 492 #ifdef CONFIG_CMD_UBIFS 493 /* 494 * Special-case ubi, ubi goes through a mtd, rathen then through 495 * a regular block device. 496 */ 497 if (0 == strcmp(ifname, "ubi")) { 498 if (!ubifs_is_mounted()) { 499 printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); 500 return -1; 501 } 502 503 *dev_desc = NULL; 504 memset(info, 0, sizeof(*info)); 505 strcpy((char *)info->type, BOOT_PART_TYPE); 506 strcpy((char *)info->name, "UBI"); 507 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 508 info->uuid[0] = 0; 509 #endif 510 return 0; 511 } 512 #endif 513 514 /* If no dev_part_str, use bootdevice environment variable */ 515 if (!dev_part_str || !strlen(dev_part_str) || 516 !strcmp(dev_part_str, "-")) 517 dev_part_str = env_get("bootdevice"); 518 519 /* If still no dev_part_str, it's an error */ 520 if (!dev_part_str) { 521 printf("** No device specified **\n"); 522 goto cleanup; 523 } 524 525 /* Separate device and partition ID specification */ 526 part_str = strchr(dev_part_str, ':'); 527 if (part_str) { 528 dup_str = strdup(dev_part_str); 529 dup_str[part_str - dev_part_str] = 0; 530 dev_str = dup_str; 531 part_str++; 532 } else { 533 dev_str = dev_part_str; 534 } 535 536 /* Look up the device */ 537 dev = blk_get_device_by_str(ifname, dev_str, dev_desc); 538 if (dev < 0) 539 goto cleanup; 540 541 /* Convert partition ID string to number */ 542 if (!part_str || !*part_str) { 543 part = PART_UNSPECIFIED; 544 } else if (!strcmp(part_str, "auto")) { 545 part = PART_AUTO; 546 } else { 547 /* Something specified -> use exactly that */ 548 part = (int)simple_strtoul(part_str, &ep, 16); 549 /* 550 * Less than whole string converted, 551 * or request for whole device, but caller requires partition. 552 */ 553 if (*ep || (part == 0 && !allow_whole_dev)) { 554 printf("** Bad partition specification %s %s **\n", 555 ifname, dev_part_str); 556 goto cleanup; 557 } 558 } 559 560 /* 561 * No partition table on device, 562 * or user requested partition 0 (entire device). 563 */ 564 if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) || 565 (part == 0)) { 566 if (!(*dev_desc)->lba) { 567 printf("** Bad device size - %s %s **\n", ifname, 568 dev_str); 569 goto cleanup; 570 } 571 572 /* 573 * If user specified a partition ID other than 0, 574 * or the calling command only accepts partitions, 575 * it's an error. 576 */ 577 if ((part > 0) || (!allow_whole_dev)) { 578 printf("** No partition table - %s %s **\n", ifname, 579 dev_str); 580 goto cleanup; 581 } 582 583 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 584 585 part_get_info_whole_disk(*dev_desc, info); 586 587 ret = 0; 588 goto cleanup; 589 } 590 591 /* 592 * Now there's known to be a partition table, 593 * not specifying a partition means to pick partition 1. 594 */ 595 if (part == PART_UNSPECIFIED) 596 part = 1; 597 598 /* 599 * If user didn't specify a partition number, or did specify something 600 * other than "auto", use that partition number directly. 601 */ 602 if (part != PART_AUTO) { 603 ret = part_get_info(*dev_desc, part, info); 604 if (ret) { 605 printf("** Invalid partition %d **\n", part); 606 goto cleanup; 607 } 608 } else { 609 /* 610 * Find the first bootable partition. 611 * If none are bootable, fall back to the first valid partition. 612 */ 613 part = 0; 614 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 615 ret = part_get_info(*dev_desc, p, info); 616 if (ret) 617 continue; 618 619 /* 620 * First valid partition, or new better partition? 621 * If so, save partition ID. 622 */ 623 if (!part || info->bootable) 624 part = p; 625 626 /* Best possible partition? Stop searching. */ 627 if (info->bootable) 628 break; 629 630 /* 631 * We now need to search further for best possible. 632 * If we what we just queried was the best so far, 633 * save the info since we over-write it next loop. 634 */ 635 if (part == p) 636 tmpinfo = *info; 637 } 638 /* If we found any acceptable partition */ 639 if (part) { 640 /* 641 * If we searched all possible partition IDs, 642 * return the first valid partition we found. 643 */ 644 if (p == MAX_SEARCH_PARTITIONS + 1) 645 *info = tmpinfo; 646 } else { 647 printf("** No valid partitions found **\n"); 648 ret = -1; 649 goto cleanup; 650 } 651 } 652 if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { 653 printf("** Invalid partition type \"%.32s\"" 654 " (expect \"" BOOT_PART_TYPE "\")\n", 655 info->type); 656 ret = -1; 657 goto cleanup; 658 } 659 660 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 661 662 ret = part; 663 goto cleanup; 664 665 cleanup: 666 free(dup_str); 667 return ret; 668 } 669 670 int part_get_info_by_name(struct blk_desc *dev_desc, const char *name, 671 disk_partition_t *info) 672 { 673 struct part_driver *part_drv; 674 int ret; 675 int i; 676 677 part_drv = part_driver_lookup_type(dev_desc); 678 if (!part_drv) 679 return -1; 680 for (i = 1; i < part_drv->max_entries; i++) { 681 ret = part_drv->get_info(dev_desc, i, info); 682 if (ret != 0) { 683 /* no more entries in table */ 684 break; 685 } 686 if (strcmp(name, (const char *)info->name) == 0) { 687 /* matched */ 688 return i; 689 } 690 } 691 692 return -1; 693 } 694 695 void part_set_generic_name(const struct blk_desc *dev_desc, 696 int part_num, char *name) 697 { 698 char *devtype; 699 700 switch (dev_desc->if_type) { 701 case IF_TYPE_IDE: 702 case IF_TYPE_SATA: 703 case IF_TYPE_ATAPI: 704 devtype = "hd"; 705 break; 706 case IF_TYPE_SCSI: 707 devtype = "sd"; 708 break; 709 case IF_TYPE_USB: 710 devtype = "usbd"; 711 break; 712 case IF_TYPE_DOC: 713 devtype = "docd"; 714 break; 715 case IF_TYPE_MMC: 716 case IF_TYPE_SD: 717 devtype = "mmcsd"; 718 break; 719 default: 720 devtype = "xx"; 721 break; 722 } 723 724 sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num); 725 } 726