qmi_encdec.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  4. * Copyright (C) 2017 Linaro Ltd.
  5. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  6. */
  7. #include <linux/slab.h>
  8. #include <linux/uaccess.h>
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/errno.h>
  12. #include <linux/string.h>
  13. #include <linux/soc/qcom/qmi.h>
  14. #define QMI_ENCDEC_ENCODE_TLV(type, length, p_dst) do { \
  15. *p_dst++ = type; \
  16. *p_dst++ = ((u8)((length) & 0xFF)); \
  17. *p_dst++ = ((u8)(((length) >> 8) & 0xFF)); \
  18. } while (0)
  19. #define QMI_ENCDEC_DECODE_TLV(p_type, p_length, p_src) do { \
  20. *p_type = (u8)*p_src++; \
  21. *p_length = (u8)*p_src++; \
  22. *p_length |= ((u8)*p_src) << 8; \
  23. } while (0)
  24. #define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \
  25. do { \
  26. memcpy(p_dst, p_src, size); \
  27. p_dst = (u8 *)p_dst + size; \
  28. p_src = (u8 *)p_src + size; \
  29. } while (0)
  30. #define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \
  31. do { \
  32. memcpy(p_dst, p_src, size); \
  33. p_dst = (u8 *)p_dst + size; \
  34. p_src = (u8 *)p_src + size; \
  35. } while (0)
  36. #define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \
  37. encoded_bytes, tlv_len, encode_tlv, rc) \
  38. do { \
  39. buf_dst = (u8 *)buf_dst + rc; \
  40. encoded_bytes += rc; \
  41. tlv_len += rc; \
  42. temp_si = temp_si + 1; \
  43. encode_tlv = 1; \
  44. } while (0)
  45. #define UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc) \
  46. do { \
  47. buf_src = (u8 *)buf_src + rc; \
  48. decoded_bytes += rc; \
  49. } while (0)
  50. #define TLV_LEN_SIZE sizeof(u16)
  51. #define TLV_TYPE_SIZE sizeof(u8)
  52. #define OPTIONAL_TLV_TYPE_START 0x10
  53. static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
  54. const void *in_c_struct, u32 out_buf_len,
  55. int enc_level);
  56. static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
  57. const void *in_buf, u32 in_buf_len, int dec_level);
  58. /**
  59. * skip_to_next_elem() - Skip to next element in the structure to be encoded
  60. * @ei_array: Struct info describing the element to be skipped.
  61. * @level: Depth level of encoding/decoding to identify nested structures.
  62. *
  63. * This function is used while encoding optional elements. If the flag
  64. * corresponding to an optional element is not set, then encoding the
  65. * optional element can be skipped. This function can be used to perform
  66. * that operation.
  67. *
  68. * Return: struct info of the next element that can be encoded.
  69. */
  70. static const struct qmi_elem_info *
  71. skip_to_next_elem(const struct qmi_elem_info *ei_array, int level)
  72. {
  73. const struct qmi_elem_info *temp_ei = ei_array;
  74. u8 tlv_type;
  75. if (level > 1) {
  76. temp_ei = temp_ei + 1;
  77. } else {
  78. do {
  79. tlv_type = temp_ei->tlv_type;
  80. temp_ei = temp_ei + 1;
  81. } while (tlv_type == temp_ei->tlv_type);
  82. }
  83. return temp_ei;
  84. }
  85. /**
  86. * qmi_calc_min_msg_len() - Calculate the minimum length of a QMI message
  87. * @ei_array: Struct info array describing the structure.
  88. * @level: Level to identify the depth of the nested structures.
  89. *
  90. * Return: Expected minimum length of the QMI message or 0 on error.
  91. */
  92. static int qmi_calc_min_msg_len(const struct qmi_elem_info *ei_array,
  93. int level)
  94. {
  95. int min_msg_len = 0;
  96. const struct qmi_elem_info *temp_ei = ei_array;
  97. if (!ei_array)
  98. return min_msg_len;
  99. while (temp_ei->data_type != QMI_EOTI) {
  100. /* Optional elements do not count in minimum length */
  101. if (temp_ei->data_type == QMI_OPT_FLAG) {
  102. temp_ei = skip_to_next_elem(temp_ei, level);
  103. continue;
  104. }
  105. if (temp_ei->data_type == QMI_DATA_LEN) {
  106. min_msg_len += (temp_ei->elem_size == sizeof(u8) ?
  107. sizeof(u8) : sizeof(u16));
  108. temp_ei++;
  109. continue;
  110. } else if (temp_ei->data_type == QMI_STRUCT) {
  111. min_msg_len += qmi_calc_min_msg_len(temp_ei->ei_array,
  112. (level + 1));
  113. temp_ei++;
  114. } else if (temp_ei->data_type == QMI_STRING) {
  115. if (level > 1)
  116. min_msg_len += temp_ei->elem_len <= U8_MAX ?
  117. sizeof(u8) : sizeof(u16);
  118. min_msg_len += temp_ei->elem_len * temp_ei->elem_size;
  119. temp_ei++;
  120. } else {
  121. min_msg_len += (temp_ei->elem_len * temp_ei->elem_size);
  122. temp_ei++;
  123. }
  124. /*
  125. * Type & Length info. not prepended for elements in the
  126. * nested structure.
  127. */
  128. if (level == 1)
  129. min_msg_len += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
  130. }
  131. return min_msg_len;
  132. }
  133. /**
  134. * qmi_encode_basic_elem() - Encodes elements of basic/primary data type
  135. * @buf_dst: Buffer to store the encoded information.
  136. * @buf_src: Buffer containing the elements to be encoded.
  137. * @elem_len: Number of elements, in the buf_src, to be encoded.
  138. * @elem_size: Size of a single instance of the element to be encoded.
  139. *
  140. * This function encodes the "elem_len" number of data elements, each of
  141. * size "elem_size" bytes from the source buffer "buf_src" and stores the
  142. * encoded information in the destination buffer "buf_dst". The elements are
  143. * of primary data type which include u8 - u64 or similar. This
  144. * function returns the number of bytes of encoded information.
  145. *
  146. * Return: The number of bytes of encoded information.
  147. */
  148. static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src,
  149. u32 elem_len, u32 elem_size)
  150. {
  151. u32 i, rc = 0;
  152. for (i = 0; i < elem_len; i++) {
  153. QMI_ENCDEC_ENCODE_N_BYTES(buf_dst, buf_src, elem_size);
  154. rc += elem_size;
  155. }
  156. return rc;
  157. }
  158. /**
  159. * qmi_encode_struct_elem() - Encodes elements of struct data type
  160. * @ei_array: Struct info array descibing the struct element.
  161. * @buf_dst: Buffer to store the encoded information.
  162. * @buf_src: Buffer containing the elements to be encoded.
  163. * @elem_len: Number of elements, in the buf_src, to be encoded.
  164. * @out_buf_len: Available space in the encode buffer.
  165. * @enc_level: Depth of the nested structure from the main structure.
  166. *
  167. * This function encodes the "elem_len" number of struct elements, each of
  168. * size "ei_array->elem_size" bytes from the source buffer "buf_src" and
  169. * stores the encoded information in the destination buffer "buf_dst". The
  170. * elements are of struct data type which includes any C structure. This
  171. * function returns the number of bytes of encoded information.
  172. *
  173. * Return: The number of bytes of encoded information on success or negative
  174. * errno on error.
  175. */
  176. static int qmi_encode_struct_elem(const struct qmi_elem_info *ei_array,
  177. void *buf_dst, const void *buf_src,
  178. u32 elem_len, u32 out_buf_len,
  179. int enc_level)
  180. {
  181. int i, rc, encoded_bytes = 0;
  182. const struct qmi_elem_info *temp_ei = ei_array;
  183. for (i = 0; i < elem_len; i++) {
  184. rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src,
  185. out_buf_len - encoded_bytes, enc_level);
  186. if (rc < 0) {
  187. pr_err("%s: STRUCT Encode failure\n", __func__);
  188. return rc;
  189. }
  190. buf_dst = buf_dst + rc;
  191. buf_src = buf_src + temp_ei->elem_size;
  192. encoded_bytes += rc;
  193. }
  194. return encoded_bytes;
  195. }
  196. /**
  197. * qmi_encode_string_elem() - Encodes elements of string data type
  198. * @ei_array: Struct info array descibing the string element.
  199. * @buf_dst: Buffer to store the encoded information.
  200. * @buf_src: Buffer containing the elements to be encoded.
  201. * @out_buf_len: Available space in the encode buffer.
  202. * @enc_level: Depth of the string element from the main structure.
  203. *
  204. * This function encodes a string element of maximum length "ei_array->elem_len"
  205. * bytes from the source buffer "buf_src" and stores the encoded information in
  206. * the destination buffer "buf_dst". This function returns the number of bytes
  207. * of encoded information.
  208. *
  209. * Return: The number of bytes of encoded information on success or negative
  210. * errno on error.
  211. */
  212. static int qmi_encode_string_elem(const struct qmi_elem_info *ei_array,
  213. void *buf_dst, const void *buf_src,
  214. u32 out_buf_len, int enc_level)
  215. {
  216. int rc;
  217. int encoded_bytes = 0;
  218. const struct qmi_elem_info *temp_ei = ei_array;
  219. u32 string_len = 0;
  220. u32 string_len_sz = 0;
  221. string_len = strlen(buf_src);
  222. string_len_sz = temp_ei->elem_len <= U8_MAX ?
  223. sizeof(u8) : sizeof(u16);
  224. if (string_len > temp_ei->elem_len) {
  225. pr_err("%s: String to be encoded is longer - %d > %d\n",
  226. __func__, string_len, temp_ei->elem_len);
  227. return -EINVAL;
  228. }
  229. if (enc_level == 1) {
  230. if (string_len + TLV_LEN_SIZE + TLV_TYPE_SIZE >
  231. out_buf_len) {
  232. pr_err("%s: Output len %d > Out Buf len %d\n",
  233. __func__, string_len, out_buf_len);
  234. return -ETOOSMALL;
  235. }
  236. } else {
  237. if (string_len + string_len_sz > out_buf_len) {
  238. pr_err("%s: Output len %d > Out Buf len %d\n",
  239. __func__, string_len, out_buf_len);
  240. return -ETOOSMALL;
  241. }
  242. rc = qmi_encode_basic_elem(buf_dst, &string_len,
  243. 1, string_len_sz);
  244. encoded_bytes += rc;
  245. }
  246. rc = qmi_encode_basic_elem(buf_dst + encoded_bytes, buf_src,
  247. string_len, temp_ei->elem_size);
  248. encoded_bytes += rc;
  249. return encoded_bytes;
  250. }
  251. /**
  252. * qmi_encode() - Core Encode Function
  253. * @ei_array: Struct info array describing the structure to be encoded.
  254. * @out_buf: Buffer to hold the encoded QMI message.
  255. * @in_c_struct: Pointer to the C structure to be encoded.
  256. * @out_buf_len: Available space in the encode buffer.
  257. * @enc_level: Encode level to indicate the depth of the nested structure,
  258. * within the main structure, being encoded.
  259. *
  260. * Return: The number of bytes of encoded information on success or negative
  261. * errno on error.
  262. */
  263. static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
  264. const void *in_c_struct, u32 out_buf_len,
  265. int enc_level)
  266. {
  267. const struct qmi_elem_info *temp_ei = ei_array;
  268. u8 opt_flag_value = 0;
  269. u32 data_len_value = 0, data_len_sz;
  270. u8 *buf_dst = (u8 *)out_buf;
  271. u8 *tlv_pointer;
  272. u32 tlv_len;
  273. u8 tlv_type;
  274. u32 encoded_bytes = 0;
  275. const void *buf_src;
  276. int encode_tlv = 0;
  277. int rc;
  278. if (!ei_array)
  279. return 0;
  280. tlv_pointer = buf_dst;
  281. tlv_len = 0;
  282. if (enc_level == 1)
  283. buf_dst = buf_dst + (TLV_LEN_SIZE + TLV_TYPE_SIZE);
  284. while (temp_ei->data_type != QMI_EOTI) {
  285. buf_src = in_c_struct + temp_ei->offset;
  286. tlv_type = temp_ei->tlv_type;
  287. if (temp_ei->array_type == NO_ARRAY) {
  288. data_len_value = 1;
  289. } else if (temp_ei->array_type == STATIC_ARRAY) {
  290. data_len_value = temp_ei->elem_len;
  291. } else if (data_len_value <= 0 ||
  292. temp_ei->elem_len < data_len_value) {
  293. pr_err("%s: Invalid data length\n", __func__);
  294. return -EINVAL;
  295. }
  296. switch (temp_ei->data_type) {
  297. case QMI_OPT_FLAG:
  298. rc = qmi_encode_basic_elem(&opt_flag_value, buf_src,
  299. 1, sizeof(u8));
  300. if (opt_flag_value)
  301. temp_ei = temp_ei + 1;
  302. else
  303. temp_ei = skip_to_next_elem(temp_ei, enc_level);
  304. break;
  305. case QMI_DATA_LEN:
  306. memcpy(&data_len_value, buf_src, temp_ei->elem_size);
  307. data_len_sz = temp_ei->elem_size == sizeof(u8) ?
  308. sizeof(u8) : sizeof(u16);
  309. /* Check to avoid out of range buffer access */
  310. if ((data_len_sz + encoded_bytes + TLV_LEN_SIZE +
  311. TLV_TYPE_SIZE) > out_buf_len) {
  312. pr_err("%s: Too Small Buffer @DATA_LEN\n",
  313. __func__);
  314. return -ETOOSMALL;
  315. }
  316. rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
  317. 1, data_len_sz);
  318. UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
  319. encoded_bytes, tlv_len,
  320. encode_tlv, rc);
  321. if (!data_len_value)
  322. temp_ei = skip_to_next_elem(temp_ei, enc_level);
  323. else
  324. encode_tlv = 0;
  325. break;
  326. case QMI_UNSIGNED_1_BYTE:
  327. case QMI_UNSIGNED_2_BYTE:
  328. case QMI_UNSIGNED_4_BYTE:
  329. case QMI_UNSIGNED_8_BYTE:
  330. case QMI_SIGNED_2_BYTE_ENUM:
  331. case QMI_SIGNED_4_BYTE_ENUM:
  332. /* Check to avoid out of range buffer access */
  333. if (((data_len_value * temp_ei->elem_size) +
  334. encoded_bytes + TLV_LEN_SIZE + TLV_TYPE_SIZE) >
  335. out_buf_len) {
  336. pr_err("%s: Too Small Buffer @data_type:%d\n",
  337. __func__, temp_ei->data_type);
  338. return -ETOOSMALL;
  339. }
  340. rc = qmi_encode_basic_elem(buf_dst, buf_src,
  341. data_len_value,
  342. temp_ei->elem_size);
  343. UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
  344. encoded_bytes, tlv_len,
  345. encode_tlv, rc);
  346. break;
  347. case QMI_STRUCT:
  348. rc = qmi_encode_struct_elem(temp_ei, buf_dst, buf_src,
  349. data_len_value,
  350. out_buf_len - encoded_bytes,
  351. enc_level + 1);
  352. if (rc < 0)
  353. return rc;
  354. UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
  355. encoded_bytes, tlv_len,
  356. encode_tlv, rc);
  357. break;
  358. case QMI_STRING:
  359. rc = qmi_encode_string_elem(temp_ei, buf_dst, buf_src,
  360. out_buf_len - encoded_bytes,
  361. enc_level);
  362. if (rc < 0)
  363. return rc;
  364. UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
  365. encoded_bytes, tlv_len,
  366. encode_tlv, rc);
  367. break;
  368. default:
  369. pr_err("%s: Unrecognized data type\n", __func__);
  370. return -EINVAL;
  371. }
  372. if (encode_tlv && enc_level == 1) {
  373. QMI_ENCDEC_ENCODE_TLV(tlv_type, tlv_len, tlv_pointer);
  374. encoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
  375. tlv_pointer = buf_dst;
  376. tlv_len = 0;
  377. buf_dst = buf_dst + TLV_LEN_SIZE + TLV_TYPE_SIZE;
  378. encode_tlv = 0;
  379. }
  380. }
  381. return encoded_bytes;
  382. }
  383. /**
  384. * qmi_decode_basic_elem() - Decodes elements of basic/primary data type
  385. * @buf_dst: Buffer to store the decoded element.
  386. * @buf_src: Buffer containing the elements in QMI wire format.
  387. * @elem_len: Number of elements to be decoded.
  388. * @elem_size: Size of a single instance of the element to be decoded.
  389. * @src_len: Source buffer length.
  390. *
  391. * This function decodes the "elem_len" number of elements in QMI wire format,
  392. * each of size "elem_size" bytes from the source buffer "buf_src" and stores
  393. * the decoded elements in the destination buffer "buf_dst". The elements are
  394. * of primary data type which include u8 - u64 or similar. This
  395. * function returns the number of bytes of decoded information.
  396. *
  397. * Return: The total size of the decoded data elements, in bytes.
  398. */
  399. static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src,
  400. u32 elem_len, u32 elem_size, u32 src_len)
  401. {
  402. u32 i, rc = 0;
  403. if (elem_len * elem_size > src_len)
  404. return -EINVAL;
  405. for (i = 0; i < elem_len; i++) {
  406. QMI_ENCDEC_DECODE_N_BYTES(buf_dst, buf_src, elem_size);
  407. rc += elem_size;
  408. }
  409. return rc;
  410. }
  411. /**
  412. * qmi_decode_struct_elem() - Decodes elements of struct data type
  413. * @ei_array: Struct info array describing the struct element.
  414. * @buf_dst: Buffer to store the decoded element.
  415. * @buf_src: Buffer containing the elements in QMI wire format.
  416. * @elem_len: Number of elements to be decoded.
  417. * @tlv_len: Total size of the encoded information corresponding to
  418. * this struct element.
  419. * @dec_level: Depth of the nested structure from the main structure.
  420. * @src_len: Source buffer length.
  421. *
  422. * This function decodes the "elem_len" number of elements in QMI wire format,
  423. * each of size "(tlv_len/elem_len)" bytes from the source buffer "buf_src"
  424. * and stores the decoded elements in the destination buffer "buf_dst". The
  425. * elements are of struct data type which includes any C structure. This
  426. * function returns the number of bytes of decoded information.
  427. *
  428. * Return: The total size of the decoded data elements on success, negative
  429. * errno on error.
  430. */
  431. static int qmi_decode_struct_elem(const struct qmi_elem_info *ei_array,
  432. void *buf_dst, const void *buf_src,
  433. u32 elem_len, u32 tlv_len,
  434. int dec_level, u32 src_len)
  435. {
  436. int i, rc, decoded_bytes = 0;
  437. const struct qmi_elem_info *temp_ei = ei_array;
  438. if (tlv_len > src_len)
  439. return -EINVAL;
  440. for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) {
  441. rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src,
  442. tlv_len - decoded_bytes, dec_level);
  443. if (rc < 0)
  444. return rc;
  445. buf_src = buf_src + rc;
  446. buf_dst = buf_dst + temp_ei->elem_size;
  447. decoded_bytes += rc;
  448. }
  449. if ((dec_level <= 2 && decoded_bytes != tlv_len) ||
  450. (dec_level > 2 && (i < elem_len || decoded_bytes > tlv_len))) {
  451. pr_err("%s: Fault in decoding: dl(%d), db(%d), tl(%d), i(%d), el(%d)\n",
  452. __func__, dec_level, decoded_bytes, tlv_len,
  453. i, elem_len);
  454. return -EFAULT;
  455. }
  456. return decoded_bytes;
  457. }
  458. /**
  459. * qmi_decode_string_elem() - Decodes elements of string data type
  460. * @ei_array: Struct info array describing the string element.
  461. * @buf_dst: Buffer to store the decoded element.
  462. * @buf_src: Buffer containing the elements in QMI wire format.
  463. * @tlv_len: Total size of the encoded information corresponding to
  464. * this string element.
  465. * @dec_level: Depth of the string element from the main structure.
  466. * @src_len: Source buffer length.
  467. *
  468. * This function decodes the string element of maximum length
  469. * "ei_array->elem_len" from the source buffer "buf_src" and puts it into
  470. * the destination buffer "buf_dst". This function returns number of bytes
  471. * decoded from the input buffer.
  472. *
  473. * Return: The total size of the decoded data elements on success, negative
  474. * errno on error.
  475. */
  476. static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array,
  477. void *buf_dst, const void *buf_src,
  478. u32 tlv_len, int dec_level, u32 src_len)
  479. {
  480. int rc;
  481. int decoded_bytes = 0;
  482. u32 string_len = 0;
  483. u32 string_len_sz = 0;
  484. const struct qmi_elem_info *temp_ei = ei_array;
  485. if (dec_level == 1) {
  486. string_len = tlv_len;
  487. } else {
  488. string_len_sz = temp_ei->elem_len <= U8_MAX ?
  489. sizeof(u8) : sizeof(u16);
  490. rc = qmi_decode_basic_elem(&string_len, buf_src,
  491. 1, string_len_sz, src_len);
  492. if (rc < 0)
  493. return rc;
  494. decoded_bytes += rc;
  495. }
  496. if (string_len >= temp_ei->elem_len) {
  497. pr_err("%s: String len %d >= Max Len %d\n",
  498. __func__, string_len, temp_ei->elem_len);
  499. return -ETOOSMALL;
  500. } else if (string_len > tlv_len) {
  501. pr_err("%s: String len %d > Input Buffer Len %d\n",
  502. __func__, string_len, tlv_len);
  503. return -EFAULT;
  504. }
  505. rc = qmi_decode_basic_elem(buf_dst, buf_src + decoded_bytes,
  506. string_len, temp_ei->elem_size,
  507. src_len - decoded_bytes);
  508. if (rc < 0)
  509. return rc;
  510. *((char *)buf_dst + string_len) = '\0';
  511. decoded_bytes += rc;
  512. return decoded_bytes;
  513. }
  514. /**
  515. * find_ei() - Find element info corresponding to TLV Type
  516. * @ei_array: Struct info array of the message being decoded.
  517. * @type: TLV Type of the element being searched.
  518. *
  519. * Every element that got encoded in the QMI message will have a type
  520. * information associated with it. While decoding the QMI message,
  521. * this function is used to find the struct info regarding the element
  522. * that corresponds to the type being decoded.
  523. *
  524. * Return: Pointer to struct info, if found
  525. */
  526. static const struct qmi_elem_info *find_ei(const struct qmi_elem_info *ei_array,
  527. u32 type)
  528. {
  529. const struct qmi_elem_info *temp_ei = ei_array;
  530. while (temp_ei->data_type != QMI_EOTI) {
  531. if (temp_ei->tlv_type == (u8)type)
  532. return temp_ei;
  533. temp_ei = temp_ei + 1;
  534. }
  535. return NULL;
  536. }
  537. /**
  538. * qmi_decode() - Core Decode Function
  539. * @ei_array: Struct info array describing the structure to be decoded.
  540. * @out_c_struct: Buffer to hold the decoded C struct
  541. * @in_buf: Buffer containing the QMI message to be decoded
  542. * @in_buf_len: Length of the QMI message to be decoded
  543. * @dec_level: Decode level to indicate the depth of the nested structure,
  544. * within the main structure, being decoded
  545. *
  546. * Return: The number of bytes of decoded information on success, negative
  547. * errno on error.
  548. */
  549. static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
  550. const void *in_buf, u32 in_buf_len,
  551. int dec_level)
  552. {
  553. const struct qmi_elem_info *temp_ei = ei_array;
  554. u8 opt_flag_value = 1;
  555. u32 data_len_value = 0, data_len_sz = 0;
  556. u8 *buf_dst = out_c_struct;
  557. const u8 *tlv_pointer;
  558. u32 tlv_len = 0;
  559. u32 tlv_type;
  560. u32 decoded_bytes = 0;
  561. const void *buf_src = in_buf;
  562. int rc;
  563. while (decoded_bytes < in_buf_len) {
  564. if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI)
  565. return decoded_bytes;
  566. if (dec_level == 1) {
  567. tlv_pointer = buf_src;
  568. if (decoded_bytes + TLV_TYPE_SIZE + TLV_LEN_SIZE > in_buf_len)
  569. return -EINVAL;
  570. QMI_ENCDEC_DECODE_TLV(&tlv_type,
  571. &tlv_len, tlv_pointer);
  572. buf_src += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
  573. decoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
  574. temp_ei = find_ei(ei_array, tlv_type);
  575. if (!temp_ei && tlv_type < OPTIONAL_TLV_TYPE_START) {
  576. pr_err("%s: Inval element info\n", __func__);
  577. return -EINVAL;
  578. } else if (!temp_ei) {
  579. UPDATE_DECODE_VARIABLES(buf_src,
  580. decoded_bytes, tlv_len);
  581. continue;
  582. }
  583. } else {
  584. /*
  585. * No length information for elements in nested
  586. * structures. So use remaining decodable buffer space.
  587. */
  588. tlv_len = in_buf_len - decoded_bytes;
  589. }
  590. buf_dst = out_c_struct + temp_ei->offset;
  591. if (temp_ei->data_type == QMI_OPT_FLAG) {
  592. memcpy(buf_dst, &opt_flag_value, sizeof(u8));
  593. temp_ei = temp_ei + 1;
  594. buf_dst = out_c_struct + temp_ei->offset;
  595. }
  596. if (temp_ei->data_type == QMI_DATA_LEN) {
  597. data_len_sz = temp_ei->elem_size == sizeof(u8) ?
  598. sizeof(u8) : sizeof(u16);
  599. rc = qmi_decode_basic_elem(&data_len_value, buf_src,
  600. 1, data_len_sz,
  601. in_buf_len - decoded_bytes);
  602. if (rc < 0)
  603. return rc;
  604. memcpy(buf_dst, &data_len_value, sizeof(u32));
  605. temp_ei = temp_ei + 1;
  606. buf_dst = out_c_struct + temp_ei->offset;
  607. tlv_len -= data_len_sz;
  608. UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
  609. }
  610. if (temp_ei->array_type == NO_ARRAY) {
  611. data_len_value = 1;
  612. } else if (temp_ei->array_type == STATIC_ARRAY) {
  613. data_len_value = temp_ei->elem_len;
  614. } else if (data_len_value > temp_ei->elem_len) {
  615. pr_err("%s: Data len %d > max spec %d\n",
  616. __func__, data_len_value, temp_ei->elem_len);
  617. return -ETOOSMALL;
  618. }
  619. switch (temp_ei->data_type) {
  620. case QMI_UNSIGNED_1_BYTE:
  621. case QMI_UNSIGNED_2_BYTE:
  622. case QMI_UNSIGNED_4_BYTE:
  623. case QMI_UNSIGNED_8_BYTE:
  624. case QMI_SIGNED_2_BYTE_ENUM:
  625. case QMI_SIGNED_4_BYTE_ENUM:
  626. rc = qmi_decode_basic_elem(buf_dst, buf_src,
  627. data_len_value,
  628. temp_ei->elem_size,
  629. in_buf_len - decoded_bytes);
  630. if (rc < 0)
  631. return rc;
  632. UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
  633. break;
  634. case QMI_STRUCT:
  635. rc = qmi_decode_struct_elem(temp_ei, buf_dst, buf_src,
  636. data_len_value, tlv_len,
  637. dec_level + 1,
  638. in_buf_len - decoded_bytes);
  639. if (rc < 0)
  640. return rc;
  641. UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
  642. break;
  643. case QMI_STRING:
  644. rc = qmi_decode_string_elem(temp_ei, buf_dst, buf_src,
  645. tlv_len, dec_level,
  646. in_buf_len - decoded_bytes);
  647. if (rc < 0)
  648. return rc;
  649. UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
  650. break;
  651. default:
  652. pr_err("%s: Unrecognized data type\n", __func__);
  653. return -EINVAL;
  654. }
  655. temp_ei = temp_ei + 1;
  656. }
  657. return decoded_bytes;
  658. }
  659. /**
  660. * qmi_encode_message() - Encode C structure as QMI encoded message
  661. * @type: Type of QMI message
  662. * @msg_id: Message ID of the message
  663. * @len: Passed as max length of the message, updated to actual size
  664. * @txn_id: Transaction ID
  665. * @ei: QMI message descriptor
  666. * @c_struct: Reference to structure to encode
  667. *
  668. * Return: Buffer with encoded message, or negative ERR_PTR() on error
  669. */
  670. void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
  671. unsigned int txn_id, const struct qmi_elem_info *ei,
  672. const void *c_struct)
  673. {
  674. struct qmi_header *hdr;
  675. ssize_t msglen = 0;
  676. void *msg;
  677. int ret;
  678. /* Check the possibility of a zero length QMI message */
  679. if (!c_struct) {
  680. ret = qmi_calc_min_msg_len(ei, 1);
  681. if (ret) {
  682. pr_err("%s: Calc. len %d != 0, but NULL c_struct\n",
  683. __func__, ret);
  684. return ERR_PTR(-EINVAL);
  685. }
  686. }
  687. msg = kzalloc(sizeof(*hdr) + *len, GFP_KERNEL);
  688. if (!msg)
  689. return ERR_PTR(-ENOMEM);
  690. /* Encode message, if we have a message */
  691. if (c_struct) {
  692. msglen = qmi_encode(ei, msg + sizeof(*hdr), c_struct, *len, 1);
  693. if (msglen < 0) {
  694. kfree(msg);
  695. return ERR_PTR(msglen);
  696. }
  697. }
  698. hdr = msg;
  699. hdr->type = type;
  700. hdr->txn_id = txn_id;
  701. hdr->msg_id = msg_id;
  702. hdr->msg_len = msglen;
  703. *len = sizeof(*hdr) + msglen;
  704. return msg;
  705. }
  706. EXPORT_SYMBOL(qmi_encode_message);
  707. /**
  708. * qmi_decode_message() - Decode QMI encoded message to C structure
  709. * @buf: Buffer with encoded message
  710. * @len: Amount of data in @buf
  711. * @ei: QMI message descriptor
  712. * @c_struct: Reference to structure to decode into
  713. *
  714. * Return: The number of bytes of decoded information on success, negative
  715. * errno on error.
  716. */
  717. int qmi_decode_message(const void *buf, size_t len,
  718. const struct qmi_elem_info *ei, void *c_struct)
  719. {
  720. if (!ei)
  721. return -EINVAL;
  722. if (!c_struct || !buf || !len)
  723. return -EINVAL;
  724. return qmi_decode(ei, c_struct, buf + sizeof(struct qmi_header),
  725. len - sizeof(struct qmi_header), 1);
  726. }
  727. EXPORT_SYMBOL(qmi_decode_message);
  728. /* Common header in all QMI responses */
  729. const struct qmi_elem_info qmi_response_type_v01_ei[] = {
  730. {
  731. .data_type = QMI_SIGNED_2_BYTE_ENUM,
  732. .elem_len = 1,
  733. .elem_size = sizeof(u16),
  734. .array_type = NO_ARRAY,
  735. .tlv_type = QMI_COMMON_TLV_TYPE,
  736. .offset = offsetof(struct qmi_response_type_v01, result),
  737. .ei_array = NULL,
  738. },
  739. {
  740. .data_type = QMI_SIGNED_2_BYTE_ENUM,
  741. .elem_len = 1,
  742. .elem_size = sizeof(u16),
  743. .array_type = NO_ARRAY,
  744. .tlv_type = QMI_COMMON_TLV_TYPE,
  745. .offset = offsetof(struct qmi_response_type_v01, error),
  746. .ei_array = NULL,
  747. },
  748. {
  749. .data_type = QMI_EOTI,
  750. .elem_len = 0,
  751. .elem_size = 0,
  752. .array_type = NO_ARRAY,
  753. .tlv_type = QMI_COMMON_TLV_TYPE,
  754. .offset = 0,
  755. .ei_array = NULL,
  756. },
  757. };
  758. EXPORT_SYMBOL(qmi_response_type_v01_ei);
  759. MODULE_DESCRIPTION("QMI encoder/decoder helper");
  760. MODULE_LICENSE("GPL v2");