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