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