xref: /openbmc/linux/drivers/media/i2c/ccs/ccs-data.c (revision 360823a09426347ea8f232b0b0b5156d0aed0302)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * CCS static data binary parser library
4  *
5  * Copyright 2019--2020 Intel Corporation
6  */
7 
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <linux/limits.h>
11 #include <linux/mm.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 
15 #include "ccs-data-defs.h"
16 
17 struct bin_container {
18 	void *base;
19 	void *now;
20 	void *end;
21 	size_t size;
22 };
23 
bin_alloc(struct bin_container * bin,size_t len)24 static void *bin_alloc(struct bin_container *bin, size_t len)
25 {
26 	void *ptr;
27 
28 	len = ALIGN(len, 8);
29 
30 	if (bin->end - bin->now < len)
31 		return NULL;
32 
33 	ptr = bin->now;
34 	bin->now += len;
35 
36 	return ptr;
37 }
38 
bin_reserve(struct bin_container * bin,size_t len)39 static void bin_reserve(struct bin_container *bin, size_t len)
40 {
41 	bin->size += ALIGN(len, 8);
42 }
43 
bin_backing_alloc(struct bin_container * bin)44 static int bin_backing_alloc(struct bin_container *bin)
45 {
46 	bin->base = bin->now = kvzalloc(bin->size, GFP_KERNEL);
47 	if (!bin->base)
48 		return -ENOMEM;
49 
50 	bin->end = bin->base + bin->size;
51 
52 	return 0;
53 }
54 
55 #define is_contained(var, endp)				\
56 	(sizeof(*var) <= (endp) - (void *)(var))
57 #define has_headroom(ptr, headroom, endp)	\
58 	((headroom) <= (endp) - (void *)(ptr))
59 #define is_contained_with_headroom(var, headroom, endp)		\
60 	(sizeof(*var) + (headroom) <= (endp) - (void *)(var))
61 
62 static int
ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier * __len,size_t * __hlen,size_t * __plen,const void * endp)63 ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier *__len,
64 				size_t *__hlen, size_t *__plen,
65 				const void *endp)
66 {
67 	size_t hlen, plen;
68 
69 	if (!is_contained(__len, endp))
70 		return -ENODATA;
71 
72 	switch (__len->length >> CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) {
73 	case CCS_DATA_LENGTH_SPECIFIER_1:
74 		hlen = sizeof(*__len);
75 		plen = __len->length &
76 			((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1);
77 		break;
78 	case CCS_DATA_LENGTH_SPECIFIER_2: {
79 		struct __ccs_data_length_specifier2 *__len2 = (void *)__len;
80 
81 		if (!is_contained(__len2, endp))
82 			return -ENODATA;
83 
84 		hlen = sizeof(*__len2);
85 		plen = ((size_t)
86 			(__len2->length[0] &
87 			 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
88 			<< 8) + __len2->length[1];
89 		break;
90 	}
91 	case CCS_DATA_LENGTH_SPECIFIER_3: {
92 		struct __ccs_data_length_specifier3 *__len3 = (void *)__len;
93 
94 		if (!is_contained(__len3, endp))
95 			return -ENODATA;
96 
97 		hlen = sizeof(*__len3);
98 		plen = ((size_t)
99 			(__len3->length[0] &
100 			 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
101 			<< 16) + (__len3->length[1] << 8) + __len3->length[2];
102 		break;
103 	}
104 	default:
105 		return -EINVAL;
106 	}
107 
108 	if (!has_headroom(__len, hlen + plen, endp))
109 		return -ENODATA;
110 
111 	*__hlen = hlen;
112 	*__plen = plen;
113 
114 	return 0;
115 }
116 
117 static u8
ccs_data_parse_format_version(const struct __ccs_data_block * block)118 ccs_data_parse_format_version(const struct __ccs_data_block *block)
119 {
120 	return block->id >> CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT;
121 }
122 
ccs_data_parse_block_id(const struct __ccs_data_block * block,bool is_first)123 static u8 ccs_data_parse_block_id(const struct __ccs_data_block *block,
124 				       bool is_first)
125 {
126 	if (!is_first)
127 		return block->id;
128 
129 	return block->id & ((1 << CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT) - 1);
130 }
131 
ccs_data_parse_version(struct bin_container * bin,struct ccs_data_container * ccsdata,const void * payload,const void * endp)132 static int ccs_data_parse_version(struct bin_container *bin,
133 				  struct ccs_data_container *ccsdata,
134 				  const void *payload, const void *endp)
135 {
136 	const struct __ccs_data_block_version *v = payload;
137 	struct ccs_data_block_version *vv;
138 
139 	if (v + 1 != endp)
140 		return -ENODATA;
141 
142 	if (!bin->base) {
143 		bin_reserve(bin, sizeof(*ccsdata->version));
144 		return 0;
145 	}
146 
147 	ccsdata->version = bin_alloc(bin, sizeof(*ccsdata->version));
148 	if (!ccsdata->version)
149 		return -ENOMEM;
150 
151 	vv = ccsdata->version;
152 	vv->version_major = ((u16)v->static_data_version_major[0] << 8) +
153 		v->static_data_version_major[1];
154 	vv->version_minor = ((u16)v->static_data_version_minor[0] << 8) +
155 		v->static_data_version_minor[1];
156 	vv->date_year =  ((u16)v->year[0] << 8) + v->year[1];
157 	vv->date_month = v->month;
158 	vv->date_day = v->day;
159 
160 	return 0;
161 }
162 
print_ccs_data_version(struct device * dev,struct ccs_data_block_version * v)163 static void print_ccs_data_version(struct device *dev,
164 				   struct ccs_data_block_version *v)
165 {
166 	dev_dbg(dev,
167 		"static data version %4.4x.%4.4x, date %4.4u-%2.2u-%2.2u\n",
168 		v->version_major, v->version_minor,
169 		v->date_year, v->date_month, v->date_day);
170 }
171 
ccs_data_block_parse_header(const struct __ccs_data_block * block,bool is_first,unsigned int * __block_id,const void ** payload,const struct __ccs_data_block ** next_block,const void * endp,struct device * dev,bool verbose)172 static int ccs_data_block_parse_header(const struct __ccs_data_block *block,
173 				       bool is_first, unsigned int *__block_id,
174 				       const void **payload,
175 				       const struct __ccs_data_block **next_block,
176 				       const void *endp, struct device *dev,
177 				       bool verbose)
178 {
179 	size_t plen, hlen;
180 	u8 block_id;
181 	int rval;
182 
183 	if (!is_contained(block, endp))
184 		return -ENODATA;
185 
186 	rval = ccs_data_parse_length_specifier(&block->length, &hlen, &plen,
187 					       endp);
188 	if (rval < 0)
189 		return rval;
190 
191 	block_id = ccs_data_parse_block_id(block, is_first);
192 
193 	if (verbose)
194 		dev_dbg(dev,
195 			"Block ID 0x%2.2x, header length %zu, payload length %zu\n",
196 			block_id, hlen, plen);
197 
198 	if (!has_headroom(&block->length, hlen + plen, endp))
199 		return -ENODATA;
200 
201 	if (__block_id)
202 		*__block_id = block_id;
203 
204 	if (payload)
205 		*payload = (void *)&block->length + hlen;
206 
207 	if (next_block)
208 		*next_block = (void *)&block->length + hlen + plen;
209 
210 	return 0;
211 }
212 
ccs_data_parse_regs(struct bin_container * bin,struct ccs_reg ** __regs,size_t * __num_regs,const void * payload,const void * endp,struct device * dev)213 static int ccs_data_parse_regs(struct bin_container *bin,
214 			       struct ccs_reg **__regs,
215 			       size_t *__num_regs, const void *payload,
216 			       const void *endp, struct device *dev)
217 {
218 	struct ccs_reg *regs_base = NULL, *regs = NULL;
219 	size_t num_regs = 0;
220 	u16 addr = 0;
221 
222 	if (bin->base && __regs) {
223 		regs = regs_base = bin_alloc(bin, sizeof(*regs) * *__num_regs);
224 		if (!regs)
225 			return -ENOMEM;
226 	}
227 
228 	while (payload < endp && num_regs < INT_MAX) {
229 		const struct __ccs_data_block_regs *r = payload;
230 		size_t len;
231 		const void *data;
232 
233 		if (!is_contained(r, endp))
234 			return -ENODATA;
235 
236 		switch (r->reg_len >> CCS_DATA_BLOCK_REGS_SEL_SHIFT) {
237 		case CCS_DATA_BLOCK_REGS_SEL_REGS:
238 			addr += r->reg_len & CCS_DATA_BLOCK_REGS_ADDR_MASK;
239 			len = ((r->reg_len & CCS_DATA_BLOCK_REGS_LEN_MASK)
240 			       >> CCS_DATA_BLOCK_REGS_LEN_SHIFT) + 1;
241 
242 			if (!is_contained_with_headroom(r, len, endp))
243 				return -ENODATA;
244 
245 			data = r + 1;
246 			break;
247 		case CCS_DATA_BLOCK_REGS_SEL_REGS2: {
248 			const struct __ccs_data_block_regs2 *r2 = payload;
249 
250 			if (!is_contained(r2, endp))
251 				return -ENODATA;
252 
253 			addr += ((u16)(r2->reg_len &
254 				       CCS_DATA_BLOCK_REGS_2_ADDR_MASK) << 8)
255 				+ r2->addr;
256 			len = ((r2->reg_len & CCS_DATA_BLOCK_REGS_2_LEN_MASK)
257 			       >> CCS_DATA_BLOCK_REGS_2_LEN_SHIFT) + 1;
258 
259 			if (!is_contained_with_headroom(r2, len, endp))
260 				return -ENODATA;
261 
262 			data = r2 + 1;
263 			break;
264 		}
265 		case CCS_DATA_BLOCK_REGS_SEL_REGS3: {
266 			const struct __ccs_data_block_regs3 *r3 = payload;
267 
268 			if (!is_contained(r3, endp))
269 				return -ENODATA;
270 
271 			addr = ((u16)r3->addr[0] << 8) + r3->addr[1];
272 			len = (r3->reg_len & CCS_DATA_BLOCK_REGS_3_LEN_MASK) + 1;
273 
274 			if (!is_contained_with_headroom(r3, len, endp))
275 				return -ENODATA;
276 
277 			data = r3 + 1;
278 			break;
279 		}
280 		default:
281 			return -EINVAL;
282 		}
283 
284 		num_regs++;
285 
286 		if (!bin->base) {
287 			bin_reserve(bin, len);
288 		} else if (__regs) {
289 			if (!regs)
290 				return -EIO;
291 
292 			regs->addr = addr;
293 			regs->len = len;
294 			regs->value = bin_alloc(bin, len);
295 			if (!regs->value)
296 				return -ENOMEM;
297 
298 			memcpy(regs->value, data, len);
299 			regs++;
300 		}
301 
302 		addr += len;
303 		payload = data + len;
304 	}
305 
306 	if (!bin->base)
307 		bin_reserve(bin, sizeof(*regs) * num_regs);
308 
309 	if (__num_regs)
310 		*__num_regs = num_regs;
311 
312 	if (bin->base && __regs) {
313 		if (!regs_base)
314 			return -EIO;
315 
316 		*__regs = regs_base;
317 	}
318 
319 	return 0;
320 }
321 
ccs_data_parse_reg_rules(struct bin_container * bin,struct ccs_reg ** __regs,size_t * __num_regs,const void * payload,const void * endp,struct device * dev)322 static int ccs_data_parse_reg_rules(struct bin_container *bin,
323 				    struct ccs_reg **__regs,
324 				    size_t *__num_regs,
325 				    const void *payload,
326 				    const void *endp, struct device *dev)
327 {
328 	int rval;
329 
330 	if (!bin->base)
331 		return ccs_data_parse_regs(bin, NULL, NULL, payload, endp, dev);
332 
333 	rval = ccs_data_parse_regs(bin, NULL, __num_regs, payload, endp, dev);
334 	if (rval)
335 		return rval;
336 
337 	return ccs_data_parse_regs(bin, __regs, __num_regs, payload, endp,
338 				   dev);
339 }
340 
assign_ffd_entry(struct ccs_frame_format_desc * desc,const struct __ccs_data_block_ffd_entry * ent)341 static void assign_ffd_entry(struct ccs_frame_format_desc *desc,
342 			     const struct __ccs_data_block_ffd_entry *ent)
343 {
344 	desc->pixelcode = ent->pixelcode;
345 	desc->value = ((u16)ent->value[0] << 8) + ent->value[1];
346 }
347 
ccs_data_parse_ffd(struct bin_container * bin,struct ccs_frame_format_descs ** ffd,const void * payload,const void * endp,struct device * dev)348 static int ccs_data_parse_ffd(struct bin_container *bin,
349 			      struct ccs_frame_format_descs **ffd,
350 			      const void *payload,
351 			      const void *endp, struct device *dev)
352 {
353 	const struct __ccs_data_block_ffd *__ffd = payload;
354 	const struct __ccs_data_block_ffd_entry *__entry;
355 	unsigned int i;
356 
357 	if (!is_contained(__ffd, endp))
358 		return -ENODATA;
359 
360 	if ((void *)__ffd + sizeof(*__ffd) +
361 	    ((u32)__ffd->num_column_descs +
362 	     (u32)__ffd->num_row_descs) *
363 	    sizeof(struct __ccs_data_block_ffd_entry) != endp)
364 		return -ENODATA;
365 
366 	if (!bin->base) {
367 		bin_reserve(bin, sizeof(**ffd));
368 		bin_reserve(bin, __ffd->num_column_descs *
369 			    sizeof(struct ccs_frame_format_desc));
370 		bin_reserve(bin, __ffd->num_row_descs *
371 			    sizeof(struct ccs_frame_format_desc));
372 
373 		return 0;
374 	}
375 
376 	*ffd = bin_alloc(bin, sizeof(**ffd));
377 	if (!*ffd)
378 		return -ENOMEM;
379 
380 	(*ffd)->num_column_descs = __ffd->num_column_descs;
381 	(*ffd)->num_row_descs = __ffd->num_row_descs;
382 	__entry = (void *)(__ffd + 1);
383 
384 	(*ffd)->column_descs = bin_alloc(bin, __ffd->num_column_descs *
385 					 sizeof(*(*ffd)->column_descs));
386 	if (!(*ffd)->column_descs)
387 		return -ENOMEM;
388 
389 	for (i = 0; i < __ffd->num_column_descs; i++, __entry++)
390 		assign_ffd_entry(&(*ffd)->column_descs[i], __entry);
391 
392 	(*ffd)->row_descs = bin_alloc(bin, __ffd->num_row_descs *
393 				      sizeof(*(*ffd)->row_descs));
394 	if (!(*ffd)->row_descs)
395 		return -ENOMEM;
396 
397 	for (i = 0; i < __ffd->num_row_descs; i++, __entry++)
398 		assign_ffd_entry(&(*ffd)->row_descs[i], __entry);
399 
400 	if (__entry != endp)
401 		return -EPROTO;
402 
403 	return 0;
404 }
405 
ccs_data_parse_pdaf_readout(struct bin_container * bin,struct ccs_pdaf_readout ** pdaf_readout,const void * payload,const void * endp,struct device * dev)406 static int ccs_data_parse_pdaf_readout(struct bin_container *bin,
407 				       struct ccs_pdaf_readout **pdaf_readout,
408 				       const void *payload,
409 				       const void *endp, struct device *dev)
410 {
411 	const struct __ccs_data_block_pdaf_readout *__pdaf = payload;
412 
413 	if (!is_contained(__pdaf, endp))
414 		return -ENODATA;
415 
416 	if (!bin->base) {
417 		bin_reserve(bin, sizeof(**pdaf_readout));
418 	} else {
419 		*pdaf_readout = bin_alloc(bin, sizeof(**pdaf_readout));
420 		if (!*pdaf_readout)
421 			return -ENOMEM;
422 
423 		(*pdaf_readout)->pdaf_readout_info_order =
424 			__pdaf->pdaf_readout_info_order;
425 	}
426 
427 	return ccs_data_parse_ffd(bin, !bin->base ? NULL : &(*pdaf_readout)->ffd,
428 				  __pdaf + 1, endp, dev);
429 }
430 
ccs_data_parse_rules(struct bin_container * bin,struct ccs_rule ** __rules,size_t * __num_rules,const void * payload,const void * endp,struct device * dev)431 static int ccs_data_parse_rules(struct bin_container *bin,
432 				struct ccs_rule **__rules,
433 				size_t *__num_rules, const void *payload,
434 				const void *endp, struct device *dev)
435 {
436 	struct ccs_rule *rules_base = NULL, *rules = NULL, *next_rule = NULL;
437 	size_t num_rules = 0;
438 	const void *__next_rule = payload;
439 	int rval;
440 
441 	if (bin->base) {
442 		rules_base = next_rule =
443 			bin_alloc(bin, sizeof(*rules) * *__num_rules);
444 		if (!rules_base)
445 			return -ENOMEM;
446 	}
447 
448 	while (__next_rule < endp) {
449 		size_t rule_hlen, rule_plen, rule_plen2;
450 		const u8 *__rule_type;
451 		const void *rule_payload;
452 
453 		/* Size of a single rule */
454 		rval = ccs_data_parse_length_specifier(__next_rule, &rule_hlen,
455 						       &rule_plen, endp);
456 
457 		if (rval < 0)
458 			return rval;
459 
460 		__rule_type = __next_rule + rule_hlen;
461 
462 		if (!is_contained(__rule_type, endp))
463 			return -ENODATA;
464 
465 		rule_payload = __rule_type + 1;
466 		rule_plen2 = rule_plen - sizeof(*__rule_type);
467 
468 		if (*__rule_type == CCS_DATA_BLOCK_RULE_ID_IF) {
469 			const struct __ccs_data_block_rule_if *__if_rules =
470 				rule_payload;
471 			const size_t __num_if_rules =
472 				rule_plen2 / sizeof(*__if_rules);
473 			struct ccs_if_rule *if_rule;
474 
475 			if (!has_headroom(__if_rules,
476 					  sizeof(*__if_rules) * __num_if_rules,
477 					  rule_payload + rule_plen2))
478 				return -ENODATA;
479 
480 			/* Also check there is no extra data */
481 			if (__if_rules + __num_if_rules !=
482 			    rule_payload + rule_plen2)
483 				return -EINVAL;
484 
485 			if (!bin->base) {
486 				bin_reserve(bin,
487 					    sizeof(*if_rule) *
488 					    __num_if_rules);
489 				num_rules++;
490 			} else {
491 				unsigned int i;
492 
493 				if (!next_rule)
494 					return -EIO;
495 
496 				rules = next_rule;
497 				next_rule++;
498 
499 				if_rule = bin_alloc(bin,
500 						    sizeof(*if_rule) *
501 						    __num_if_rules);
502 				if (!if_rule)
503 					return -ENOMEM;
504 
505 				for (i = 0; i < __num_if_rules; i++) {
506 					if_rule[i].addr =
507 						((u16)__if_rules[i].addr[0]
508 						 << 8) +
509 						__if_rules[i].addr[1];
510 					if_rule[i].value = __if_rules[i].value;
511 					if_rule[i].mask = __if_rules[i].mask;
512 				}
513 
514 				rules->if_rules = if_rule;
515 				rules->num_if_rules = __num_if_rules;
516 			}
517 		} else {
518 			/* Check there was an if rule before any other rules */
519 			if (bin->base && !rules)
520 				return -EINVAL;
521 
522 			switch (*__rule_type) {
523 			case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
524 				rval = ccs_data_parse_reg_rules(bin,
525 								rules ?
526 								&rules->read_only_regs : NULL,
527 								rules ?
528 								&rules->num_read_only_regs : NULL,
529 								rule_payload,
530 								rule_payload + rule_plen2,
531 								dev);
532 				if (rval)
533 					return rval;
534 				break;
535 			case CCS_DATA_BLOCK_RULE_ID_FFD:
536 				rval = ccs_data_parse_ffd(bin, rules ?
537 							  &rules->frame_format : NULL,
538 							  rule_payload,
539 							  rule_payload + rule_plen2,
540 							  dev);
541 				if (rval)
542 					return rval;
543 				break;
544 			case CCS_DATA_BLOCK_RULE_ID_MSR:
545 				rval = ccs_data_parse_reg_rules(bin,
546 								rules ?
547 								&rules->manufacturer_regs : NULL,
548 								rules ?
549 								&rules->num_manufacturer_regs : NULL,
550 								rule_payload,
551 								rule_payload + rule_plen2,
552 								dev);
553 				if (rval)
554 					return rval;
555 				break;
556 			case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
557 				rval = ccs_data_parse_pdaf_readout(bin,
558 								   rules ?
559 								   &rules->pdaf_readout : NULL,
560 								   rule_payload,
561 								   rule_payload + rule_plen2,
562 								   dev);
563 				if (rval)
564 					return rval;
565 				break;
566 			default:
567 				dev_dbg(dev,
568 					"Don't know how to handle rule type %u!\n",
569 					*__rule_type);
570 				return -EINVAL;
571 			}
572 		}
573 		__next_rule = __next_rule + rule_hlen + rule_plen;
574 	}
575 
576 	if (!bin->base) {
577 		bin_reserve(bin, sizeof(*rules) * num_rules);
578 		*__num_rules = num_rules;
579 	} else {
580 		if (!rules_base)
581 			return -EIO;
582 
583 		*__rules = rules_base;
584 	}
585 
586 	return 0;
587 }
588 
ccs_data_parse_pdaf(struct bin_container * bin,struct ccs_pdaf_pix_loc ** pdaf,const void * payload,const void * endp,struct device * dev)589 static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf,
590 			       const void *payload, const void *endp,
591 			       struct device *dev)
592 {
593 	const struct __ccs_data_block_pdaf_pix_loc *__pdaf = payload;
594 	const struct __ccs_data_block_pdaf_pix_loc_block_desc_group *__bdesc_group;
595 	const struct __ccs_data_block_pdaf_pix_loc_pixel_desc *__pixel_desc;
596 	unsigned int i;
597 	u16 num_block_desc_groups;
598 	u8 max_block_type_id = 0;
599 	const u8 *__num_pixel_descs;
600 
601 	if (!is_contained(__pdaf, endp))
602 		return -ENODATA;
603 
604 	if (bin->base) {
605 		*pdaf = bin_alloc(bin, sizeof(**pdaf));
606 		if (!*pdaf)
607 			return -ENOMEM;
608 	} else {
609 		bin_reserve(bin, sizeof(**pdaf));
610 	}
611 
612 	num_block_desc_groups =
613 		((u16)__pdaf->num_block_desc_groups[0] << 8) +
614 		__pdaf->num_block_desc_groups[1];
615 
616 	if (bin->base) {
617 		(*pdaf)->main_offset_x =
618 			((u16)__pdaf->main_offset_x[0] << 8) +
619 			__pdaf->main_offset_x[1];
620 		(*pdaf)->main_offset_y =
621 			((u16)__pdaf->main_offset_y[0] << 8) +
622 			__pdaf->main_offset_y[1];
623 		(*pdaf)->global_pdaf_type = __pdaf->global_pdaf_type;
624 		(*pdaf)->block_width = __pdaf->block_width;
625 		(*pdaf)->block_height = __pdaf->block_height;
626 		(*pdaf)->num_block_desc_groups = num_block_desc_groups;
627 	}
628 
629 	__bdesc_group = (const void *)(__pdaf + 1);
630 
631 	if (bin->base) {
632 		(*pdaf)->block_desc_groups =
633 			bin_alloc(bin,
634 				  sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
635 				  num_block_desc_groups);
636 		if (!(*pdaf)->block_desc_groups)
637 			return -ENOMEM;
638 	} else {
639 		bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
640 			    num_block_desc_groups);
641 	}
642 
643 	for (i = 0; i < num_block_desc_groups; i++) {
644 		const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc;
645 		u16 num_block_descs;
646 		unsigned int j;
647 
648 		if (!is_contained(__bdesc_group, endp))
649 			return -ENODATA;
650 
651 		num_block_descs =
652 			((u16)__bdesc_group->num_block_descs[0] << 8) +
653 			__bdesc_group->num_block_descs[1];
654 
655 		if (bin->base) {
656 			(*pdaf)->block_desc_groups[i].repeat_y =
657 				__bdesc_group->repeat_y;
658 			(*pdaf)->block_desc_groups[i].num_block_descs =
659 				num_block_descs;
660 		}
661 
662 		__bdesc = (const void *)(__bdesc_group + 1);
663 
664 		if (bin->base) {
665 			(*pdaf)->block_desc_groups[i].block_descs =
666 				bin_alloc(bin,
667 					  sizeof(struct ccs_pdaf_pix_loc_block_desc) *
668 					  num_block_descs);
669 			if (!(*pdaf)->block_desc_groups[i].block_descs)
670 				return -ENOMEM;
671 		} else {
672 			bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) *
673 				    num_block_descs);
674 		}
675 
676 		for (j = 0; j < num_block_descs; j++, __bdesc++) {
677 			struct ccs_pdaf_pix_loc_block_desc *bdesc;
678 
679 			if (!is_contained(__bdesc, endp))
680 				return -ENODATA;
681 
682 			if (max_block_type_id <= __bdesc->block_type_id)
683 				max_block_type_id = __bdesc->block_type_id + 1;
684 
685 			if (!bin->base)
686 				continue;
687 
688 			bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j];
689 
690 			bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8)
691 				+ __bdesc->repeat_x[1];
692 
693 			if (__bdesc->block_type_id >= num_block_descs)
694 				return -EINVAL;
695 
696 			bdesc->block_type_id = __bdesc->block_type_id;
697 		}
698 
699 		__bdesc_group = (const void *)__bdesc;
700 	}
701 
702 	__num_pixel_descs = (const void *)__bdesc_group;
703 
704 	if (bin->base) {
705 		(*pdaf)->pixel_desc_groups =
706 			bin_alloc(bin,
707 				  sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
708 				  max_block_type_id);
709 		if (!(*pdaf)->pixel_desc_groups)
710 			return -ENOMEM;
711 		(*pdaf)->num_pixel_desc_grups = max_block_type_id;
712 	} else {
713 		bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
714 			    max_block_type_id);
715 	}
716 
717 	for (i = 0; i < max_block_type_id; i++) {
718 		struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL;
719 		unsigned int j;
720 
721 		if (!is_contained(__num_pixel_descs, endp))
722 			return -ENODATA;
723 
724 		if (bin->base) {
725 			pdgroup = &(*pdaf)->pixel_desc_groups[i];
726 			pdgroup->descs =
727 				bin_alloc(bin,
728 					  sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
729 					  *__num_pixel_descs);
730 			if (!pdgroup->descs)
731 				return -ENOMEM;
732 			pdgroup->num_descs = *__num_pixel_descs;
733 		} else {
734 			bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
735 				    *__num_pixel_descs);
736 		}
737 
738 		__pixel_desc = (const void *)(__num_pixel_descs + 1);
739 
740 		for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) {
741 			struct ccs_pdaf_pix_loc_pixel_desc *pdesc;
742 
743 			if (!is_contained(__pixel_desc, endp))
744 				return -ENODATA;
745 
746 			if (!bin->base)
747 				continue;
748 
749 			if (!pdgroup)
750 				return -EIO;
751 
752 			pdesc = &pdgroup->descs[j];
753 			pdesc->pixel_type = __pixel_desc->pixel_type;
754 			pdesc->small_offset_x = __pixel_desc->small_offset_x;
755 			pdesc->small_offset_y = __pixel_desc->small_offset_y;
756 		}
757 
758 		__num_pixel_descs = (const void *)(__pixel_desc + 1);
759 	}
760 
761 	return 0;
762 }
763 
ccs_data_parse_license(struct bin_container * bin,char ** __license,size_t * __license_length,const void * payload,const void * endp)764 static int ccs_data_parse_license(struct bin_container *bin,
765 				  char **__license,
766 				  size_t *__license_length,
767 				  const void *payload, const void *endp)
768 {
769 	size_t size = endp - payload;
770 	char *license;
771 
772 	if (!bin->base) {
773 		bin_reserve(bin, size);
774 		return 0;
775 	}
776 
777 	license = bin_alloc(bin, size);
778 	if (!license)
779 		return -ENOMEM;
780 
781 	memcpy(license, payload, size);
782 
783 	*__license = license;
784 	*__license_length = size;
785 
786 	return 0;
787 }
788 
ccs_data_parse_end(bool * end,const void * payload,const void * endp,struct device * dev)789 static int ccs_data_parse_end(bool *end, const void *payload, const void *endp,
790 			      struct device *dev)
791 {
792 	const struct __ccs_data_block_end *__end = payload;
793 
794 	if (__end + 1 != endp) {
795 		dev_dbg(dev, "Invalid end block length %u\n",
796 			(unsigned int)(endp - payload));
797 		return -ENODATA;
798 	}
799 
800 	*end = true;
801 
802 	return 0;
803 }
804 
__ccs_data_parse(struct bin_container * bin,struct ccs_data_container * ccsdata,const void * data,size_t len,struct device * dev,bool verbose)805 static int __ccs_data_parse(struct bin_container *bin,
806 			    struct ccs_data_container *ccsdata,
807 			    const void *data, size_t len, struct device *dev,
808 			    bool verbose)
809 {
810 	const struct __ccs_data_block *block = data;
811 	const struct __ccs_data_block *endp = data + len;
812 	unsigned int version;
813 	bool is_first = true;
814 	int rval;
815 
816 	version = ccs_data_parse_format_version(block);
817 	if (version != CCS_STATIC_DATA_VERSION) {
818 		dev_dbg(dev, "Don't know how to handle version %u\n", version);
819 		return -EINVAL;
820 	}
821 
822 	if (verbose)
823 		dev_dbg(dev, "Parsing CCS static data version %u\n", version);
824 
825 	if (!bin->base)
826 		*ccsdata = (struct ccs_data_container){ 0 };
827 
828 	while (block < endp) {
829 		const struct __ccs_data_block *next_block;
830 		unsigned int block_id;
831 		const void *payload;
832 
833 		rval = ccs_data_block_parse_header(block, is_first, &block_id,
834 						   &payload, &next_block, endp,
835 						   dev,
836 						   bin->base ? false : verbose);
837 
838 		if (rval < 0)
839 			return rval;
840 
841 		switch (block_id) {
842 		case CCS_DATA_BLOCK_ID_DUMMY:
843 			break;
844 		case CCS_DATA_BLOCK_ID_DATA_VERSION:
845 			rval = ccs_data_parse_version(bin, ccsdata, payload,
846 						      next_block);
847 			if (rval < 0)
848 				return rval;
849 			break;
850 		case CCS_DATA_BLOCK_ID_SENSOR_READ_ONLY_REGS:
851 			rval = ccs_data_parse_regs(
852 				bin, &ccsdata->sensor_read_only_regs,
853 				&ccsdata->num_sensor_read_only_regs, payload,
854 				next_block, dev);
855 			if (rval < 0)
856 				return rval;
857 			break;
858 		case CCS_DATA_BLOCK_ID_SENSOR_MANUFACTURER_REGS:
859 			rval = ccs_data_parse_regs(
860 				bin, &ccsdata->sensor_manufacturer_regs,
861 				&ccsdata->num_sensor_manufacturer_regs, payload,
862 				next_block, dev);
863 			if (rval < 0)
864 				return rval;
865 			break;
866 		case CCS_DATA_BLOCK_ID_MODULE_READ_ONLY_REGS:
867 			rval = ccs_data_parse_regs(
868 				bin, &ccsdata->module_read_only_regs,
869 				&ccsdata->num_module_read_only_regs, payload,
870 				next_block, dev);
871 			if (rval < 0)
872 				return rval;
873 			break;
874 		case CCS_DATA_BLOCK_ID_MODULE_MANUFACTURER_REGS:
875 			rval = ccs_data_parse_regs(
876 				bin, &ccsdata->module_manufacturer_regs,
877 				&ccsdata->num_module_manufacturer_regs, payload,
878 				next_block, dev);
879 			if (rval < 0)
880 				return rval;
881 			break;
882 		case CCS_DATA_BLOCK_ID_SENSOR_PDAF_PIXEL_LOCATION:
883 			rval = ccs_data_parse_pdaf(bin, &ccsdata->sensor_pdaf,
884 						   payload, next_block, dev);
885 			if (rval < 0)
886 				return rval;
887 			break;
888 		case CCS_DATA_BLOCK_ID_MODULE_PDAF_PIXEL_LOCATION:
889 			rval = ccs_data_parse_pdaf(bin, &ccsdata->module_pdaf,
890 						   payload, next_block, dev);
891 			if (rval < 0)
892 				return rval;
893 			break;
894 		case CCS_DATA_BLOCK_ID_SENSOR_RULE_BASED_BLOCK:
895 			rval = ccs_data_parse_rules(
896 				bin, &ccsdata->sensor_rules,
897 				&ccsdata->num_sensor_rules, payload, next_block,
898 				dev);
899 			if (rval < 0)
900 				return rval;
901 			break;
902 		case CCS_DATA_BLOCK_ID_MODULE_RULE_BASED_BLOCK:
903 			rval = ccs_data_parse_rules(
904 				bin, &ccsdata->module_rules,
905 				&ccsdata->num_module_rules, payload, next_block,
906 				dev);
907 			if (rval < 0)
908 				return rval;
909 			break;
910 		case CCS_DATA_BLOCK_ID_LICENSE:
911 			rval = ccs_data_parse_license(bin, &ccsdata->license,
912 						      &ccsdata->license_length,
913 						      payload, next_block);
914 			if (rval < 0)
915 				return rval;
916 			break;
917 		case CCS_DATA_BLOCK_ID_END:
918 			rval = ccs_data_parse_end(&ccsdata->end, payload,
919 						  next_block, dev);
920 			if (rval < 0)
921 				return rval;
922 			break;
923 		default:
924 			dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n",
925 				block_id);
926 		}
927 
928 		block = next_block;
929 		is_first = false;
930 	}
931 
932 	return 0;
933 }
934 
935 /**
936  * ccs_data_parse - Parse a CCS static data file into a usable in-memory
937  *		    data structure
938  * @ccsdata:	CCS static data in-memory data structure
939  * @data:	CCS static data binary
940  * @len:	Length of @data
941  * @dev:	Device the data is related to (used for printing debug messages)
942  * @verbose:	Whether to be verbose or not
943  */
ccs_data_parse(struct ccs_data_container * ccsdata,const void * data,size_t len,struct device * dev,bool verbose)944 int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
945 		   size_t len, struct device *dev, bool verbose)
946 {
947 	struct bin_container bin = { 0 };
948 	int rval;
949 
950 	rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose);
951 	if (rval)
952 		goto out_cleanup;
953 
954 	rval = bin_backing_alloc(&bin);
955 	if (rval)
956 		goto out_cleanup;
957 
958 	rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false);
959 	if (rval)
960 		goto out_cleanup;
961 
962 	if (verbose && ccsdata->version)
963 		print_ccs_data_version(dev, ccsdata->version);
964 
965 	if (bin.now != bin.end) {
966 		rval = -EPROTO;
967 		dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n",
968 			bin.base, bin.now, bin.end);
969 		goto out_cleanup;
970 	}
971 
972 	ccsdata->backing = bin.base;
973 
974 	return 0;
975 
976 out_cleanup:
977 	kvfree(bin.base);
978 	memset(ccsdata, 0, sizeof(*ccsdata));
979 
980 	return rval;
981 }
982