uboot/disk/part.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 */
   6
   7#include <common.h>
   8#include <command.h>
   9#include <env.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/* Check all partition types */
  25#define PART_TYPE_ALL           -1
  26
  27static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc)
  28{
  29        struct part_driver *drv =
  30                ll_entry_start(struct part_driver, part_driver);
  31        const int n_ents = ll_entry_count(struct part_driver, part_driver);
  32        struct part_driver *entry;
  33
  34        if (dev_desc->part_type == PART_TYPE_UNKNOWN) {
  35                for (entry = drv; entry != drv + n_ents; entry++) {
  36                        int ret;
  37
  38                        ret = entry->test(dev_desc);
  39                        if (!ret) {
  40                                dev_desc->part_type = entry->part_type;
  41                                return entry;
  42                        }
  43                }
  44        } else {
  45                for (entry = drv; entry != drv + n_ents; entry++) {
  46                        if (dev_desc->part_type == entry->part_type)
  47                                return entry;
  48                }
  49        }
  50
  51        /* Not found */
  52        return NULL;
  53}
  54
  55#ifdef CONFIG_HAVE_BLOCK_DEVICE
  56static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
  57{
  58        struct blk_desc *dev_desc;
  59        int ret;
  60
  61        dev_desc = blk_get_devnum_by_typename(ifname, dev);
  62        if (!dev_desc) {
  63                debug("%s: No device for iface '%s', dev %d\n", __func__,
  64                      ifname, dev);
  65                return NULL;
  66        }
  67        ret = blk_dselect_hwpart(dev_desc, hwpart);
  68        if (ret) {
  69                debug("%s: Failed to select h/w partition: err-%d\n", __func__,
  70                      ret);
  71                return NULL;
  72        }
  73
  74        return dev_desc;
  75}
  76
  77struct blk_desc *blk_get_dev(const char *ifname, int dev)
  78{
  79        return get_dev_hwpart(ifname, dev, 0);
  80}
  81#else
  82struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
  83{
  84        return NULL;
  85}
  86
  87struct blk_desc *blk_get_dev(const char *ifname, int dev)
  88{
  89        return NULL;
  90}
  91#endif
  92
  93#ifdef CONFIG_HAVE_BLOCK_DEVICE
  94
  95/* ------------------------------------------------------------------------- */
  96/*
  97 * reports device info to the user
  98 */
  99
 100#ifdef CONFIG_LBA48
 101typedef uint64_t lba512_t;
 102#else
 103typedef lbaint_t lba512_t;
 104#endif
 105
 106/*
 107 * Overflowless variant of (block_count * mul_by / 2**div_by)
 108 * when div_by > mul_by
 109 */
 110static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, int div_by)
 111{
 112        lba512_t bc_quot, bc_rem;
 113
 114        /* x * m / d == x / d * m + (x % d) * m / d */
 115        bc_quot = block_count >> div_by;
 116        bc_rem  = block_count - (bc_quot << div_by);
 117        return bc_quot * mul_by + ((bc_rem * mul_by) >> div_by);
 118}
 119
 120void dev_print (struct blk_desc *dev_desc)
 121{
 122        lba512_t lba512; /* number of blocks if 512bytes block size */
 123
 124        if (dev_desc->type == DEV_TYPE_UNKNOWN) {
 125                puts ("not available\n");
 126                return;
 127        }
 128
 129        switch (dev_desc->if_type) {
 130        case IF_TYPE_SCSI:
 131                printf ("(%d:%d) Vendor: %s Prod.: %s Rev: %s\n",
 132                        dev_desc->target,dev_desc->lun,
 133                        dev_desc->vendor,
 134                        dev_desc->product,
 135                        dev_desc->revision);
 136                break;
 137        case IF_TYPE_ATAPI:
 138        case IF_TYPE_IDE:
 139        case IF_TYPE_SATA:
 140                printf ("Model: %s Firm: %s Ser#: %s\n",
 141                        dev_desc->vendor,
 142                        dev_desc->revision,
 143                        dev_desc->product);
 144                break;
 145        case IF_TYPE_SD:
 146        case IF_TYPE_MMC:
 147        case IF_TYPE_USB:
 148        case IF_TYPE_NVME:
 149                printf ("Vendor: %s Rev: %s Prod: %s\n",
 150                        dev_desc->vendor,
 151                        dev_desc->revision,
 152                        dev_desc->product);
 153                break;
 154        case IF_TYPE_VIRTIO:
 155                printf("%s VirtIO Block Device\n", dev_desc->vendor);
 156                break;
 157        case IF_TYPE_DOC:
 158                puts("device type DOC\n");
 159                return;
 160        case IF_TYPE_UNKNOWN:
 161                puts("device type unknown\n");
 162                return;
 163        default:
 164                printf("Unhandled device type: %i\n", dev_desc->if_type);
 165                return;
 166        }
 167        puts ("            Type: ");
 168        if (dev_desc->removable)
 169                puts ("Removable ");
 170        switch (dev_desc->type & 0x1F) {
 171        case DEV_TYPE_HARDDISK:
 172                puts ("Hard Disk");
 173                break;
 174        case DEV_TYPE_CDROM:
 175                puts ("CD ROM");
 176                break;
 177        case DEV_TYPE_OPDISK:
 178                puts ("Optical Device");
 179                break;
 180        case DEV_TYPE_TAPE:
 181                puts ("Tape");
 182                break;
 183        default:
 184                printf ("# %02X #", dev_desc->type & 0x1F);
 185                break;
 186        }
 187        puts ("\n");
 188        if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
 189                ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
 190                lbaint_t lba;
 191
 192                lba = dev_desc->lba;
 193
 194                lba512 = (lba * (dev_desc->blksz/512));
 195                /* round to 1 digit */
 196                /* 2048 = (1024 * 1024) / 512 MB */
 197                mb = lba512_muldiv(lba512, 10, 11);
 198
 199                mb_quot = mb / 10;
 200                mb_rem  = mb - (10 * mb_quot);
 201
 202                gb = mb / 1024;
 203                gb_quot = gb / 10;
 204                gb_rem  = gb - (10 * gb_quot);
 205#ifdef CONFIG_LBA48
 206                if (dev_desc->lba48)
 207                        printf ("            Supports 48-bit addressing\n");
 208#endif
 209#if defined(CONFIG_SYS_64BIT_LBA)
 210                printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%llu x %lu)\n",
 211                        mb_quot, mb_rem,
 212                        gb_quot, gb_rem,
 213                        lba,
 214                        dev_desc->blksz);
 215#else
 216                printf ("            Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)\n",
 217                        mb_quot, mb_rem,
 218                        gb_quot, gb_rem,
 219                        (ulong)lba,
 220                        dev_desc->blksz);
 221#endif
 222        } else {
 223                puts ("            Capacity: not available\n");
 224        }
 225}
 226#endif
 227
 228#ifdef CONFIG_HAVE_BLOCK_DEVICE
 229
 230void part_init(struct blk_desc *dev_desc)
 231{
 232        struct part_driver *drv =
 233                ll_entry_start(struct part_driver, part_driver);
 234        const int n_ents = ll_entry_count(struct part_driver, part_driver);
 235        struct part_driver *entry;
 236
 237        blkcache_invalidate(dev_desc->if_type, dev_desc->devnum);
 238
 239        dev_desc->part_type = PART_TYPE_UNKNOWN;
 240        for (entry = drv; entry != drv + n_ents; entry++) {
 241                int ret;
 242
 243                ret = entry->test(dev_desc);
 244                debug("%s: try '%s': ret=%d\n", __func__, entry->name, ret);
 245                if (!ret) {
 246                        dev_desc->part_type = entry->part_type;
 247                        break;
 248                }
 249        }
 250}
 251
 252static void print_part_header(const char *type, struct blk_desc *dev_desc)
 253{
 254#if CONFIG_IS_ENABLED(MAC_PARTITION) || \
 255        CONFIG_IS_ENABLED(DOS_PARTITION) || \
 256        CONFIG_IS_ENABLED(ISO_PARTITION) || \
 257        CONFIG_IS_ENABLED(AMIGA_PARTITION) || \
 258        CONFIG_IS_ENABLED(EFI_PARTITION)
 259        puts ("\nPartition Map for ");
 260        switch (dev_desc->if_type) {
 261        case IF_TYPE_IDE:
 262                puts ("IDE");
 263                break;
 264        case IF_TYPE_SATA:
 265                puts ("SATA");
 266                break;
 267        case IF_TYPE_SCSI:
 268                puts ("SCSI");
 269                break;
 270        case IF_TYPE_ATAPI:
 271                puts ("ATAPI");
 272                break;
 273        case IF_TYPE_USB:
 274                puts ("USB");
 275                break;
 276        case IF_TYPE_DOC:
 277                puts ("DOC");
 278                break;
 279        case IF_TYPE_MMC:
 280                puts ("MMC");
 281                break;
 282        case IF_TYPE_HOST:
 283                puts ("HOST");
 284                break;
 285        case IF_TYPE_NVME:
 286                puts ("NVMe");
 287                break;
 288        case IF_TYPE_VIRTIO:
 289                puts("VirtIO");
 290                break;
 291        default:
 292                puts ("UNKNOWN");
 293                break;
 294        }
 295        printf (" device %d  --   Partition Type: %s\n\n",
 296                        dev_desc->devnum, type);
 297#endif /* any CONFIG_..._PARTITION */
 298}
 299
 300void part_print(struct blk_desc *dev_desc)
 301{
 302        struct part_driver *drv;
 303
 304        drv = part_driver_lookup_type(dev_desc);
 305        if (!drv) {
 306                printf("## Unknown partition table type %x\n",
 307                       dev_desc->part_type);
 308                return;
 309        }
 310
 311        PRINTF("## Testing for valid %s partition ##\n", drv->name);
 312        print_part_header(drv->name, dev_desc);
 313        if (drv->print)
 314                drv->print(dev_desc);
 315}
 316
 317#endif /* CONFIG_HAVE_BLOCK_DEVICE */
 318
 319int part_get_info(struct blk_desc *dev_desc, int part,
 320                       disk_partition_t *info)
 321{
 322#ifdef CONFIG_HAVE_BLOCK_DEVICE
 323        struct part_driver *drv;
 324
 325#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
 326        /* The common case is no UUID support */
 327        info->uuid[0] = 0;
 328#endif
 329#ifdef CONFIG_PARTITION_TYPE_GUID
 330        info->type_guid[0] = 0;
 331#endif
 332
 333        drv = part_driver_lookup_type(dev_desc);
 334        if (!drv) {
 335                debug("## Unknown partition table type %x\n",
 336                      dev_desc->part_type);
 337                return -EPROTONOSUPPORT;
 338        }
 339        if (!drv->get_info) {
 340                PRINTF("## Driver %s does not have the get_info() method\n",
 341                       drv->name);
 342                return -ENOSYS;
 343        }
 344        if (drv->get_info(dev_desc, part, info) == 0) {
 345                PRINTF("## Valid %s partition found ##\n", drv->name);
 346                return 0;
 347        }
 348#endif /* CONFIG_HAVE_BLOCK_DEVICE */
 349
 350        return -1;
 351}
 352
 353int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info)
 354{
 355        info->start = 0;
 356        info->size = dev_desc->lba;
 357        info->blksz = dev_desc->blksz;
 358        info->bootable = 0;
 359        strcpy((char *)info->type, BOOT_PART_TYPE);
 360        strcpy((char *)info->name, "Whole Disk");
 361#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
 362        info->uuid[0] = 0;
 363#endif
 364#ifdef CONFIG_PARTITION_TYPE_GUID
 365        info->type_guid[0] = 0;
 366#endif
 367
 368        return 0;
 369}
 370
 371int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
 372                          struct blk_desc **dev_desc)
 373{
 374        char *ep;
 375        char *dup_str = NULL;
 376        const char *dev_str, *hwpart_str;
 377        int dev, hwpart;
 378
 379        hwpart_str = strchr(dev_hwpart_str, '.');
 380        if (hwpart_str) {
 381                dup_str = strdup(dev_hwpart_str);
 382                dup_str[hwpart_str - dev_hwpart_str] = 0;
 383                dev_str = dup_str;
 384                hwpart_str++;
 385        } else {
 386                dev_str = dev_hwpart_str;
 387                hwpart = 0;
 388        }
 389
 390        dev = simple_strtoul(dev_str, &ep, 16);
 391        if (*ep) {
 392                printf("** Bad device specification %s %s **\n",
 393                       ifname, dev_str);
 394                dev = -EINVAL;
 395                goto cleanup;
 396        }
 397
 398        if (hwpart_str) {
 399                hwpart = simple_strtoul(hwpart_str, &ep, 16);
 400                if (*ep) {
 401                        printf("** Bad HW partition specification %s %s **\n",
 402                            ifname, hwpart_str);
 403                        dev = -EINVAL;
 404                        goto cleanup;
 405                }
 406        }
 407
 408        *dev_desc = get_dev_hwpart(ifname, dev, hwpart);
 409        if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
 410                debug("** Bad device %s %s **\n", ifname, dev_hwpart_str);
 411                dev = -ENOENT;
 412                goto cleanup;
 413        }
 414
 415#ifdef CONFIG_HAVE_BLOCK_DEVICE
 416        /*
 417         * Updates the partition table for the specified hw partition.
 418         * Always should be done, otherwise hw partition 0 will return stale
 419         * data after displaying a non-zero hw partition.
 420         */
 421        part_init(*dev_desc);
 422#endif
 423
 424cleanup:
 425        free(dup_str);
 426        return dev;
 427}
 428
 429#define PART_UNSPECIFIED -2
 430#define PART_AUTO -1
 431int 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#if CONFIG_IS_ENABLED(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, rather than 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#if CONFIG_IS_ENABLED(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 = env_get("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                part_get_info_whole_disk(*dev_desc, info);
 563
 564                ret = 0;
 565                goto cleanup;
 566        }
 567
 568        /*
 569         * Now there's known to be a partition table,
 570         * not specifying a partition means to pick partition 1.
 571         */
 572        if (part == PART_UNSPECIFIED)
 573                part = 1;
 574
 575        /*
 576         * If user didn't specify a partition number, or did specify something
 577         * other than "auto", use that partition number directly.
 578         */
 579        if (part != PART_AUTO) {
 580                ret = part_get_info(*dev_desc, part, info);
 581                if (ret) {
 582                        printf("** Invalid partition %d **\n", part);
 583                        goto cleanup;
 584                }
 585        } else {
 586                /*
 587                 * Find the first bootable partition.
 588                 * If none are bootable, fall back to the first valid partition.
 589                 */
 590                part = 0;
 591                for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
 592                        ret = part_get_info(*dev_desc, p, info);
 593                        if (ret)
 594                                continue;
 595
 596                        /*
 597                         * First valid partition, or new better partition?
 598                         * If so, save partition ID.
 599                         */
 600                        if (!part || info->bootable)
 601                                part = p;
 602
 603                        /* Best possible partition? Stop searching. */
 604                        if (info->bootable)
 605                                break;
 606
 607                        /*
 608                         * We now need to search further for best possible.
 609                         * If we what we just queried was the best so far,
 610                         * save the info since we over-write it next loop.
 611                         */
 612                        if (part == p)
 613                                tmpinfo = *info;
 614                }
 615                /* If we found any acceptable partition */
 616                if (part) {
 617                        /*
 618                         * If we searched all possible partition IDs,
 619                         * return the first valid partition we found.
 620                         */
 621                        if (p == MAX_SEARCH_PARTITIONS + 1)
 622                                *info = tmpinfo;
 623                } else {
 624                        printf("** No valid partitions found **\n");
 625                        ret = -1;
 626                        goto cleanup;
 627                }
 628        }
 629        if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
 630                printf("** Invalid partition type \"%.32s\""
 631                        " (expect \"" BOOT_PART_TYPE "\")\n",
 632                        info->type);
 633                ret  = -1;
 634                goto cleanup;
 635        }
 636
 637        (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
 638
 639        ret = part;
 640        goto cleanup;
 641
 642cleanup:
 643        free(dup_str);
 644        return ret;
 645}
 646
 647int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
 648                               disk_partition_t *info, int part_type)
 649{
 650        struct part_driver *part_drv;
 651        int ret;
 652        int i;
 653
 654        part_drv = part_driver_lookup_type(dev_desc);
 655        if (!part_drv)
 656                return -1;
 657        for (i = 1; i < part_drv->max_entries; i++) {
 658                ret = part_drv->get_info(dev_desc, i, info);
 659                if (ret != 0) {
 660                        /* no more entries in table */
 661                        break;
 662                }
 663                if (strcmp(name, (const char *)info->name) == 0) {
 664                        /* matched */
 665                        return i;
 666                }
 667        }
 668
 669        return -1;
 670}
 671
 672int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
 673                          disk_partition_t *info)
 674{
 675        return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
 676}
 677
 678/**
 679 * Get partition info from device number and partition name.
 680 *
 681 * Parse a device number and partition name string in the form of
 682 * "device_num#partition_name", for example "0#misc". If the partition
 683 * is found, sets dev_desc and part_info accordingly with the information
 684 * of the partition with the given partition_name.
 685 *
 686 * @param[in] dev_iface Device interface
 687 * @param[in] dev_part_str Input string argument, like "0#misc"
 688 * @param[out] dev_desc Place to store the device description pointer
 689 * @param[out] part_info Place to store the partition information
 690 * @return 0 on success, or a negative on error
 691 */
 692static int part_get_info_by_dev_and_name(const char *dev_iface,
 693                                         const char *dev_part_str,
 694                                         struct blk_desc **dev_desc,
 695                                         disk_partition_t *part_info)
 696{
 697        char *ep;
 698        const char *part_str;
 699        int dev_num;
 700
 701        part_str = strchr(dev_part_str, '#');
 702        if (!part_str || part_str == dev_part_str)
 703                return -EINVAL;
 704
 705        dev_num = simple_strtoul(dev_part_str, &ep, 16);
 706        if (ep != part_str) {
 707                /* Not all the first part before the # was parsed. */
 708                return -EINVAL;
 709        }
 710        part_str++;
 711
 712        *dev_desc = blk_get_dev(dev_iface, dev_num);
 713        if (!*dev_desc) {
 714                printf("Could not find %s %d\n", dev_iface, dev_num);
 715                return -EINVAL;
 716        }
 717        if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
 718                printf("Could not find \"%s\" partition\n", part_str);
 719                return -EINVAL;
 720        }
 721        return 0;
 722}
 723
 724int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
 725                                         const char *dev_part_str,
 726                                         struct blk_desc **dev_desc,
 727                                         disk_partition_t *part_info)
 728{
 729        /* Split the part_name if passed as "$dev_num#part_name". */
 730        if (!part_get_info_by_dev_and_name(dev_iface, dev_part_str,
 731                                           dev_desc, part_info))
 732                return 0;
 733        /*
 734         * Couldn't lookup by name, try looking up the partition description
 735         * directly.
 736         */
 737        if (blk_get_device_part_str(dev_iface, dev_part_str,
 738                                    dev_desc, part_info, 1) < 0) {
 739                printf("Couldn't find partition %s %s\n",
 740                       dev_iface, dev_part_str);
 741                return -EINVAL;
 742        }
 743        return 0;
 744}
 745
 746void part_set_generic_name(const struct blk_desc *dev_desc,
 747        int part_num, char *name)
 748{
 749        char *devtype;
 750
 751        switch (dev_desc->if_type) {
 752        case IF_TYPE_IDE:
 753        case IF_TYPE_SATA:
 754        case IF_TYPE_ATAPI:
 755                devtype = "hd";
 756                break;
 757        case IF_TYPE_SCSI:
 758                devtype = "sd";
 759                break;
 760        case IF_TYPE_USB:
 761                devtype = "usbd";
 762                break;
 763        case IF_TYPE_DOC:
 764                devtype = "docd";
 765                break;
 766        case IF_TYPE_MMC:
 767        case IF_TYPE_SD:
 768                devtype = "mmcsd";
 769                break;
 770        default:
 771                devtype = "xx";
 772                break;
 773        }
 774
 775        sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num);
 776}
 777