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