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 #ifdef HAVE_BLOCK_DEVICE 497 /* 498 * Updates the partition table for the specified hw partition. 499 * Does not need to be done for hwpart 0 since it is default and 500 * already loaded. 501 */ 502 if(hwpart != 0) 503 init_part(*dev_desc); 504 #endif 505 506 cleanup: 507 free(dup_str); 508 return dev; 509 } 510 511 #define PART_UNSPECIFIED -2 512 #define PART_AUTO -1 513 #define MAX_SEARCH_PARTITIONS 16 514 int get_device_and_partition(const char *ifname, const char *dev_part_str, 515 block_dev_desc_t **dev_desc, 516 disk_partition_t *info, int allow_whole_dev) 517 { 518 int ret = -1; 519 const char *part_str; 520 char *dup_str = NULL; 521 const char *dev_str; 522 int dev; 523 char *ep; 524 int p; 525 int part; 526 disk_partition_t tmpinfo; 527 528 #if defined CONFIG_SANDBOX && defined CONFIG_CMD_UBIFS 529 #error Only one of CONFIG_SANDBOX and CONFIG_CMD_UBIFS may be selected 530 #endif 531 532 #ifdef CONFIG_SANDBOX 533 /* 534 * Special-case a pseudo block device "hostfs", to allow access to the 535 * host's own filesystem. 536 */ 537 if (0 == strcmp(ifname, "hostfs")) { 538 *dev_desc = NULL; 539 info->start = 0; 540 info->size = 0; 541 info->blksz = 0; 542 info->bootable = 0; 543 strcpy((char *)info->type, BOOT_PART_TYPE); 544 strcpy((char *)info->name, "Sandbox host"); 545 #ifdef CONFIG_PARTITION_UUIDS 546 info->uuid[0] = 0; 547 #endif 548 #ifdef CONFIG_PARTITION_TYPE_GUID 549 info->type_guid[0] = 0; 550 #endif 551 552 return 0; 553 } 554 #endif 555 556 #ifdef CONFIG_CMD_UBIFS 557 /* 558 * Special-case ubi, ubi goes through a mtd, rathen then through 559 * a regular block device. 560 */ 561 if (0 == strcmp(ifname, "ubi")) { 562 if (!ubifs_is_mounted()) { 563 printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); 564 return -1; 565 } 566 567 *dev_desc = NULL; 568 memset(info, 0, sizeof(*info)); 569 strcpy((char *)info->type, BOOT_PART_TYPE); 570 strcpy((char *)info->name, "UBI"); 571 #ifdef CONFIG_PARTITION_UUIDS 572 info->uuid[0] = 0; 573 #endif 574 return 0; 575 } 576 #endif 577 578 /* If no dev_part_str, use bootdevice environment variable */ 579 if (!dev_part_str || !strlen(dev_part_str) || 580 !strcmp(dev_part_str, "-")) 581 dev_part_str = getenv("bootdevice"); 582 583 /* If still no dev_part_str, it's an error */ 584 if (!dev_part_str) { 585 printf("** No device specified **\n"); 586 goto cleanup; 587 } 588 589 /* Separate device and partition ID specification */ 590 part_str = strchr(dev_part_str, ':'); 591 if (part_str) { 592 dup_str = strdup(dev_part_str); 593 dup_str[part_str - dev_part_str] = 0; 594 dev_str = dup_str; 595 part_str++; 596 } else { 597 dev_str = dev_part_str; 598 } 599 600 /* Look up the device */ 601 dev = get_device(ifname, dev_str, dev_desc); 602 if (dev < 0) 603 goto cleanup; 604 605 /* Convert partition ID string to number */ 606 if (!part_str || !*part_str) { 607 part = PART_UNSPECIFIED; 608 } else if (!strcmp(part_str, "auto")) { 609 part = PART_AUTO; 610 } else { 611 /* Something specified -> use exactly that */ 612 part = (int)simple_strtoul(part_str, &ep, 16); 613 /* 614 * Less than whole string converted, 615 * or request for whole device, but caller requires partition. 616 */ 617 if (*ep || (part == 0 && !allow_whole_dev)) { 618 printf("** Bad partition specification %s %s **\n", 619 ifname, dev_part_str); 620 goto cleanup; 621 } 622 } 623 624 /* 625 * No partition table on device, 626 * or user requested partition 0 (entire device). 627 */ 628 if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) || 629 (part == 0)) { 630 if (!(*dev_desc)->lba) { 631 printf("** Bad device size - %s %s **\n", ifname, 632 dev_str); 633 goto cleanup; 634 } 635 636 /* 637 * If user specified a partition ID other than 0, 638 * or the calling command only accepts partitions, 639 * it's an error. 640 */ 641 if ((part > 0) || (!allow_whole_dev)) { 642 printf("** No partition table - %s %s **\n", ifname, 643 dev_str); 644 goto cleanup; 645 } 646 647 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 648 649 info->start = 0; 650 info->size = (*dev_desc)->lba; 651 info->blksz = (*dev_desc)->blksz; 652 info->bootable = 0; 653 strcpy((char *)info->type, BOOT_PART_TYPE); 654 strcpy((char *)info->name, "Whole Disk"); 655 #ifdef CONFIG_PARTITION_UUIDS 656 info->uuid[0] = 0; 657 #endif 658 #ifdef CONFIG_PARTITION_TYPE_GUID 659 info->type_guid[0] = 0; 660 #endif 661 662 ret = 0; 663 goto cleanup; 664 } 665 666 /* 667 * Now there's known to be a partition table, 668 * not specifying a partition means to pick partition 1. 669 */ 670 if (part == PART_UNSPECIFIED) 671 part = 1; 672 673 /* 674 * If user didn't specify a partition number, or did specify something 675 * other than "auto", use that partition number directly. 676 */ 677 if (part != PART_AUTO) { 678 ret = get_partition_info(*dev_desc, part, info); 679 if (ret) { 680 printf("** Invalid partition %d **\n", part); 681 goto cleanup; 682 } 683 } else { 684 /* 685 * Find the first bootable partition. 686 * If none are bootable, fall back to the first valid partition. 687 */ 688 part = 0; 689 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { 690 ret = get_partition_info(*dev_desc, p, info); 691 if (ret) 692 continue; 693 694 /* 695 * First valid partition, or new better partition? 696 * If so, save partition ID. 697 */ 698 if (!part || info->bootable) 699 part = p; 700 701 /* Best possible partition? Stop searching. */ 702 if (info->bootable) 703 break; 704 705 /* 706 * We now need to search further for best possible. 707 * If we what we just queried was the best so far, 708 * save the info since we over-write it next loop. 709 */ 710 if (part == p) 711 tmpinfo = *info; 712 } 713 /* If we found any acceptable partition */ 714 if (part) { 715 /* 716 * If we searched all possible partition IDs, 717 * return the first valid partition we found. 718 */ 719 if (p == MAX_SEARCH_PARTITIONS + 1) 720 *info = tmpinfo; 721 } else { 722 printf("** No valid partitions found **\n"); 723 ret = -1; 724 goto cleanup; 725 } 726 } 727 if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { 728 printf("** Invalid partition type \"%.32s\"" 729 " (expect \"" BOOT_PART_TYPE "\")\n", 730 info->type); 731 ret = -1; 732 goto cleanup; 733 } 734 735 (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); 736 737 ret = part; 738 goto cleanup; 739 740 cleanup: 741 free(dup_str); 742 return ret; 743 } 744