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_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 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 case IF_TYPE_RKNAND: 286 puts("RKNAND"); 287 break; 288 default: 289 puts ("UNKNOWN"); 290 break; 291 } 292 printf (" device %d -- Partition Type: %s\n\n", 293 dev_desc->devnum, type); 294 #endif /* any CONFIG_..._PARTITION */ 295 } 296 297 void part_print(struct blk_desc *dev_desc) 298 { 299 struct part_driver *drv; 300 301 drv = part_driver_lookup_type(dev_desc); 302 if (!drv) { 303 printf("## Unknown partition table type %x\n", 304 dev_desc->part_type); 305 return; 306 } 307 308 PRINTF("## Testing for valid %s partition ##\n", drv->name); 309 print_part_header(drv->name, dev_desc); 310 if (drv->print) 311 drv->print(dev_desc); 312 } 313 314 #endif /* HAVE_BLOCK_DEVICE */ 315 316 int part_get_info(struct blk_desc *dev_desc, int part, 317 disk_partition_t *info) 318 { 319 #ifdef HAVE_BLOCK_DEVICE 320 struct part_driver *drv; 321 322 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 323 /* The common case is no UUID support */ 324 info->uuid[0] = 0; 325 #endif 326 #ifdef CONFIG_PARTITION_TYPE_GUID 327 info->type_guid[0] = 0; 328 #endif 329 330 drv = part_driver_lookup_type(dev_desc); 331 if (!drv) { 332 debug("## Unknown partition table type %x\n", 333 dev_desc->part_type); 334 return -EPROTONOSUPPORT; 335 } 336 if (!drv->get_info) { 337 PRINTF("## Driver %s does not have the get_info() method\n", 338 drv->name); 339 return -ENOSYS; 340 } 341 if (drv->get_info(dev_desc, part, info) == 0) { 342 PRINTF("## Valid %s partition found ##\n", drv->name); 343 return 0; 344 } 345 #endif /* HAVE_BLOCK_DEVICE */ 346 347 return -1; 348 } 349 350 int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) 351 { 352 info->start = 0; 353 info->size = dev_desc->lba; 354 info->blksz = dev_desc->blksz; 355 info->bootable = 0; 356 strcpy((char *)info->type, BOOT_PART_TYPE); 357 strcpy((char *)info->name, "Whole Disk"); 358 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 359 info->uuid[0] = 0; 360 #endif 361 #ifdef CONFIG_PARTITION_TYPE_GUID 362 info->type_guid[0] = 0; 363 #endif 364 365 return 0; 366 } 367 368 int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, 369 struct blk_desc **dev_desc) 370 { 371 char *ep; 372 char *dup_str = NULL; 373 const char *dev_str, *hwpart_str; 374 int dev, hwpart; 375 376 hwpart_str = strchr(dev_hwpart_str, '.'); 377 if (hwpart_str) { 378 dup_str = strdup(dev_hwpart_str); 379 dup_str[hwpart_str - dev_hwpart_str] = 0; 380 dev_str = dup_str; 381 hwpart_str++; 382 } else { 383 dev_str = dev_hwpart_str; 384 hwpart = 0; 385 } 386 387 dev = simple_strtoul(dev_str, &ep, 16); 388 if (*ep) { 389 printf("** Bad device specification %s %s **\n", 390 ifname, dev_str); 391 dev = -EINVAL; 392 goto cleanup; 393 } 394 395 if (hwpart_str) { 396 hwpart = simple_strtoul(hwpart_str, &ep, 16); 397 if (*ep) { 398 printf("** Bad HW partition specification %s %s **\n", 399 ifname, hwpart_str); 400 dev = -EINVAL; 401 goto cleanup; 402 } 403 } 404 405 *dev_desc = get_dev_hwpart(ifname, dev, hwpart); 406 if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) { 407 printf("** Bad device %s %s **\n", ifname, dev_hwpart_str); 408 dev = -ENOENT; 409 goto cleanup; 410 } 411 412 #ifdef HAVE_BLOCK_DEVICE 413 /* 414 * Updates the partition table for the specified hw partition. 415 * Does not need to be done for hwpart 0 since it is default and 416 * already loaded. 417 */ 418 if(hwpart != 0) 419 part_init(*dev_desc); 420 #endif 421 422 cleanup: 423 free(dup_str); 424 return dev; 425 } 426 427 #define PART_UNSPECIFIED -2 428 #define PART_AUTO -1 429 int blk_get_device_part_str(const char *ifname, const char *dev_part_str, 430 struct blk_desc **dev_desc, 431 disk_partition_t *info, int allow_whole_dev) 432 { 433 int ret = -1; 434 const char *part_str; 435 char *dup_str = NULL; 436 const char *dev_str; 437 int dev; 438 char *ep; 439 int p; 440 int part; 441 disk_partition_t tmpinfo; 442 443 #ifdef CONFIG_SANDBOX 444 /* 445 * Special-case a pseudo block device "hostfs", to allow access to the 446 * host's own filesystem. 447 */ 448 if (0 == strcmp(ifname, "hostfs")) { 449 *dev_desc = NULL; 450 info->start = 0; 451 info->size = 0; 452 info->blksz = 0; 453 info->bootable = 0; 454 strcpy((char *)info->type, BOOT_PART_TYPE); 455 strcpy((char *)info->name, "Sandbox host"); 456 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 457 info->uuid[0] = 0; 458 #endif 459 #ifdef CONFIG_PARTITION_TYPE_GUID 460 info->type_guid[0] = 0; 461 #endif 462 463 return 0; 464 } 465 #endif 466 467 #ifdef CONFIG_CMD_UBIFS 468 /* 469 * Special-case ubi, ubi goes through a mtd, rathen then through 470 * a regular block device. 471 */ 472 if (0 == strcmp(ifname, "ubi")) { 473 if (!ubifs_is_mounted()) { 474 printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); 475 return -1; 476 } 477 478 *dev_desc = NULL; 479 memset(info, 0, sizeof(*info)); 480 strcpy((char *)info->type, BOOT_PART_TYPE); 481 strcpy((char *)info->name, "UBI"); 482 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 483 info->uuid[0] = 0; 484 #endif 485 return 0; 486 } 487 #endif 488 489 /* If no dev_part_str, use bootdevice environment variable */ 490 if (!dev_part_str || !strlen(dev_part_str) || 491 !strcmp(dev_part_str, "-")) 492 dev_part_str = env_get("bootdevice"); 493 494 /* If still no dev_part_str, it's an error */ 495 if (!dev_part_str) { 496 printf("** No device specified **\n"); 497 goto cleanup; 498 } 499 500 /* Separate device and partition ID specification */ 501 part_str = strchr(dev_part_str, ':'); 502 if (part_str) { 503 dup_str = strdup(dev_part_str); 504 dup_str[part_str - dev_part_str] = 0; 505 dev_str = dup_str; 506 part_str++; 507 } else { 508 dev_str = dev_part_str; 509 } 510 511 /* Look up the device */ 512 dev = blk_get_device_by_str(ifname, dev_str, dev_desc); 513 if (dev < 0) 514 goto cleanup; 515 516 /* Convert partition ID string to number */ 517 if (!part_str || !*part_str) { 518 part = PART_UNSPECIFIED; 519 } else if (!strcmp(part_str, "auto")) { 520 part = PART_AUTO; 521 } else { 522 /* Something specified -> use exactly that */ 523 part = (int)simple_strtoul(part_str, &ep, 16); 524 /* 525 * Less than whole string converted, 526 * or request for whole device, but caller requires partition. 527 */ 528 if (*ep || (part == 0 && !allow_whole_dev)) { 529 printf("** Bad partition specification %s %s **\n", 530 ifname, dev_part_str); 531 goto cleanup; 532 } 533 } 534 535 /* 536 * No partition table on device, 537 * or user requested partition 0 (entire device). 538 */ 539 if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) || 540 (part == 0)) { 541 if (!(*dev_desc)->lba) { 542 printf("** Bad device size - %s %s **\n", ifname, 543 dev_str); 544 goto cleanup; 545 } 546 547 /* 548 * If user specified a partition ID other than 0, 549 * or the calling command only accepts partitions, 550 * it's an error. 551 */ 552 if ((part > 0) || (!allow_whole_dev)) { 553 printf("** No partition table - %s %s **\n", ifname, 554 dev_str); 555 goto cleanup; 556 } 557 558 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 559 560 part_get_info_whole_disk(*dev_desc, info); 561 562 ret = 0; 563 goto cleanup; 564 } 565 566 /* 567 * Now there's known to be a partition table, 568 * not specifying a partition means to pick partition 1. 569 */ 570 if (part == PART_UNSPECIFIED) 571 part = 1; 572 573 /* 574 * If user didn't specify a partition number, or did specify something 575 * other than "auto", use that partition number directly. 576 */ 577 if (part != PART_AUTO) { 578 ret = part_get_info(*dev_desc, part, info); 579 if (ret) { 580 printf("** Invalid partition %d **\n", part); 581 goto cleanup; 582 } 583 } else { 584 /* 585 * Find the first bootable partition. 586 * If none are bootable, fall back to the first valid partition. 587 */ 588 part = 0; 589 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 590 ret = part_get_info(*dev_desc, p, info); 591 if (ret) 592 continue; 593 594 /* 595 * First valid partition, or new better partition? 596 * If so, save partition ID. 597 */ 598 if (!part || info->bootable) 599 part = p; 600 601 /* Best possible partition? Stop searching. */ 602 if (info->bootable) 603 break; 604 605 /* 606 * We now need to search further for best possible. 607 * If we what we just queried was the best so far, 608 * save the info since we over-write it next loop. 609 */ 610 if (part == p) 611 tmpinfo = *info; 612 } 613 /* If we found any acceptable partition */ 614 if (part) { 615 /* 616 * If we searched all possible partition IDs, 617 * return the first valid partition we found. 618 */ 619 if (p == MAX_SEARCH_PARTITIONS + 1) 620 *info = tmpinfo; 621 } else { 622 printf("** No valid partitions found **\n"); 623 ret = -1; 624 goto cleanup; 625 } 626 } 627 if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { 628 printf("** Invalid partition type \"%.32s\"" 629 " (expect \"" BOOT_PART_TYPE "\")\n", 630 info->type); 631 ret = -1; 632 goto cleanup; 633 } 634 635 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 636 637 ret = part; 638 goto cleanup; 639 640 cleanup: 641 free(dup_str); 642 return ret; 643 } 644 645 int part_get_info_by_name(struct blk_desc *dev_desc, const char *name, 646 disk_partition_t *info) 647 { 648 struct part_driver *part_drv; 649 int ret; 650 int i; 651 652 part_drv = part_driver_lookup_type(dev_desc); 653 if (!part_drv) 654 return -1; 655 for (i = 1; i < part_drv->max_entries; i++) { 656 ret = part_drv->get_info(dev_desc, i, info); 657 if (ret != 0) { 658 /* no more entries in table */ 659 break; 660 } 661 if (strcmp(name, (const char *)info->name) == 0) { 662 /* matched */ 663 return i; 664 } 665 } 666 667 return -1; 668 } 669 670 void part_set_generic_name(const struct blk_desc *dev_desc, 671 int part_num, char *name) 672 { 673 char *devtype; 674 675 switch (dev_desc->if_type) { 676 case IF_TYPE_IDE: 677 case IF_TYPE_SATA: 678 case IF_TYPE_ATAPI: 679 devtype = "hd"; 680 break; 681 case IF_TYPE_SCSI: 682 devtype = "sd"; 683 break; 684 case IF_TYPE_USB: 685 devtype = "usbd"; 686 break; 687 case IF_TYPE_DOC: 688 devtype = "docd"; 689 break; 690 case IF_TYPE_MMC: 691 case IF_TYPE_SD: 692 devtype = "mmcsd"; 693 break; 694 default: 695 devtype = "xx"; 696 break; 697 } 698 699 sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num); 700 } 701