Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi/dev-path-parser: Add struct definition for vendor type device path nodes

In preparation of adding support for loading the initrd via a special
device path, add the struct definition of a vendor GUIDed device path
node to efi.h.

Since we will be producing these data structures rather than just
consumsing the ones instantiated by the firmware, refactor the various
device path node definitions so we can take the size of each node using
sizeof() rather than having to resort to opaque arithmetic in the static
initializers.

While at it, drop the #if IS_ENABLED() check for the declaration of
efi_get_device_by_path(), which is unnecessary, and constify its first
argument as well.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+52 -42
+4 -4
drivers/firmware/efi/apple-properties.c
··· 46 46 }; 47 47 48 48 static void __init unmarshal_key_value_pairs(struct dev_header *dev_header, 49 - struct device *dev, void *ptr, 49 + struct device *dev, const void *ptr, 50 50 struct property_entry entry[]) 51 51 { 52 52 int i; ··· 117 117 while (offset + sizeof(struct dev_header) < properties->len) { 118 118 struct dev_header *dev_header = (void *)properties + offset; 119 119 struct property_entry *entry = NULL; 120 + const struct efi_dev_path *ptr; 120 121 struct device *dev; 121 122 size_t len; 122 123 int ret, i; 123 - void *ptr; 124 124 125 125 if (offset + dev_header->len > properties->len || 126 126 dev_header->len <= sizeof(*dev_header)) { ··· 131 131 ptr = dev_header->path; 132 132 len = dev_header->len - sizeof(*dev_header); 133 133 134 - dev = efi_get_device_by_path((struct efi_dev_path **)&ptr, &len); 134 + dev = efi_get_device_by_path(&ptr, &len); 135 135 if (IS_ERR(dev)) { 136 136 pr_err("device path parse error %ld at %#zx:\n", 137 - PTR_ERR(dev), ptr - (void *)dev_header); 137 + PTR_ERR(dev), (void *)ptr - (void *)dev_header); 138 138 print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET, 139 139 16, 1, dev_header, dev_header->len, true); 140 140 dev = NULL;
+19 -19
drivers/firmware/efi/dev-path-parser.c
··· 31 31 return !strcmp("0", hid_uid.uid); 32 32 } 33 33 34 - static long __init parse_acpi_path(struct efi_dev_path *node, 34 + static long __init parse_acpi_path(const struct efi_dev_path *node, 35 35 struct device *parent, struct device **child) 36 36 { 37 37 struct acpi_hid_uid hid_uid = {}; 38 38 struct device *phys_dev; 39 39 40 - if (node->length != 12) 40 + if (node->header.length != 12) 41 41 return -EINVAL; 42 42 43 43 sprintf(hid_uid.hid[0].id, "%c%c%c%04X", ··· 69 69 return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn; 70 70 } 71 71 72 - static long __init parse_pci_path(struct efi_dev_path *node, 72 + static long __init parse_pci_path(const struct efi_dev_path *node, 73 73 struct device *parent, struct device **child) 74 74 { 75 75 unsigned int devfn; 76 76 77 - if (node->length != 6) 77 + if (node->header.length != 6) 78 78 return -EINVAL; 79 79 if (!parent) 80 80 return -EINVAL; ··· 105 105 * search for a device. 106 106 */ 107 107 108 - static long __init parse_end_path(struct efi_dev_path *node, 108 + static long __init parse_end_path(const struct efi_dev_path *node, 109 109 struct device *parent, struct device **child) 110 110 { 111 - if (node->length != 4) 111 + if (node->header.length != 4) 112 112 return -EINVAL; 113 - if (node->sub_type != EFI_DEV_END_INSTANCE && 114 - node->sub_type != EFI_DEV_END_ENTIRE) 113 + if (node->header.sub_type != EFI_DEV_END_INSTANCE && 114 + node->header.sub_type != EFI_DEV_END_ENTIRE) 115 115 return -EINVAL; 116 116 if (!parent) 117 117 return -ENODEV; 118 118 119 119 *child = get_device(parent); 120 - return node->sub_type; 120 + return node->header.sub_type; 121 121 } 122 122 123 123 /** ··· 156 156 * %ERR_PTR(-EINVAL) if a node is malformed or exceeds @len, 157 157 * %ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented. 158 158 */ 159 - struct device * __init efi_get_device_by_path(struct efi_dev_path **node, 159 + struct device * __init efi_get_device_by_path(const struct efi_dev_path **node, 160 160 size_t *len) 161 161 { 162 162 struct device *parent = NULL, *child; ··· 166 166 return NULL; 167 167 168 168 while (!ret) { 169 - if (*len < 4 || *len < (*node)->length) 169 + if (*len < 4 || *len < (*node)->header.length) 170 170 ret = -EINVAL; 171 - else if ((*node)->type == EFI_DEV_ACPI && 172 - (*node)->sub_type == EFI_DEV_BASIC_ACPI) 171 + else if ((*node)->header.type == EFI_DEV_ACPI && 172 + (*node)->header.sub_type == EFI_DEV_BASIC_ACPI) 173 173 ret = parse_acpi_path(*node, parent, &child); 174 - else if ((*node)->type == EFI_DEV_HW && 175 - (*node)->sub_type == EFI_DEV_PCI) 174 + else if ((*node)->header.type == EFI_DEV_HW && 175 + (*node)->header.sub_type == EFI_DEV_PCI) 176 176 ret = parse_pci_path(*node, parent, &child); 177 - else if (((*node)->type == EFI_DEV_END_PATH || 178 - (*node)->type == EFI_DEV_END_PATH2)) 177 + else if (((*node)->header.type == EFI_DEV_END_PATH || 178 + (*node)->header.type == EFI_DEV_END_PATH2)) 179 179 ret = parse_end_path(*node, parent, &child); 180 180 else 181 181 ret = -ENOTSUPP; ··· 185 185 return ERR_PTR(ret); 186 186 187 187 parent = child; 188 - *node = (void *)*node + (*node)->length; 189 - *len -= (*node)->length; 188 + *node = (void *)*node + (*node)->header.length; 189 + *len -= (*node)->header.length; 190 190 } 191 191 192 192 if (ret == EFI_DEV_END_ENTIRE)
+29 -19
include/linux/efi.h
··· 855 855 #define EFI_DEV_END_ENTIRE 0xFF 856 856 857 857 struct efi_generic_dev_path { 858 - u8 type; 859 - u8 sub_type; 860 - u16 length; 861 - } __attribute ((packed)); 858 + u8 type; 859 + u8 sub_type; 860 + u16 length; 861 + } __packed; 862 + 863 + struct efi_acpi_dev_path { 864 + struct efi_generic_dev_path header; 865 + u32 hid; 866 + u32 uid; 867 + } __packed; 868 + 869 + struct efi_pci_dev_path { 870 + struct efi_generic_dev_path header; 871 + u8 fn; 872 + u8 dev; 873 + } __packed; 874 + 875 + struct efi_vendor_dev_path { 876 + struct efi_generic_dev_path header; 877 + efi_guid_t vendorguid; 878 + u8 vendordata[]; 879 + } __packed; 862 880 863 881 struct efi_dev_path { 864 - u8 type; /* can be replaced with unnamed */ 865 - u8 sub_type; /* struct efi_generic_dev_path; */ 866 - u16 length; /* once we've moved to -std=c11 */ 867 882 union { 868 - struct { 869 - u32 hid; 870 - u32 uid; 871 - } acpi; 872 - struct { 873 - u8 fn; 874 - u8 dev; 875 - } pci; 883 + struct efi_generic_dev_path header; 884 + struct efi_acpi_dev_path acpi; 885 + struct efi_pci_dev_path pci; 886 + struct efi_vendor_dev_path vendor; 876 887 }; 877 - } __attribute ((packed)); 888 + } __packed; 878 889 879 - #if IS_ENABLED(CONFIG_EFI_DEV_PATH_PARSER) 880 - struct device *efi_get_device_by_path(struct efi_dev_path **node, size_t *len); 881 - #endif 890 + struct device *efi_get_device_by_path(const struct efi_dev_path **node, 891 + size_t *len); 882 892 883 893 static inline void memrange_efi_to_native(u64 *addr, u64 *npages) 884 894 {