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_USB: 147 case IF_TYPE_NVME: 148 case IF_TYPE_RKNAND: 149 printf ("Vendor: %s Rev: %s Prod: %s\n", 150 dev_desc->vendor, 151 dev_desc->revision, 152 dev_desc->product); 153 break; 154 case IF_TYPE_RKSFC: 155 printf ("Vendor: %s Rev: %s Prod: %s\n", 156 dev_desc->vendor, 157 dev_desc->revision, 158 dev_desc->product); 159 break; 160 case IF_TYPE_DOC: 161 puts("device type DOC\n"); 162 return; 163 case IF_TYPE_UNKNOWN: 164 puts("device type unknown\n"); 165 return; 166 default: 167 printf("Unhandled device type: %i\n", dev_desc->if_type); 168 return; 169 } 170 puts (" Type: "); 171 if (dev_desc->removable) 172 puts ("Removable "); 173 switch (dev_desc->type & 0x1F) { 174 case DEV_TYPE_HARDDISK: 175 puts ("Hard Disk"); 176 break; 177 case DEV_TYPE_CDROM: 178 puts ("CD ROM"); 179 break; 180 case DEV_TYPE_OPDISK: 181 puts ("Optical Device"); 182 break; 183 case DEV_TYPE_TAPE: 184 puts ("Tape"); 185 break; 186 default: 187 printf ("# %02X #", dev_desc->type & 0x1F); 188 break; 189 } 190 puts ("\n"); 191 if (dev_desc->lba > 0L && dev_desc->blksz > 0L) { 192 ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem; 193 lbaint_t lba; 194 195 lba = dev_desc->lba; 196 197 lba512 = (lba * (dev_desc->blksz/512)); 198 /* round to 1 digit */ 199 /* 2048 = (1024 * 1024) / 512 MB */ 200 mb = lba512_muldiv(lba512, 10, 2048); 201 202 mb_quot = mb / 10; 203 mb_rem = mb - (10 * mb_quot); 204 205 gb = mb / 1024; 206 gb_quot = gb / 10; 207 gb_rem = gb - (10 * gb_quot); 208 #ifdef CONFIG_LBA48 209 if (dev_desc->lba48) 210 printf (" Supports 48-bit addressing\n"); 211 #endif 212 #if defined(CONFIG_SYS_64BIT_LBA) 213 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n", 214 mb_quot, mb_rem, 215 gb_quot, gb_rem, 216 lba, 217 dev_desc->blksz); 218 #else 219 printf (" Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n", 220 mb_quot, mb_rem, 221 gb_quot, gb_rem, 222 (ulong)lba, 223 dev_desc->blksz); 224 #endif 225 } else { 226 puts (" Capacity: not available\n"); 227 } 228 } 229 #endif 230 231 #ifdef HAVE_BLOCK_DEVICE 232 233 void part_init(struct blk_desc *dev_desc) 234 { 235 struct part_driver *drv = 236 ll_entry_start(struct part_driver, part_driver); 237 const int n_ents = ll_entry_count(struct part_driver, part_driver); 238 struct part_driver *entry; 239 240 blkcache_invalidate(dev_desc->if_type, dev_desc->devnum); 241 242 dev_desc->part_type = PART_TYPE_UNKNOWN; 243 for (entry = drv; entry != drv + n_ents; entry++) { 244 int ret; 245 246 ret = entry->test(dev_desc); 247 debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret); 248 if (!ret) { 249 dev_desc->part_type = entry->part_type; 250 break; 251 } 252 } 253 } 254 255 static void print_part_header(const char *type, struct blk_desc *dev_desc) 256 { 257 #if CONFIG_IS_ENABLED(MAC_PARTITION) || \ 258 CONFIG_IS_ENABLED(DOS_PARTITION) || \ 259 CONFIG_IS_ENABLED(ISO_PARTITION) || \ 260 CONFIG_IS_ENABLED(AMIGA_PARTITION) || \ 261 CONFIG_IS_ENABLED(EFI_PARTITION) 262 puts ("\nPartition Map for "); 263 switch (dev_desc->if_type) { 264 case IF_TYPE_IDE: 265 puts ("IDE"); 266 break; 267 case IF_TYPE_SATA: 268 puts ("SATA"); 269 break; 270 case IF_TYPE_SCSI: 271 puts ("SCSI"); 272 break; 273 case IF_TYPE_ATAPI: 274 puts ("ATAPI"); 275 break; 276 case IF_TYPE_USB: 277 puts ("USB"); 278 break; 279 case IF_TYPE_DOC: 280 puts ("DOC"); 281 break; 282 case IF_TYPE_MMC: 283 puts ("MMC"); 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_RKSFC: 295 puts("RKSFC"); 296 break; 297 default: 298 puts ("UNKNOWN"); 299 break; 300 } 301 printf (" device %d -- Partition Type: %s\n\n", 302 dev_desc->devnum, type); 303 #endif /* any CONFIG_..._PARTITION */ 304 } 305 306 void part_print(struct blk_desc *dev_desc) 307 { 308 struct part_driver *drv; 309 310 drv = part_driver_lookup_type(dev_desc); 311 if (!drv) { 312 printf("## Unknown partition table type %x\n", 313 dev_desc->part_type); 314 return; 315 } 316 317 PRINTF("## Testing for valid %s partition ##\n", drv->name); 318 print_part_header(drv->name, dev_desc); 319 if (drv->print) 320 drv->print(dev_desc); 321 } 322 323 #endif /* HAVE_BLOCK_DEVICE */ 324 325 int part_get_info(struct blk_desc *dev_desc, int part, 326 disk_partition_t *info) 327 { 328 #ifdef HAVE_BLOCK_DEVICE 329 struct part_driver *drv; 330 331 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 332 /* The common case is no UUID support */ 333 info->uuid[0] = 0; 334 #endif 335 #ifdef CONFIG_PARTITION_TYPE_GUID 336 info->type_guid[0] = 0; 337 #endif 338 339 drv = part_driver_lookup_type(dev_desc); 340 if (!drv) { 341 debug("## Unknown partition table type %x\n", 342 dev_desc->part_type); 343 return -EPROTONOSUPPORT; 344 } 345 if (!drv->get_info) { 346 PRINTF("## Driver %s does not have the get_info() method\n", 347 drv->name); 348 return -ENOSYS; 349 } 350 if (drv->get_info(dev_desc, part, info) == 0) { 351 PRINTF("## Valid %s partition found ##\n", drv->name); 352 return 0; 353 } 354 #endif /* HAVE_BLOCK_DEVICE */ 355 356 return -1; 357 } 358 359 int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) 360 { 361 info->start = 0; 362 info->size = dev_desc->lba; 363 info->blksz = dev_desc->blksz; 364 info->bootable = 0; 365 strcpy((char *)info->type, BOOT_PART_TYPE); 366 strcpy((char *)info->name, "Whole Disk"); 367 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 368 info->uuid[0] = 0; 369 #endif 370 #ifdef CONFIG_PARTITION_TYPE_GUID 371 info->type_guid[0] = 0; 372 #endif 373 374 return 0; 375 } 376 377 int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, 378 struct blk_desc **dev_desc) 379 { 380 char *ep; 381 char *dup_str = NULL; 382 const char *dev_str, *hwpart_str; 383 int dev, hwpart; 384 385 hwpart_str = strchr(dev_hwpart_str, '.'); 386 if (hwpart_str) { 387 dup_str = strdup(dev_hwpart_str); 388 dup_str[hwpart_str - dev_hwpart_str] = 0; 389 dev_str = dup_str; 390 hwpart_str++; 391 } else { 392 dev_str = dev_hwpart_str; 393 hwpart = 0; 394 } 395 396 dev = simple_strtoul(dev_str, &ep, 16); 397 if (*ep) { 398 printf("** Bad device specification %s %s **\n", 399 ifname, dev_str); 400 dev = -EINVAL; 401 goto cleanup; 402 } 403 404 if (hwpart_str) { 405 hwpart = simple_strtoul(hwpart_str, &ep, 16); 406 if (*ep) { 407 printf("** Bad HW partition specification %s %s **\n", 408 ifname, hwpart_str); 409 dev = -EINVAL; 410 goto cleanup; 411 } 412 } 413 414 *dev_desc = get_dev_hwpart(ifname, dev, hwpart); 415 if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) { 416 printf("** Bad device %s %s **\n", ifname, dev_hwpart_str); 417 dev = -ENOENT; 418 goto cleanup; 419 } 420 421 #ifdef HAVE_BLOCK_DEVICE 422 /* 423 * Updates the partition table for the specified hw partition. 424 * Does not need to be done for hwpart 0 since it is default and 425 * already loaded. 426 */ 427 if(hwpart != 0) 428 part_init(*dev_desc); 429 #endif 430 431 cleanup: 432 free(dup_str); 433 return dev; 434 } 435 436 #define PART_UNSPECIFIED -2 437 #define PART_AUTO -1 438 int blk_get_device_part_str(const char *ifname, const char *dev_part_str, 439 struct blk_desc **dev_desc, 440 disk_partition_t *info, int allow_whole_dev) 441 { 442 int ret = -1; 443 const char *part_str; 444 char *dup_str = NULL; 445 const char *dev_str; 446 int dev; 447 char *ep; 448 int p; 449 int part; 450 disk_partition_t tmpinfo; 451 452 #ifdef CONFIG_SANDBOX 453 /* 454 * Special-case a pseudo block device "hostfs", to allow access to the 455 * host's own filesystem. 456 */ 457 if (0 == strcmp(ifname, "hostfs")) { 458 *dev_desc = NULL; 459 info->start = 0; 460 info->size = 0; 461 info->blksz = 0; 462 info->bootable = 0; 463 strcpy((char *)info->type, BOOT_PART_TYPE); 464 strcpy((char *)info->name, "Sandbox host"); 465 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 466 info->uuid[0] = 0; 467 #endif 468 #ifdef CONFIG_PARTITION_TYPE_GUID 469 info->type_guid[0] = 0; 470 #endif 471 472 return 0; 473 } 474 #endif 475 476 #ifdef CONFIG_CMD_UBIFS 477 /* 478 * Special-case ubi, ubi goes through a mtd, rathen then through 479 * a regular block device. 480 */ 481 if (0 == strcmp(ifname, "ubi")) { 482 if (!ubifs_is_mounted()) { 483 printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); 484 return -1; 485 } 486 487 *dev_desc = NULL; 488 memset(info, 0, sizeof(*info)); 489 strcpy((char *)info->type, BOOT_PART_TYPE); 490 strcpy((char *)info->name, "UBI"); 491 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 492 info->uuid[0] = 0; 493 #endif 494 return 0; 495 } 496 #endif 497 498 /* If no dev_part_str, use bootdevice environment variable */ 499 if (!dev_part_str || !strlen(dev_part_str) || 500 !strcmp(dev_part_str, "-")) 501 dev_part_str = env_get("bootdevice"); 502 503 /* If still no dev_part_str, it's an error */ 504 if (!dev_part_str) { 505 printf("** No device specified **\n"); 506 goto cleanup; 507 } 508 509 /* Separate device and partition ID specification */ 510 part_str = strchr(dev_part_str, ':'); 511 if (part_str) { 512 dup_str = strdup(dev_part_str); 513 dup_str[part_str - dev_part_str] = 0; 514 dev_str = dup_str; 515 part_str++; 516 } else { 517 dev_str = dev_part_str; 518 } 519 520 /* Look up the device */ 521 dev = blk_get_device_by_str(ifname, dev_str, dev_desc); 522 if (dev < 0) 523 goto cleanup; 524 525 /* Convert partition ID string to number */ 526 if (!part_str || !*part_str) { 527 part = PART_UNSPECIFIED; 528 } else if (!strcmp(part_str, "auto")) { 529 part = PART_AUTO; 530 } else { 531 /* Something specified -> use exactly that */ 532 part = (int)simple_strtoul(part_str, &ep, 16); 533 /* 534 * Less than whole string converted, 535 * or request for whole device, but caller requires partition. 536 */ 537 if (*ep || (part == 0 && !allow_whole_dev)) { 538 printf("** Bad partition specification %s %s **\n", 539 ifname, dev_part_str); 540 goto cleanup; 541 } 542 } 543 544 /* 545 * No partition table on device, 546 * or user requested partition 0 (entire device). 547 */ 548 if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) || 549 (part == 0)) { 550 if (!(*dev_desc)->lba) { 551 printf("** Bad device size - %s %s **\n", ifname, 552 dev_str); 553 goto cleanup; 554 } 555 556 /* 557 * If user specified a partition ID other than 0, 558 * or the calling command only accepts partitions, 559 * it's an error. 560 */ 561 if ((part > 0) || (!allow_whole_dev)) { 562 printf("** No partition table - %s %s **\n", ifname, 563 dev_str); 564 goto cleanup; 565 } 566 567 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 568 569 part_get_info_whole_disk(*dev_desc, info); 570 571 ret = 0; 572 goto cleanup; 573 } 574 575 /* 576 * Now there's known to be a partition table, 577 * not specifying a partition means to pick partition 1. 578 */ 579 if (part == PART_UNSPECIFIED) 580 part = 1; 581 582 /* 583 * If user didn't specify a partition number, or did specify something 584 * other than "auto", use that partition number directly. 585 */ 586 if (part != PART_AUTO) { 587 ret = part_get_info(*dev_desc, part, info); 588 if (ret) { 589 printf("** Invalid partition %d **\n", part); 590 goto cleanup; 591 } 592 } else { 593 /* 594 * Find the first bootable partition. 595 * If none are bootable, fall back to the first valid partition. 596 */ 597 part = 0; 598 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 599 ret = part_get_info(*dev_desc, p, info); 600 if (ret) 601 continue; 602 603 /* 604 * First valid partition, or new better partition? 605 * If so, save partition ID. 606 */ 607 if (!part || info->bootable) 608 part = p; 609 610 /* Best possible partition? Stop searching. */ 611 if (info->bootable) 612 break; 613 614 /* 615 * We now need to search further for best possible. 616 * If we what we just queried was the best so far, 617 * save the info since we over-write it next loop. 618 */ 619 if (part == p) 620 tmpinfo = *info; 621 } 622 /* If we found any acceptable partition */ 623 if (part) { 624 /* 625 * If we searched all possible partition IDs, 626 * return the first valid partition we found. 627 */ 628 if (p == MAX_SEARCH_PARTITIONS + 1) 629 *info = tmpinfo; 630 } else { 631 printf("** No valid partitions found **\n"); 632 ret = -1; 633 goto cleanup; 634 } 635 } 636 if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { 637 printf("** Invalid partition type \"%.32s\"" 638 " (expect \"" BOOT_PART_TYPE "\")\n", 639 info->type); 640 ret = -1; 641 goto cleanup; 642 } 643 644 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 645 646 ret = part; 647 goto cleanup; 648 649 cleanup: 650 free(dup_str); 651 return ret; 652 } 653 654 int part_get_info_by_name(struct blk_desc *dev_desc, const char *name, 655 disk_partition_t *info) 656 { 657 struct part_driver *part_drv; 658 int ret; 659 int i; 660 661 part_drv = part_driver_lookup_type(dev_desc); 662 if (!part_drv) 663 return -1; 664 for (i = 1; i < part_drv->max_entries; i++) { 665 ret = part_drv->get_info(dev_desc, i, info); 666 if (ret != 0) { 667 /* no more entries in table */ 668 break; 669 } 670 if (strcmp(name, (const char *)info->name) == 0) { 671 /* matched */ 672 return i; 673 } 674 } 675 676 return -1; 677 } 678 679 void part_set_generic_name(const struct blk_desc *dev_desc, 680 int part_num, char *name) 681 { 682 char *devtype; 683 684 switch (dev_desc->if_type) { 685 case IF_TYPE_IDE: 686 case IF_TYPE_SATA: 687 case IF_TYPE_ATAPI: 688 devtype = "hd"; 689 break; 690 case IF_TYPE_SCSI: 691 devtype = "sd"; 692 break; 693 case IF_TYPE_USB: 694 devtype = "usbd"; 695 break; 696 case IF_TYPE_DOC: 697 devtype = "docd"; 698 break; 699 case IF_TYPE_MMC: 700 case IF_TYPE_SD: 701 devtype = "mmcsd"; 702 break; 703 default: 704 devtype = "xx"; 705 break; 706 } 707 708 sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num); 709 } 710