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/types.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 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 39 static void bin_reserve(struct bin_container *bin, size_t len) 40 { 41 bin->size += ALIGN(len, 8); 42 } 43 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 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[0] << 8) + __len3->length[1]; 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 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 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 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_major[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 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 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 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, *regs; 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 regs->addr = addr; 290 regs->len = len; 291 regs->value = bin_alloc(bin, len); 292 if (!regs->value) 293 return -ENOMEM; 294 295 memcpy(regs->value, data, len); 296 regs++; 297 } 298 299 addr += len; 300 payload = data + len; 301 } 302 303 if (!bin->base) 304 bin_reserve(bin, sizeof(*regs) * num_regs); 305 306 if (__num_regs) 307 *__num_regs = num_regs; 308 309 if (bin->base && __regs) 310 *__regs = regs_base; 311 312 return 0; 313 } 314 315 static int ccs_data_parse_reg_rules(struct bin_container *bin, 316 struct ccs_reg **__regs, 317 size_t *__num_regs, 318 const void *payload, 319 const void *endp, struct device *dev) 320 { 321 int rval; 322 323 if (!bin->base) 324 return ccs_data_parse_regs(bin, NULL, NULL, payload, endp, dev); 325 326 rval = ccs_data_parse_regs(bin, NULL, __num_regs, payload, endp, dev); 327 if (rval) 328 return rval; 329 330 return ccs_data_parse_regs(bin, __regs, __num_regs, payload, endp, 331 dev); 332 } 333 334 static void assign_ffd_entry(struct ccs_frame_format_desc *desc, 335 const struct __ccs_data_block_ffd_entry *ent) 336 { 337 desc->pixelcode = ent->pixelcode; 338 desc->value = ((u16)ent->value[0] << 8) + ent->value[1]; 339 } 340 341 static int ccs_data_parse_ffd(struct bin_container *bin, 342 struct ccs_frame_format_descs **ffd, 343 const void *payload, 344 const void *endp, struct device *dev) 345 { 346 const struct __ccs_data_block_ffd *__ffd = payload; 347 const struct __ccs_data_block_ffd_entry *__entry; 348 unsigned int i; 349 350 if (!is_contained(__ffd, endp)) 351 return -ENODATA; 352 353 if ((void *)__ffd + sizeof(*__ffd) + 354 ((u32)__ffd->num_column_descs + 355 (u32)__ffd->num_row_descs) * 356 sizeof(struct __ccs_data_block_ffd_entry) != endp) 357 return -ENODATA; 358 359 if (!bin->base) { 360 bin_reserve(bin, sizeof(**ffd)); 361 bin_reserve(bin, __ffd->num_column_descs * 362 sizeof(struct ccs_frame_format_desc)); 363 bin_reserve(bin, __ffd->num_row_descs * 364 sizeof(struct ccs_frame_format_desc)); 365 366 return 0; 367 } 368 369 *ffd = bin_alloc(bin, sizeof(**ffd)); 370 if (!*ffd) 371 return -ENOMEM; 372 373 (*ffd)->num_column_descs = __ffd->num_column_descs; 374 (*ffd)->num_row_descs = __ffd->num_row_descs; 375 __entry = (void *)(__ffd + 1); 376 377 (*ffd)->column_descs = bin_alloc(bin, __ffd->num_column_descs * 378 sizeof(*(*ffd)->column_descs)); 379 if (!(*ffd)->column_descs) 380 return -ENOMEM; 381 382 for (i = 0; i < __ffd->num_column_descs; i++, __entry++) 383 assign_ffd_entry(&(*ffd)->column_descs[i], __entry); 384 385 (*ffd)->row_descs = bin_alloc(bin, __ffd->num_row_descs * 386 sizeof(*(*ffd)->row_descs)); 387 if (!(*ffd)->row_descs) 388 return -ENOMEM; 389 390 for (i = 0; i < __ffd->num_row_descs; i++, __entry++) 391 assign_ffd_entry(&(*ffd)->row_descs[i], __entry); 392 393 if (__entry != endp) 394 return -EPROTO; 395 396 return 0; 397 } 398 399 static int ccs_data_parse_pdaf_readout(struct bin_container *bin, 400 struct ccs_pdaf_readout **pdaf_readout, 401 const void *payload, 402 const void *endp, struct device *dev) 403 { 404 const struct __ccs_data_block_pdaf_readout *__pdaf = payload; 405 406 if (!is_contained(__pdaf, endp)) 407 return -ENODATA; 408 409 if (!bin->base) { 410 bin_reserve(bin, sizeof(**pdaf_readout)); 411 } else { 412 *pdaf_readout = bin_alloc(bin, sizeof(**pdaf_readout)); 413 if (!*pdaf_readout) 414 return -ENOMEM; 415 416 (*pdaf_readout)->pdaf_readout_info_order = 417 __pdaf->pdaf_readout_info_order; 418 } 419 420 return ccs_data_parse_ffd(bin, !bin->base ? NULL : &(*pdaf_readout)->ffd, 421 __pdaf + 1, endp, dev); 422 } 423 424 static int ccs_data_parse_rules(struct bin_container *bin, 425 struct ccs_rule **__rules, 426 size_t *__num_rules, const void *payload, 427 const void *endp, struct device *dev) 428 { 429 struct ccs_rule *rules_base, *rules = NULL, *next_rule; 430 size_t num_rules = 0; 431 const void *__next_rule = payload; 432 int rval; 433 434 if (bin->base) { 435 rules_base = next_rule = 436 bin_alloc(bin, sizeof(*rules) * *__num_rules); 437 if (!rules_base) 438 return -ENOMEM; 439 } 440 441 while (__next_rule < endp) { 442 size_t rule_hlen, rule_plen, rule_plen2; 443 const u8 *__rule_type; 444 const void *rule_payload; 445 446 /* Size of a single rule */ 447 rval = ccs_data_parse_length_specifier(__next_rule, &rule_hlen, 448 &rule_plen, endp); 449 450 if (rval < 0) 451 return rval; 452 453 __rule_type = __next_rule + rule_hlen; 454 455 if (!is_contained(__rule_type, endp)) 456 return -ENODATA; 457 458 rule_payload = __rule_type + 1; 459 rule_plen2 = rule_plen - sizeof(*__rule_type); 460 461 switch (*__rule_type) { 462 case CCS_DATA_BLOCK_RULE_ID_IF: { 463 const struct __ccs_data_block_rule_if *__if_rules = 464 rule_payload; 465 const size_t __num_if_rules = 466 rule_plen2 / sizeof(*__if_rules); 467 struct ccs_if_rule *if_rule; 468 469 if (!has_headroom(__if_rules, 470 sizeof(*__if_rules) * __num_if_rules, 471 rule_payload + rule_plen2)) 472 return -ENODATA; 473 474 /* Also check there is no extra data */ 475 if (__if_rules + __num_if_rules != 476 rule_payload + rule_plen2) 477 return -EINVAL; 478 479 if (!bin->base) { 480 bin_reserve(bin, 481 sizeof(*if_rule) * 482 __num_if_rules); 483 num_rules++; 484 } else { 485 unsigned int i; 486 487 rules = next_rule; 488 next_rule++; 489 490 if_rule = bin_alloc(bin, 491 sizeof(*if_rule) * 492 __num_if_rules); 493 if (!if_rule) 494 return -ENOMEM; 495 496 for (i = 0; i < __num_if_rules; i++) { 497 if_rule[i].addr = 498 ((u16)__if_rules[i].addr[0] 499 << 8) + 500 __if_rules[i].addr[1]; 501 if_rule[i].value = __if_rules[i].value; 502 if_rule[i].mask = __if_rules[i].mask; 503 } 504 505 rules->if_rules = if_rule; 506 rules->num_if_rules = __num_if_rules; 507 } 508 break; 509 } 510 case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS: 511 rval = ccs_data_parse_reg_rules(bin, &rules->read_only_regs, 512 &rules->num_read_only_regs, 513 rule_payload, 514 rule_payload + rule_plen2, 515 dev); 516 if (rval) 517 return rval; 518 break; 519 case CCS_DATA_BLOCK_RULE_ID_FFD: 520 rval = ccs_data_parse_ffd(bin, &rules->frame_format, 521 rule_payload, 522 rule_payload + rule_plen2, 523 dev); 524 if (rval) 525 return rval; 526 break; 527 case CCS_DATA_BLOCK_RULE_ID_MSR: 528 rval = ccs_data_parse_reg_rules(bin, 529 &rules->manufacturer_regs, 530 &rules->num_manufacturer_regs, 531 rule_payload, 532 rule_payload + rule_plen2, 533 dev); 534 if (rval) 535 return rval; 536 break; 537 case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT: 538 rval = ccs_data_parse_pdaf_readout(bin, 539 &rules->pdaf_readout, 540 rule_payload, 541 rule_payload + rule_plen2, 542 dev); 543 if (rval) 544 return rval; 545 break; 546 default: 547 dev_dbg(dev, 548 "Don't know how to handle rule type %u!\n", 549 *__rule_type); 550 return -EINVAL; 551 } 552 __next_rule = __next_rule + rule_hlen + rule_plen; 553 } 554 555 if (!bin->base) { 556 bin_reserve(bin, sizeof(*rules) * num_rules); 557 *__num_rules = num_rules; 558 } else { 559 *__rules = rules_base; 560 } 561 562 return 0; 563 } 564 565 static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_loc **pdaf, 566 const void *payload, const void *endp, 567 struct device *dev) 568 { 569 const struct __ccs_data_block_pdaf_pix_loc *__pdaf = payload; 570 const struct __ccs_data_block_pdaf_pix_loc_block_desc_group *__bdesc_group; 571 const struct __ccs_data_block_pdaf_pix_loc_pixel_desc *__pixel_desc; 572 unsigned int i; 573 u16 num_block_desc_groups; 574 u8 max_block_type_id = 0; 575 const u8 *__num_pixel_descs; 576 577 if (!is_contained(__pdaf, endp)) 578 return -ENODATA; 579 580 if (bin->base) { 581 *pdaf = bin_alloc(bin, sizeof(**pdaf)); 582 if (!*pdaf) 583 return -ENOMEM; 584 } else { 585 bin_reserve(bin, sizeof(**pdaf)); 586 } 587 588 num_block_desc_groups = 589 ((u16)__pdaf->num_block_desc_groups[0] << 8) + 590 __pdaf->num_block_desc_groups[1]; 591 592 if (bin->base) { 593 (*pdaf)->main_offset_x = 594 ((u16)__pdaf->main_offset_x[0] << 8) + 595 __pdaf->main_offset_x[1]; 596 (*pdaf)->main_offset_y = 597 ((u16)__pdaf->main_offset_y[0] << 8) + 598 __pdaf->main_offset_y[1]; 599 (*pdaf)->global_pdaf_type = __pdaf->global_pdaf_type; 600 (*pdaf)->block_width = __pdaf->block_width; 601 (*pdaf)->block_height = __pdaf->block_height; 602 (*pdaf)->num_block_desc_groups = num_block_desc_groups; 603 } 604 605 __bdesc_group = (const void *)(__pdaf + 1); 606 607 if (bin->base) { 608 (*pdaf)->block_desc_groups = 609 bin_alloc(bin, 610 sizeof(struct ccs_pdaf_pix_loc_block_desc_group) * 611 num_block_desc_groups); 612 if (!(*pdaf)->block_desc_groups) 613 return -ENOMEM; 614 } else { 615 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc_group) * 616 num_block_desc_groups); 617 } 618 619 for (i = 0; i < num_block_desc_groups; i++) { 620 const struct __ccs_data_block_pdaf_pix_loc_block_desc *__bdesc; 621 u16 num_block_descs; 622 unsigned int j; 623 624 if (!is_contained(__bdesc_group, endp)) 625 return -ENODATA; 626 627 num_block_descs = 628 ((u16)__bdesc_group->num_block_descs[0] << 8) + 629 __bdesc_group->num_block_descs[1]; 630 631 if (bin->base) { 632 (*pdaf)->block_desc_groups[i].repeat_y = 633 __bdesc_group->repeat_y; 634 (*pdaf)->block_desc_groups[i].num_block_descs = 635 num_block_descs; 636 } 637 638 __bdesc = (const void *)(__bdesc_group + 1); 639 640 if (bin->base) { 641 (*pdaf)->block_desc_groups[i].block_descs = 642 bin_alloc(bin, 643 sizeof(struct ccs_pdaf_pix_loc_block_desc) * 644 num_block_descs); 645 if (!(*pdaf)->block_desc_groups[i].block_descs) 646 return -ENOMEM; 647 } else { 648 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_block_desc) * 649 num_block_descs); 650 } 651 652 for (j = 0; j < num_block_descs; j++, __bdesc++) { 653 struct ccs_pdaf_pix_loc_block_desc *bdesc; 654 655 if (!is_contained(__bdesc, endp)) 656 return -ENODATA; 657 658 if (max_block_type_id <= __bdesc->block_type_id) 659 max_block_type_id = __bdesc->block_type_id + 1; 660 661 if (!bin->base) 662 continue; 663 664 bdesc = &(*pdaf)->block_desc_groups[i].block_descs[j]; 665 666 bdesc->repeat_x = ((u16)__bdesc->repeat_x[0] << 8) 667 + __bdesc->repeat_x[1]; 668 669 if (__bdesc->block_type_id >= num_block_descs) 670 return -EINVAL; 671 672 bdesc->block_type_id = __bdesc->block_type_id; 673 } 674 675 __bdesc_group = (const void *)__bdesc; 676 } 677 678 __num_pixel_descs = (const void *)__bdesc_group; 679 680 if (bin->base) { 681 (*pdaf)->pixel_desc_groups = 682 bin_alloc(bin, 683 sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) * 684 max_block_type_id); 685 if (!(*pdaf)->pixel_desc_groups) 686 return -ENOMEM; 687 (*pdaf)->num_pixel_desc_grups = max_block_type_id; 688 } else { 689 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc_group) * 690 max_block_type_id); 691 } 692 693 for (i = 0; i < max_block_type_id; i++) { 694 struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup; 695 unsigned int j; 696 697 if (!is_contained(__num_pixel_descs, endp)) 698 return -ENODATA; 699 700 if (bin->base) { 701 pdgroup = &(*pdaf)->pixel_desc_groups[i]; 702 pdgroup->descs = 703 bin_alloc(bin, 704 sizeof(struct ccs_pdaf_pix_loc_pixel_desc) * 705 *__num_pixel_descs); 706 if (!pdgroup->descs) 707 return -ENOMEM; 708 pdgroup->num_descs = *__num_pixel_descs; 709 } else { 710 bin_reserve(bin, sizeof(struct ccs_pdaf_pix_loc_pixel_desc) * 711 *__num_pixel_descs); 712 } 713 714 __pixel_desc = (const void *)(__num_pixel_descs + 1); 715 716 for (j = 0; j < *__num_pixel_descs; j++, __pixel_desc++) { 717 struct ccs_pdaf_pix_loc_pixel_desc *pdesc; 718 719 if (!is_contained(__pixel_desc, endp)) 720 return -ENODATA; 721 722 if (!bin->base) 723 continue; 724 725 pdesc = &pdgroup->descs[j]; 726 pdesc->pixel_type = __pixel_desc->pixel_type; 727 pdesc->small_offset_x = __pixel_desc->small_offset_x; 728 pdesc->small_offset_y = __pixel_desc->small_offset_y; 729 } 730 731 __num_pixel_descs = (const void *)(__pixel_desc + 1); 732 } 733 734 return 0; 735 } 736 737 static int ccs_data_parse_license(struct bin_container *bin, 738 char **__license, 739 size_t *__license_length, 740 const void *payload, const void *endp) 741 { 742 size_t size = endp - payload; 743 char *license; 744 745 if (!bin->base) { 746 bin_reserve(bin, size); 747 return 0; 748 } 749 750 license = bin_alloc(bin, size); 751 if (!license) 752 return -ENOMEM; 753 754 memcpy(license, payload, size); 755 756 *__license = license; 757 *__license_length = size; 758 759 return 0; 760 } 761 762 static int ccs_data_parse_end(bool *end, const void *payload, const void *endp, 763 struct device *dev) 764 { 765 const struct __ccs_data_block_end *__end = payload; 766 767 if (__end + 1 != endp) { 768 dev_dbg(dev, "Invalid end block length %u\n", 769 (unsigned int)(endp - payload)); 770 return -ENODATA; 771 } 772 773 *end = true; 774 775 return 0; 776 } 777 778 static int __ccs_data_parse(struct bin_container *bin, 779 struct ccs_data_container *ccsdata, 780 const void *data, size_t len, struct device *dev, 781 bool verbose) 782 { 783 const struct __ccs_data_block *block = data; 784 const struct __ccs_data_block *endp = data + len; 785 unsigned int version; 786 bool is_first = true; 787 int rval; 788 789 version = ccs_data_parse_format_version(block); 790 if (version != CCS_STATIC_DATA_VERSION) { 791 dev_dbg(dev, "Don't know how to handle version %u\n", version); 792 return -EINVAL; 793 } 794 795 if (verbose) 796 dev_dbg(dev, "Parsing CCS static data version %u\n", version); 797 798 if (!bin->base) 799 *ccsdata = (struct ccs_data_container){ 0 }; 800 801 while (block < endp) { 802 const struct __ccs_data_block *next_block; 803 unsigned int block_id; 804 const void *payload; 805 806 rval = ccs_data_block_parse_header(block, is_first, &block_id, 807 &payload, &next_block, endp, 808 dev, 809 bin->base ? false : verbose); 810 811 if (rval < 0) 812 return rval; 813 814 switch (block_id) { 815 case CCS_DATA_BLOCK_ID_DUMMY: 816 break; 817 case CCS_DATA_BLOCK_ID_DATA_VERSION: 818 rval = ccs_data_parse_version(bin, ccsdata, payload, 819 next_block); 820 if (rval < 0) 821 return rval; 822 break; 823 case CCS_DATA_BLOCK_ID_SENSOR_READ_ONLY_REGS: 824 rval = ccs_data_parse_regs( 825 bin, &ccsdata->sensor_read_only_regs, 826 &ccsdata->num_sensor_read_only_regs, payload, 827 next_block, dev); 828 if (rval < 0) 829 return rval; 830 break; 831 case CCS_DATA_BLOCK_ID_SENSOR_MANUFACTURER_REGS: 832 rval = ccs_data_parse_regs( 833 bin, &ccsdata->sensor_manufacturer_regs, 834 &ccsdata->num_sensor_manufacturer_regs, payload, 835 next_block, dev); 836 if (rval < 0) 837 return rval; 838 break; 839 case CCS_DATA_BLOCK_ID_MODULE_READ_ONLY_REGS: 840 rval = ccs_data_parse_regs( 841 bin, &ccsdata->module_read_only_regs, 842 &ccsdata->num_module_read_only_regs, payload, 843 next_block, dev); 844 if (rval < 0) 845 return rval; 846 break; 847 case CCS_DATA_BLOCK_ID_MODULE_MANUFACTURER_REGS: 848 rval = ccs_data_parse_regs( 849 bin, &ccsdata->module_manufacturer_regs, 850 &ccsdata->num_module_manufacturer_regs, payload, 851 next_block, dev); 852 if (rval < 0) 853 return rval; 854 break; 855 case CCS_DATA_BLOCK_ID_SENSOR_PDAF_PIXEL_LOCATION: 856 rval = ccs_data_parse_pdaf(bin, &ccsdata->sensor_pdaf, 857 payload, next_block, dev); 858 if (rval < 0) 859 return rval; 860 break; 861 case CCS_DATA_BLOCK_ID_MODULE_PDAF_PIXEL_LOCATION: 862 rval = ccs_data_parse_pdaf(bin, &ccsdata->module_pdaf, 863 payload, next_block, dev); 864 if (rval < 0) 865 return rval; 866 break; 867 case CCS_DATA_BLOCK_ID_SENSOR_RULE_BASED_BLOCK: 868 rval = ccs_data_parse_rules( 869 bin, &ccsdata->sensor_rules, 870 &ccsdata->num_sensor_rules, payload, next_block, 871 dev); 872 if (rval < 0) 873 return rval; 874 break; 875 case CCS_DATA_BLOCK_ID_MODULE_RULE_BASED_BLOCK: 876 rval = ccs_data_parse_rules( 877 bin, &ccsdata->module_rules, 878 &ccsdata->num_module_rules, payload, next_block, 879 dev); 880 if (rval < 0) 881 return rval; 882 break; 883 case CCS_DATA_BLOCK_ID_LICENSE: 884 rval = ccs_data_parse_license(bin, &ccsdata->license, 885 &ccsdata->license_length, 886 payload, next_block); 887 if (rval < 0) 888 return rval; 889 break; 890 case CCS_DATA_BLOCK_ID_END: 891 rval = ccs_data_parse_end(&ccsdata->end, payload, 892 next_block, dev); 893 if (rval < 0) 894 return rval; 895 break; 896 default: 897 dev_dbg(dev, "WARNING: not handling block ID 0x%2.2x\n", 898 block_id); 899 } 900 901 block = next_block; 902 is_first = false; 903 } 904 905 return 0; 906 } 907 908 /** 909 * ccs_data_parse - Parse a CCS static data file into a usable in-memory 910 * data structure 911 * @ccsdata: CCS static data in-memory data structure 912 * @data: CCS static data binary 913 * @len: Length of @data 914 * @dev: Device the data is related to (used for printing debug messages) 915 * @verbose: Whether to be verbose or not 916 */ 917 int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data, 918 size_t len, struct device *dev, bool verbose) 919 { 920 struct bin_container bin = { 0 }; 921 int rval; 922 923 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose); 924 if (rval) 925 return rval; 926 927 rval = bin_backing_alloc(&bin); 928 if (rval) 929 return rval; 930 931 rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false); 932 if (rval) 933 goto out_free; 934 935 if (verbose && ccsdata->version) 936 print_ccs_data_version(dev, ccsdata->version); 937 938 if (bin.now != bin.end) { 939 rval = -EPROTO; 940 dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n", 941 bin.base, bin.now, bin.end); 942 goto out_free; 943 } 944 945 ccsdata->backing = bin.base; 946 947 return 0; 948 949 out_free: 950 kvfree(bin.base); 951 952 return rval; 953 } 954