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