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