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