uboot/lib/efi_loader/efi_device_path.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * EFI device path from u-boot device-model mapping
   4 *
   5 * (C) Copyright 2017 Rob Clark
   6 */
   7
   8#include <common.h>
   9#include <blk.h>
  10#include <dm.h>
  11#include <log.h>
  12#include <net.h>
  13#include <usb.h>
  14#include <mmc.h>
  15#include <nvme.h>
  16#include <efi_loader.h>
  17#include <part.h>
  18#include <sandboxblockdev.h>
  19#include <asm-generic/unaligned.h>
  20#include <linux/compat.h> /* U16_MAX */
  21
  22#ifdef CONFIG_SANDBOX
  23const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
  24#endif
  25#ifdef CONFIG_VIRTIO_BLK
  26const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID;
  27#endif
  28
  29/* template END node: */
  30static const struct efi_device_path END = {
  31        .type     = DEVICE_PATH_TYPE_END,
  32        .sub_type = DEVICE_PATH_SUB_TYPE_END,
  33        .length   = sizeof(END),
  34};
  35
  36/* template ROOT node: */
  37static const struct efi_device_path_vendor ROOT = {
  38        .dp = {
  39                .type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
  40                .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
  41                .length   = sizeof(ROOT),
  42        },
  43        .guid = U_BOOT_GUID,
  44};
  45
  46#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
  47/*
  48 * Determine if an MMC device is an SD card.
  49 *
  50 * @desc        block device descriptor
  51 * @return      true if the device is an SD card
  52 */
  53static bool is_sd(struct blk_desc *desc)
  54{
  55        struct mmc *mmc = find_mmc_device(desc->devnum);
  56
  57        if (!mmc)
  58                return false;
  59
  60        return IS_SD(mmc) != 0U;
  61}
  62#endif
  63
  64static void *dp_alloc(size_t sz)
  65{
  66        void *buf;
  67
  68        if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
  69            EFI_SUCCESS) {
  70                debug("EFI: ERROR: out of memory in %s\n", __func__);
  71                return NULL;
  72        }
  73
  74        memset(buf, 0, sz);
  75        return buf;
  76}
  77
  78/*
  79 * Iterate to next block in device-path, terminating (returning NULL)
  80 * at /End* node.
  81 */
  82struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
  83{
  84        if (dp == NULL)
  85                return NULL;
  86        if (dp->type == DEVICE_PATH_TYPE_END)
  87                return NULL;
  88        dp = ((void *)dp) + dp->length;
  89        if (dp->type == DEVICE_PATH_TYPE_END)
  90                return NULL;
  91        return (struct efi_device_path *)dp;
  92}
  93
  94/*
  95 * Compare two device-paths, stopping when the shorter of the two hits
  96 * an End* node. This is useful to, for example, compare a device-path
  97 * representing a device with one representing a file on the device, or
  98 * a device with a parent device.
  99 */
 100int efi_dp_match(const struct efi_device_path *a,
 101                 const struct efi_device_path *b)
 102{
 103        while (1) {
 104                int ret;
 105
 106                ret = memcmp(&a->length, &b->length, sizeof(a->length));
 107                if (ret)
 108                        return ret;
 109
 110                ret = memcmp(a, b, a->length);
 111                if (ret)
 112                        return ret;
 113
 114                a = efi_dp_next(a);
 115                b = efi_dp_next(b);
 116
 117                if (!a || !b)
 118                        return 0;
 119        }
 120}
 121
 122/*
 123 * We can have device paths that start with a USB WWID or a USB Class node,
 124 * and a few other cases which don't encode the full device path with bus
 125 * hierarchy:
 126 *
 127 *   - MESSAGING:USB_WWID
 128 *   - MESSAGING:USB_CLASS
 129 *   - MEDIA:FILE_PATH
 130 *   - MEDIA:HARD_DRIVE
 131 *   - MESSAGING:URI
 132 *
 133 * See UEFI spec (section 3.1.2, about short-form device-paths)
 134 */
 135static struct efi_device_path *shorten_path(struct efi_device_path *dp)
 136{
 137        while (dp) {
 138                /*
 139                 * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
 140                 * in practice fallback.efi just uses MEDIA:HARD_DRIVE
 141                 * so not sure when we would see these other cases.
 142                 */
 143                if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
 144                    EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
 145                    EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
 146                        return dp;
 147
 148                dp = efi_dp_next(dp);
 149        }
 150
 151        return dp;
 152}
 153
 154static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
 155                                   struct efi_device_path **rem)
 156{
 157        struct efi_object *efiobj;
 158        efi_uintn_t dp_size = efi_dp_instance_size(dp);
 159
 160        list_for_each_entry(efiobj, &efi_obj_list, link) {
 161                struct efi_handler *handler;
 162                struct efi_device_path *obj_dp;
 163                efi_status_t ret;
 164
 165                ret = efi_search_protocol(efiobj,
 166                                          &efi_guid_device_path, &handler);
 167                if (ret != EFI_SUCCESS)
 168                        continue;
 169                obj_dp = handler->protocol_interface;
 170
 171                do {
 172                        if (efi_dp_match(dp, obj_dp) == 0) {
 173                                if (rem) {
 174                                        /*
 175                                         * Allow partial matches, but inform
 176                                         * the caller.
 177                                         */
 178                                        *rem = ((void *)dp) +
 179                                                efi_dp_instance_size(obj_dp);
 180                                        return efiobj;
 181                                } else {
 182                                        /* Only return on exact matches */
 183                                        if (efi_dp_instance_size(obj_dp) ==
 184                                            dp_size)
 185                                                return efiobj;
 186                                }
 187                        }
 188
 189                        obj_dp = shorten_path(efi_dp_next(obj_dp));
 190                } while (short_path && obj_dp);
 191        }
 192
 193        return NULL;
 194}
 195
 196/*
 197 * Find an efiobj from device-path, if 'rem' is not NULL, returns the
 198 * remaining part of the device path after the matched object.
 199 */
 200struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
 201                                   struct efi_device_path **rem)
 202{
 203        struct efi_object *efiobj;
 204
 205        /* Search for an exact match first */
 206        efiobj = find_obj(dp, false, NULL);
 207
 208        /* Then for a fuzzy match */
 209        if (!efiobj)
 210                efiobj = find_obj(dp, false, rem);
 211
 212        /* And now for a fuzzy short match */
 213        if (!efiobj)
 214                efiobj = find_obj(dp, true, rem);
 215
 216        return efiobj;
 217}
 218
 219/*
 220 * Determine the last device path node that is not the end node.
 221 *
 222 * @dp          device path
 223 * @return      last node before the end node if it exists
 224 *              otherwise NULL
 225 */
 226const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
 227{
 228        struct efi_device_path *ret;
 229
 230        if (!dp || dp->type == DEVICE_PATH_TYPE_END)
 231                return NULL;
 232        while (dp) {
 233                ret = (struct efi_device_path *)dp;
 234                dp = efi_dp_next(dp);
 235        }
 236        return ret;
 237}
 238
 239/* get size of the first device path instance excluding end node */
 240efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
 241{
 242        efi_uintn_t sz = 0;
 243
 244        if (!dp || dp->type == DEVICE_PATH_TYPE_END)
 245                return 0;
 246        while (dp) {
 247                sz += dp->length;
 248                dp = efi_dp_next(dp);
 249        }
 250
 251        return sz;
 252}
 253
 254/* get size of multi-instance device path excluding end node */
 255efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
 256{
 257        const struct efi_device_path *p = dp;
 258
 259        if (!p)
 260                return 0;
 261        while (p->type != DEVICE_PATH_TYPE_END ||
 262               p->sub_type != DEVICE_PATH_SUB_TYPE_END)
 263                p = (void *)p + p->length;
 264
 265        return (void *)p - (void *)dp;
 266}
 267
 268/* copy multi-instance device path */
 269struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
 270{
 271        struct efi_device_path *ndp;
 272        size_t sz = efi_dp_size(dp) + sizeof(END);
 273
 274        if (!dp)
 275                return NULL;
 276
 277        ndp = dp_alloc(sz);
 278        if (!ndp)
 279                return NULL;
 280        memcpy(ndp, dp, sz);
 281
 282        return ndp;
 283}
 284
 285struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
 286                                      const struct efi_device_path *dp2)
 287{
 288        struct efi_device_path *ret;
 289
 290        if (!dp1 && !dp2) {
 291                /* return an end node */
 292                ret = efi_dp_dup(&END);
 293        } else if (!dp1) {
 294                ret = efi_dp_dup(dp2);
 295        } else if (!dp2) {
 296                ret = efi_dp_dup(dp1);
 297        } else {
 298                /* both dp1 and dp2 are non-null */
 299                unsigned sz1 = efi_dp_size(dp1);
 300                unsigned sz2 = efi_dp_size(dp2);
 301                void *p = dp_alloc(sz1 + sz2 + sizeof(END));
 302                if (!p)
 303                        return NULL;
 304                memcpy(p, dp1, sz1);
 305                /* the end node of the second device path has to be retained */
 306                memcpy(p + sz1, dp2, sz2 + sizeof(END));
 307                ret = p;
 308        }
 309
 310        return ret;
 311}
 312
 313struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 314                                           const struct efi_device_path *node)
 315{
 316        struct efi_device_path *ret;
 317
 318        if (!node && !dp) {
 319                ret = efi_dp_dup(&END);
 320        } else if (!node) {
 321                ret = efi_dp_dup(dp);
 322        } else if (!dp) {
 323                size_t sz = node->length;
 324                void *p = dp_alloc(sz + sizeof(END));
 325                if (!p)
 326                        return NULL;
 327                memcpy(p, node, sz);
 328                memcpy(p + sz, &END, sizeof(END));
 329                ret = p;
 330        } else {
 331                /* both dp and node are non-null */
 332                size_t sz = efi_dp_size(dp);
 333                void *p = dp_alloc(sz + node->length + sizeof(END));
 334                if (!p)
 335                        return NULL;
 336                memcpy(p, dp, sz);
 337                memcpy(p + sz, node, node->length);
 338                memcpy(p + sz + node->length, &END, sizeof(END));
 339                ret = p;
 340        }
 341
 342        return ret;
 343}
 344
 345struct efi_device_path *efi_dp_create_device_node(const u8 type,
 346                                                  const u8 sub_type,
 347                                                  const u16 length)
 348{
 349        struct efi_device_path *ret;
 350
 351        if (length < sizeof(struct efi_device_path))
 352                return NULL;
 353
 354        ret = dp_alloc(length);
 355        if (!ret)
 356                return ret;
 357        ret->type = type;
 358        ret->sub_type = sub_type;
 359        ret->length = length;
 360        return ret;
 361}
 362
 363struct efi_device_path *efi_dp_append_instance(
 364                const struct efi_device_path *dp,
 365                const struct efi_device_path *dpi)
 366{
 367        size_t sz, szi;
 368        struct efi_device_path *p, *ret;
 369
 370        if (!dpi)
 371                return NULL;
 372        if (!dp)
 373                return efi_dp_dup(dpi);
 374        sz = efi_dp_size(dp);
 375        szi = efi_dp_instance_size(dpi);
 376        p = dp_alloc(sz + szi + 2 * sizeof(END));
 377        if (!p)
 378                return NULL;
 379        ret = p;
 380        memcpy(p, dp, sz + sizeof(END));
 381        p = (void *)p + sz;
 382        p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END;
 383        p = (void *)p + sizeof(END);
 384        memcpy(p, dpi, szi);
 385        p = (void *)p + szi;
 386        memcpy(p, &END, sizeof(END));
 387        return ret;
 388}
 389
 390struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
 391                                                 efi_uintn_t *size)
 392{
 393        size_t sz;
 394        struct efi_device_path *p;
 395
 396        if (size)
 397                *size = 0;
 398        if (!dp || !*dp)
 399                return NULL;
 400        sz = efi_dp_instance_size(*dp);
 401        p = dp_alloc(sz + sizeof(END));
 402        if (!p)
 403                return NULL;
 404        memcpy(p, *dp, sz + sizeof(END));
 405        *dp = (void *)*dp + sz;
 406        if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END)
 407                *dp = (void *)*dp + sizeof(END);
 408        else
 409                *dp = NULL;
 410        if (size)
 411                *size = sz + sizeof(END);
 412        return p;
 413}
 414
 415bool efi_dp_is_multi_instance(const struct efi_device_path *dp)
 416{
 417        const struct efi_device_path *p = dp;
 418
 419        if (!p)
 420                return false;
 421        while (p->type != DEVICE_PATH_TYPE_END)
 422                p = (void *)p + p->length;
 423        return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END;
 424}
 425
 426#ifdef CONFIG_DM
 427/* size of device-path not including END node for device and all parents
 428 * up to the root device.
 429 */
 430__maybe_unused static unsigned int dp_size(struct udevice *dev)
 431{
 432        if (!dev || !dev->driver)
 433                return sizeof(ROOT);
 434
 435        switch (dev->driver->id) {
 436        case UCLASS_ROOT:
 437        case UCLASS_SIMPLE_BUS:
 438                /* stop traversing parents at this point: */
 439                return sizeof(ROOT);
 440        case UCLASS_ETH:
 441                return dp_size(dev->parent) +
 442                        sizeof(struct efi_device_path_mac_addr);
 443#ifdef CONFIG_BLK
 444        case UCLASS_BLK:
 445                switch (dev->parent->uclass->uc_drv->id) {
 446#ifdef CONFIG_IDE
 447                case UCLASS_IDE:
 448                        return dp_size(dev->parent) +
 449                                sizeof(struct efi_device_path_atapi);
 450#endif
 451#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
 452                case UCLASS_SCSI:
 453                        return dp_size(dev->parent) +
 454                                sizeof(struct efi_device_path_scsi);
 455#endif
 456#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 457                case UCLASS_MMC:
 458                        return dp_size(dev->parent) +
 459                                sizeof(struct efi_device_path_sd_mmc_path);
 460#endif
 461#if defined(CONFIG_AHCI) || defined(CONFIG_SATA)
 462                case UCLASS_AHCI:
 463                        return dp_size(dev->parent) +
 464                                sizeof(struct efi_device_path_sata);
 465#endif
 466#if defined(CONFIG_NVME)
 467                case UCLASS_NVME:
 468                        return dp_size(dev->parent) +
 469                                sizeof(struct efi_device_path_nvme);
 470#endif
 471#ifdef CONFIG_SANDBOX
 472                case UCLASS_ROOT:
 473                         /*
 474                          * Sandbox's host device will be represented
 475                          * as vendor device with extra one byte for
 476                          * device number
 477                          */
 478                        return dp_size(dev->parent)
 479                                + sizeof(struct efi_device_path_vendor) + 1;
 480#endif
 481#ifdef CONFIG_VIRTIO_BLK
 482                case UCLASS_VIRTIO:
 483                         /*
 484                          * Virtio devices will be represented as a vendor
 485                          * device node with an extra byte for the device
 486                          * number.
 487                          */
 488                        return dp_size(dev->parent)
 489                                + sizeof(struct efi_device_path_vendor) + 1;
 490#endif
 491                default:
 492                        return dp_size(dev->parent);
 493                }
 494#endif
 495#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 496        case UCLASS_MMC:
 497                return dp_size(dev->parent) +
 498                        sizeof(struct efi_device_path_sd_mmc_path);
 499#endif
 500        case UCLASS_MASS_STORAGE:
 501        case UCLASS_USB_HUB:
 502                return dp_size(dev->parent) +
 503                        sizeof(struct efi_device_path_usb_class);
 504        default:
 505                /* just skip over unknown classes: */
 506                return dp_size(dev->parent);
 507        }
 508}
 509
 510/*
 511 * Recursively build a device path.
 512 *
 513 * @buf         pointer to the end of the device path
 514 * @dev         device
 515 * @return      pointer to the end of the device path
 516 */
 517__maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
 518{
 519        if (!dev || !dev->driver)
 520                return buf;
 521
 522        switch (dev->driver->id) {
 523        case UCLASS_ROOT:
 524        case UCLASS_SIMPLE_BUS: {
 525                /* stop traversing parents at this point: */
 526                struct efi_device_path_vendor *vdp = buf;
 527                *vdp = ROOT;
 528                return &vdp[1];
 529        }
 530#ifdef CONFIG_DM_ETH
 531        case UCLASS_ETH: {
 532                struct efi_device_path_mac_addr *dp =
 533                        dp_fill(buf, dev->parent);
 534                struct eth_pdata *pdata = dev_get_plat(dev);
 535
 536                dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 537                dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
 538                dp->dp.length = sizeof(*dp);
 539                memset(&dp->mac, 0, sizeof(dp->mac));
 540                /* We only support IPv4 */
 541                memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
 542                /* Ethernet */
 543                dp->if_type = 1;
 544                return &dp[1];
 545        }
 546#endif
 547#ifdef CONFIG_BLK
 548        case UCLASS_BLK:
 549                switch (dev->parent->uclass->uc_drv->id) {
 550#ifdef CONFIG_SANDBOX
 551                case UCLASS_ROOT: {
 552                        /* stop traversing parents at this point: */
 553                        struct efi_device_path_vendor *dp;
 554                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 555
 556                        dp_fill(buf, dev->parent);
 557                        dp = buf;
 558                        ++dp;
 559                        dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
 560                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
 561                        dp->dp.length = sizeof(*dp) + 1;
 562                        memcpy(&dp->guid, &efi_guid_host_dev,
 563                               sizeof(efi_guid_t));
 564                        dp->vendor_data[0] = desc->devnum;
 565                        return &dp->vendor_data[1];
 566                        }
 567#endif
 568#ifdef CONFIG_VIRTIO_BLK
 569                case UCLASS_VIRTIO: {
 570                        struct efi_device_path_vendor *dp;
 571                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 572
 573                        dp_fill(buf, dev->parent);
 574                        dp = buf;
 575                        ++dp;
 576                        dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
 577                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
 578                        dp->dp.length = sizeof(*dp) + 1;
 579                        memcpy(&dp->guid, &efi_guid_virtio_dev,
 580                               sizeof(efi_guid_t));
 581                        dp->vendor_data[0] = desc->devnum;
 582                        return &dp->vendor_data[1];
 583                        }
 584#endif
 585#ifdef CONFIG_IDE
 586                case UCLASS_IDE: {
 587                        struct efi_device_path_atapi *dp =
 588                        dp_fill(buf, dev->parent);
 589                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 590
 591                        dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 592                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
 593                        dp->dp.length = sizeof(*dp);
 594                        dp->logical_unit_number = desc->devnum;
 595                        dp->primary_secondary = IDE_BUS(desc->devnum);
 596                        dp->slave_master = desc->devnum %
 597                                (CONFIG_SYS_IDE_MAXDEVICE /
 598                                 CONFIG_SYS_IDE_MAXBUS);
 599                        return &dp[1];
 600                        }
 601#endif
 602#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
 603                case UCLASS_SCSI: {
 604                        struct efi_device_path_scsi *dp =
 605                                dp_fill(buf, dev->parent);
 606                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 607
 608                        dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 609                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
 610                        dp->dp.length = sizeof(*dp);
 611                        dp->logical_unit_number = desc->lun;
 612                        dp->target_id = desc->target;
 613                        return &dp[1];
 614                        }
 615#endif
 616#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 617                case UCLASS_MMC: {
 618                        struct efi_device_path_sd_mmc_path *sddp =
 619                                dp_fill(buf, dev->parent);
 620                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 621
 622                        sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 623                        sddp->dp.sub_type = is_sd(desc) ?
 624                                DEVICE_PATH_SUB_TYPE_MSG_SD :
 625                                DEVICE_PATH_SUB_TYPE_MSG_MMC;
 626                        sddp->dp.length   = sizeof(*sddp);
 627                        sddp->slot_number = dev_seq(dev);
 628                        return &sddp[1];
 629                        }
 630#endif
 631#if defined(CONFIG_AHCI) || defined(CONFIG_SATA)
 632                case UCLASS_AHCI: {
 633                        struct efi_device_path_sata *dp =
 634                                dp_fill(buf, dev->parent);
 635                        struct blk_desc *desc = dev_get_uclass_plat(dev);
 636
 637                        dp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 638                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SATA;
 639                        dp->dp.length   = sizeof(*dp);
 640                        dp->hba_port = desc->devnum;
 641                        /* default 0xffff implies no port multiplier */
 642                        dp->port_multiplier_port = 0xffff;
 643                        dp->logical_unit_number = desc->lun;
 644                        return &dp[1];
 645                        }
 646#endif
 647#if defined(CONFIG_NVME)
 648                case UCLASS_NVME: {
 649                        struct efi_device_path_nvme *dp =
 650                                dp_fill(buf, dev->parent);
 651                        u32 ns_id;
 652
 653                        dp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 654                        dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_NVME;
 655                        dp->dp.length   = sizeof(*dp);
 656                        nvme_get_namespace_id(dev, &ns_id, dp->eui64);
 657                        memcpy(&dp->ns_id, &ns_id, sizeof(ns_id));
 658                        return &dp[1];
 659                        }
 660#endif
 661                default:
 662                        debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
 663                              __FILE__, __LINE__, __func__,
 664                              dev->name, dev->parent->uclass->uc_drv->id);
 665                        return dp_fill(buf, dev->parent);
 666                }
 667#endif
 668#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 669        case UCLASS_MMC: {
 670                struct efi_device_path_sd_mmc_path *sddp =
 671                        dp_fill(buf, dev->parent);
 672                struct mmc *mmc = mmc_get_mmc_dev(dev);
 673                struct blk_desc *desc = mmc_get_blk_desc(mmc);
 674
 675                sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 676                sddp->dp.sub_type = is_sd(desc) ?
 677                        DEVICE_PATH_SUB_TYPE_MSG_SD :
 678                        DEVICE_PATH_SUB_TYPE_MSG_MMC;
 679                sddp->dp.length   = sizeof(*sddp);
 680                sddp->slot_number = dev_seq(dev);
 681
 682                return &sddp[1];
 683        }
 684#endif
 685        case UCLASS_MASS_STORAGE:
 686        case UCLASS_USB_HUB: {
 687                struct efi_device_path_usb_class *udp =
 688                        dp_fill(buf, dev->parent);
 689                struct usb_device *udev = dev_get_parent_priv(dev);
 690                struct usb_device_descriptor *desc = &udev->descriptor;
 691
 692                udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 693                udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
 694                udp->dp.length   = sizeof(*udp);
 695                udp->vendor_id   = desc->idVendor;
 696                udp->product_id  = desc->idProduct;
 697                udp->device_class    = desc->bDeviceClass;
 698                udp->device_subclass = desc->bDeviceSubClass;
 699                udp->device_protocol = desc->bDeviceProtocol;
 700
 701                return &udp[1];
 702        }
 703        default:
 704                debug("%s(%u) %s: unhandled device class: %s (%u)\n",
 705                      __FILE__, __LINE__, __func__,
 706                      dev->name, dev->driver->id);
 707                return dp_fill(buf, dev->parent);
 708        }
 709}
 710#endif
 711
 712static unsigned dp_part_size(struct blk_desc *desc, int part)
 713{
 714        unsigned dpsize;
 715
 716#ifdef CONFIG_BLK
 717        {
 718                struct udevice *dev;
 719                int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
 720
 721                if (ret)
 722                        dev = desc->bdev->parent;
 723                dpsize = dp_size(dev);
 724        }
 725#else
 726        dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
 727#endif
 728
 729        if (part == 0) /* the actual disk, not a partition */
 730                return dpsize;
 731
 732        if (desc->part_type == PART_TYPE_ISO)
 733                dpsize += sizeof(struct efi_device_path_cdrom_path);
 734        else
 735                dpsize += sizeof(struct efi_device_path_hard_drive_path);
 736
 737        return dpsize;
 738}
 739
 740/*
 741 * Create a device node for a block device partition.
 742 *
 743 * @buf         buffer to which the device path is written
 744 * @desc        block device descriptor
 745 * @part        partition number, 0 identifies a block device
 746 */
 747static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
 748{
 749        struct disk_partition info;
 750
 751        part_get_info(desc, part, &info);
 752
 753        if (desc->part_type == PART_TYPE_ISO) {
 754                struct efi_device_path_cdrom_path *cddp = buf;
 755
 756                cddp->boot_entry = part;
 757                cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
 758                cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
 759                cddp->dp.length = sizeof(*cddp);
 760                cddp->partition_start = info.start;
 761                cddp->partition_size = info.size;
 762
 763                buf = &cddp[1];
 764        } else {
 765                struct efi_device_path_hard_drive_path *hddp = buf;
 766
 767                hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
 768                hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
 769                hddp->dp.length = sizeof(*hddp);
 770                hddp->partition_number = part;
 771                hddp->partition_start = info.start;
 772                hddp->partition_end = info.size;
 773                if (desc->part_type == PART_TYPE_EFI)
 774                        hddp->partmap_type = 2;
 775                else
 776                        hddp->partmap_type = 1;
 777
 778                switch (desc->sig_type) {
 779                case SIG_TYPE_NONE:
 780                default:
 781                        hddp->signature_type = 0;
 782                        memset(hddp->partition_signature, 0,
 783                               sizeof(hddp->partition_signature));
 784                        break;
 785                case SIG_TYPE_MBR:
 786                        hddp->signature_type = 1;
 787                        memset(hddp->partition_signature, 0,
 788                               sizeof(hddp->partition_signature));
 789                        memcpy(hddp->partition_signature, &desc->mbr_sig,
 790                               sizeof(desc->mbr_sig));
 791                        break;
 792                case SIG_TYPE_GUID:
 793                        hddp->signature_type = 2;
 794                        memcpy(hddp->partition_signature, &desc->guid_sig,
 795                               sizeof(hddp->partition_signature));
 796                        break;
 797                }
 798
 799                buf = &hddp[1];
 800        }
 801
 802        return buf;
 803}
 804
 805/*
 806 * Create a device path for a block device or one of its partitions.
 807 *
 808 * @buf         buffer to which the device path is written
 809 * @desc        block device descriptor
 810 * @part        partition number, 0 identifies a block device
 811 */
 812static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
 813{
 814#ifdef CONFIG_BLK
 815        {
 816                struct udevice *dev;
 817                int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
 818
 819                if (ret)
 820                        dev = desc->bdev->parent;
 821                buf = dp_fill(buf, dev);
 822        }
 823#else
 824        /*
 825         * We *could* make a more accurate path, by looking at if_type
 826         * and handling all the different cases like we do for non-
 827         * legacy (i.e. CONFIG_BLK=y) case. But most important thing
 828         * is just to have a unique device-path for if_type+devnum.
 829         * So map things to a fictitious USB device.
 830         */
 831        struct efi_device_path_usb *udp;
 832
 833        memcpy(buf, &ROOT, sizeof(ROOT));
 834        buf += sizeof(ROOT);
 835
 836        udp = buf;
 837        udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 838        udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
 839        udp->dp.length = sizeof(*udp);
 840        udp->parent_port_number = desc->if_type;
 841        udp->usb_interface = desc->devnum;
 842        buf = &udp[1];
 843#endif
 844
 845        if (part == 0) /* the actual disk, not a partition */
 846                return buf;
 847
 848        return dp_part_node(buf, desc, part);
 849}
 850
 851/* Construct a device-path from a partition on a block device: */
 852struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
 853{
 854        void *buf, *start;
 855
 856        start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
 857        if (!buf)
 858                return NULL;
 859
 860        buf = dp_part_fill(buf, desc, part);
 861
 862        *((struct efi_device_path *)buf) = END;
 863
 864        return start;
 865}
 866
 867/*
 868 * Create a device node for a block device partition.
 869 *
 870 * @buf         buffer to which the device path is written
 871 * @desc        block device descriptor
 872 * @part        partition number, 0 identifies a block device
 873 */
 874struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
 875{
 876        efi_uintn_t dpsize;
 877        void *buf;
 878
 879        if (desc->part_type == PART_TYPE_ISO)
 880                dpsize = sizeof(struct efi_device_path_cdrom_path);
 881        else
 882                dpsize = sizeof(struct efi_device_path_hard_drive_path);
 883        buf = dp_alloc(dpsize);
 884
 885        dp_part_node(buf, desc, part);
 886
 887        return buf;
 888}
 889
 890/**
 891 * path_to_uefi() - convert UTF-8 path to an UEFI style path
 892 *
 893 * Convert UTF-8 path to a UEFI style path (i.e. with backslashes as path
 894 * separators and UTF-16).
 895 *
 896 * @src:        source buffer
 897 * @uefi:       target buffer, possibly unaligned
 898 */
 899static void path_to_uefi(void *uefi, const char *src)
 900{
 901        u16 *pos = uefi;
 902
 903        /*
 904         * efi_set_bootdev() calls this routine indirectly before the UEFI
 905         * subsystem is initialized. So we cannot assume unaligned access to be
 906         * enabled.
 907         */
 908        allow_unaligned();
 909
 910        while (*src) {
 911                s32 code = utf8_get(&src);
 912
 913                if (code < 0)
 914                        code = '?';
 915                else if (code == '/')
 916                        code = '\\';
 917                utf16_put(code, &pos);
 918        }
 919        *pos = 0;
 920}
 921
 922/*
 923 * If desc is NULL, this creates a path with only the file component,
 924 * otherwise it creates a full path with both device and file components
 925 */
 926struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
 927                const char *path)
 928{
 929        struct efi_device_path_file_path *fp;
 930        void *buf, *start;
 931        size_t dpsize = 0, fpsize;
 932
 933        if (desc)
 934                dpsize = dp_part_size(desc, part);
 935
 936        fpsize = sizeof(struct efi_device_path) +
 937                 2 * (utf8_utf16_strlen(path) + 1);
 938        if (fpsize > U16_MAX)
 939                return NULL;
 940
 941        dpsize += fpsize;
 942
 943        start = buf = dp_alloc(dpsize + sizeof(END));
 944        if (!buf)
 945                return NULL;
 946
 947        if (desc)
 948                buf = dp_part_fill(buf, desc, part);
 949
 950        /* add file-path: */
 951        fp = buf;
 952        fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
 953        fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
 954        fp->dp.length = (u16)fpsize;
 955        path_to_uefi(fp->str, path);
 956        buf += fpsize;
 957
 958        *((struct efi_device_path *)buf) = END;
 959
 960        return start;
 961}
 962
 963struct efi_device_path *efi_dp_from_uart(void)
 964{
 965        void *buf, *pos;
 966        struct efi_device_path_uart *uart;
 967        size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
 968
 969        buf = dp_alloc(dpsize);
 970        if (!buf)
 971                return NULL;
 972        pos = buf;
 973        memcpy(pos, &ROOT, sizeof(ROOT));
 974        pos += sizeof(ROOT);
 975        uart = pos;
 976        uart->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
 977        uart->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_UART;
 978        uart->dp.length = sizeof(*uart);
 979        pos += sizeof(*uart);
 980        memcpy(pos, &END, sizeof(END));
 981
 982        return buf;
 983}
 984
 985#ifdef CONFIG_NET
 986struct efi_device_path *efi_dp_from_eth(void)
 987{
 988#ifndef CONFIG_DM_ETH
 989        struct efi_device_path_mac_addr *ndp;
 990#endif
 991        void *buf, *start;
 992        unsigned dpsize = 0;
 993
 994        assert(eth_get_dev());
 995
 996#ifdef CONFIG_DM_ETH
 997        dpsize += dp_size(eth_get_dev());
 998#else
 999        dpsize += sizeof(ROOT);
1000        dpsize += sizeof(*ndp);
1001#endif
1002
1003        start = buf = dp_alloc(dpsize + sizeof(END));
1004        if (!buf)
1005                return NULL;
1006
1007#ifdef CONFIG_DM_ETH
1008        buf = dp_fill(buf, eth_get_dev());
1009#else
1010        memcpy(buf, &ROOT, sizeof(ROOT));
1011        buf += sizeof(ROOT);
1012
1013        ndp = buf;
1014        ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
1015        ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
1016        ndp->dp.length = sizeof(*ndp);
1017        ndp->if_type = 1; /* Ethernet */
1018        memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
1019        buf = &ndp[1];
1020#endif
1021
1022        *((struct efi_device_path *)buf) = END;
1023
1024        return start;
1025}
1026#endif
1027
1028/* Construct a device-path for memory-mapped image */
1029struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
1030                                        uint64_t start_address,
1031                                        uint64_t end_address)
1032{
1033        struct efi_device_path_memory *mdp;
1034        void *buf, *start;
1035
1036        start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
1037        if (!buf)
1038                return NULL;
1039
1040        mdp = buf;
1041        mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
1042        mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
1043        mdp->dp.length = sizeof(*mdp);
1044        mdp->memory_type = memory_type;
1045        mdp->start_address = start_address;
1046        mdp->end_address = end_address;
1047        buf = &mdp[1];
1048
1049        *((struct efi_device_path *)buf) = END;
1050
1051        return start;
1052}
1053
1054/**
1055 * efi_dp_split_file_path() - split of relative file path from device path
1056 *
1057 * Given a device path indicating a file on a device, separate the device
1058 * path in two: the device path of the actual device and the file path
1059 * relative to this device.
1060 *
1061 * @full_path:          device path including device and file path
1062 * @device_path:        path of the device
1063 * @file_path:          relative path of the file or NULL if there is none
1064 * Return:              status code
1065 */
1066efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
1067                                    struct efi_device_path **device_path,
1068                                    struct efi_device_path **file_path)
1069{
1070        struct efi_device_path *p, *dp, *fp = NULL;
1071
1072        *device_path = NULL;
1073        *file_path = NULL;
1074        dp = efi_dp_dup(full_path);
1075        if (!dp)
1076                return EFI_OUT_OF_RESOURCES;
1077        p = dp;
1078        while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
1079                p = efi_dp_next(p);
1080                if (!p)
1081                        goto out;
1082        }
1083        fp = efi_dp_dup(p);
1084        if (!fp)
1085                return EFI_OUT_OF_RESOURCES;
1086        p->type = DEVICE_PATH_TYPE_END;
1087        p->sub_type = DEVICE_PATH_SUB_TYPE_END;
1088        p->length = sizeof(*p);
1089
1090out:
1091        *device_path = dp;
1092        *file_path = fp;
1093        return EFI_SUCCESS;
1094}
1095
1096/**
1097 * efi_dp_from_name() - convert U-Boot device and file path to device path
1098 *
1099 * @dev:        U-Boot device, e.g. 'mmc'
1100 * @devnr:      U-Boot device number, e.g. 1 for 'mmc:1'
1101 * @path:       file path relative to U-Boot device, may be NULL
1102 * @device:     pointer to receive device path of the device
1103 * @file:       pointer to receive device path for the file
1104 * Return:      status code
1105 */
1106efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
1107                              const char *path,
1108                              struct efi_device_path **device,
1109                              struct efi_device_path **file)
1110{
1111        struct blk_desc *desc = NULL;
1112        struct disk_partition fs_partition;
1113        int part = 0;
1114        char filename[32] = { 0 }; /* dp->str is u16[32] long */
1115        char *s;
1116
1117        if (path && !file)
1118                return EFI_INVALID_PARAMETER;
1119
1120        if (!strcmp(dev, "Net")) {
1121#ifdef CONFIG_NET
1122                if (device)
1123                        *device = efi_dp_from_eth();
1124#endif
1125        } else if (!strcmp(dev, "Uart")) {
1126                if (device)
1127                        *device = efi_dp_from_uart();
1128        } else {
1129                part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
1130                                               1);
1131                if (part < 0 || !desc)
1132                        return EFI_INVALID_PARAMETER;
1133
1134                if (device)
1135                        *device = efi_dp_from_part(desc, part);
1136        }
1137
1138        if (!path)
1139                return EFI_SUCCESS;
1140
1141        snprintf(filename, sizeof(filename), "%s", path);
1142        /* DOS style file path: */
1143        s = filename;
1144        while ((s = strchr(s, '/')))
1145                *s++ = '\\';
1146        *file = efi_dp_from_file(desc, part, filename);
1147
1148        if (!*file)
1149                return EFI_INVALID_PARAMETER;
1150
1151        return EFI_SUCCESS;
1152}
1153
1154/**
1155 * efi_dp_check_length() - check length of a device path
1156 *
1157 * @dp:         pointer to device path
1158 * @maxlen:     maximum length of the device path
1159 * Return:
1160 * * length of the device path if it is less or equal @maxlen
1161 * * -1 if the device path is longer then @maxlen
1162 * * -1 if a device path node has a length of less than 4
1163 * * -EINVAL if maxlen exceeds SSIZE_MAX
1164 */
1165ssize_t efi_dp_check_length(const struct efi_device_path *dp,
1166                            const size_t maxlen)
1167{
1168        ssize_t ret = 0;
1169        u16 len;
1170
1171        if (maxlen > SSIZE_MAX)
1172                return -EINVAL;
1173        for (;;) {
1174                len = dp->length;
1175                if (len < 4)
1176                        return -1;
1177                ret += len;
1178                if (ret > maxlen)
1179                        return -1;
1180                if (dp->type == DEVICE_PATH_TYPE_END &&
1181                    dp->sub_type == DEVICE_PATH_SUB_TYPE_END)
1182                        return ret;
1183                dp = (const struct efi_device_path *)((const u8 *)dp + len);
1184        }
1185}
1186