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