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