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 #include <linux/string.h> 14 15 #include "ccs-data-defs.h" 16 17 struct bin_container { 18 void *base; 19 void *now; 20 void *end; 21 size_t size; 22 }; 23 bin_alloc(struct bin_container * bin,size_t len)24 static void *bin_alloc(struct bin_container *bin, size_t len) 25 { 26 void *ptr; 27 28 len = ALIGN(len, 8); 29 30 if (bin->end - bin->now < len) 31 return NULL; 32 33 ptr = bin->now; 34 bin->now += len; 35 36 return ptr; 37 } 38 bin_reserve(struct bin_container * bin,size_t len)39 static void bin_reserve(struct bin_container *bin, size_t len) 40 { 41 bin->size += ALIGN(len, 8); 42 } 43 bin_backing_alloc(struct bin_container * bin)44 static int bin_backing_alloc(struct bin_container *bin) 45 { 46 bin->base = bin->now = kvzalloc(bin->size, GFP_KERNEL); 47 if (!bin->base) 48 return -ENOMEM; 49 50 bin->end = bin->base + bin->size; 51 52 return 0; 53 } 54 55 #define is_contained(var, endp) \ 56 (sizeof(*var) <= (endp) - (void *)(var)) 57 #define has_headroom(ptr, headroom, endp) \ 58 ((headroom) <= (endp) - (void *)(ptr)) 59 #define is_contained_with_headroom(var, headroom, endp) \ 60 (sizeof(*var) + (headroom) <= (endp) - (void *)(var)) 61 62 static int ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier * __len,size_t * __hlen,size_t * __plen,const void * endp)63 ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier *__len, 64 size_t *__hlen, size_t *__plen, 65 const void *endp) 66 { 67 size_t hlen, plen; 68 69 if (!is_contained(__len, endp)) 70 return -ENODATA; 71 72 switch (__len->length >> CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) { 73 case CCS_DATA_LENGTH_SPECIFIER_1: 74 hlen = sizeof(*__len); 75 plen = __len->length & 76 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1); 77 break; 78 case CCS_DATA_LENGTH_SPECIFIER_2: { 79 struct __ccs_data_length_specifier2 *__len2 = (void *)__len; 80 81 if (!is_contained(__len2, endp)) 82 return -ENODATA; 83 84 hlen = sizeof(*__len2); 85 plen = ((size_t) 86 (__len2->length[0] & 87 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1)) 88 << 8) + __len2->length[1]; 89 break; 90 } 91 case CCS_DATA_LENGTH_SPECIFIER_3: { 92 struct __ccs_data_length_specifier3 *__len3 = (void *)__len; 93 94 if (!is_contained(__len3, endp)) 95 return -ENODATA; 96 97 hlen = sizeof(*__len3); 98 plen = ((size_t) 99 (__len3->length[0] & 100 ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1)) 101 << 16) + (__len3->length[1] << 8) + __len3->length[2]; 102 break; 103 } 104 default: 105 return -EINVAL; 106 } 107 108 if (!has_headroom(__len, hlen + plen, endp)) 109 return -ENODATA; 110 111 *__hlen = hlen; 112 *__plen = plen; 113 114 return 0; 115 } 116 117 static u8 ccs_data_parse_format_version(const struct __ccs_data_block * block)118 ccs_data_parse_format_version(const struct __ccs_data_block *block) 119 { 120 return block->id >> CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT; 121 } 122 ccs_data_parse_block_id(const struct __ccs_data_block * block,bool is_first)123 static u8 ccs_data_parse_block_id(const struct __ccs_data_block *block, 124 bool is_first) 125 { 126 if (!is_first) 127 return block->id; 128 129 return block->id & ((1 << CCS_DATA_BLOCK_HEADER_ID_VERSION_SHIFT) - 1); 130 } 131 ccs_data_parse_version(struct bin_container * bin,struct ccs_data_container * ccsdata,const void * payload,const void * endp)132 static int ccs_data_parse_version(struct bin_container *bin, 133 struct ccs_data_container *ccsdata, 134 const void *payload, const void *endp) 135 { 136 const struct __ccs_data_block_version *v = payload; 137 struct ccs_data_block_version *vv; 138 139 if (v + 1 != endp) 140 return -ENODATA; 141 142 if (!bin->base) { 143 bin_reserve(bin, sizeof(*ccsdata->version)); 144 return 0; 145 } 146 147 ccsdata->version = bin_alloc(bin, sizeof(*ccsdata->version)); 148 if (!ccsdata->version) 149 return -ENOMEM; 150 151 vv = ccsdata->version; 152 vv->version_major = ((u16)v->static_data_version_major[0] << 8) + 153 v->static_data_version_major[1]; 154 vv->version_minor = ((u16)v->static_data_version_minor[0] << 8) + 155 v->static_data_version_minor[1]; 156 vv->date_year = ((u16)v->year[0] << 8) + v->year[1]; 157 vv->date_month = v->month; 158 vv->date_day = v->day; 159 160 return 0; 161 } 162 print_ccs_data_version(struct device * dev,struct ccs_data_block_version * v)163 static void print_ccs_data_version(struct device *dev, 164 struct ccs_data_block_version *v) 165 { 166 dev_dbg(dev, 167 "static data version %4.4x.%4.4x, date %4.4u-%2.2u-%2.2u\n", 168 v->version_major, v->version_minor, 169 v->date_year, v->date_month, v->date_day); 170 } 171 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)172 static int ccs_data_block_parse_header(const struct __ccs_data_block *block, 173 bool is_first, unsigned int *__block_id, 174 const void **payload, 175 const struct __ccs_data_block **next_block, 176 const void *endp, struct device *dev, 177 bool verbose) 178 { 179 size_t plen, hlen; 180 u8 block_id; 181 int rval; 182 183 if (!is_contained(block, endp)) 184 return -ENODATA; 185 186 rval = ccs_data_parse_length_specifier(&block->length, &hlen, &plen, 187 endp); 188 if (rval < 0) 189 return rval; 190 191 block_id = ccs_data_parse_block_id(block, is_first); 192 193 if (verbose) 194 dev_dbg(dev, 195 "Block ID 0x%2.2x, header length %zu, payload length %zu\n", 196 block_id, hlen, plen); 197 198 if (!has_headroom(&block->length, hlen + plen, endp)) 199 return -ENODATA; 200 201 if (__block_id) 202 *__block_id = block_id; 203 204 if (payload) 205 *payload = (void *)&block->length + hlen; 206 207 if (next_block) 208 *next_block = (void *)&block->length + hlen + plen; 209 210 return 0; 211 } 212 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)213 static int ccs_data_parse_regs(struct bin_container *bin, 214 struct ccs_reg **__regs, 215 size_t *__num_regs, const void *payload, 216 const void *endp, struct device *dev) 217 { 218 struct ccs_reg *regs_base = NULL, *regs = NULL; 219 size_t num_regs = 0; 220 u16 addr = 0; 221 222 if (bin->base && __regs) { 223 regs = regs_base = bin_alloc(bin, sizeof(*regs) * *__num_regs); 224 if (!regs) 225 return -ENOMEM; 226 } 227 228 while (payload < endp && num_regs < INT_MAX) { 229 const struct __ccs_data_block_regs *r = payload; 230 size_t len; 231 const void *data; 232 233 if (!is_contained(r, endp)) 234 return -ENODATA; 235 236 switch (r->reg_len >> CCS_DATA_BLOCK_REGS_SEL_SHIFT) { 237 case CCS_DATA_BLOCK_REGS_SEL_REGS: 238 addr += r->reg_len & CCS_DATA_BLOCK_REGS_ADDR_MASK; 239 len = ((r->reg_len & CCS_DATA_BLOCK_REGS_LEN_MASK) 240 >> CCS_DATA_BLOCK_REGS_LEN_SHIFT) + 1; 241 242 if (!is_contained_with_headroom(r, len, endp)) 243 return -ENODATA; 244 245 data = r + 1; 246 break; 247 case CCS_DATA_BLOCK_REGS_SEL_REGS2: { 248 const struct __ccs_data_block_regs2 *r2 = payload; 249 250 if (!is_contained(r2, endp)) 251 return -ENODATA; 252 253 addr += ((u16)(r2->reg_len & 254 CCS_DATA_BLOCK_REGS_2_ADDR_MASK) << 8) 255 + r2->addr; 256 len = ((r2->reg_len & CCS_DATA_BLOCK_REGS_2_LEN_MASK) 257 >> CCS_DATA_BLOCK_REGS_2_LEN_SHIFT) + 1; 258 259 if (!is_contained_with_headroom(r2, len, endp)) 260 return -ENODATA; 261 262 data = r2 + 1; 263 break; 264 } 265 case CCS_DATA_BLOCK_REGS_SEL_REGS3: { 266 const struct __ccs_data_block_regs3 *r3 = payload; 267 268 if (!is_contained(r3, endp)) 269 return -ENODATA; 270 271 addr = ((u16)r3->addr[0] << 8) + r3->addr[1]; 272 len = (r3->reg_len & CCS_DATA_BLOCK_REGS_3_LEN_MASK) + 1; 273 274 if (!is_contained_with_headroom(r3, len, endp)) 275 return -ENODATA; 276 277 data = r3 + 1; 278 break; 279 } 280 default: 281 return -EINVAL; 282 } 283 284 num_regs++; 285 286 if (!bin->base) { 287 bin_reserve(bin, len); 288 } else if (__regs) { 289 if (!regs) 290 return -EIO; 291 292 regs->addr = addr; 293 regs->len = len; 294 regs->value = bin_alloc(bin, len); 295 if (!regs->value) 296 return -ENOMEM; 297 298 memcpy(regs->value, data, len); 299 regs++; 300 } 301 302 addr += len; 303 payload = data + len; 304 } 305 306 if (!bin->base) 307 bin_reserve(bin, sizeof(*regs) * num_regs); 308 309 if (__num_regs) 310 *__num_regs = num_regs; 311 312 if (bin->base && __regs) { 313 if (!regs_base) 314 return -EIO; 315 316 *__regs = regs_base; 317 } 318 319 return 0; 320 } 321 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)322 static int ccs_data_parse_reg_rules(struct bin_container *bin, 323 struct ccs_reg **__regs, 324 size_t *__num_regs, 325 const void *payload, 326 const void *endp, struct device *dev) 327 { 328 int rval; 329 330 if (!bin->base) 331 return ccs_data_parse_regs(bin, NULL, NULL, payload, endp, dev); 332 333 rval = ccs_data_parse_regs(bin, NULL, __num_regs, payload, endp, dev); 334 if (rval) 335 return rval; 336 337 return ccs_data_parse_regs(bin, __regs, __num_regs, payload, endp, 338 dev); 339 } 340 assign_ffd_entry(struct ccs_frame_format_desc * desc,const struct __ccs_data_block_ffd_entry * ent)341 static void assign_ffd_entry(struct ccs_frame_format_desc *desc, 342 const struct __ccs_data_block_ffd_entry *ent) 343 { 344 desc->pixelcode = ent->pixelcode; 345 desc->value = ((u16)ent->value[0] << 8) + ent->value[1]; 346 } 347 ccs_data_parse_ffd(struct bin_container * bin,struct ccs_frame_format_descs ** ffd,const void * payload,const void * endp,struct device * dev)348 static int ccs_data_parse_ffd(struct bin_container *bin, 349 struct ccs_frame_format_descs **ffd, 350 const void *payload, 351 const void *endp, struct device *dev) 352 { 353 const struct __ccs_data_block_ffd *__ffd = payload; 354 const struct __ccs_data_block_ffd_entry *__entry; 355 unsigned int i; 356 357 if (!is_contained(__ffd, endp)) 358 return -ENODATA; 359 360 if ((void *)__ffd + sizeof(*__ffd) + 361 ((u32)__ffd->num_column_descs + 362 (u32)__ffd->num_row_descs) * 363 sizeof(struct __ccs_data_block_ffd_entry) != endp) 364 return -ENODATA; 365 366 if (!bin->base) { 367 bin_reserve(bin, sizeof(**ffd)); 368 bin_reserve(bin, __ffd->num_column_descs * 369 sizeof(struct ccs_frame_format_desc)); 370 bin_reserve(bin, __ffd->num_row_descs * 371 sizeof(struct ccs_frame_format_desc)); 372 373 return 0; 374 } 375 376 *ffd = bin_alloc(bin, sizeof(**ffd)); 377 if (!*ffd) 378 return -ENOMEM; 379 380 (*ffd)->num_column_descs = __ffd->num_column_descs; 381 (*ffd)->num_row_descs = __ffd->num_row_descs; 382 __entry = (void *)(__ffd + 1); 383 384 (*ffd)->column_descs = bin_alloc(bin, __ffd->num_column_descs * 385 sizeof(*(*ffd)->column_descs)); 386 if (!(*ffd)->column_descs) 387 return -ENOMEM; 388 389 for (i = 0; i < __ffd->num_column_descs; i++, __entry++) 390 assign_ffd_entry(&(*ffd)->column_descs[i], __entry); 391 392 (*ffd)->row_descs = bin_alloc(bin, __ffd->num_row_descs * 393 sizeof(*(*ffd)->row_descs)); 394 if (!(*ffd)->row_descs) 395 return -ENOMEM; 396 397 for (i = 0; i < __ffd->num_row_descs; i++, __entry++) 398 assign_ffd_entry(&(*ffd)->row_descs[i], __entry); 399 400 if (__entry != endp) 401 return -EPROTO; 402 403 return 0; 404 } 405 ccs_data_parse_pdaf_readout(struct bin_container * bin,struct ccs_pdaf_readout ** pdaf_readout,const void * payload,const void * endp,struct device * dev)406 static int ccs_data_parse_pdaf_readout(struct bin_container *bin, 407 struct ccs_pdaf_readout **pdaf_readout, 408 const void *payload, 409 const void *endp, struct device *dev) 410 { 411 const struct __ccs_data_block_pdaf_readout *__pdaf = payload; 412 413 if (!is_contained(__pdaf, endp)) 414 return -ENODATA; 415 416 if (!bin->base) { 417 bin_reserve(bin, sizeof(**pdaf_readout)); 418 } else { 419 *pdaf_readout = bin_alloc(bin, sizeof(**pdaf_readout)); 420 if (!*pdaf_readout) 421 return -ENOMEM; 422 423 (*pdaf_readout)->pdaf_readout_info_order = 424 __pdaf->pdaf_readout_info_order; 425 } 426 427 return ccs_data_parse_ffd(bin, !bin->base ? NULL : &(*pdaf_readout)->ffd, 428 __pdaf + 1, endp, dev); 429 } 430 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)431 static int ccs_data_parse_rules(struct bin_container *bin, 432 struct ccs_rule **__rules, 433 size_t *__num_rules, const void *payload, 434 const void *endp, struct device *dev) 435 { 436 struct ccs_rule *rules_base = NULL, *rules = NULL, *next_rule = NULL; 437 size_t num_rules = 0; 438 const void *__next_rule = payload; 439 int rval; 440 441 if (bin->base) { 442 rules_base = next_rule = 443 bin_alloc(bin, sizeof(*rules) * *__num_rules); 444 if (!rules_base) 445 return -ENOMEM; 446 } 447 448 while (__next_rule < endp) { 449 size_t rule_hlen, rule_plen, rule_plen2; 450 const u8 *__rule_type; 451 const void *rule_payload; 452 453 /* Size of a single rule */ 454 rval = ccs_data_parse_length_specifier(__next_rule, &rule_hlen, 455 &rule_plen, endp); 456 457 if (rval < 0) 458 return rval; 459 460 __rule_type = __next_rule + rule_hlen; 461 462 if (!is_contained(__rule_type, endp)) 463 return -ENODATA; 464 465 rule_payload = __rule_type + 1; 466 rule_plen2 = rule_plen - sizeof(*__rule_type); 467 468 if (*__rule_type == 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 /* Also check there is no extra data */ 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 } else { 518 /* Check there was an if rule before any other rules */ 519 if (bin->base && !rules) 520 return -EINVAL; 521 522 switch (*__rule_type) { 523 case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS: 524 rval = ccs_data_parse_reg_rules(bin, 525 rules ? 526 &rules->read_only_regs : NULL, 527 rules ? 528 &rules->num_read_only_regs : NULL, 529 rule_payload, 530 rule_payload + rule_plen2, 531 dev); 532 if (rval) 533 return rval; 534 break; 535 case CCS_DATA_BLOCK_RULE_ID_FFD: 536 rval = ccs_data_parse_ffd(bin, rules ? 537 &rules->frame_format : NULL, 538 rule_payload, 539 rule_payload + rule_plen2, 540 dev); 541 if (rval) 542 return rval; 543 break; 544 case CCS_DATA_BLOCK_RULE_ID_MSR: 545 rval = ccs_data_parse_reg_rules(bin, 546 rules ? 547 &rules->manufacturer_regs : NULL, 548 rules ? 549 &rules->num_manufacturer_regs : NULL, 550 rule_payload, 551 rule_payload + rule_plen2, 552 dev); 553 if (rval) 554 return rval; 555 break; 556 case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT: 557 rval = ccs_data_parse_pdaf_readout(bin, 558 rules ? 559 &rules->pdaf_readout : NULL, 560 rule_payload, 561 rule_payload + rule_plen2, 562 dev); 563 if (rval) 564 return rval; 565 break; 566 default: 567 dev_dbg(dev, 568 "Don't know how to handle rule type %u!\n", 569 *__rule_type); 570 return -EINVAL; 571 } 572 } 573 __next_rule = __next_rule + rule_hlen + rule_plen; 574 } 575 576 if (!bin->base) { 577 bin_reserve(bin, sizeof(*rules) * num_rules); 578 *__num_rules = num_rules; 579 } else { 580 if (!rules_base) 581 return -EIO; 582 583 *__rules = rules_base; 584 } 585 586 return 0; 587 } 588 ccs_data_parse_pdaf(struct bin_container * bin,struct ccs_pdaf_pix_loc ** pdaf,const void * payload,const void * endp,struct device * dev)589 static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf, 590 const void *payload, const void *endp, 591 struct device *dev) 592 { 593 const struct __ccs_data_block_pdaf_pix_loc *__pdaf = payload; 594 const struct __ccs_data_block_pdaf_pix_loc_block_desc_group *__bdesc_group; 595 const struct __ccs_data_block_pdaf_pix_loc_pixel_desc *__pixel_desc; 596 unsigned int i; 597 u16 num_block_desc_groups; 598 u8 max_block_type_id = 0; 599 const u8 *__num_pixel_descs; 600 601 if (!is_contained(__pdaf, endp)) 602 return -ENODATA; 603 604 if (bin->base) { 605 *pdaf = bin_alloc(bin, sizeof(**pdaf)); 606 if (!*pdaf) 607 return -ENOMEM; 608 } else { 609 bin_reserve(bin, sizeof(**pdaf)); 610 } 611 612 num_block_desc_groups = 613 ((u16)__pdaf->num_block_desc_groups[0] << 8) + 614 __pdaf->num_block_desc_groups[1]; 615 616 if (bin->base) { 617 (*pdaf)->main_offset_x = 618 ((u16)__pdaf->main_offset_x[0] << 8) + 619 __pdaf->main_offset_x[1]; 620 (*pdaf)->main_offset_y = 621 ((u16)__pdaf->main_offset_y[0] << 8) + 622 __pdaf->main_offset_y[1]; 623 (*pdaf)->global_pdaf_type = __pdaf->global_pdaf_type; 624 (*pdaf)->block_width = __pdaf->block_width; 625 (*pdaf)->block_height = __pdaf->block_height; 626 (*pdaf)->num_block_desc_groups = num_block_desc_groups; 627 } 628 629 __bdesc_group = (const void *)(__pdaf + 1); 630 631 if (bin->base) { 632 (*pdaf)->block_desc_groups = 633 bin_alloc(bin, 634 sizeof(struct ccs_pdaf_pix_loc_block_desc_group) * 635 num_block_desc_groups); 636 if (!(*pdaf)->block_desc_groups) 637 return -ENOMEM; 638 } else { 639 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) * 640 num_block_desc_groups); 641 } 642 643 for (i = 0; i < num_block_desc_groups; i++) { 644 const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc; 645 u16 num_block_descs; 646 unsigned int j; 647 648 if (!is_contained(__bdesc_group, endp)) 649 return -ENODATA; 650 651 num_block_descs = 652 ((u16)__bdesc_group->num_block_descs[0] << 8) + 653 __bdesc_group->num_block_descs[1]; 654 655 if (bin->base) { 656 (*pdaf)->block_desc_groups[i].repeat_y = 657 __bdesc_group->repeat_y; 658 (*pdaf)->block_desc_groups[i].num_block_descs = 659 num_block_descs; 660 } 661 662 __bdesc = (const void *)(__bdesc_group + 1); 663 664 if (bin->base) { 665 (*pdaf)->block_desc_groups[i].block_descs = 666 bin_alloc(bin, 667 sizeof(struct ccs_pdaf_pix_loc_block_desc) * 668 num_block_descs); 669 if (!(*pdaf)->block_desc_groups[i].block_descs) 670 return -ENOMEM; 671 } else { 672 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) * 673 num_block_descs); 674 } 675 676 for (j = 0; j < num_block_descs; j++, __bdesc++) { 677 struct ccs_pdaf_pix_loc_block_desc *bdesc; 678 679 if (!is_contained(__bdesc, endp)) 680 return -ENODATA; 681 682 if (max_block_type_id <= __bdesc->block_type_id) 683 max_block_type_id = __bdesc->block_type_id + 1; 684 685 if (!bin->base) 686 continue; 687 688 bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j]; 689 690 bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8) 691 + __bdesc->repeat_x[1]; 692 693 if (__bdesc->block_type_id >= num_block_descs) 694 return -EINVAL; 695 696 bdesc->block_type_id = __bdesc->block_type_id; 697 } 698 699 __bdesc_group = (const void *)__bdesc; 700 } 701 702 __num_pixel_descs = (const void *)__bdesc_group; 703 704 if (bin->base) { 705 (*pdaf)->pixel_desc_groups = 706 bin_alloc(bin, 707 sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) * 708 max_block_type_id); 709 if (!(*pdaf)->pixel_desc_groups) 710 return -ENOMEM; 711 (*pdaf)->num_pixel_desc_grups = max_block_type_id; 712 } else { 713 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) * 714 max_block_type_id); 715 } 716 717 for (i = 0; i < max_block_type_id; i++) { 718 struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL; 719 unsigned int j; 720 721 if (!is_contained(__num_pixel_descs, endp)) 722 return -ENODATA; 723 724 if (bin->base) { 725 pdgroup = &(*pdaf)->pixel_desc_groups[i]; 726 pdgroup->descs = 727 bin_alloc(bin, 728 sizeof(struct ccs_pdaf_pix_loc_pixel_desc) * 729 *__num_pixel_descs); 730 if (!pdgroup->descs) 731 return -ENOMEM; 732 pdgroup->num_descs = *__num_pixel_descs; 733 } else { 734 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) * 735 *__num_pixel_descs); 736 } 737 738 __pixel_desc = (const void *)(__num_pixel_descs + 1); 739 740 for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) { 741 struct ccs_pdaf_pix_loc_pixel_desc *pdesc; 742 743 if (!is_contained(__pixel_desc, endp)) 744 return -ENODATA; 745 746 if (!bin->base) 747 continue; 748 749 if (!pdgroup) 750 return -EIO; 751 752 pdesc = &pdgroup->descs[j]; 753 pdesc->pixel_type = __pixel_desc->pixel_type; 754 pdesc->small_offset_x = __pixel_desc->small_offset_x; 755 pdesc->small_offset_y = __pixel_desc->small_offset_y; 756 } 757 758 __num_pixel_descs = (const void *)(__pixel_desc + 1); 759 } 760 761 return 0; 762 } 763 ccs_data_parse_license(struct bin_container * bin,char ** __license,size_t * __license_length,const void * payload,const void * endp)764 static int ccs_data_parse_license(struct bin_container *bin, 765 char **__license, 766 size_t *__license_length, 767 const void *payload, const void *endp) 768 { 769 size_t size = endp - payload; 770 char *license; 771 772 if (!bin->base) { 773 bin_reserve(bin, size); 774 return 0; 775 } 776 777 license = bin_alloc(bin, size); 778 if (!license) 779 return -ENOMEM; 780 781 memcpy(license, payload, size); 782 783 *__license = license; 784 *__license_length = size; 785 786 return 0; 787 } 788 ccs_data_parse_end(bool * end,const void * payload,const void * endp,struct device * dev)789 static int ccs_data_parse_end(bool *end, const void *payload, const void *endp, 790 struct device *dev) 791 { 792 const struct __ccs_data_block_end *__end = payload; 793 794 if (__end + 1 != endp) { 795 dev_dbg(dev, "Invalid end block length %u\n", 796 (unsigned int)(endp - payload)); 797 return -ENODATA; 798 } 799 800 *end = true; 801 802 return 0; 803 } 804 __ccs_data_parse(struct bin_container * bin,struct ccs_data_container * ccsdata,const void * data,size_t len,struct device * dev,bool verbose)805 static int __ccs_data_parse(struct bin_container *bin, 806 struct ccs_data_container *ccsdata, 807 const void *data, size_t len, struct device *dev, 808 bool verbose) 809 { 810 const struct __ccs_data_block *block = data; 811 const struct __ccs_data_block *endp = data + len; 812 unsigned int version; 813 bool is_first = true; 814 int rval; 815 816 version = ccs_data_parse_format_version(block); 817 if (version != CCS_STATIC_DATA_VERSION) { 818 dev_dbg(dev, "Don't know how to handle version %u\n", version); 819 return -EINVAL; 820 } 821 822 if (verbose) 823 dev_dbg(dev, "Parsing CCS static data version %u\n", version); 824 825 if (!bin->base) 826 *ccsdata = (struct ccs_data_container){ 0 }; 827 828 while (block < endp) { 829 const struct __ccs_data_block *next_block; 830 unsigned int block_id; 831 const void *payload; 832 833 rval = ccs_data_block_parse_header(block, is_first, &block_id, 834 &payload, &next_block, endp, 835 dev, 836 bin->base ? false : verbose); 837 838 if (rval < 0) 839 return rval; 840 841 switch (block_id) { 842 case CCS_DATA_BLOCK_ID_DUMMY: 843 break; 844 case CCS_DATA_BLOCK_ID_DATA_VERSION: 845 rval = ccs_data_parse_version(bin, ccsdata, payload, 846 next_block); 847 if (rval < 0) 848 return rval; 849 break; 850 case CCS_DATA_BLOCK_ID_SENSOR_READ_ONLY_REGS: 851 rval = ccs_data_parse_regs( 852 bin, &ccsdata->sensor_read_only_regs, 853 &ccsdata->num_sensor_read_only_regs, payload, 854 next_block, dev); 855 if (rval < 0) 856 return rval; 857 break; 858 case CCS_DATA_BLOCK_ID_SENSOR_MANUFACTURER_REGS: 859 rval = ccs_data_parse_regs( 860 bin, &ccsdata->sensor_manufacturer_regs, 861 &ccsdata->num_sensor_manufacturer_regs, payload, 862 next_block, dev); 863 if (rval < 0) 864 return rval; 865 break; 866 case CCS_DATA_BLOCK_ID_MODULE_READ_ONLY_REGS: 867 rval = ccs_data_parse_regs( 868 bin, &ccsdata->module_read_only_regs, 869 &ccsdata->num_module_read_only_regs, payload, 870 next_block, dev); 871 if (rval < 0) 872 return rval; 873 break; 874 case CCS_DATA_BLOCK_ID_MODULE_MANUFACTURER_REGS: 875 rval = ccs_data_parse_regs( 876 bin, &ccsdata->module_manufacturer_regs, 877 &ccsdata->num_module_manufacturer_regs, payload, 878 next_block, dev); 879 if (rval < 0) 880 return rval; 881 break; 882 case CCS_DATA_BLOCK_ID_SENSOR_PDAF_PIXEL_LOCATION: 883 rval = ccs_data_parse_pdaf(bin, &ccsdata->sensor_pdaf, 884 payload, next_block, dev); 885 if (rval < 0) 886 return rval; 887 break; 888 case CCS_DATA_BLOCK_ID_MODULE_PDAF_PIXEL_LOCATION: 889 rval = ccs_data_parse_pdaf(bin, &ccsdata->module_pdaf, 890 payload, next_block, dev); 891 if (rval < 0) 892 return rval; 893 break; 894 case CCS_DATA_BLOCK_ID_SENSOR_RULE_BASED_BLOCK: 895 rval = ccs_data_parse_rules( 896 bin, &ccsdata->sensor_rules, 897 &ccsdata->num_sensor_rules, payload, next_block, 898 dev); 899 if (rval < 0) 900 return rval; 901 break; 902 case CCS_DATA_BLOCK_ID_MODULE_RULE_BASED_BLOCK: 903 rval = ccs_data_parse_rules( 904 bin, &ccsdata->module_rules, 905 &ccsdata->num_module_rules, payload, next_block, 906 dev); 907 if (rval < 0) 908 return rval; 909 break; 910 case CCS_DATA_BLOCK_ID_LICENSE: 911 rval = ccs_data_parse_license(bin, &ccsdata->license, 912 &ccsdata->license_length, 913 payload, next_block); 914 if (rval < 0) 915 return rval; 916 break; 917 case CCS_DATA_BLOCK_ID_END: 918 rval = ccs_data_parse_end(&ccsdata->end, payload, 919 next_block, dev); 920 if (rval < 0) 921 return rval; 922 break; 923 default: 924 dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n", 925 block_id); 926 } 927 928 block = next_block; 929 is_first = false; 930 } 931 932 return 0; 933 } 934 935 /** 936 * ccs_data_parse - Parse a CCS static data file into a usable in-memory 937 * data structure 938 * @ccsdata: CCS static data in-memory data structure 939 * @data: CCS static data binary 940 * @len: Length of @data 941 * @dev: Device the data is related to (used for printing debug messages) 942 * @verbose: Whether to be verbose or not 943 */ ccs_data_parse(struct ccs_data_container * ccsdata,const void * data,size_t len,struct device * dev,bool verbose)944 int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data, 945 size_t len, struct device *dev, bool verbose) 946 { 947 struct bin_container bin = { 0 }; 948 int rval; 949 950 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose); 951 if (rval) 952 goto out_cleanup; 953 954 rval = bin_backing_alloc(&bin); 955 if (rval) 956 goto out_cleanup; 957 958 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false); 959 if (rval) 960 goto out_cleanup; 961 962 if (verbose && ccsdata->version) 963 print_ccs_data_version(dev, ccsdata->version); 964 965 if (bin.now != bin.end) { 966 rval = -EPROTO; 967 dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n", 968 bin.base, bin.now, bin.end); 969 goto out_cleanup; 970 } 971 972 ccsdata->backing = bin.base; 973 974 return 0; 975 976 out_cleanup: 977 kvfree(bin.base); 978 memset(ccsdata, 0, sizeof(*ccsdata)); 979 980 return rval; 981 } 982