ccs-data.c 23 KB

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