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