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