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