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
16struct bin_container {
17	void *base;
18	void *now;
19	void *end;
20	size_t size;
21};
22
23static 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
38static void bin_reserve(struct bin_container *bin, size_t len)
39{
40	bin->size += ALIGN(len, 8);
41}
42
43static 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
61static int
62ccs_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
116static u8
117ccs_data_parse_format_version(const struct __ccs_data_block *block)
118{
119	return block->id >> CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT;
120}
121
122static 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
131static 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
162static 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
171static 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
212static 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
321static 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
340static 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
347static 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
405static 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
430static 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
588static 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
763static 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
788static 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
804static 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 */
943int 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
975out_free:
976	kvfree(bin.base);
977
978	return rval;
979}
980