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