diff options
Diffstat (limited to 'drivers/greybus/manifest.c')
-rw-r--r-- | drivers/greybus/manifest.c | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/drivers/greybus/manifest.c b/drivers/greybus/manifest.c new file mode 100644 index 000000000000..dd7040697bde --- /dev/null +++ b/drivers/greybus/manifest.c | |||
@@ -0,0 +1,533 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Greybus manifest parsing | ||
4 | * | ||
5 | * Copyright 2014-2015 Google Inc. | ||
6 | * Copyright 2014-2015 Linaro Ltd. | ||
7 | */ | ||
8 | |||
9 | #include <linux/greybus.h> | ||
10 | |||
11 | static const char *get_descriptor_type_string(u8 type) | ||
12 | { | ||
13 | switch (type) { | ||
14 | case GREYBUS_TYPE_INVALID: | ||
15 | return "invalid"; | ||
16 | case GREYBUS_TYPE_STRING: | ||
17 | return "string"; | ||
18 | case GREYBUS_TYPE_INTERFACE: | ||
19 | return "interface"; | ||
20 | case GREYBUS_TYPE_CPORT: | ||
21 | return "cport"; | ||
22 | case GREYBUS_TYPE_BUNDLE: | ||
23 | return "bundle"; | ||
24 | default: | ||
25 | WARN_ON(1); | ||
26 | return "unknown"; | ||
27 | } | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * We scan the manifest once to identify where all the descriptors | ||
32 | * are. The result is a list of these manifest_desc structures. We | ||
33 | * then pick through them for what we're looking for (starting with | ||
34 | * the interface descriptor). As each is processed we remove it from | ||
35 | * the list. When we're done the list should (probably) be empty. | ||
36 | */ | ||
37 | struct manifest_desc { | ||
38 | struct list_head links; | ||
39 | |||
40 | size_t size; | ||
41 | void *data; | ||
42 | enum greybus_descriptor_type type; | ||
43 | }; | ||
44 | |||
45 | static void release_manifest_descriptor(struct manifest_desc *descriptor) | ||
46 | { | ||
47 | list_del(&descriptor->links); | ||
48 | kfree(descriptor); | ||
49 | } | ||
50 | |||
51 | static void release_manifest_descriptors(struct gb_interface *intf) | ||
52 | { | ||
53 | struct manifest_desc *descriptor; | ||
54 | struct manifest_desc *next; | ||
55 | |||
56 | list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) | ||
57 | release_manifest_descriptor(descriptor); | ||
58 | } | ||
59 | |||
60 | static void release_cport_descriptors(struct list_head *head, u8 bundle_id) | ||
61 | { | ||
62 | struct manifest_desc *desc, *tmp; | ||
63 | struct greybus_descriptor_cport *desc_cport; | ||
64 | |||
65 | list_for_each_entry_safe(desc, tmp, head, links) { | ||
66 | desc_cport = desc->data; | ||
67 | |||
68 | if (desc->type != GREYBUS_TYPE_CPORT) | ||
69 | continue; | ||
70 | |||
71 | if (desc_cport->bundle == bundle_id) | ||
72 | release_manifest_descriptor(desc); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) | ||
77 | { | ||
78 | struct manifest_desc *descriptor; | ||
79 | struct manifest_desc *next; | ||
80 | |||
81 | list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) | ||
82 | if (descriptor->type == GREYBUS_TYPE_BUNDLE) | ||
83 | return descriptor; | ||
84 | |||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Validate the given descriptor. Its reported size must fit within | ||
90 | * the number of bytes remaining, and it must have a recognized | ||
91 | * type. Check that the reported size is at least as big as what | ||
92 | * we expect to see. (It could be bigger, perhaps for a new version | ||
93 | * of the format.) | ||
94 | * | ||
95 | * Returns the (non-zero) number of bytes consumed by the descriptor, | ||
96 | * or a negative errno. | ||
97 | */ | ||
98 | static int identify_descriptor(struct gb_interface *intf, | ||
99 | struct greybus_descriptor *desc, size_t size) | ||
100 | { | ||
101 | struct greybus_descriptor_header *desc_header = &desc->header; | ||
102 | struct manifest_desc *descriptor; | ||
103 | size_t desc_size; | ||
104 | size_t expected_size; | ||
105 | |||
106 | if (size < sizeof(*desc_header)) { | ||
107 | dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, | ||
108 | sizeof(*desc_header)); | ||
109 | return -EINVAL; /* Must at least have header */ | ||
110 | } | ||
111 | |||
112 | desc_size = le16_to_cpu(desc_header->size); | ||
113 | if (desc_size > size) { | ||
114 | dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", | ||
115 | desc_size, size); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
119 | /* Descriptor needs to at least have a header */ | ||
120 | expected_size = sizeof(*desc_header); | ||
121 | |||
122 | switch (desc_header->type) { | ||
123 | case GREYBUS_TYPE_STRING: | ||
124 | expected_size += sizeof(struct greybus_descriptor_string); | ||
125 | expected_size += desc->string.length; | ||
126 | |||
127 | /* String descriptors are padded to 4 byte boundaries */ | ||
128 | expected_size = ALIGN(expected_size, 4); | ||
129 | break; | ||
130 | case GREYBUS_TYPE_INTERFACE: | ||
131 | expected_size += sizeof(struct greybus_descriptor_interface); | ||
132 | break; | ||
133 | case GREYBUS_TYPE_BUNDLE: | ||
134 | expected_size += sizeof(struct greybus_descriptor_bundle); | ||
135 | break; | ||
136 | case GREYBUS_TYPE_CPORT: | ||
137 | expected_size += sizeof(struct greybus_descriptor_cport); | ||
138 | break; | ||
139 | case GREYBUS_TYPE_INVALID: | ||
140 | default: | ||
141 | dev_err(&intf->dev, "invalid descriptor type (%u)\n", | ||
142 | desc_header->type); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | if (desc_size < expected_size) { | ||
147 | dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", | ||
148 | get_descriptor_type_string(desc_header->type), | ||
149 | desc_size, expected_size); | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | /* Descriptor bigger than what we expect */ | ||
154 | if (desc_size > expected_size) { | ||
155 | dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", | ||
156 | get_descriptor_type_string(desc_header->type), | ||
157 | expected_size, desc_size); | ||
158 | } | ||
159 | |||
160 | descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); | ||
161 | if (!descriptor) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | descriptor->size = desc_size; | ||
165 | descriptor->data = (char *)desc + sizeof(*desc_header); | ||
166 | descriptor->type = desc_header->type; | ||
167 | list_add_tail(&descriptor->links, &intf->manifest_descs); | ||
168 | |||
169 | /* desc_size is positive and is known to fit in a signed int */ | ||
170 | |||
171 | return desc_size; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Find the string descriptor having the given id, validate it, and | ||
176 | * allocate a duplicate copy of it. The duplicate has an extra byte | ||
177 | * which guarantees the returned string is NUL-terminated. | ||
178 | * | ||
179 | * String index 0 is valid (it represents "no string"), and for | ||
180 | * that a null pointer is returned. | ||
181 | * | ||
182 | * Otherwise returns a pointer to a newly-allocated copy of the | ||
183 | * descriptor string, or an error-coded pointer on failure. | ||
184 | */ | ||
185 | static char *gb_string_get(struct gb_interface *intf, u8 string_id) | ||
186 | { | ||
187 | struct greybus_descriptor_string *desc_string; | ||
188 | struct manifest_desc *descriptor; | ||
189 | bool found = false; | ||
190 | char *string; | ||
191 | |||
192 | /* A zero string id means no string (but no error) */ | ||
193 | if (!string_id) | ||
194 | return NULL; | ||
195 | |||
196 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { | ||
197 | if (descriptor->type != GREYBUS_TYPE_STRING) | ||
198 | continue; | ||
199 | |||
200 | desc_string = descriptor->data; | ||
201 | if (desc_string->id == string_id) { | ||
202 | found = true; | ||
203 | break; | ||
204 | } | ||
205 | } | ||
206 | if (!found) | ||
207 | return ERR_PTR(-ENOENT); | ||
208 | |||
209 | /* Allocate an extra byte so we can guarantee it's NUL-terminated */ | ||
210 | string = kmemdup(&desc_string->string, desc_string->length + 1, | ||
211 | GFP_KERNEL); | ||
212 | if (!string) | ||
213 | return ERR_PTR(-ENOMEM); | ||
214 | string[desc_string->length] = '\0'; | ||
215 | |||
216 | /* Ok we've used this string, so we're done with it */ | ||
217 | release_manifest_descriptor(descriptor); | ||
218 | |||
219 | return string; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Find cport descriptors in the manifest associated with the given | ||
224 | * bundle, and set up data structures for the functions that use | ||
225 | * them. Returns the number of cports set up for the bundle, or 0 | ||
226 | * if there is an error. | ||
227 | */ | ||
228 | static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) | ||
229 | { | ||
230 | struct gb_interface *intf = bundle->intf; | ||
231 | struct greybus_descriptor_cport *desc_cport; | ||
232 | struct manifest_desc *desc, *next, *tmp; | ||
233 | LIST_HEAD(list); | ||
234 | u8 bundle_id = bundle->id; | ||
235 | u16 cport_id; | ||
236 | u32 count = 0; | ||
237 | int i; | ||
238 | |||
239 | /* Set up all cport descriptors associated with this bundle */ | ||
240 | list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { | ||
241 | if (desc->type != GREYBUS_TYPE_CPORT) | ||
242 | continue; | ||
243 | |||
244 | desc_cport = desc->data; | ||
245 | if (desc_cport->bundle != bundle_id) | ||
246 | continue; | ||
247 | |||
248 | cport_id = le16_to_cpu(desc_cport->id); | ||
249 | if (cport_id > CPORT_ID_MAX) | ||
250 | goto exit; | ||
251 | |||
252 | /* Nothing else should have its cport_id as control cport id */ | ||
253 | if (cport_id == GB_CONTROL_CPORT_ID) { | ||
254 | dev_err(&bundle->dev, "invalid cport id found (%02u)\n", | ||
255 | cport_id); | ||
256 | goto exit; | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * Found one, move it to our temporary list after checking for | ||
261 | * duplicates. | ||
262 | */ | ||
263 | list_for_each_entry(tmp, &list, links) { | ||
264 | desc_cport = tmp->data; | ||
265 | if (cport_id == le16_to_cpu(desc_cport->id)) { | ||
266 | dev_err(&bundle->dev, | ||
267 | "duplicate CPort %u found\n", cport_id); | ||
268 | goto exit; | ||
269 | } | ||
270 | } | ||
271 | list_move_tail(&desc->links, &list); | ||
272 | count++; | ||
273 | } | ||
274 | |||
275 | if (!count) | ||
276 | return 0; | ||
277 | |||
278 | bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), | ||
279 | GFP_KERNEL); | ||
280 | if (!bundle->cport_desc) | ||
281 | goto exit; | ||
282 | |||
283 | bundle->num_cports = count; | ||
284 | |||
285 | i = 0; | ||
286 | list_for_each_entry_safe(desc, next, &list, links) { | ||
287 | desc_cport = desc->data; | ||
288 | memcpy(&bundle->cport_desc[i++], desc_cport, | ||
289 | sizeof(*desc_cport)); | ||
290 | |||
291 | /* Release the cport descriptor */ | ||
292 | release_manifest_descriptor(desc); | ||
293 | } | ||
294 | |||
295 | return count; | ||
296 | exit: | ||
297 | release_cport_descriptors(&list, bundle_id); | ||
298 | /* | ||
299 | * Free all cports for this bundle to avoid 'excess descriptors' | ||
300 | * warnings. | ||
301 | */ | ||
302 | release_cport_descriptors(&intf->manifest_descs, bundle_id); | ||
303 | |||
304 | return 0; /* Error; count should also be 0 */ | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Find bundle descriptors in the manifest and set up their data | ||
309 | * structures. Returns the number of bundles set up for the | ||
310 | * given interface. | ||
311 | */ | ||
312 | static u32 gb_manifest_parse_bundles(struct gb_interface *intf) | ||
313 | { | ||
314 | struct manifest_desc *desc; | ||
315 | struct gb_bundle *bundle; | ||
316 | struct gb_bundle *bundle_next; | ||
317 | u32 count = 0; | ||
318 | u8 bundle_id; | ||
319 | u8 class; | ||
320 | |||
321 | while ((desc = get_next_bundle_desc(intf))) { | ||
322 | struct greybus_descriptor_bundle *desc_bundle; | ||
323 | |||
324 | /* Found one. Set up its bundle structure*/ | ||
325 | desc_bundle = desc->data; | ||
326 | bundle_id = desc_bundle->id; | ||
327 | class = desc_bundle->class; | ||
328 | |||
329 | /* Done with this bundle descriptor */ | ||
330 | release_manifest_descriptor(desc); | ||
331 | |||
332 | /* Ignore any legacy control bundles */ | ||
333 | if (bundle_id == GB_CONTROL_BUNDLE_ID) { | ||
334 | dev_dbg(&intf->dev, "%s - ignoring control bundle\n", | ||
335 | __func__); | ||
336 | release_cport_descriptors(&intf->manifest_descs, | ||
337 | bundle_id); | ||
338 | continue; | ||
339 | } | ||
340 | |||
341 | /* Nothing else should have its class set to control class */ | ||
342 | if (class == GREYBUS_CLASS_CONTROL) { | ||
343 | dev_err(&intf->dev, | ||
344 | "bundle %u cannot use control class\n", | ||
345 | bundle_id); | ||
346 | goto cleanup; | ||
347 | } | ||
348 | |||
349 | bundle = gb_bundle_create(intf, bundle_id, class); | ||
350 | if (!bundle) | ||
351 | goto cleanup; | ||
352 | |||
353 | /* | ||
354 | * Now go set up this bundle's functions and cports. | ||
355 | * | ||
356 | * A 'bundle' represents a device in greybus. It may require | ||
357 | * multiple cports for its functioning. If we fail to setup any | ||
358 | * cport of a bundle, we better reject the complete bundle as | ||
359 | * the device may not be able to function properly then. | ||
360 | * | ||
361 | * But, failing to setup a cport of bundle X doesn't mean that | ||
362 | * the device corresponding to bundle Y will not work properly. | ||
363 | * Bundles should be treated as separate independent devices. | ||
364 | * | ||
365 | * While parsing manifest for an interface, treat bundles as | ||
366 | * separate entities and don't reject entire interface and its | ||
367 | * bundles on failing to initialize a cport. But make sure the | ||
368 | * bundle which needs the cport, gets destroyed properly. | ||
369 | */ | ||
370 | if (!gb_manifest_parse_cports(bundle)) { | ||
371 | gb_bundle_destroy(bundle); | ||
372 | continue; | ||
373 | } | ||
374 | |||
375 | count++; | ||
376 | } | ||
377 | |||
378 | return count; | ||
379 | cleanup: | ||
380 | /* An error occurred; undo any changes we've made */ | ||
381 | list_for_each_entry_safe(bundle, bundle_next, &intf->bundles, links) { | ||
382 | gb_bundle_destroy(bundle); | ||
383 | count--; | ||
384 | } | ||
385 | return 0; /* Error; count should also be 0 */ | ||
386 | } | ||
387 | |||
388 | static bool gb_manifest_parse_interface(struct gb_interface *intf, | ||
389 | struct manifest_desc *interface_desc) | ||
390 | { | ||
391 | struct greybus_descriptor_interface *desc_intf = interface_desc->data; | ||
392 | struct gb_control *control = intf->control; | ||
393 | char *str; | ||
394 | |||
395 | /* Handle the strings first--they can fail */ | ||
396 | str = gb_string_get(intf, desc_intf->vendor_stringid); | ||
397 | if (IS_ERR(str)) | ||
398 | return false; | ||
399 | control->vendor_string = str; | ||
400 | |||
401 | str = gb_string_get(intf, desc_intf->product_stringid); | ||
402 | if (IS_ERR(str)) | ||
403 | goto out_free_vendor_string; | ||
404 | control->product_string = str; | ||
405 | |||
406 | /* Assign feature flags communicated via manifest */ | ||
407 | intf->features = desc_intf->features; | ||
408 | |||
409 | /* Release the interface descriptor, now that we're done with it */ | ||
410 | release_manifest_descriptor(interface_desc); | ||
411 | |||
412 | /* An interface must have at least one bundle descriptor */ | ||
413 | if (!gb_manifest_parse_bundles(intf)) { | ||
414 | dev_err(&intf->dev, "manifest bundle descriptors not valid\n"); | ||
415 | goto out_err; | ||
416 | } | ||
417 | |||
418 | return true; | ||
419 | out_err: | ||
420 | kfree(control->product_string); | ||
421 | control->product_string = NULL; | ||
422 | out_free_vendor_string: | ||
423 | kfree(control->vendor_string); | ||
424 | control->vendor_string = NULL; | ||
425 | |||
426 | return false; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Parse a buffer containing an interface manifest. | ||
431 | * | ||
432 | * If we find anything wrong with the content/format of the buffer | ||
433 | * we reject it. | ||
434 | * | ||
435 | * The first requirement is that the manifest's version is | ||
436 | * one we can parse. | ||
437 | * | ||
438 | * We make an initial pass through the buffer and identify all of | ||
439 | * the descriptors it contains, keeping track for each its type | ||
440 | * and the location size of its data in the buffer. | ||
441 | * | ||
442 | * Next we scan the descriptors, looking for an interface descriptor; | ||
443 | * there must be exactly one of those. When found, we record the | ||
444 | * information it contains, and then remove that descriptor (and any | ||
445 | * string descriptors it refers to) from further consideration. | ||
446 | * | ||
447 | * After that we look for the interface's bundles--there must be at | ||
448 | * least one of those. | ||
449 | * | ||
450 | * Returns true if parsing was successful, false otherwise. | ||
451 | */ | ||
452 | bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) | ||
453 | { | ||
454 | struct greybus_manifest *manifest; | ||
455 | struct greybus_manifest_header *header; | ||
456 | struct greybus_descriptor *desc; | ||
457 | struct manifest_desc *descriptor; | ||
458 | struct manifest_desc *interface_desc = NULL; | ||
459 | u16 manifest_size; | ||
460 | u32 found = 0; | ||
461 | bool result; | ||
462 | |||
463 | /* Manifest descriptor list should be empty here */ | ||
464 | if (WARN_ON(!list_empty(&intf->manifest_descs))) | ||
465 | return false; | ||
466 | |||
467 | /* we have to have at _least_ the manifest header */ | ||
468 | if (size < sizeof(*header)) { | ||
469 | dev_err(&intf->dev, "short manifest (%zu < %zu)\n", | ||
470 | size, sizeof(*header)); | ||
471 | return false; | ||
472 | } | ||
473 | |||
474 | /* Make sure the size is right */ | ||
475 | manifest = data; | ||
476 | header = &manifest->header; | ||
477 | manifest_size = le16_to_cpu(header->size); | ||
478 | if (manifest_size != size) { | ||
479 | dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", | ||
480 | size, manifest_size); | ||
481 | return false; | ||
482 | } | ||
483 | |||
484 | /* Validate major/minor number */ | ||
485 | if (header->version_major > GREYBUS_VERSION_MAJOR) { | ||
486 | dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", | ||
487 | header->version_major, header->version_minor, | ||
488 | GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); | ||
489 | return false; | ||
490 | } | ||
491 | |||
492 | /* OK, find all the descriptors */ | ||
493 | desc = manifest->descriptors; | ||
494 | size -= sizeof(*header); | ||
495 | while (size) { | ||
496 | int desc_size; | ||
497 | |||
498 | desc_size = identify_descriptor(intf, desc, size); | ||
499 | if (desc_size < 0) { | ||
500 | result = false; | ||
501 | goto out; | ||
502 | } | ||
503 | desc = (struct greybus_descriptor *)((char *)desc + desc_size); | ||
504 | size -= desc_size; | ||
505 | } | ||
506 | |||
507 | /* There must be a single interface descriptor */ | ||
508 | list_for_each_entry(descriptor, &intf->manifest_descs, links) { | ||
509 | if (descriptor->type == GREYBUS_TYPE_INTERFACE) | ||
510 | if (!found++) | ||
511 | interface_desc = descriptor; | ||
512 | } | ||
513 | if (found != 1) { | ||
514 | dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", | ||
515 | found); | ||
516 | result = false; | ||
517 | goto out; | ||
518 | } | ||
519 | |||
520 | /* Parse the manifest, starting with the interface descriptor */ | ||
521 | result = gb_manifest_parse_interface(intf, interface_desc); | ||
522 | |||
523 | /* | ||
524 | * We really should have no remaining descriptors, but we | ||
525 | * don't know what newer format manifests might leave. | ||
526 | */ | ||
527 | if (result && !list_empty(&intf->manifest_descs)) | ||
528 | dev_info(&intf->dev, "excess descriptors in interface manifest\n"); | ||
529 | out: | ||
530 | release_manifest_descriptors(intf); | ||
531 | |||
532 | return result; | ||
533 | } | ||