efi_loader: device path for virtio block devices
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Wed, 20 May 2020 20:39:35 +0000 (22:39 +0200)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Thu, 21 May 2020 08:00:17 +0000 (10:00 +0200)
The UEFI specification does not define a device sub-type for virtio.
Let's use a vendor hardware node here.

This avoids creation of two handles with the same device path indicating
our root node.

Reported-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
include/efi_loader.h
lib/efi_loader/efi_device_path.c

index 4b48f99773b9ea5e622bacfba388c214d1421e3b..9533df26dc9e60bad72f0c21f47fa2ef1cd61439 100644 (file)
@@ -45,6 +45,10 @@ static inline void *guidcpy(void *dst, const void *src)
 #define U_BOOT_HOST_DEV_GUID \
        EFI_GUID(0xbbe4e671, 0x5773, 0x4ea1, \
                 0x9a, 0xab, 0x3a, 0x7d, 0xbf, 0x40, 0xc4, 0x82)
+/* GUID used as root for virtio devices */
+#define U_BOOT_VIRTIO_DEV_GUID \
+       EFI_GUID(0x63293792, 0xadf5, 0x9325, \
+                0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e)
 
 /* Use internal device tree when starting UEFI application */
 #define EFI_FDT_USE_INTERNAL NULL
index 2b537c1e2eff2c5bf53101f3058fc2ba91fe33c1..f049b9e0cd0843e19e3f67238b5fb7b37878d739 100644 (file)
@@ -22,6 +22,9 @@
 #ifdef CONFIG_SANDBOX
 const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
 #endif
+#ifdef CONFIG_VIRTIO_BLK
+const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID;
+#endif
 
 /* template END node: */
 static const struct efi_device_path END = {
@@ -469,6 +472,16 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
                          */
                        return dp_size(dev->parent)
                                + sizeof(struct efi_device_path_vendor) + 1;
+#endif
+#ifdef CONFIG_VIRTIO_BLK
+               case UCLASS_VIRTIO:
+                        /*
+                         * Virtio devices will be represented as a vendor
+                         * device node with an extra byte for the device
+                         * number.
+                         */
+                       return dp_size(dev->parent)
+                               + sizeof(struct efi_device_path_vendor) + 1;
 #endif
                default:
                        return dp_size(dev->parent);
@@ -547,6 +560,23 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
                        return &dp->vendor_data[1];
                        }
 #endif
+#ifdef CONFIG_VIRTIO_BLK
+               case UCLASS_VIRTIO: {
+                       struct efi_device_path_vendor *dp;
+                       struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+                       dp_fill(buf, dev->parent);
+                       dp = buf;
+                       ++dp;
+                       dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+                       dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+                       dp->dp.length = sizeof(*dp) + 1;
+                       memcpy(&dp->guid, &efi_guid_virtio_dev,
+                              sizeof(efi_guid_t));
+                       dp->vendor_data[0] = desc->devnum;
+                       return &dp->vendor_data[1];
+                       }
+#endif
 #ifdef CONFIG_IDE
                case UCLASS_IDE: {
                        struct efi_device_path_atapi *dp =