1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * CCS static data binary parser library
5 * Copyright 2019--2020 Intel Corporation
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <linux/limits.h>
12 #include <linux/slab.h>
14 #include "ccs-data-defs.h"
16 struct bin_container {
23 static void *bin_alloc(struct bin_container *bin, size_t len)
29 if (bin->end - bin->now < len)
38 static void bin_reserve(struct bin_container *bin, size_t len)
40 bin->size += ALIGN(len, 8);
43 static int bin_backing_alloc(struct bin_container *bin)
45 bin->base = bin->now = kvzalloc(bin->size, GFP_KERNEL);
49 bin->end = bin->base + bin->size;
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))
62 ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier *__len,
63 size_t *__hlen, size_t *__plen,
68 if (!is_contained(__len, endp))
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);
77 case CCS_DATA_LENGTH_SPECIFIER_2: {
78 struct __ccs_data_length_specifier2 *__len2 = (void *)__len;
80 if (!is_contained(__len2, endp))
83 hlen = sizeof(*__len2);
86 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
87 << 8) + __len2->length[1];
90 case CCS_DATA_LENGTH_SPECIFIER_3: {
91 struct __ccs_data_length_specifier3 *__len3 = (void *)__len;
93 if (!is_contained(__len3, endp))
96 hlen = sizeof(*__len3);
99 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
100 << 16) + (__len3->length[0] << 8) + __len3->length[1];
107 if (!has_headroom(__len, hlen + plen, endp))
117 ccs_data_parse_format_version(const struct __ccs_data_block *block)
119 return block->id >> CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT;
122 static u8 ccs_data_parse_block_id(const struct __ccs_data_block *block,
128 return block->id & ((1 << CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT) - 1);
131 static int ccs_data_parse_version(struct bin_container *bin,
132 struct ccs_data_container *ccsdata,
133 const void *payload, const void *endp)
135 const struct __ccs_data_block_version *v = payload;
136 struct ccs_data_block_version *vv;
142 bin_reserve(bin, sizeof(*ccsdata->version));
146 ccsdata->version = bin_alloc(bin, sizeof(*ccsdata->version));
147 if (!ccsdata->version)
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;
162 static void print_ccs_data_version(struct device *dev,
163 struct ccs_data_block_version *v)
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);
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,
182 if (!is_contained(block, endp))
185 rval = ccs_data_parse_length_specifier(&block->length, &hlen, &plen,
190 block_id = ccs_data_parse_block_id(block, is_first);
194 "Block ID 0x%2.2x, header length %zu, payload length %zu\n",
195 block_id, hlen, plen);
197 if (!has_headroom(&block->length, hlen + plen, endp))
201 *__block_id = block_id;
204 *payload = (void *)&block->length + hlen;
207 *next_block = (void *)&block->length + hlen + plen;
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)
217 struct ccs_reg *regs_base = NULL, *regs = NULL;
221 if (bin->base && __regs) {
222 regs = regs_base = bin_alloc(bin, sizeof(*regs) * *__num_regs);
227 while (payload < endp && num_regs < INT_MAX) {
228 const struct __ccs_data_block_regs *r = payload;
232 if (!is_contained(r, endp))
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;
241 if (!is_contained_with_headroom(r, len, endp))
246 case CCS_DATA_BLOCK_REGS_SEL_REGS2: {
247 const struct __ccs_data_block_regs2 *r2 = payload;
249 if (!is_contained(r2, endp))
252 addr += ((u16)(r2->reg_len &
253 CCS_DATA_BLOCK_REGS_2_ADDR_MASK) << 8)
255 len = ((r2->reg_len & CCS_DATA_BLOCK_REGS_2_LEN_MASK)
256 >> CCS_DATA_BLOCK_REGS_2_LEN_SHIFT) + 1;
258 if (!is_contained_with_headroom(r2, len, endp))
264 case CCS_DATA_BLOCK_REGS_SEL_REGS3: {
265 const struct __ccs_data_block_regs3 *r3 = payload;
267 if (!is_contained(r3, endp))
270 addr = ((u16)r3->addr[0] << 8) + r3->addr[1];
271 len = (r3->reg_len & CCS_DATA_BLOCK_REGS_3_LEN_MASK) + 1;
273 if (!is_contained_with_headroom(r3, len, endp))
286 bin_reserve(bin, len);
293 regs->value = bin_alloc(bin, len);
297 memcpy(regs->value, data, len);
302 payload = data + len;
306 bin_reserve(bin, sizeof(*regs) * num_regs);
309 *__num_regs = num_regs;
311 if (bin->base && __regs) {
321 static int ccs_data_parse_reg_rules(struct bin_container *bin,
322 struct ccs_reg **__regs,
325 const void *endp, struct device *dev)
330 return ccs_data_parse_regs(bin, NULL, NULL, payload, endp, dev);
332 rval = ccs_data_parse_regs(bin, NULL, __num_regs, payload, endp, dev);
336 return ccs_data_parse_regs(bin, __regs, __num_regs, payload, endp,
340 static void assign_ffd_entry(struct ccs_frame_format_desc *desc,
341 const struct __ccs_data_block_ffd_entry *ent)
343 desc->pixelcode = ent->pixelcode;
344 desc->value = ((u16)ent->value[0] << 8) + ent->value[1];
347 static int ccs_data_parse_ffd(struct bin_container *bin,
348 struct ccs_frame_format_descs **ffd,
350 const void *endp, struct device *dev)
352 const struct __ccs_data_block_ffd *__ffd = payload;
353 const struct __ccs_data_block_ffd_entry *__entry;
356 if (!is_contained(__ffd, endp))
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)
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));
375 *ffd = bin_alloc(bin, sizeof(**ffd));
379 (*ffd)->num_column_descs = __ffd->num_column_descs;
380 (*ffd)->num_row_descs = __ffd->num_row_descs;
381 __entry = (void *)(__ffd + 1);
383 (*ffd)->column_descs = bin_alloc(bin, __ffd->num_column_descs *
384 sizeof(*(*ffd)->column_descs));
385 if (!(*ffd)->column_descs)
388 for (i = 0; i < __ffd->num_column_descs; i++, __entry++)
389 assign_ffd_entry(&(*ffd)->column_descs[i], __entry);
391 (*ffd)->row_descs = bin_alloc(bin, __ffd->num_row_descs *
392 sizeof(*(*ffd)->row_descs));
393 if (!(*ffd)->row_descs)
396 for (i = 0; i < __ffd->num_row_descs; i++, __entry++)
397 assign_ffd_entry(&(*ffd)->row_descs[i], __entry);
405 static int ccs_data_parse_pdaf_readout(struct bin_container *bin,
406 struct ccs_pdaf_readout **pdaf_readout,
408 const void *endp, struct device *dev)
410 const struct __ccs_data_block_pdaf_readout *__pdaf = payload;
412 if (!is_contained(__pdaf, endp))
416 bin_reserve(bin, sizeof(**pdaf_readout));
418 *pdaf_readout = bin_alloc(bin, sizeof(**pdaf_readout));
422 (*pdaf_readout)->pdaf_readout_info_order =
423 __pdaf->pdaf_readout_info_order;
426 return ccs_data_parse_ffd(bin, !bin->base ? NULL : &(*pdaf_readout)->ffd,
427 __pdaf + 1, endp, 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)
435 struct ccs_rule *rules_base = NULL, *rules = NULL, *next_rule = NULL;
436 size_t num_rules = 0;
437 const void *__next_rule = payload;
441 rules_base = next_rule =
442 bin_alloc(bin, sizeof(*rules) * *__num_rules);
447 while (__next_rule < endp) {
448 size_t rule_hlen, rule_plen, rule_plen2;
449 const u8 *__rule_type;
450 const void *rule_payload;
452 /* Size of a single rule */
453 rval = ccs_data_parse_length_specifier(__next_rule, &rule_hlen,
459 __rule_type = __next_rule + rule_hlen;
461 if (!is_contained(__rule_type, endp))
464 rule_payload = __rule_type + 1;
465 rule_plen2 = rule_plen - sizeof(*__rule_type);
467 if (*__rule_type == CCS_DATA_BLOCK_RULE_ID_IF) {
468 const struct __ccs_data_block_rule_if *__if_rules =
470 const size_t __num_if_rules =
471 rule_plen2 / sizeof(*__if_rules);
472 struct ccs_if_rule *if_rule;
474 if (!has_headroom(__if_rules,
475 sizeof(*__if_rules) * __num_if_rules,
476 rule_payload + rule_plen2))
479 /* Also check there is no extra data */
480 if (__if_rules + __num_if_rules !=
481 rule_payload + rule_plen2)
498 if_rule = bin_alloc(bin,
504 for (i = 0; i < __num_if_rules; i++) {
506 ((u16)__if_rules[i].addr[0]
508 __if_rules[i].addr[1];
509 if_rule[i].value = __if_rules[i].value;
510 if_rule[i].mask = __if_rules[i].mask;
513 rules->if_rules = if_rule;
514 rules->num_if_rules = __num_if_rules;
517 /* Check there was an if rule before any other rules */
518 if (bin->base && !rules)
521 switch (*__rule_type) {
522 case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
523 rval = ccs_data_parse_reg_rules(bin,
525 &rules->read_only_regs : NULL,
527 &rules->num_read_only_regs : NULL,
529 rule_payload + rule_plen2,
534 case CCS_DATA_BLOCK_RULE_ID_FFD:
535 rval = ccs_data_parse_ffd(bin, rules ?
536 &rules->frame_format : NULL,
538 rule_payload + rule_plen2,
543 case CCS_DATA_BLOCK_RULE_ID_MSR:
544 rval = ccs_data_parse_reg_rules(bin,
546 &rules->manufacturer_regs : NULL,
548 &rules->num_manufacturer_regs : NULL,
550 rule_payload + rule_plen2,
555 case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
556 rval = ccs_data_parse_pdaf_readout(bin,
558 &rules->pdaf_readout : NULL,
560 rule_payload + rule_plen2,
567 "Don't know how to handle rule type %u!\n",
572 __next_rule = __next_rule + rule_hlen + rule_plen;
576 bin_reserve(bin, sizeof(*rules) * num_rules);
577 *__num_rules = num_rules;
582 *__rules = rules_base;
588 static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf,
589 const void *payload, const void *endp,
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;
596 u16 num_block_desc_groups;
597 u8 max_block_type_id = 0;
598 const u8 *__num_pixel_descs;
600 if (!is_contained(__pdaf, endp))
604 *pdaf = bin_alloc(bin, sizeof(**pdaf));
608 bin_reserve(bin, sizeof(**pdaf));
611 num_block_desc_groups =
612 ((u16)__pdaf->num_block_desc_groups[0] << 8) +
613 __pdaf->num_block_desc_groups[1];
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;
628 __bdesc_group = (const void *)(__pdaf + 1);
631 (*pdaf)->block_desc_groups =
633 sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
634 num_block_desc_groups);
635 if (!(*pdaf)->block_desc_groups)
638 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
639 num_block_desc_groups);
642 for (i = 0; i < num_block_desc_groups; i++) {
643 const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc;
647 if (!is_contained(__bdesc_group, endp))
651 ((u16)__bdesc_group->num_block_descs[0] << 8) +
652 __bdesc_group->num_block_descs[1];
655 (*pdaf)->block_desc_groups[i].repeat_y =
656 __bdesc_group->repeat_y;
657 (*pdaf)->block_desc_groups[i].num_block_descs =
661 __bdesc = (const void *)(__bdesc_group + 1);
664 (*pdaf)->block_desc_groups[i].block_descs =
666 sizeof(struct ccs_pdaf_pix_loc_block_desc) *
668 if (!(*pdaf)->block_desc_groups[i].block_descs)
671 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) *
675 for (j = 0; j < num_block_descs; j++, __bdesc++) {
676 struct ccs_pdaf_pix_loc_block_desc *bdesc;
678 if (!is_contained(__bdesc, endp))
681 if (max_block_type_id <= __bdesc->block_type_id)
682 max_block_type_id = __bdesc->block_type_id + 1;
687 bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j];
689 bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8)
690 + __bdesc->repeat_x[1];
692 if (__bdesc->block_type_id >= num_block_descs)
695 bdesc->block_type_id = __bdesc->block_type_id;
698 __bdesc_group = (const void *)__bdesc;
701 __num_pixel_descs = (const void *)__bdesc_group;
704 (*pdaf)->pixel_desc_groups =
706 sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
708 if (!(*pdaf)->pixel_desc_groups)
710 (*pdaf)->num_pixel_desc_grups = max_block_type_id;
712 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
716 for (i = 0; i < max_block_type_id; i++) {
717 struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL;
720 if (!is_contained(__num_pixel_descs, endp))
724 pdgroup = &(*pdaf)->pixel_desc_groups[i];
727 sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
731 pdgroup->num_descs = *__num_pixel_descs;
733 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
737 __pixel_desc = (const void *)(__num_pixel_descs + 1);
739 for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) {
740 struct ccs_pdaf_pix_loc_pixel_desc *pdesc;
742 if (!is_contained(__pixel_desc, endp))
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;
757 __num_pixel_descs = (const void *)(__pixel_desc + 1);
763 static int ccs_data_parse_license(struct bin_container *bin,
765 size_t *__license_length,
766 const void *payload, const void *endp)
768 size_t size = endp - payload;
772 bin_reserve(bin, size);
776 license = bin_alloc(bin, size);
780 memcpy(license, payload, size);
782 *__license = license;
783 *__license_length = size;
788 static int ccs_data_parse_end(bool *end, const void *payload, const void *endp,
791 const struct __ccs_data_block_end *__end = payload;
793 if (__end + 1 != endp) {
794 dev_dbg(dev, "Invalid end block length %u\n",
795 (unsigned int)(endp - payload));
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,
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;
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);
822 dev_dbg(dev, "Parsing CCS static data version %u\n", version);
825 *ccsdata = (struct ccs_data_container){ 0 };
827 while (block < endp) {
828 const struct __ccs_data_block *next_block;
829 unsigned int block_id;
832 rval = ccs_data_block_parse_header(block, is_first, &block_id,
833 &payload, &next_block, endp,
835 bin->base ? false : verbose);
841 case CCS_DATA_BLOCK_ID_DUMMY:
843 case CCS_DATA_BLOCK_ID_DATA_VERSION:
844 rval = ccs_data_parse_version(bin, ccsdata, payload,
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,
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,
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,
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,
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);
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);
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,
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,
909 case CCS_DATA_BLOCK_ID_LICENSE:
910 rval = ccs_data_parse_license(bin, &ccsdata->license,
911 &ccsdata->license_length,
912 payload, next_block);
916 case CCS_DATA_BLOCK_ID_END:
917 rval = ccs_data_parse_end(&ccsdata->end, payload,
923 dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n",
935 * ccs_data_parse - Parse a CCS static data file into a usable in-memory
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
943 int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
944 size_t len, struct device *dev, bool verbose)
946 struct bin_container bin = { 0 };
949 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose);
953 rval = bin_backing_alloc(&bin);
957 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false);
961 if (verbose && ccsdata->version)
962 print_ccs_data_version(dev, ccsdata->version);
964 if (bin.now != bin.end) {
966 dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n",
967 bin.base, bin.now, bin.end);
971 ccsdata->backing = bin.base;