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