]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/greybus/manifest.c
greybus: start improving manifest parsing
[karo-tx-linux.git] / drivers / staging / greybus / manifest.c
1 /*
2  * Greybus module manifest parsing
3  *
4  * Copyright 2014 Google Inc.
5  *
6  * Released under the GPLv2 only.
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/err.h>
12
13 #include "greybus.h"
14
15 /*
16  * We scan the manifest once to identify where all the descriptors
17  * are.  The result is a list of these manifest_desc structures.  We
18  * then pick through them for what we're looking for (starting with
19  * the module descriptor).  As each is processed we remove it from
20  * the list.  When we're done the list should (probably) be empty.
21  */
22 struct manifest_desc {
23         struct list_head                links;
24
25         size_t                          size;
26         void                            *data;
27         enum greybus_descriptor_type    type;
28 };
29
30 static LIST_HEAD(manifest_descs);
31
32 static void release_manifest_descriptor(struct manifest_desc *descriptor)
33 {
34         list_del(&descriptor->links);
35         kfree(descriptor);
36 }
37
38 static void release_manifest_descriptors(void)
39 {
40         struct manifest_desc *descriptor;
41         struct manifest_desc *next;
42
43         list_for_each_entry_safe(descriptor, next, &manifest_descs, links)
44                 release_manifest_descriptor(descriptor);
45 }
46
47 /*
48  * Validate the given descriptor.  Its reported size must fit within
49  * the number of bytes reamining, and it must have a recognized
50  * type.  Check that the reported size is at least as big as what
51  * we expect to see.  (It could be bigger, perhaps for a new version
52  * of the format.)
53  *
54  * Returns the number of bytes consumed by the descriptor, or a
55  * negative errno.
56  */
57 static int identify_descriptor(struct greybus_descriptor *desc, size_t size)
58 {
59         struct greybus_descriptor_header *desc_header = &desc->header;
60         struct manifest_desc *descriptor;
61         int desc_size;
62         size_t expected_size;
63
64         if (size < sizeof(*desc_header)) {
65                 pr_err("manifest too small\n");
66                 return -EINVAL;         /* Must at least have header */
67         }
68
69         desc_size = (int)le16_to_cpu(desc_header->size);
70         if ((size_t)desc_size > size) {
71                 pr_err("descriptor too big\n");
72                 return -EINVAL;
73         }
74
75         switch (desc_header->type) {
76         case GREYBUS_TYPE_MODULE:
77                 if (desc_size < sizeof(struct greybus_descriptor_module)) {
78                         pr_err("module descriptor too small (%u)\n",
79                                 desc_size);
80                         return -EINVAL;
81                 }
82                 break;
83         case GREYBUS_TYPE_DEVICE:
84                 break;
85         case GREYBUS_TYPE_CLASS:
86                 pr_err("class descriptor found (ignoring)\n");
87                 break;
88         case GREYBUS_TYPE_STRING:
89                 expected_size = sizeof(struct greybus_descriptor_header);
90                 expected_size += sizeof(struct greybus_descriptor_string);
91                 expected_size += (size_t)desc->string.length;
92                 if (desc_size < expected_size) {
93                         pr_err("string descriptor too small (%u)\n",
94                                 desc_size);
95                         return -EINVAL;
96                 }
97                 break;
98         case GREYBUS_TYPE_CPORT:
99                 if (desc_size < sizeof(struct greybus_descriptor_cport)) {
100                         pr_err("cport descriptor too small (%u)\n",
101                                 desc_size);
102                         return -EINVAL;
103                 }
104                 break;
105         case GREYBUS_TYPE_INVALID:
106         default:
107                 pr_err("invalid descriptor type (%hhu)\n", desc_header->type);
108                 return -EINVAL;
109         }
110
111         descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL);
112         if (!descriptor)
113                 return -ENOMEM;
114
115         descriptor->size = desc_size;
116         descriptor->data = desc;
117         descriptor->type = desc_header->type;
118         list_add_tail(&descriptor->links, &manifest_descs);
119
120         return desc_size;
121 }
122
123 /*
124  * Find the string descriptor having the given id, validate it, and
125  * allocate a duplicate copy of it.  The duplicate has an extra byte
126  * which guarantees the returned string is NUL-terminated.
127  *
128  * String index 0 is valid (it represents "no string"), and for
129  * that a null pointer is returned.
130  *
131  * Otherwise returns a pointer to a newly-allocated copy of the
132  * descriptor string, or an error-coded pointer on failure.
133  */
134 static char *gb_string_get(u8 string_id)
135 {
136         struct greybus_descriptor_string *desc_string;
137         struct manifest_desc *descriptor;
138         bool found = false;
139         char *string;
140
141         /* A zero string id means no string (but no error) */
142         if (!string_id)
143                 return NULL;
144
145         list_for_each_entry(descriptor, &manifest_descs, links) {
146                 struct greybus_descriptor *desc;
147
148                 if (descriptor->type != GREYBUS_TYPE_STRING)
149                         continue;
150
151                 desc = descriptor->data;
152                 desc_string = &desc->string;
153                 if (desc_string->id == string_id) {
154                         found = true;
155                         break;
156                 }
157         }
158         if (!found)
159                 return ERR_PTR(-ENOENT);
160
161         /* Allocate an extra byte so we can guarantee it's NUL-terminated */
162         string = kmemdup(&desc_string->string, (size_t)desc_string->length + 1,
163                                 GFP_KERNEL);
164         if (!string)
165                 return ERR_PTR(-ENOMEM);
166         string[desc_string->length] = '\0';
167
168         /* Ok we've used this string, so we're done with it */
169         release_manifest_descriptor(descriptor);
170
171         return string;
172 }
173
174 struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc)
175 {
176         struct greybus_descriptor *desc = module_desc->data;
177         struct greybus_descriptor_module *desc_module = &desc->module;
178         struct gb_module *gmod;
179
180         gmod = kzalloc(sizeof(*gmod), GFP_KERNEL);
181         if (!gmod)
182                 return NULL;
183
184         /* Handle the strings first--they can fail */
185         gmod->vendor_string = gb_string_get(desc_module->vendor_stringid);
186         if (IS_ERR(gmod->vendor_string)) {
187                 kfree(gmod);
188                 return NULL;
189         }
190         gmod->product_string = gb_string_get(desc_module->product_stringid);
191         if (IS_ERR(gmod->product_string)) {
192                 kfree(gmod->vendor_string);
193                 kfree(gmod);
194                 return NULL;
195         }
196
197         gmod->vendor = le16_to_cpu(desc_module->vendor);
198         gmod->product = le16_to_cpu(desc_module->product);
199         gmod->version = le16_to_cpu(desc_module->version);
200         gmod->serial_number = le64_to_cpu(desc_module->serial_number);
201
202         /* Release the module descriptor, now that we're done with it */
203         release_manifest_descriptor(module_desc);
204
205         return gmod;
206 }
207
208 /*
209  * Parse a buffer containing a module manifest.
210  *
211  * If we find anything wrong with the content/format of the buffer
212  * we reject it.
213  *
214  * The first requirement is that the manifest's version is
215  * one we can parse.
216  *
217  * We make an initial pass through the buffer and identify all of
218  * the descriptors it contains, keeping track for each its type
219  * and the location size of its data in the buffer.
220  *
221  * Next we scan the descriptors, looking for a module descriptor;
222  * there must be exactly one of those.  When found, we record the
223  * information it contains, and then remove that descriptor (and any
224  * string descriptors it refers to) from further consideration.
225  *
226  * After that we look for the module's interfaces--there must be at
227  * least one of those.
228  *
229  * Return a pointer to an initialized gb_module structure
230  * representing the content of the module manifest, or a null
231  * pointer if an error occurs.
232  */
233 struct gb_module *gb_manifest_parse(void *data, size_t size)
234 {
235         struct greybus_manifest *manifest;
236         struct greybus_manifest_header *header;
237         struct greybus_descriptor *desc;
238         struct manifest_desc *descriptor;
239         struct manifest_desc *module_desc = NULL;
240         struct gb_module *gmod;
241         u16 manifest_size;
242         u32 found = 0;
243
244         /* we have to have at _least_ the manifest header */
245         if (size <= sizeof(manifest->header)) {
246                 pr_err("short manifest (%zu)\n", size);
247                 return NULL;
248         }
249
250         /* Make sure the size is right */
251         manifest = data;
252         header = &manifest->header;
253         manifest_size = le16_to_cpu(header->size);
254         if (manifest_size != size) {
255                 pr_err("manifest size mismatch %zu != %hu\n",
256                         size, manifest_size);
257                 return NULL;
258         }
259
260         /* Validate major/minor number */
261         if (header->version_major > GREYBUS_VERSION_MAJOR) {
262                 pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n",
263                         header->version_major, header->version_minor,
264                         GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR);
265                 return NULL;
266         }
267
268         /* OK, find all the descriptors */
269         desc = (struct greybus_descriptor *)(header + 1);
270         size -= sizeof(*header);
271         while (size) {
272                 int desc_size;
273
274                 desc_size = identify_descriptor(desc, size);
275                 if (desc_size <= 0) {
276                         if (!desc_size)
277                                 pr_err("zero-sized manifest descriptor\n");
278                         goto out_err;
279                 }
280                 desc = (struct greybus_descriptor *)((char *)desc + desc_size);
281                 size -= desc_size;
282         }
283
284         /* There must be a single module descriptor */
285         list_for_each_entry(descriptor, &manifest_descs, links) {
286                 if (descriptor->type == GREYBUS_TYPE_MODULE)
287                         if (!found++)
288                                 module_desc = descriptor;
289         }
290         if (found != 1) {
291                 pr_err("manifest must have 1 module descriptor (%u found)\n",
292                         found);
293                 goto out_err;
294         }
295
296         /* Parse the module manifest, starting with the module descriptor */
297         gmod = gb_manifest_parse_module(module_desc);
298
299         /*
300          * We really should have no remaining descriptors, but we
301          * don't know what newer format manifests might leave.
302          */
303         if (!list_empty(&manifest_descs)) {
304                 pr_info("excess descriptors in module manifest\n");
305                 release_manifest_descriptors();
306         }
307
308         return gmod;
309 out_err:
310         release_manifest_descriptors();
311
312         return NULL;
313 }