0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/errno.h>
0010 #include <linux/limits.h>
0011 #include <linux/mm.h>
0012 #include <linux/slab.h>
0013
0014 #include "ccs-data-defs.h"
0015
0016 struct bin_container {
0017 void *base;
0018 void *now;
0019 void *end;
0020 size_t size;
0021 };
0022
0023 static void *bin_alloc(struct bin_container *bin, size_t len)
0024 {
0025 void *ptr;
0026
0027 len = ALIGN(len, 8);
0028
0029 if (bin->end - bin->now < len)
0030 return NULL;
0031
0032 ptr = bin->now;
0033 bin->now += len;
0034
0035 return ptr;
0036 }
0037
0038 static void bin_reserve(struct bin_container *bin, size_t len)
0039 {
0040 bin->size += ALIGN(len, 8);
0041 }
0042
0043 static int bin_backing_alloc(struct bin_container *bin)
0044 {
0045 bin->base = bin->now = kvzalloc(bin->size, GFP_KERNEL);
0046 if (!bin->base)
0047 return -ENOMEM;
0048
0049 bin->end = bin->base + bin->size;
0050
0051 return 0;
0052 }
0053
0054 #define is_contained(var, endp) \
0055 (sizeof(*var) <= (endp) - (void *)(var))
0056 #define has_headroom(ptr, headroom, endp) \
0057 ((headroom) <= (endp) - (void *)(ptr))
0058 #define is_contained_with_headroom(var, headroom, endp) \
0059 (sizeof(*var) + (headroom) <= (endp) - (void *)(var))
0060
0061 static int
0062 ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier *__len,
0063 size_t *__hlen, size_t *__plen,
0064 const void *endp)
0065 {
0066 size_t hlen, plen;
0067
0068 if (!is_contained(__len, endp))
0069 return -ENODATA;
0070
0071 switch (__len->length >> CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) {
0072 case CCS_DATA_LENGTH_SPECIFIER_1:
0073 hlen = sizeof(*__len);
0074 plen = __len->length &
0075 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1);
0076 break;
0077 case CCS_DATA_LENGTH_SPECIFIER_2: {
0078 struct __ccs_data_length_specifier2 *__len2 = (void *)__len;
0079
0080 if (!is_contained(__len2, endp))
0081 return -ENODATA;
0082
0083 hlen = sizeof(*__len2);
0084 plen = ((size_t)
0085 (__len2->length[0] &
0086 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
0087 << 8) + __len2->length[1];
0088 break;
0089 }
0090 case CCS_DATA_LENGTH_SPECIFIER_3: {
0091 struct __ccs_data_length_specifier3 *__len3 = (void *)__len;
0092
0093 if (!is_contained(__len3, endp))
0094 return -ENODATA;
0095
0096 hlen = sizeof(*__len3);
0097 plen = ((size_t)
0098 (__len3->length[0] &
0099 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
0100 << 16) + (__len3->length[0] << 8) + __len3->length[1];
0101 break;
0102 }
0103 default:
0104 return -EINVAL;
0105 }
0106
0107 if (!has_headroom(__len, hlen + plen, endp))
0108 return -ENODATA;
0109
0110 *__hlen = hlen;
0111 *__plen = plen;
0112
0113 return 0;
0114 }
0115
0116 static u8
0117 ccs_data_parse_format_version(const struct __ccs_data_block *block)
0118 {
0119 return block->id >> CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT;
0120 }
0121
0122 static u8 ccs_data_parse_block_id(const struct __ccs_data_block *block,
0123 bool is_first)
0124 {
0125 if (!is_first)
0126 return block->id;
0127
0128 return block->id & ((1 << CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT) - 1);
0129 }
0130
0131 static int ccs_data_parse_version(struct bin_container *bin,
0132 struct ccs_data_container *ccsdata,
0133 const void *payload, const void *endp)
0134 {
0135 const struct __ccs_data_block_version *v = payload;
0136 struct ccs_data_block_version *vv;
0137
0138 if (v + 1 != endp)
0139 return -ENODATA;
0140
0141 if (!bin->base) {
0142 bin_reserve(bin, sizeof(*ccsdata->version));
0143 return 0;
0144 }
0145
0146 ccsdata->version = bin_alloc(bin, sizeof(*ccsdata->version));
0147 if (!ccsdata->version)
0148 return -ENOMEM;
0149
0150 vv = ccsdata->version;
0151 vv->version_major = ((u16)v->static_data_version_major[0] << 8) +
0152 v->static_data_version_major[1];
0153 vv->version_minor = ((u16)v->static_data_version_minor[0] << 8) +
0154 v->static_data_version_minor[1];
0155 vv->date_year = ((u16)v->year[0] << 8) + v->year[1];
0156 vv->date_month = v->month;
0157 vv->date_day = v->day;
0158
0159 return 0;
0160 }
0161
0162 static void print_ccs_data_version(struct device *dev,
0163 struct ccs_data_block_version *v)
0164 {
0165 dev_dbg(dev,
0166 "static data version %4.4x.%4.4x, date %4.4u-%2.2u-%2.2u\n",
0167 v->version_major, v->version_minor,
0168 v->date_year, v->date_month, v->date_day);
0169 }
0170
0171 static int ccs_data_block_parse_header(const struct __ccs_data_block *block,
0172 bool is_first, unsigned int *__block_id,
0173 const void **payload,
0174 const struct __ccs_data_block **next_block,
0175 const void *endp, struct device *dev,
0176 bool verbose)
0177 {
0178 size_t plen, hlen;
0179 u8 block_id;
0180 int rval;
0181
0182 if (!is_contained(block, endp))
0183 return -ENODATA;
0184
0185 rval = ccs_data_parse_length_specifier(&block->length, &hlen, &plen,
0186 endp);
0187 if (rval < 0)
0188 return rval;
0189
0190 block_id = ccs_data_parse_block_id(block, is_first);
0191
0192 if (verbose)
0193 dev_dbg(dev,
0194 "Block ID 0x%2.2x, header length %zu, payload length %zu\n",
0195 block_id, hlen, plen);
0196
0197 if (!has_headroom(&block->length, hlen + plen, endp))
0198 return -ENODATA;
0199
0200 if (__block_id)
0201 *__block_id = block_id;
0202
0203 if (payload)
0204 *payload = (void *)&block->length + hlen;
0205
0206 if (next_block)
0207 *next_block = (void *)&block->length + hlen + plen;
0208
0209 return 0;
0210 }
0211
0212 static int ccs_data_parse_regs(struct bin_container *bin,
0213 struct ccs_reg **__regs,
0214 size_t *__num_regs, const void *payload,
0215 const void *endp, struct device *dev)
0216 {
0217 struct ccs_reg *regs_base = NULL, *regs = NULL;
0218 size_t num_regs = 0;
0219 u16 addr = 0;
0220
0221 if (bin->base && __regs) {
0222 regs = regs_base = bin_alloc(bin, sizeof(*regs) * *__num_regs);
0223 if (!regs)
0224 return -ENOMEM;
0225 }
0226
0227 while (payload < endp && num_regs < INT_MAX) {
0228 const struct __ccs_data_block_regs *r = payload;
0229 size_t len;
0230 const void *data;
0231
0232 if (!is_contained(r, endp))
0233 return -ENODATA;
0234
0235 switch (r->reg_len >> CCS_DATA_BLOCK_REGS_SEL_SHIFT) {
0236 case CCS_DATA_BLOCK_REGS_SEL_REGS:
0237 addr += r->reg_len & CCS_DATA_BLOCK_REGS_ADDR_MASK;
0238 len = ((r->reg_len & CCS_DATA_BLOCK_REGS_LEN_MASK)
0239 >> CCS_DATA_BLOCK_REGS_LEN_SHIFT) + 1;
0240
0241 if (!is_contained_with_headroom(r, len, endp))
0242 return -ENODATA;
0243
0244 data = r + 1;
0245 break;
0246 case CCS_DATA_BLOCK_REGS_SEL_REGS2: {
0247 const struct __ccs_data_block_regs2 *r2 = payload;
0248
0249 if (!is_contained(r2, endp))
0250 return -ENODATA;
0251
0252 addr += ((u16)(r2->reg_len &
0253 CCS_DATA_BLOCK_REGS_2_ADDR_MASK) << 8)
0254 + r2->addr;
0255 len = ((r2->reg_len & CCS_DATA_BLOCK_REGS_2_LEN_MASK)
0256 >> CCS_DATA_BLOCK_REGS_2_LEN_SHIFT) + 1;
0257
0258 if (!is_contained_with_headroom(r2, len, endp))
0259 return -ENODATA;
0260
0261 data = r2 + 1;
0262 break;
0263 }
0264 case CCS_DATA_BLOCK_REGS_SEL_REGS3: {
0265 const struct __ccs_data_block_regs3 *r3 = payload;
0266
0267 if (!is_contained(r3, endp))
0268 return -ENODATA;
0269
0270 addr = ((u16)r3->addr[0] << 8) + r3->addr[1];
0271 len = (r3->reg_len & CCS_DATA_BLOCK_REGS_3_LEN_MASK) + 1;
0272
0273 if (!is_contained_with_headroom(r3, len, endp))
0274 return -ENODATA;
0275
0276 data = r3 + 1;
0277 break;
0278 }
0279 default:
0280 return -EINVAL;
0281 }
0282
0283 num_regs++;
0284
0285 if (!bin->base) {
0286 bin_reserve(bin, len);
0287 } else if (__regs) {
0288 if (!regs)
0289 return -EIO;
0290
0291 regs->addr = addr;
0292 regs->len = len;
0293 regs->value = bin_alloc(bin, len);
0294 if (!regs->value)
0295 return -ENOMEM;
0296
0297 memcpy(regs->value, data, len);
0298 regs++;
0299 }
0300
0301 addr += len;
0302 payload = data + len;
0303 }
0304
0305 if (!bin->base)
0306 bin_reserve(bin, sizeof(*regs) * num_regs);
0307
0308 if (__num_regs)
0309 *__num_regs = num_regs;
0310
0311 if (bin->base && __regs) {
0312 if (!regs_base)
0313 return -EIO;
0314
0315 *__regs = regs_base;
0316 }
0317
0318 return 0;
0319 }
0320
0321 static int ccs_data_parse_reg_rules(struct bin_container *bin,
0322 struct ccs_reg **__regs,
0323 size_t *__num_regs,
0324 const void *payload,
0325 const void *endp, struct device *dev)
0326 {
0327 int rval;
0328
0329 if (!bin->base)
0330 return ccs_data_parse_regs(bin, NULL, NULL, payload, endp, dev);
0331
0332 rval = ccs_data_parse_regs(bin, NULL, __num_regs, payload, endp, dev);
0333 if (rval)
0334 return rval;
0335
0336 return ccs_data_parse_regs(bin, __regs, __num_regs, payload, endp,
0337 dev);
0338 }
0339
0340 static void assign_ffd_entry(struct ccs_frame_format_desc *desc,
0341 const struct __ccs_data_block_ffd_entry *ent)
0342 {
0343 desc->pixelcode = ent->pixelcode;
0344 desc->value = ((u16)ent->value[0] << 8) + ent->value[1];
0345 }
0346
0347 static int ccs_data_parse_ffd(struct bin_container *bin,
0348 struct ccs_frame_format_descs **ffd,
0349 const void *payload,
0350 const void *endp, struct device *dev)
0351 {
0352 const struct __ccs_data_block_ffd *__ffd = payload;
0353 const struct __ccs_data_block_ffd_entry *__entry;
0354 unsigned int i;
0355
0356 if (!is_contained(__ffd, endp))
0357 return -ENODATA;
0358
0359 if ((void *)__ffd + sizeof(*__ffd) +
0360 ((u32)__ffd->num_column_descs +
0361 (u32)__ffd->num_row_descs) *
0362 sizeof(struct __ccs_data_block_ffd_entry) != endp)
0363 return -ENODATA;
0364
0365 if (!bin->base) {
0366 bin_reserve(bin, sizeof(**ffd));
0367 bin_reserve(bin, __ffd->num_column_descs *
0368 sizeof(struct ccs_frame_format_desc));
0369 bin_reserve(bin, __ffd->num_row_descs *
0370 sizeof(struct ccs_frame_format_desc));
0371
0372 return 0;
0373 }
0374
0375 *ffd = bin_alloc(bin, sizeof(**ffd));
0376 if (!*ffd)
0377 return -ENOMEM;
0378
0379 (*ffd)->num_column_descs = __ffd->num_column_descs;
0380 (*ffd)->num_row_descs = __ffd->num_row_descs;
0381 __entry = (void *)(__ffd + 1);
0382
0383 (*ffd)->column_descs = bin_alloc(bin, __ffd->num_column_descs *
0384 sizeof(*(*ffd)->column_descs));
0385 if (!(*ffd)->column_descs)
0386 return -ENOMEM;
0387
0388 for (i = 0; i < __ffd->num_column_descs; i++, __entry++)
0389 assign_ffd_entry(&(*ffd)->column_descs[i], __entry);
0390
0391 (*ffd)->row_descs = bin_alloc(bin, __ffd->num_row_descs *
0392 sizeof(*(*ffd)->row_descs));
0393 if (!(*ffd)->row_descs)
0394 return -ENOMEM;
0395
0396 for (i = 0; i < __ffd->num_row_descs; i++, __entry++)
0397 assign_ffd_entry(&(*ffd)->row_descs[i], __entry);
0398
0399 if (__entry != endp)
0400 return -EPROTO;
0401
0402 return 0;
0403 }
0404
0405 static int ccs_data_parse_pdaf_readout(struct bin_container *bin,
0406 struct ccs_pdaf_readout **pdaf_readout,
0407 const void *payload,
0408 const void *endp, struct device *dev)
0409 {
0410 const struct __ccs_data_block_pdaf_readout *__pdaf = payload;
0411
0412 if (!is_contained(__pdaf, endp))
0413 return -ENODATA;
0414
0415 if (!bin->base) {
0416 bin_reserve(bin, sizeof(**pdaf_readout));
0417 } else {
0418 *pdaf_readout = bin_alloc(bin, sizeof(**pdaf_readout));
0419 if (!*pdaf_readout)
0420 return -ENOMEM;
0421
0422 (*pdaf_readout)->pdaf_readout_info_order =
0423 __pdaf->pdaf_readout_info_order;
0424 }
0425
0426 return ccs_data_parse_ffd(bin, !bin->base ? NULL : &(*pdaf_readout)->ffd,
0427 __pdaf + 1, endp, dev);
0428 }
0429
0430 static int ccs_data_parse_rules(struct bin_container *bin,
0431 struct ccs_rule **__rules,
0432 size_t *__num_rules, const void *payload,
0433 const void *endp, struct device *dev)
0434 {
0435 struct ccs_rule *rules_base = NULL, *rules = NULL, *next_rule = NULL;
0436 size_t num_rules = 0;
0437 const void *__next_rule = payload;
0438 int rval;
0439
0440 if (bin->base) {
0441 rules_base = next_rule =
0442 bin_alloc(bin, sizeof(*rules) * *__num_rules);
0443 if (!rules_base)
0444 return -ENOMEM;
0445 }
0446
0447 while (__next_rule < endp) {
0448 size_t rule_hlen, rule_plen, rule_plen2;
0449 const u8 *__rule_type;
0450 const void *rule_payload;
0451
0452
0453 rval = ccs_data_parse_length_specifier(__next_rule, &rule_hlen,
0454 &rule_plen, endp);
0455
0456 if (rval < 0)
0457 return rval;
0458
0459 __rule_type = __next_rule + rule_hlen;
0460
0461 if (!is_contained(__rule_type, endp))
0462 return -ENODATA;
0463
0464 rule_payload = __rule_type + 1;
0465 rule_plen2 = rule_plen - sizeof(*__rule_type);
0466
0467 switch (*__rule_type) {
0468 case CCS_DATA_BLOCK_RULE_ID_IF: {
0469 const struct __ccs_data_block_rule_if *__if_rules =
0470 rule_payload;
0471 const size_t __num_if_rules =
0472 rule_plen2 / sizeof(*__if_rules);
0473 struct ccs_if_rule *if_rule;
0474
0475 if (!has_headroom(__if_rules,
0476 sizeof(*__if_rules) * __num_if_rules,
0477 rule_payload + rule_plen2))
0478 return -ENODATA;
0479
0480
0481 if (__if_rules + __num_if_rules !=
0482 rule_payload + rule_plen2)
0483 return -EINVAL;
0484
0485 if (!bin->base) {
0486 bin_reserve(bin,
0487 sizeof(*if_rule) *
0488 __num_if_rules);
0489 num_rules++;
0490 } else {
0491 unsigned int i;
0492
0493 if (!next_rule)
0494 return -EIO;
0495
0496 rules = next_rule;
0497 next_rule++;
0498
0499 if_rule = bin_alloc(bin,
0500 sizeof(*if_rule) *
0501 __num_if_rules);
0502 if (!if_rule)
0503 return -ENOMEM;
0504
0505 for (i = 0; i < __num_if_rules; i++) {
0506 if_rule[i].addr =
0507 ((u16)__if_rules[i].addr[0]
0508 << 8) +
0509 __if_rules[i].addr[1];
0510 if_rule[i].value = __if_rules[i].value;
0511 if_rule[i].mask = __if_rules[i].mask;
0512 }
0513
0514 rules->if_rules = if_rule;
0515 rules->num_if_rules = __num_if_rules;
0516 }
0517 break;
0518 }
0519 case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
0520 rval = ccs_data_parse_reg_rules(bin, &rules->read_only_regs,
0521 &rules->num_read_only_regs,
0522 rule_payload,
0523 rule_payload + rule_plen2,
0524 dev);
0525 if (rval)
0526 return rval;
0527 break;
0528 case CCS_DATA_BLOCK_RULE_ID_FFD:
0529 rval = ccs_data_parse_ffd(bin, &rules->frame_format,
0530 rule_payload,
0531 rule_payload + rule_plen2,
0532 dev);
0533 if (rval)
0534 return rval;
0535 break;
0536 case CCS_DATA_BLOCK_RULE_ID_MSR:
0537 rval = ccs_data_parse_reg_rules(bin,
0538 &rules->manufacturer_regs,
0539 &rules->num_manufacturer_regs,
0540 rule_payload,
0541 rule_payload + rule_plen2,
0542 dev);
0543 if (rval)
0544 return rval;
0545 break;
0546 case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
0547 rval = ccs_data_parse_pdaf_readout(bin,
0548 &rules->pdaf_readout,
0549 rule_payload,
0550 rule_payload + rule_plen2,
0551 dev);
0552 if (rval)
0553 return rval;
0554 break;
0555 default:
0556 dev_dbg(dev,
0557 "Don't know how to handle rule type %u!\n",
0558 *__rule_type);
0559 return -EINVAL;
0560 }
0561 __next_rule = __next_rule + rule_hlen + rule_plen;
0562 }
0563
0564 if (!bin->base) {
0565 bin_reserve(bin, sizeof(*rules) * num_rules);
0566 *__num_rules = num_rules;
0567 } else {
0568 if (!rules_base)
0569 return -EIO;
0570
0571 *__rules = rules_base;
0572 }
0573
0574 return 0;
0575 }
0576
0577 static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf,
0578 const void *payload, const void *endp,
0579 struct device *dev)
0580 {
0581 const struct __ccs_data_block_pdaf_pix_loc *__pdaf = payload;
0582 const struct __ccs_data_block_pdaf_pix_loc_block_desc_group *__bdesc_group;
0583 const struct __ccs_data_block_pdaf_pix_loc_pixel_desc *__pixel_desc;
0584 unsigned int i;
0585 u16 num_block_desc_groups;
0586 u8 max_block_type_id = 0;
0587 const u8 *__num_pixel_descs;
0588
0589 if (!is_contained(__pdaf, endp))
0590 return -ENODATA;
0591
0592 if (bin->base) {
0593 *pdaf = bin_alloc(bin, sizeof(**pdaf));
0594 if (!*pdaf)
0595 return -ENOMEM;
0596 } else {
0597 bin_reserve(bin, sizeof(**pdaf));
0598 }
0599
0600 num_block_desc_groups =
0601 ((u16)__pdaf->num_block_desc_groups[0] << 8) +
0602 __pdaf->num_block_desc_groups[1];
0603
0604 if (bin->base) {
0605 (*pdaf)->main_offset_x =
0606 ((u16)__pdaf->main_offset_x[0] << 8) +
0607 __pdaf->main_offset_x[1];
0608 (*pdaf)->main_offset_y =
0609 ((u16)__pdaf->main_offset_y[0] << 8) +
0610 __pdaf->main_offset_y[1];
0611 (*pdaf)->global_pdaf_type = __pdaf->global_pdaf_type;
0612 (*pdaf)->block_width = __pdaf->block_width;
0613 (*pdaf)->block_height = __pdaf->block_height;
0614 (*pdaf)->num_block_desc_groups = num_block_desc_groups;
0615 }
0616
0617 __bdesc_group = (const void *)(__pdaf + 1);
0618
0619 if (bin->base) {
0620 (*pdaf)->block_desc_groups =
0621 bin_alloc(bin,
0622 sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
0623 num_block_desc_groups);
0624 if (!(*pdaf)->block_desc_groups)
0625 return -ENOMEM;
0626 } else {
0627 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) *
0628 num_block_desc_groups);
0629 }
0630
0631 for (i = 0; i < num_block_desc_groups; i++) {
0632 const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc;
0633 u16 num_block_descs;
0634 unsigned int j;
0635
0636 if (!is_contained(__bdesc_group, endp))
0637 return -ENODATA;
0638
0639 num_block_descs =
0640 ((u16)__bdesc_group->num_block_descs[0] << 8) +
0641 __bdesc_group->num_block_descs[1];
0642
0643 if (bin->base) {
0644 (*pdaf)->block_desc_groups[i].repeat_y =
0645 __bdesc_group->repeat_y;
0646 (*pdaf)->block_desc_groups[i].num_block_descs =
0647 num_block_descs;
0648 }
0649
0650 __bdesc = (const void *)(__bdesc_group + 1);
0651
0652 if (bin->base) {
0653 (*pdaf)->block_desc_groups[i].block_descs =
0654 bin_alloc(bin,
0655 sizeof(struct ccs_pdaf_pix_loc_block_desc) *
0656 num_block_descs);
0657 if (!(*pdaf)->block_desc_groups[i].block_descs)
0658 return -ENOMEM;
0659 } else {
0660 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) *
0661 num_block_descs);
0662 }
0663
0664 for (j = 0; j < num_block_descs; j++, __bdesc++) {
0665 struct ccs_pdaf_pix_loc_block_desc *bdesc;
0666
0667 if (!is_contained(__bdesc, endp))
0668 return -ENODATA;
0669
0670 if (max_block_type_id <= __bdesc->block_type_id)
0671 max_block_type_id = __bdesc->block_type_id + 1;
0672
0673 if (!bin->base)
0674 continue;
0675
0676 bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j];
0677
0678 bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8)
0679 + __bdesc->repeat_x[1];
0680
0681 if (__bdesc->block_type_id >= num_block_descs)
0682 return -EINVAL;
0683
0684 bdesc->block_type_id = __bdesc->block_type_id;
0685 }
0686
0687 __bdesc_group = (const void *)__bdesc;
0688 }
0689
0690 __num_pixel_descs = (const void *)__bdesc_group;
0691
0692 if (bin->base) {
0693 (*pdaf)->pixel_desc_groups =
0694 bin_alloc(bin,
0695 sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
0696 max_block_type_id);
0697 if (!(*pdaf)->pixel_desc_groups)
0698 return -ENOMEM;
0699 (*pdaf)->num_pixel_desc_grups = max_block_type_id;
0700 } else {
0701 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) *
0702 max_block_type_id);
0703 }
0704
0705 for (i = 0; i < max_block_type_id; i++) {
0706 struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL;
0707 unsigned int j;
0708
0709 if (!is_contained(__num_pixel_descs, endp))
0710 return -ENODATA;
0711
0712 if (bin->base) {
0713 pdgroup = &(*pdaf)->pixel_desc_groups[i];
0714 pdgroup->descs =
0715 bin_alloc(bin,
0716 sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
0717 *__num_pixel_descs);
0718 if (!pdgroup->descs)
0719 return -ENOMEM;
0720 pdgroup->num_descs = *__num_pixel_descs;
0721 } else {
0722 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) *
0723 *__num_pixel_descs);
0724 }
0725
0726 __pixel_desc = (const void *)(__num_pixel_descs + 1);
0727
0728 for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) {
0729 struct ccs_pdaf_pix_loc_pixel_desc *pdesc;
0730
0731 if (!is_contained(__pixel_desc, endp))
0732 return -ENODATA;
0733
0734 if (!bin->base)
0735 continue;
0736
0737 if (!pdgroup)
0738 return -EIO;
0739
0740 pdesc = &pdgroup->descs[j];
0741 pdesc->pixel_type = __pixel_desc->pixel_type;
0742 pdesc->small_offset_x = __pixel_desc->small_offset_x;
0743 pdesc->small_offset_y = __pixel_desc->small_offset_y;
0744 }
0745
0746 __num_pixel_descs = (const void *)(__pixel_desc + 1);
0747 }
0748
0749 return 0;
0750 }
0751
0752 static int ccs_data_parse_license(struct bin_container *bin,
0753 char **__license,
0754 size_t *__license_length,
0755 const void *payload, const void *endp)
0756 {
0757 size_t size = endp - payload;
0758 char *license;
0759
0760 if (!bin->base) {
0761 bin_reserve(bin, size);
0762 return 0;
0763 }
0764
0765 license = bin_alloc(bin, size);
0766 if (!license)
0767 return -ENOMEM;
0768
0769 memcpy(license, payload, size);
0770
0771 *__license = license;
0772 *__license_length = size;
0773
0774 return 0;
0775 }
0776
0777 static int ccs_data_parse_end(bool *end, const void *payload, const void *endp,
0778 struct device *dev)
0779 {
0780 const struct __ccs_data_block_end *__end = payload;
0781
0782 if (__end + 1 != endp) {
0783 dev_dbg(dev, "Invalid end block length %u\n",
0784 (unsigned int)(endp - payload));
0785 return -ENODATA;
0786 }
0787
0788 *end = true;
0789
0790 return 0;
0791 }
0792
0793 static int __ccs_data_parse(struct bin_container *bin,
0794 struct ccs_data_container *ccsdata,
0795 const void *data, size_t len, struct device *dev,
0796 bool verbose)
0797 {
0798 const struct __ccs_data_block *block = data;
0799 const struct __ccs_data_block *endp = data + len;
0800 unsigned int version;
0801 bool is_first = true;
0802 int rval;
0803
0804 version = ccs_data_parse_format_version(block);
0805 if (version != CCS_STATIC_DATA_VERSION) {
0806 dev_dbg(dev, "Don't know how to handle version %u\n", version);
0807 return -EINVAL;
0808 }
0809
0810 if (verbose)
0811 dev_dbg(dev, "Parsing CCS static data version %u\n", version);
0812
0813 if (!bin->base)
0814 *ccsdata = (struct ccs_data_container){ 0 };
0815
0816 while (block < endp) {
0817 const struct __ccs_data_block *next_block;
0818 unsigned int block_id;
0819 const void *payload;
0820
0821 rval = ccs_data_block_parse_header(block, is_first, &block_id,
0822 &payload, &next_block, endp,
0823 dev,
0824 bin->base ? false : verbose);
0825
0826 if (rval < 0)
0827 return rval;
0828
0829 switch (block_id) {
0830 case CCS_DATA_BLOCK_ID_DUMMY:
0831 break;
0832 case CCS_DATA_BLOCK_ID_DATA_VERSION:
0833 rval = ccs_data_parse_version(bin, ccsdata, payload,
0834 next_block);
0835 if (rval < 0)
0836 return rval;
0837 break;
0838 case CCS_DATA_BLOCK_ID_SENSOR_READ_ONLY_REGS:
0839 rval = ccs_data_parse_regs(
0840 bin, &ccsdata->sensor_read_only_regs,
0841 &ccsdata->num_sensor_read_only_regs, payload,
0842 next_block, dev);
0843 if (rval < 0)
0844 return rval;
0845 break;
0846 case CCS_DATA_BLOCK_ID_SENSOR_MANUFACTURER_REGS:
0847 rval = ccs_data_parse_regs(
0848 bin, &ccsdata->sensor_manufacturer_regs,
0849 &ccsdata->num_sensor_manufacturer_regs, payload,
0850 next_block, dev);
0851 if (rval < 0)
0852 return rval;
0853 break;
0854 case CCS_DATA_BLOCK_ID_MODULE_READ_ONLY_REGS:
0855 rval = ccs_data_parse_regs(
0856 bin, &ccsdata->module_read_only_regs,
0857 &ccsdata->num_module_read_only_regs, payload,
0858 next_block, dev);
0859 if (rval < 0)
0860 return rval;
0861 break;
0862 case CCS_DATA_BLOCK_ID_MODULE_MANUFACTURER_REGS:
0863 rval = ccs_data_parse_regs(
0864 bin, &ccsdata->module_manufacturer_regs,
0865 &ccsdata->num_module_manufacturer_regs, payload,
0866 next_block, dev);
0867 if (rval < 0)
0868 return rval;
0869 break;
0870 case CCS_DATA_BLOCK_ID_SENSOR_PDAF_PIXEL_LOCATION:
0871 rval = ccs_data_parse_pdaf(bin, &ccsdata->sensor_pdaf,
0872 payload, next_block, dev);
0873 if (rval < 0)
0874 return rval;
0875 break;
0876 case CCS_DATA_BLOCK_ID_MODULE_PDAF_PIXEL_LOCATION:
0877 rval = ccs_data_parse_pdaf(bin, &ccsdata->module_pdaf,
0878 payload, next_block, dev);
0879 if (rval < 0)
0880 return rval;
0881 break;
0882 case CCS_DATA_BLOCK_ID_SENSOR_RULE_BASED_BLOCK:
0883 rval = ccs_data_parse_rules(
0884 bin, &ccsdata->sensor_rules,
0885 &ccsdata->num_sensor_rules, payload, next_block,
0886 dev);
0887 if (rval < 0)
0888 return rval;
0889 break;
0890 case CCS_DATA_BLOCK_ID_MODULE_RULE_BASED_BLOCK:
0891 rval = ccs_data_parse_rules(
0892 bin, &ccsdata->module_rules,
0893 &ccsdata->num_module_rules, payload, next_block,
0894 dev);
0895 if (rval < 0)
0896 return rval;
0897 break;
0898 case CCS_DATA_BLOCK_ID_LICENSE:
0899 rval = ccs_data_parse_license(bin, &ccsdata->license,
0900 &ccsdata->license_length,
0901 payload, next_block);
0902 if (rval < 0)
0903 return rval;
0904 break;
0905 case CCS_DATA_BLOCK_ID_END:
0906 rval = ccs_data_parse_end(&ccsdata->end, payload,
0907 next_block, dev);
0908 if (rval < 0)
0909 return rval;
0910 break;
0911 default:
0912 dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n",
0913 block_id);
0914 }
0915
0916 block = next_block;
0917 is_first = false;
0918 }
0919
0920 return 0;
0921 }
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932 int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
0933 size_t len, struct device *dev, bool verbose)
0934 {
0935 struct bin_container bin = { 0 };
0936 int rval;
0937
0938 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose);
0939 if (rval)
0940 return rval;
0941
0942 rval = bin_backing_alloc(&bin);
0943 if (rval)
0944 return rval;
0945
0946 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false);
0947 if (rval)
0948 goto out_free;
0949
0950 if (verbose && ccsdata->version)
0951 print_ccs_data_version(dev, ccsdata->version);
0952
0953 if (bin.now != bin.end) {
0954 rval = -EPROTO;
0955 dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n",
0956 bin.base, bin.now, bin.end);
0957 goto out_free;
0958 }
0959
0960 ccsdata->backing = bin.base;
0961
0962 return 0;
0963
0964 out_free:
0965 kvfree(bin.base);
0966
0967 return rval;
0968 }