greybus: manifest: Account for padding in string descriptor
[linux-block.git] / drivers / staging / greybus / manifest.c
CommitLineData
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
16static 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 */
44struct 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
52static void release_manifest_descriptor(struct manifest_desc *descriptor)
53{
54 list_del(&descriptor->links);
55 kfree(descriptor);
56}
57
86cad666 58static 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
77static 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 157static 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
200static 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 244static 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
284static 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;
314out_err:
4ab9b3c2
GKH
315 kfree(intf->product_string);
316 intf->product_string = NULL;
50fc08f8 317out_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 347bool 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 423out:
86cad666 424 release_manifest_descriptors(intf);
b09c94a1 425
ff8aed52 426 return result;
b09c94a1 427}