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