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