This source file includes following definitions.
- match_acpi_dev
- parse_acpi_path
- match_pci_dev
- parse_pci_path
- parse_end_path
- efi_get_device_by_path
1
2
3
4
5
6
7
8
9
10
11 #include <linux/acpi.h>
12 #include <linux/efi.h>
13 #include <linux/pci.h>
14
15 struct acpi_hid_uid {
16 struct acpi_device_id hid[2];
17 char uid[11];
18 };
19
20 static int __init match_acpi_dev(struct device *dev, const void *data)
21 {
22 struct acpi_hid_uid hid_uid = *(const struct acpi_hid_uid *)data;
23 struct acpi_device *adev = to_acpi_device(dev);
24
25 if (acpi_match_device_ids(adev, hid_uid.hid))
26 return 0;
27
28 if (adev->pnp.unique_id)
29 return !strcmp(adev->pnp.unique_id, hid_uid.uid);
30 else
31 return !strcmp("0", hid_uid.uid);
32 }
33
34 static long __init parse_acpi_path(struct efi_dev_path *node,
35 struct device *parent, struct device **child)
36 {
37 struct acpi_hid_uid hid_uid = {};
38 struct device *phys_dev;
39
40 if (node->length != 12)
41 return -EINVAL;
42
43 sprintf(hid_uid.hid[0].id, "%c%c%c%04X",
44 'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
45 'A' + ((node->acpi.hid >> 5) & 0x1f) - 1,
46 'A' + ((node->acpi.hid >> 0) & 0x1f) - 1,
47 node->acpi.hid >> 16);
48 sprintf(hid_uid.uid, "%u", node->acpi.uid);
49
50 *child = bus_find_device(&acpi_bus_type, NULL, &hid_uid,
51 match_acpi_dev);
52 if (!*child)
53 return -ENODEV;
54
55 phys_dev = acpi_get_first_physical_node(to_acpi_device(*child));
56 if (phys_dev) {
57 get_device(phys_dev);
58 put_device(*child);
59 *child = phys_dev;
60 }
61
62 return 0;
63 }
64
65 static int __init match_pci_dev(struct device *dev, void *data)
66 {
67 unsigned int devfn = *(unsigned int *)data;
68
69 return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
70 }
71
72 static long __init parse_pci_path(struct efi_dev_path *node,
73 struct device *parent, struct device **child)
74 {
75 unsigned int devfn;
76
77 if (node->length != 6)
78 return -EINVAL;
79 if (!parent)
80 return -EINVAL;
81
82 devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
83
84 *child = device_find_child(parent, &devfn, match_pci_dev);
85 if (!*child)
86 return -ENODEV;
87
88 return 0;
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 static long __init parse_end_path(struct efi_dev_path *node,
109 struct device *parent, struct device **child)
110 {
111 if (node->length != 4)
112 return -EINVAL;
113 if (node->sub_type != EFI_DEV_END_INSTANCE &&
114 node->sub_type != EFI_DEV_END_ENTIRE)
115 return -EINVAL;
116 if (!parent)
117 return -ENODEV;
118
119 *child = get_device(parent);
120 return node->sub_type;
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 struct device * __init efi_get_device_by_path(struct efi_dev_path **node,
160 size_t *len)
161 {
162 struct device *parent = NULL, *child;
163 long ret = 0;
164
165 if (!*len)
166 return NULL;
167
168 while (!ret) {
169 if (*len < 4 || *len < (*node)->length)
170 ret = -EINVAL;
171 else if ((*node)->type == EFI_DEV_ACPI &&
172 (*node)->sub_type == EFI_DEV_BASIC_ACPI)
173 ret = parse_acpi_path(*node, parent, &child);
174 else if ((*node)->type == EFI_DEV_HW &&
175 (*node)->sub_type == EFI_DEV_PCI)
176 ret = parse_pci_path(*node, parent, &child);
177 else if (((*node)->type == EFI_DEV_END_PATH ||
178 (*node)->type == EFI_DEV_END_PATH2))
179 ret = parse_end_path(*node, parent, &child);
180 else
181 ret = -ENOTSUPP;
182
183 put_device(parent);
184 if (ret < 0)
185 return ERR_PTR(ret);
186
187 parent = child;
188 *node = (void *)*node + (*node)->length;
189 *len -= (*node)->length;
190 }
191
192 if (ret == EFI_DEV_END_ENTIRE)
193 *len = 0;
194
195 return child;
196 }