1
2
3
4
5
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
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 switch (*__rule_type) {
468 case 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
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 break;
518 }
519 case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
520 rval = ccs_data_parse_reg_rules(bin, &rules->read_only_regs,
521 &rules->num_read_only_regs,
522 rule_payload,
523 rule_payload + rule_plen2,
524 dev);
525 if (rval)
526 return rval;
527 break;
528 case CCS_DATA_BLOCK_RULE_ID_FFD:
529 rval = ccs_data_parse_ffd(bin, &rules->frame_format,
530 rule_payload,
531 rule_payload + rule_plen2,
532 dev);
533 if (rval)
534 return rval;
535 break;
536 case CCS_DATA_BLOCK_RULE_ID_MSR:
537 rval = ccs_data_parse_reg_rules(bin,
538 &rules->manufacturer_regs,
539 &rules->num_manufacturer_regs,
540 rule_payload,
541 rule_payload + rule_plen2,
542 dev);
543 if (rval)
544 return rval;
545 break;
546 case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
547 rval = ccs_data_parse_pdaf_readout(bin,
548 &rules->pdaf_readout,
549 rule_payload,
550 rule_payload + rule_plen2,
551 dev);
552 if (rval)
553 return rval;
554 break;
555 default:
556 dev_dbg(dev,
557 "Don't know how to handle rule type %u!\n",
558 *__rule_type);
559 return -EINVAL;
560 }
561 __next_rule = __next_rule + rule_hlen + rule_plen;
562 }
563
564 if (!bin->base) {
565 bin_reserve(bin, sizeof(*rules) * num_rules);
566 *__num_rules = num_rules;
567 } else {
568 if (!rules_base)
569 return -EIO;
570
571 *__rules = rules_base;
572 }
573
574 return 0;
575}
576
577static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf,
578 const void *payload, const void *endp,
579 struct device *dev)
580{
581 const struct __ccs_data_block_pdaf_pix_loc *__pdaf = payload;
582 const struct __ccs_data_block_pdaf_pix_loc_block_desc_group *__bdesc_group;
583 const struct __ccs_data_block_pdaf_pix_loc_pixel_desc *__pixel_desc;
584 unsigned int i;
585 u16 num_block_desc_groups;
586 u8 max_block_type_id = 0;
587 const u8 *__num_pixel_descs;
588
589 if (!is_contained(__pdaf, endp))
590 return -ENODATA;
591
592 if (bin->base) {
593 *pdaf = bin_alloc(bin, sizeof(**pdaf));
594 if (!*pdaf)
595 return -ENOMEM;
596 } else {
597 bin_reserve(bin, sizeof(**pdaf));
598 }
599
600 num_block_desc_groups =
601 ((u16)__pdaf->num_block_desc_groups[0] << 8) +
602 __pdaf->num_block_desc_groups[1];
603
604 if (bin->base) {
605 (*pdaf)->main_offset_x =
606 ((u16)__pdaf->main_offset_x[0] << 8) +
607 __pdaf->main_offset_x[1];
608 (*pdaf)->main_offset_y =
609 ((u16)__pdaf->main_offset_y[0] << 8) +
610 __pdaf->main_offset_y[1];
611 (*pdaf)->global_pdaf_type = __pdaf->global_pdaf_type;
612 (*pdaf)->block_width = __pdaf->block_width;
613 (*pdaf)->block_height = __pdaf->block_height;
614 (*pdaf)->num_block_desc_groups = num_block_desc_groups;
615 }
616
617 __bdesc_group = (const void *)(__pdaf + 1);
618
619 if (bin->base) {
620 (*pdaf)->block_desc_groups =
621 bin_alloc(bin,
622 sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
623 num_block_desc_groups);
624 if (!(*pdaf)->block_desc_groups)
625 return -ENOMEM;
626 } else {
627 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
628 num_block_desc_groups);
629 }
630
631 for (i = 0; i < num_block_desc_groups; i++) {
632 const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc;
633 u16 num_block_descs;
634 unsigned int j;
635
636 if (!is_contained(__bdesc_group, endp))
637 return -ENODATA;
638
639 num_block_descs =
640 ((u16)__bdesc_group->num_block_descs[0] << 8) +
641 __bdesc_group->num_block_descs[1];
642
643 if (bin->base) {
644 (*pdaf)->block_desc_groups[i].repeat_y =
645 __bdesc_group->repeat_y;
646 (*pdaf)->block_desc_groups[i].num_block_descs =
647 num_block_descs;
648 }
649
650 __bdesc = (const void *)(__bdesc_group + 1);
651
652 if (bin->base) {
653 (*pdaf)->block_desc_groups[i].block_descs =
654 bin_alloc(bin,
655 sizeof(struct ccs_pdaf_pix_loc_block_desc) *
656 num_block_descs);
657 if (!(*pdaf)->block_desc_groups[i].block_descs)
658 return -ENOMEM;
659 } else {
660 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) *
661 num_block_descs);
662 }
663
664 for (j = 0; j < num_block_descs; j++, __bdesc++) {
665 struct ccs_pdaf_pix_loc_block_desc *bdesc;
666
667 if (!is_contained(__bdesc, endp))
668 return -ENODATA;
669
670 if (max_block_type_id <= __bdesc->block_type_id)
671 max_block_type_id = __bdesc->block_type_id + 1;
672
673 if (!bin->base)
674 continue;
675
676 bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j];
677
678 bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8)
679 + __bdesc->repeat_x[1];
680
681 if (__bdesc->block_type_id >= num_block_descs)
682 return -EINVAL;
683
684 bdesc->block_type_id = __bdesc->block_type_id;
685 }
686
687 __bdesc_group = (const void *)__bdesc;
688 }
689
690 __num_pixel_descs = (const void *)__bdesc_group;
691
692 if (bin->base) {
693 (*pdaf)->pixel_desc_groups =
694 bin_alloc(bin,
695 sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
696 max_block_type_id);
697 if (!(*pdaf)->pixel_desc_groups)
698 return -ENOMEM;
699 (*pdaf)->num_pixel_desc_grups = max_block_type_id;
700 } else {
701 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
702 max_block_type_id);
703 }
704
705 for (i = 0; i < max_block_type_id; i++) {
706 struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL;
707 unsigned int j;
708
709 if (!is_contained(__num_pixel_descs, endp))
710 return -ENODATA;
711
712 if (bin->base) {
713 pdgroup = &(*pdaf)->pixel_desc_groups[i];
714 pdgroup->descs =
715 bin_alloc(bin,
716 sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
717 *__num_pixel_descs);
718 if (!pdgroup->descs)
719 return -ENOMEM;
720 pdgroup->num_descs = *__num_pixel_descs;
721 } else {
722 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
723 *__num_pixel_descs);
724 }
725
726 __pixel_desc = (const void *)(__num_pixel_descs + 1);
727
728 for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) {
729 struct ccs_pdaf_pix_loc_pixel_desc *pdesc;
730
731 if (!is_contained(__pixel_desc, endp))
732 return -ENODATA;
733
734 if (!bin->base)
735 continue;
736
737 if (!pdgroup)
738 return -EIO;
739
740 pdesc = &pdgroup->descs[j];
741 pdesc->pixel_type = __pixel_desc->pixel_type;
742 pdesc->small_offset_x = __pixel_desc->small_offset_x;
743 pdesc->small_offset_y = __pixel_desc->small_offset_y;
744 }
745
746 __num_pixel_descs = (const void *)(__pixel_desc + 1);
747 }
748
749 return 0;
750}
751
752static int ccs_data_parse_license(struct bin_container *bin,
753 char **__license,
754 size_t *__license_length,
755 const void *payload, const void *endp)
756{
757 size_t size = endp - payload;
758 char *license;
759
760 if (!bin->base) {
761 bin_reserve(bin, size);
762 return 0;
763 }
764
765 license = bin_alloc(bin, size);
766 if (!license)
767 return -ENOMEM;
768
769 memcpy(license, payload, size);
770
771 *__license = license;
772 *__license_length = size;
773
774 return 0;
775}
776
777static int ccs_data_parse_end(bool *end, const void *payload, const void *endp,
778 struct device *dev)
779{
780 const struct __ccs_data_block_end *__end = payload;
781
782 if (__end + 1 != endp) {
783 dev_dbg(dev, "Invalid end block length %u\n",
784 (unsigned int)(endp - payload));
785 return -ENODATA;
786 }
787
788 *end = true;
789
790 return 0;
791}
792
793static int __ccs_data_parse(struct bin_container *bin,
794 struct ccs_data_container *ccsdata,
795 const void *data, size_t len, struct device *dev,
796 bool verbose)
797{
798 const struct __ccs_data_block *block = data;
799 const struct __ccs_data_block *endp = data + len;
800 unsigned int version;
801 bool is_first = true;
802 int rval;
803
804 version = ccs_data_parse_format_version(block);
805 if (version != CCS_STATIC_DATA_VERSION) {
806 dev_dbg(dev, "Don't know how to handle version %u\n", version);
807 return -EINVAL;
808 }
809
810 if (verbose)
811 dev_dbg(dev, "Parsing CCS static data version %u\n", version);
812
813 if (!bin->base)
814 *ccsdata = (struct ccs_data_container){ 0 };
815
816 while (block < endp) {
817 const struct __ccs_data_block *next_block;
818 unsigned int block_id;
819 const void *payload;
820
821 rval = ccs_data_block_parse_header(block, is_first, &block_id,
822 &payload, &next_block, endp,
823 dev,
824 bin->base ? false : verbose);
825
826 if (rval < 0)
827 return rval;
828
829 switch (block_id) {
830 case CCS_DATA_BLOCK_ID_DUMMY:
831 break;
832 case CCS_DATA_BLOCK_ID_DATA_VERSION:
833 rval = ccs_data_parse_version(bin, ccsdata, payload,
834 next_block);
835 if (rval < 0)
836 return rval;
837 break;
838 case CCS_DATA_BLOCK_ID_SENSOR_READ_ONLY_REGS:
839 rval = ccs_data_parse_regs(
840 bin, &ccsdata->sensor_read_only_regs,
841 &ccsdata->num_sensor_read_only_regs, payload,
842 next_block, dev);
843 if (rval < 0)
844 return rval;
845 break;
846 case CCS_DATA_BLOCK_ID_SENSOR_MANUFACTURER_REGS:
847 rval = ccs_data_parse_regs(
848 bin, &ccsdata->sensor_manufacturer_regs,
849 &ccsdata->num_sensor_manufacturer_regs, payload,
850 next_block, dev);
851 if (rval < 0)
852 return rval;
853 break;
854 case CCS_DATA_BLOCK_ID_MODULE_READ_ONLY_REGS:
855 rval = ccs_data_parse_regs(
856 bin, &ccsdata->module_read_only_regs,
857 &ccsdata->num_module_read_only_regs, payload,
858 next_block, dev);
859 if (rval < 0)
860 return rval;
861 break;
862 case CCS_DATA_BLOCK_ID_MODULE_MANUFACTURER_REGS:
863 rval = ccs_data_parse_regs(
864 bin, &ccsdata->module_manufacturer_regs,
865 &ccsdata->num_module_manufacturer_regs, payload,
866 next_block, dev);
867 if (rval < 0)
868 return rval;
869 break;
870 case CCS_DATA_BLOCK_ID_SENSOR_PDAF_PIXEL_LOCATION:
871 rval = ccs_data_parse_pdaf(bin, &ccsdata->sensor_pdaf,
872 payload, next_block, dev);
873 if (rval < 0)
874 return rval;
875 break;
876 case CCS_DATA_BLOCK_ID_MODULE_PDAF_PIXEL_LOCATION:
877 rval = ccs_data_parse_pdaf(bin, &ccsdata->module_pdaf,
878 payload, next_block, dev);
879 if (rval < 0)
880 return rval;
881 break;
882 case CCS_DATA_BLOCK_ID_SENSOR_RULE_BASED_BLOCK:
883 rval = ccs_data_parse_rules(
884 bin, &ccsdata->sensor_rules,
885 &ccsdata->num_sensor_rules, payload, next_block,
886 dev);
887 if (rval < 0)
888 return rval;
889 break;
890 case CCS_DATA_BLOCK_ID_MODULE_RULE_BASED_BLOCK:
891 rval = ccs_data_parse_rules(
892 bin, &ccsdata->module_rules,
893 &ccsdata->num_module_rules, payload, next_block,
894 dev);
895 if (rval < 0)
896 return rval;
897 break;
898 case CCS_DATA_BLOCK_ID_LICENSE:
899 rval = ccs_data_parse_license(bin, &ccsdata->license,
900 &ccsdata->license_length,
901 payload, next_block);
902 if (rval < 0)
903 return rval;
904 break;
905 case CCS_DATA_BLOCK_ID_END:
906 rval = ccs_data_parse_end(&ccsdata->end, payload,
907 next_block, dev);
908 if (rval < 0)
909 return rval;
910 break;
911 default:
912 dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n",
913 block_id);
914 }
915
916 block = next_block;
917 is_first = false;
918 }
919
920 return 0;
921}
922
923
924
925
926
927
928
929
930
931
932int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
933 size_t len, struct device *dev, bool verbose)
934{
935 struct bin_container bin = { 0 };
936 int rval;
937
938 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose);
939 if (rval)
940 return rval;
941
942 rval = bin_backing_alloc(&bin);
943 if (rval)
944 return rval;
945
946 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false);
947 if (rval)
948 goto out_free;
949
950 if (verbose && ccsdata->version)
951 print_ccs_data_version(dev, ccsdata->version);
952
953 if (bin.now != bin.end) {
954 rval = -EPROTO;
955 dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n",
956 bin.base, bin.now, bin.end);
957 goto out_free;
958 }
959
960 ccsdata->backing = bin.base;
961
962 return 0;
963
964out_free:
965 kvfree(bin.base);
966
967 return rval;
968}
969