Back to home page

OSCL-LXR

 
 

    


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