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