Commit | Line | Data |
---|---|---|
b09c94a1 | 1 | /* |
a93db2d1 | 2 | * Greybus manifest parsing |
b09c94a1 | 3 | * |
d8187aa2 AE |
4 | * Copyright 2014-2015 Google Inc. |
5 | * Copyright 2014-2015 Linaro Ltd. | |
b09c94a1 AE |
6 | * |
7 | * Released under the GPLv2 only. | |
8 | */ | |
9 | ||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
11 | ||
12 | #include <linux/err.h> | |
13 | ||
14 | #include "greybus.h" | |
15 | ||
19b3b2c2 VK |
16 | static const char *get_descriptor_type_string(u8 type) |
17 | { | |
18 | switch(type) { | |
19 | case GREYBUS_TYPE_INVALID: | |
20 | return "invalid"; | |
19b3b2c2 VK |
21 | case GREYBUS_TYPE_STRING: |
22 | return "string"; | |
23 | case GREYBUS_TYPE_INTERFACE: | |
24 | return "interface"; | |
25 | case GREYBUS_TYPE_CPORT: | |
26 | return "cport"; | |
83a0cb59 VK |
27 | case GREYBUS_TYPE_BUNDLE: |
28 | return "bundle"; | |
19b3b2c2 VK |
29 | case GREYBUS_TYPE_CLASS: |
30 | return "class"; | |
31 | default: | |
32 | WARN_ON(1); | |
33 | return "unknown"; | |
34 | } | |
35 | } | |
36 | ||
b09c94a1 AE |
37 | /* |
38 | * We scan the manifest once to identify where all the descriptors | |
39 | * are. The result is a list of these manifest_desc structures. We | |
40 | * then pick through them for what we're looking for (starting with | |
a93db2d1 | 41 | * the interface descriptor). As each is processed we remove it from |
b09c94a1 AE |
42 | * the list. When we're done the list should (probably) be empty. |
43 | */ | |
44 | struct manifest_desc { | |
45 | struct list_head links; | |
46 | ||
47 | size_t size; | |
48 | void *data; | |
49 | enum greybus_descriptor_type type; | |
50 | }; | |
51 | ||
b09c94a1 AE |
52 | static void release_manifest_descriptor(struct manifest_desc *descriptor) |
53 | { | |
54 | list_del(&descriptor->links); | |
55 | kfree(descriptor); | |
56 | } | |
57 | ||
86cad666 | 58 | static void release_manifest_descriptors(struct gb_interface *intf) |
b09c94a1 AE |
59 | { |
60 | struct manifest_desc *descriptor; | |
61 | struct manifest_desc *next; | |
62 | ||
86cad666 | 63 | list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) |
b09c94a1 AE |
64 | release_manifest_descriptor(descriptor); |
65 | } | |
66 | ||
67 | /* | |
68 | * Validate the given descriptor. Its reported size must fit within | |
696e0cca | 69 | * the number of bytes remaining, and it must have a recognized |
b09c94a1 AE |
70 | * type. Check that the reported size is at least as big as what |
71 | * we expect to see. (It could be bigger, perhaps for a new version | |
72 | * of the format.) | |
73 | * | |
74 | * Returns the number of bytes consumed by the descriptor, or a | |
75 | * negative errno. | |
76 | */ | |
86cad666 GKH |
77 | static int identify_descriptor(struct gb_interface *intf, |
78 | struct greybus_descriptor *desc, size_t size) | |
b09c94a1 AE |
79 | { |
80 | struct greybus_descriptor_header *desc_header = &desc->header; | |
81 | struct manifest_desc *descriptor; | |
d8187aa2 | 82 | size_t desc_size; |
b09c94a1 AE |
83 | size_t expected_size; |
84 | ||
85 | if (size < sizeof(*desc_header)) { | |
86 | pr_err("manifest too small\n"); | |
87 | return -EINVAL; /* Must at least have header */ | |
88 | } | |
89 | ||
d8187aa2 AE |
90 | desc_size = le16_to_cpu(desc_header->size); |
91 | if (desc_size > size) { | |
b09c94a1 AE |
92 | pr_err("descriptor too big\n"); |
93 | return -EINVAL; | |
94 | } | |
95 | ||
19b3b2c2 VK |
96 | /* Descriptor needs to at least have a header */ |
97 | expected_size = sizeof(*desc_header); | |
98 | ||
b09c94a1 | 99 | switch (desc_header->type) { |
b09c94a1 | 100 | case GREYBUS_TYPE_STRING: |
b09c94a1 | 101 | expected_size += sizeof(struct greybus_descriptor_string); |
19b3b2c2 | 102 | expected_size += desc->string.length; |
fa2fbf16 VK |
103 | |
104 | /* String descriptors are padded to 4 byte boundaries */ | |
105 | expected_size = ALIGN(expected_size, 4); | |
b09c94a1 | 106 | break; |
63cc932b | 107 | case GREYBUS_TYPE_INTERFACE: |
a93db2d1 | 108 | expected_size += sizeof(struct greybus_descriptor_interface); |
63cc932b | 109 | break; |
7c183f70 VK |
110 | case GREYBUS_TYPE_BUNDLE: |
111 | expected_size += sizeof(struct greybus_descriptor_bundle); | |
112 | break; | |
b09c94a1 | 113 | case GREYBUS_TYPE_CPORT: |
19b3b2c2 | 114 | expected_size += sizeof(struct greybus_descriptor_cport); |
b09c94a1 | 115 | break; |
63cc932b AE |
116 | case GREYBUS_TYPE_CLASS: |
117 | pr_warn("class descriptor found (ignoring)\n"); | |
118 | break; | |
b09c94a1 AE |
119 | case GREYBUS_TYPE_INVALID: |
120 | default: | |
121 | pr_err("invalid descriptor type (%hhu)\n", desc_header->type); | |
122 | return -EINVAL; | |
123 | } | |
124 | ||
19b3b2c2 | 125 | if (desc_size < expected_size) { |
d8187aa2 | 126 | pr_err("%s descriptor too small (%zu < %zu)\n", |
19b3b2c2 VK |
127 | get_descriptor_type_string(desc_header->type), |
128 | desc_size, expected_size); | |
129 | return -EINVAL; | |
130 | } | |
131 | ||
b09c94a1 AE |
132 | descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); |
133 | if (!descriptor) | |
134 | return -ENOMEM; | |
135 | ||
136 | descriptor->size = desc_size; | |
7a13e2f6 | 137 | descriptor->data = (u8 *)desc + sizeof(*desc_header); |
b09c94a1 | 138 | descriptor->type = desc_header->type; |
86cad666 | 139 | list_add_tail(&descriptor->links, &intf->manifest_descs); |
b09c94a1 | 140 | |
d8187aa2 AE |
141 | /* desc_size is is positive and is known to fit in a signed int */ |
142 | ||
b09c94a1 AE |
143 | return desc_size; |
144 | } | |
145 | ||
146 | /* | |
147 | * Find the string descriptor having the given id, validate it, and | |
148 | * allocate a duplicate copy of it. The duplicate has an extra byte | |
149 | * which guarantees the returned string is NUL-terminated. | |
150 | * | |
151 | * String index 0 is valid (it represents "no string"), and for | |
152 | * that a null pointer is returned. | |
153 | * | |
154 | * Otherwise returns a pointer to a newly-allocated copy of the | |
155 | * descriptor string, or an error-coded pointer on failure. | |
156 | */ | |
86cad666 | 157 | static char *gb_string_get(struct gb_interface *intf, u8 string_id) |
b09c94a1 AE |
158 | { |
159 | struct greybus_descriptor_string *desc_string; | |
160 | struct manifest_desc *descriptor; | |
161 | bool found = false; | |
162 | char *string; | |
163 | ||
164 | /* A zero string id means no string (but no error) */ | |
165 | if (!string_id) | |
166 | return NULL; | |
167 | ||
86cad666 | 168 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { |
b09c94a1 AE |
169 | |
170 | if (descriptor->type != GREYBUS_TYPE_STRING) | |
171 | continue; | |
172 | ||
7a13e2f6 | 173 | desc_string = descriptor->data; |
b09c94a1 AE |
174 | if (desc_string->id == string_id) { |
175 | found = true; | |
176 | break; | |
177 | } | |
178 | } | |
179 | if (!found) | |
180 | return ERR_PTR(-ENOENT); | |
181 | ||
182 | /* Allocate an extra byte so we can guarantee it's NUL-terminated */ | |
183 | string = kmemdup(&desc_string->string, (size_t)desc_string->length + 1, | |
184 | GFP_KERNEL); | |
185 | if (!string) | |
186 | return ERR_PTR(-ENOMEM); | |
187 | string[desc_string->length] = '\0'; | |
188 | ||
189 | /* Ok we've used this string, so we're done with it */ | |
190 | release_manifest_descriptor(descriptor); | |
191 | ||
192 | return string; | |
193 | } | |
194 | ||
c095bbcf AE |
195 | /* |
196 | * Find cport descriptors in the manifest and set up data structures | |
1db0a5ff GKH |
197 | * for the functions that use them. Returns the number of bundles |
198 | * set up for the given interface, or 0 if there is an error. | |
c095bbcf | 199 | */ |
86cad666 GKH |
200 | static u32 gb_manifest_parse_cports(struct gb_interface *intf, |
201 | struct gb_bundle *bundle) | |
c095bbcf AE |
202 | { |
203 | u32 count = 0; | |
204 | ||
205 | while (true) { | |
206 | struct manifest_desc *descriptor; | |
207 | struct greybus_descriptor_cport *desc_cport; | |
7fba0079 | 208 | u8 protocol_id; |
c095bbcf | 209 | u16 cport_id; |
4ed16a81 | 210 | bool found = false; |
c095bbcf AE |
211 | |
212 | /* Find a cport descriptor */ | |
86cad666 | 213 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { |
c095bbcf | 214 | if (descriptor->type == GREYBUS_TYPE_CPORT) { |
63cc932b | 215 | desc_cport = descriptor->data; |
1db0a5ff | 216 | if (desc_cport->bundle == bundle->id) { |
63cc932b AE |
217 | found = true; |
218 | break; | |
219 | } | |
c095bbcf AE |
220 | } |
221 | } | |
222 | if (!found) | |
223 | break; | |
224 | ||
225 | /* Found one. Set up its function structure */ | |
7fba0079 | 226 | protocol_id = desc_cport->protocol_id; |
c095bbcf | 227 | cport_id = le16_to_cpu(desc_cport->id); |
1db0a5ff | 228 | if (!gb_connection_create(bundle, cport_id, protocol_id)) |
c095bbcf AE |
229 | return 0; /* Error */ |
230 | ||
231 | count++; | |
232 | /* Release the cport descriptor */ | |
233 | release_manifest_descriptor(descriptor); | |
234 | } | |
235 | ||
236 | return count; | |
237 | } | |
238 | ||
d88bfb5b | 239 | /* |
1db0a5ff GKH |
240 | * Find bundle descriptors in the manifest and set up their data |
241 | * structures. Returns the number of bundles set up for the | |
7c183f70 | 242 | * given interface. |
d88bfb5b | 243 | */ |
4ab9b3c2 | 244 | static u32 gb_manifest_parse_bundles(struct gb_interface *intf) |
d88bfb5b AE |
245 | { |
246 | u32 count = 0; | |
247 | ||
248 | while (true) { | |
249 | struct manifest_desc *descriptor; | |
7c183f70 | 250 | struct greybus_descriptor_bundle *desc_bundle; |
1db0a5ff | 251 | struct gb_bundle *bundle; |
d88bfb5b AE |
252 | bool found = false; |
253 | ||
1db0a5ff | 254 | /* Find an bundle descriptor */ |
86cad666 | 255 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { |
7c183f70 | 256 | if (descriptor->type == GREYBUS_TYPE_BUNDLE) { |
d88bfb5b AE |
257 | found = true; |
258 | break; | |
259 | } | |
260 | } | |
261 | if (!found) | |
262 | break; | |
263 | ||
1db0a5ff | 264 | /* Found one. Set up its bundle structure*/ |
7c183f70 VK |
265 | desc_bundle = descriptor->data; |
266 | bundle = gb_bundle_create(intf, desc_bundle->id, | |
88e6d37c | 267 | desc_bundle->class); |
1db0a5ff | 268 | if (!bundle) |
d88bfb5b | 269 | return 0; /* Error */ |
c095bbcf | 270 | |
1db0a5ff | 271 | /* Now go set up this bundle's functions and cports */ |
86cad666 | 272 | if (!gb_manifest_parse_cports(intf, bundle)) |
c095bbcf AE |
273 | return 0; /* Error parsing cports */ |
274 | ||
d88bfb5b AE |
275 | count++; |
276 | ||
1db0a5ff | 277 | /* Done with this bundle descriptor */ |
d88bfb5b AE |
278 | release_manifest_descriptor(descriptor); |
279 | } | |
280 | ||
281 | return count; | |
282 | } | |
283 | ||
a93db2d1 VK |
284 | static bool gb_manifest_parse_interface(struct gb_interface *intf, |
285 | struct manifest_desc *interface_desc) | |
b09c94a1 | 286 | { |
a93db2d1 | 287 | struct greybus_descriptor_interface *desc_intf = interface_desc->data; |
b09c94a1 AE |
288 | |
289 | /* Handle the strings first--they can fail */ | |
a93db2d1 | 290 | intf->vendor_string = gb_string_get(intf, desc_intf->vendor_stringid); |
4ab9b3c2 | 291 | if (IS_ERR(intf->vendor_string)) |
937d0da8 AE |
292 | return false; |
293 | ||
86cad666 | 294 | intf->product_string = gb_string_get(intf, |
a93db2d1 | 295 | desc_intf->product_stringid); |
4ab9b3c2 | 296 | if (IS_ERR(intf->product_string)) { |
50fc08f8 | 297 | goto out_free_vendor_string; |
b09c94a1 AE |
298 | } |
299 | ||
a93db2d1 VK |
300 | intf->vendor = le16_to_cpu(desc_intf->vendor); |
301 | intf->product = le16_to_cpu(desc_intf->product); | |
302 | intf->unique_id = le64_to_cpu(desc_intf->unique_id); | |
b09c94a1 | 303 | |
a93db2d1 VK |
304 | /* Release the interface descriptor, now that we're done with it */ |
305 | release_manifest_descriptor(interface_desc); | |
b09c94a1 | 306 | |
1db0a5ff | 307 | /* An interface must have at least one bundle descriptor */ |
4ab9b3c2 | 308 | if (!gb_manifest_parse_bundles(intf)) { |
1db0a5ff | 309 | pr_err("manifest bundle descriptors not valid\n"); |
937d0da8 | 310 | goto out_err; |
d88bfb5b AE |
311 | } |
312 | ||
937d0da8 AE |
313 | return true; |
314 | out_err: | |
4ab9b3c2 GKH |
315 | kfree(intf->product_string); |
316 | intf->product_string = NULL; | |
50fc08f8 | 317 | out_free_vendor_string: |
4ab9b3c2 GKH |
318 | kfree(intf->vendor_string); |
319 | intf->vendor_string = NULL; | |
937d0da8 AE |
320 | |
321 | return false; | |
b09c94a1 AE |
322 | } |
323 | ||
324 | /* | |
a93db2d1 | 325 | * Parse a buffer containing a Interface manifest. |
b09c94a1 AE |
326 | * |
327 | * If we find anything wrong with the content/format of the buffer | |
328 | * we reject it. | |
329 | * | |
330 | * The first requirement is that the manifest's version is | |
331 | * one we can parse. | |
332 | * | |
333 | * We make an initial pass through the buffer and identify all of | |
334 | * the descriptors it contains, keeping track for each its type | |
335 | * and the location size of its data in the buffer. | |
336 | * | |
a93db2d1 | 337 | * Next we scan the descriptors, looking for a interface descriptor; |
b09c94a1 AE |
338 | * there must be exactly one of those. When found, we record the |
339 | * information it contains, and then remove that descriptor (and any | |
340 | * string descriptors it refers to) from further consideration. | |
341 | * | |
4ab9b3c2 | 342 | * After that we look for the interface's bundles--there must be at |
b09c94a1 AE |
343 | * least one of those. |
344 | * | |
937d0da8 | 345 | * Returns true if parsing was successful, false otherwise. |
b09c94a1 | 346 | */ |
4ab9b3c2 | 347 | bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) |
b09c94a1 AE |
348 | { |
349 | struct greybus_manifest *manifest; | |
350 | struct greybus_manifest_header *header; | |
351 | struct greybus_descriptor *desc; | |
352 | struct manifest_desc *descriptor; | |
a93db2d1 | 353 | struct manifest_desc *interface_desc = NULL; |
b09c94a1 AE |
354 | u16 manifest_size; |
355 | u32 found = 0; | |
43d9431f | 356 | bool result; |
b09c94a1 | 357 | |
1dd90df4 | 358 | /* Manifest descriptor list should be empty here */ |
86cad666 | 359 | if (WARN_ON(!list_empty(&intf->manifest_descs))) |
1dd90df4 VK |
360 | return false; |
361 | ||
b09c94a1 AE |
362 | /* we have to have at _least_ the manifest header */ |
363 | if (size <= sizeof(manifest->header)) { | |
364 | pr_err("short manifest (%zu)\n", size); | |
937d0da8 | 365 | return false; |
b09c94a1 AE |
366 | } |
367 | ||
368 | /* Make sure the size is right */ | |
369 | manifest = data; | |
370 | header = &manifest->header; | |
371 | manifest_size = le16_to_cpu(header->size); | |
372 | if (manifest_size != size) { | |
373 | pr_err("manifest size mismatch %zu != %hu\n", | |
374 | size, manifest_size); | |
937d0da8 | 375 | return false; |
b09c94a1 AE |
376 | } |
377 | ||
378 | /* Validate major/minor number */ | |
379 | if (header->version_major > GREYBUS_VERSION_MAJOR) { | |
380 | pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n", | |
381 | header->version_major, header->version_minor, | |
382 | GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); | |
937d0da8 | 383 | return false; |
b09c94a1 AE |
384 | } |
385 | ||
386 | /* OK, find all the descriptors */ | |
387 | desc = (struct greybus_descriptor *)(header + 1); | |
388 | size -= sizeof(*header); | |
389 | while (size) { | |
390 | int desc_size; | |
391 | ||
86cad666 | 392 | desc_size = identify_descriptor(intf, desc, size); |
13fe6a9a | 393 | if (desc_size < 0) { |
ff8aed52 | 394 | result = false; |
937d0da8 | 395 | goto out; |
b09c94a1 AE |
396 | } |
397 | desc = (struct greybus_descriptor *)((char *)desc + desc_size); | |
398 | size -= desc_size; | |
86bf33af | 399 | } |
b09c94a1 | 400 | |
a93db2d1 | 401 | /* There must be a single interface descriptor */ |
86cad666 | 402 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { |
a93db2d1 | 403 | if (descriptor->type == GREYBUS_TYPE_INTERFACE) |
86bf33af | 404 | if (!found++) |
a93db2d1 | 405 | interface_desc = descriptor; |
86bf33af GKH |
406 | } |
407 | if (found != 1) { | |
a93db2d1 | 408 | pr_err("manifest must have 1 interface descriptor (%u found)\n", |
86bf33af GKH |
409 | found); |
410 | result = false; | |
411 | goto out; | |
b09c94a1 AE |
412 | } |
413 | ||
a93db2d1 VK |
414 | /* Parse the manifest, starting with the interface descriptor */ |
415 | result = gb_manifest_parse_interface(intf, interface_desc); | |
b09c94a1 AE |
416 | |
417 | /* | |
418 | * We really should have no remaining descriptors, but we | |
419 | * don't know what newer format manifests might leave. | |
420 | */ | |
86cad666 | 421 | if (result && !list_empty(&intf->manifest_descs)) |
a93db2d1 | 422 | pr_info("excess descriptors in interface manifest\n"); |
937d0da8 | 423 | out: |
86cad666 | 424 | release_manifest_descriptors(intf); |
b09c94a1 | 425 | |
ff8aed52 | 426 | return result; |
b09c94a1 | 427 | } |