xref: /linux/drivers/firmware/efi/dev-path-parser.c (revision ab520be8cd5d56867fc95cfbc34b90880faf1f9d)
1 /*
2  * dev-path-parser.c - EFI Device Path parser
3  * Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License (version 2) as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <linux/acpi.h>
19 #include <linux/efi.h>
20 #include <linux/pci.h>
21 
22 struct acpi_hid_uid {
23 	struct acpi_device_id hid[2];
24 	char uid[11]; /* UINT_MAX + null byte */
25 };
26 
27 static int __init match_acpi_dev(struct device *dev, void *data)
28 {
29 	struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
30 	struct acpi_device *adev = to_acpi_device(dev);
31 
32 	if (acpi_match_device_ids(adev, hid_uid.hid))
33 		return 0;
34 
35 	if (adev->pnp.unique_id)
36 		return !strcmp(adev->pnp.unique_id, hid_uid.uid);
37 	else
38 		return !strcmp("0", hid_uid.uid);
39 }
40 
41 static long __init parse_acpi_path(struct efi_dev_path *node,
42 				   struct device *parent, struct device **child)
43 {
44 	struct acpi_hid_uid hid_uid = {};
45 	struct device *phys_dev;
46 
47 	if (node->length != 12)
48 		return -EINVAL;
49 
50 	sprintf(hid_uid.hid[0].id, "%c%c%c%04X",
51 		'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
52 		'A' + ((node->acpi.hid >>  5) & 0x1f) - 1,
53 		'A' + ((node->acpi.hid >>  0) & 0x1f) - 1,
54 			node->acpi.hid >> 16);
55 	sprintf(hid_uid.uid, "%u", node->acpi.uid);
56 
57 	*child = bus_find_device(&acpi_bus_type, NULL, &hid_uid,
58 				 match_acpi_dev);
59 	if (!*child)
60 		return -ENODEV;
61 
62 	phys_dev = acpi_get_first_physical_node(to_acpi_device(*child));
63 	if (phys_dev) {
64 		get_device(phys_dev);
65 		put_device(*child);
66 		*child = phys_dev;
67 	}
68 
69 	return 0;
70 }
71 
72 static int __init match_pci_dev(struct device *dev, void *data)
73 {
74 	unsigned int devfn = *(unsigned int *)data;
75 
76 	return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
77 }
78 
79 static long __init parse_pci_path(struct efi_dev_path *node,
80 				  struct device *parent, struct device **child)
81 {
82 	unsigned int devfn;
83 
84 	if (node->length != 6)
85 		return -EINVAL;
86 	if (!parent)
87 		return -EINVAL;
88 
89 	devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
90 
91 	*child = device_find_child(parent, &devfn, match_pci_dev);
92 	if (!*child)
93 		return -ENODEV;
94 
95 	return 0;
96 }
97 
98 /*
99  * Insert parsers for further node types here.
100  *
101  * Each parser takes a pointer to the @node and to the @parent (will be NULL
102  * for the first device path node). If a device corresponding to @node was
103  * found below @parent, its reference count should be incremented and the
104  * device returned in @child.
105  *
106  * The return value should be 0 on success or a negative int on failure.
107  * The special return values 0x01 (EFI_DEV_END_INSTANCE) and 0xFF
108  * (EFI_DEV_END_ENTIRE) signal the end of the device path, only
109  * parse_end_path() is supposed to return this.
110  *
111  * Be sure to validate the node length and contents before commencing the
112  * search for a device.
113  */
114 
115 static long __init parse_end_path(struct efi_dev_path *node,
116 				  struct device *parent, struct device **child)
117 {
118 	if (node->length != 4)
119 		return -EINVAL;
120 	if (node->sub_type != EFI_DEV_END_INSTANCE &&
121 	    node->sub_type != EFI_DEV_END_ENTIRE)
122 		return -EINVAL;
123 	if (!parent)
124 		return -ENODEV;
125 
126 	*child = get_device(parent);
127 	return node->sub_type;
128 }
129 
130 /**
131  * efi_get_device_by_path - find device by EFI Device Path
132  * @node: EFI Device Path
133  * @len: maximum length of EFI Device Path in bytes
134  *
135  * Parse a series of EFI Device Path nodes at @node and find the corresponding
136  * device.  If the device was found, its reference count is incremented and a
137  * pointer to it is returned.  The caller needs to drop the reference with
138  * put_device() after use.  The @node pointer is updated to point to the
139  * location immediately after the "End of Hardware Device Path" node.
140  *
141  * If another Device Path instance follows, @len is decremented by the number
142  * of bytes consumed.  Otherwise @len is set to %0.
143  *
144  * If a Device Path node is malformed or its corresponding device is not found,
145  * @node is updated to point to this offending node and an ERR_PTR is returned.
146  *
147  * If @len is initially %0, the function returns %NULL.  Thus, to iterate over
148  * all instances in a path, the following idiom may be used:
149  *
150  *	while (!IS_ERR_OR_NULL(dev = efi_get_device_by_path(&node, &len))) {
151  *		// do something with dev
152  *		put_device(dev);
153  *	}
154  *	if (IS_ERR(dev))
155  *		// report error
156  *
157  * Devices can only be found if they're already instantiated. Most buses
158  * instantiate devices in the "subsys" initcall level, hence the earliest
159  * initcall level in which this function should be called is "fs".
160  *
161  * Returns the device on success or
162  *	%ERR_PTR(-ENODEV) if no device was found,
163  *	%ERR_PTR(-EINVAL) if a node is malformed or exceeds @len,
164  *	%ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented.
165  */
166 struct device * __init efi_get_device_by_path(struct efi_dev_path **node,
167 					      size_t *len)
168 {
169 	struct device *parent = NULL, *child;
170 	long ret = 0;
171 
172 	if (!*len)
173 		return NULL;
174 
175 	while (!ret) {
176 		if (*len < 4 || *len < (*node)->length)
177 			ret = -EINVAL;
178 		else if ((*node)->type     == EFI_DEV_ACPI &&
179 			 (*node)->sub_type == EFI_DEV_BASIC_ACPI)
180 			ret = parse_acpi_path(*node, parent, &child);
181 		else if ((*node)->type     == EFI_DEV_HW &&
182 			 (*node)->sub_type == EFI_DEV_PCI)
183 			ret = parse_pci_path(*node, parent, &child);
184 		else if (((*node)->type    == EFI_DEV_END_PATH ||
185 			  (*node)->type    == EFI_DEV_END_PATH2))
186 			ret = parse_end_path(*node, parent, &child);
187 		else
188 			ret = -ENOTSUPP;
189 
190 		put_device(parent);
191 		if (ret < 0)
192 			return ERR_PTR(ret);
193 
194 		parent = child;
195 		*node  = (void *)*node + (*node)->length;
196 		*len  -= (*node)->length;
197 	}
198 
199 	if (ret == EFI_DEV_END_ENTIRE)
200 		*len = 0;
201 
202 	return child;
203 }
204