1 /* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2  * Copyright (C) 2017-2018 Linaro Ltd.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *	* Redistributions of source code must retain the above copyright
9  *	  notice, this list of conditions and the following disclaimer.
10  *	* Redistributions in binary form must reproduce the above
11  *	  copyright notice, this list of conditions and the following
12  *	  disclaimer in the documentation and/or other materials provided
13  *	  with the distribution.
14  *	* Neither the name of The Linux Foundation nor the names of its
15  *	  contributors may be used to endorse or promote products derived
16  *	  from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <errno.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "libqrtr.h"
37 #include "logging.h"
38 
39 /**
40  * qmi_header - wireformat header of QMI messages
41  * @type:       type of message
42  * @txn_id:     transaction id
43  * @msg_id:     message id
44  * @msg_len:    length of message payload following header
45  */
46 struct qmi_header {
47 	uint8_t type;
48 	uint16_t txn_id;
49 	uint16_t msg_id;
50 	uint16_t msg_len;
51 } __attribute__((packed));
52 
53 
54 #define QMI_ENCDEC_ENCODE_TLV(type, length, p_dst) do { \
55 	*p_dst++ = type; \
56 	*p_dst++ = ((uint8_t)((length) & 0xFF)); \
57 	*p_dst++ = ((uint8_t)(((length) >> 8) & 0xFF)); \
58 } while (0)
59 
60 #define QMI_ENCDEC_DECODE_TLV(p_type, p_length, p_src) do { \
61 	*p_type = (uint8_t)*p_src++; \
62 	*p_length = (uint8_t)*p_src++; \
63 	*p_length |= ((uint8_t)*p_src) << 8; \
64 } while (0)
65 
66 #define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \
67 do { \
68 	memcpy(p_dst, p_src, size); \
69 	p_dst = (uint8_t *)p_dst + size; \
70 	p_src = (uint8_t *)p_src + size; \
71 } while (0)
72 
73 #define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \
74 do { \
75 	memcpy(p_dst, p_src, size); \
76 	p_dst = (uint8_t *)p_dst + size; \
77 	p_src = (uint8_t *)p_src + size; \
78 } while (0)
79 
80 #define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \
81 				encoded_bytes, tlv_len, encode_tlv, rc) \
82 do { \
83 	buf_dst = (uint8_t *)buf_dst + rc; \
84 	encoded_bytes += rc; \
85 	tlv_len += rc; \
86 	temp_si = temp_si + 1; \
87 	encode_tlv = 1; \
88 } while (0)
89 
90 #define UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc) \
91 do { \
92 	buf_src = (uint8_t *)buf_src + rc; \
93 	decoded_bytes += rc; \
94 } while (0)
95 
96 #define TLV_LEN_SIZE sizeof(uint16_t)
97 #define TLV_TYPE_SIZE sizeof(uint8_t)
98 #define OPTIONAL_TLV_TYPE_START 0x10
99 
100 static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
101 		      const void *in_c_struct, uint32_t out_buf_len,
102 		      int enc_level);
103 
104 static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
105 		      const void *in_buf, uint32_t in_buf_len, int dec_level);
106 
107 /**
108  * skip_to_next_elem() - Skip to next element in the structure to be encoded
109  * @ei_array: Struct info describing the element to be skipped.
110  * @level: Depth level of encoding/decoding to identify nested structures.
111  *
112  * This function is used while encoding optional elements. If the flag
113  * corresponding to an optional element is not set, then encoding the
114  * optional element can be skipped. This function can be used to perform
115  * that operation.
116  *
117  * Return: struct info of the next element that can be encoded.
118  */
skip_to_next_elem(struct qmi_elem_info * ei_array,int level)119 static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array,
120 					       int level)
121 {
122 	struct qmi_elem_info *temp_ei = ei_array;
123 	uint8_t tlv_type;
124 
125 	if (level > 1) {
126 		temp_ei = temp_ei + 1;
127 	} else {
128 		do {
129 			tlv_type = temp_ei->tlv_type;
130 			temp_ei = temp_ei + 1;
131 		} while (tlv_type == temp_ei->tlv_type);
132 	}
133 
134 	return temp_ei;
135 }
136 
137 /**
138  * qmi_calc_min_msg_len() - Calculate the minimum length of a QMI message
139  * @ei_array: Struct info array describing the structure.
140  * @level: Level to identify the depth of the nested structures.
141  *
142  * Return: Expected minimum length of the QMI message or 0 on error.
143  */
qmi_calc_min_msg_len(struct qmi_elem_info * ei_array,int level)144 static int qmi_calc_min_msg_len(struct qmi_elem_info *ei_array,
145 				int level)
146 {
147 	int min_msg_len = 0;
148 	struct qmi_elem_info *temp_ei = ei_array;
149 
150 	if (!ei_array)
151 		return min_msg_len;
152 
153 	while (temp_ei->data_type != QMI_EOTI) {
154 		/* Optional elements do not count in minimum length */
155 		if (temp_ei->data_type == QMI_OPT_FLAG) {
156 			temp_ei = skip_to_next_elem(temp_ei, level);
157 			continue;
158 		}
159 
160 		if (temp_ei->data_type == QMI_DATA_LEN) {
161 			min_msg_len += (temp_ei->elem_size == sizeof(uint8_t) ?
162 					sizeof(uint8_t) : sizeof(uint16_t));
163 			temp_ei++;
164 			continue;
165 		} else if (temp_ei->data_type == QMI_STRUCT) {
166 			min_msg_len += qmi_calc_min_msg_len(temp_ei->ei_array,
167 							    (level + 1));
168 			temp_ei++;
169 		} else if (temp_ei->data_type == QMI_STRING) {
170 			if (level > 1)
171 				min_msg_len += temp_ei->elem_len <= 256 ?
172 					sizeof(uint8_t) : sizeof(uint16_t);
173 			min_msg_len += temp_ei->elem_len * temp_ei->elem_size;
174 			temp_ei++;
175 		} else {
176 			min_msg_len += (temp_ei->elem_len * temp_ei->elem_size);
177 			temp_ei++;
178 		}
179 
180 		/*
181 		 * Type & Length info. not prepended for elements in the
182 		 * nested structure.
183 		 */
184 		if (level == 1)
185 			min_msg_len += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
186 	}
187 
188 	return min_msg_len;
189 }
190 
191 /**
192  * qmi_encode_basic_elem() - Encodes elements of basic/primary data type
193  * @buf_dst: Buffer to store the encoded information.
194  * @buf_src: Buffer containing the elements to be encoded.
195  * @elem_len: Number of elements, in the buf_src, to be encoded.
196  * @elem_size: Size of a single instance of the element to be encoded.
197  *
198  * This function encodes the "elem_len" number of data elements, each of
199  * size "elem_size" bytes from the source buffer "buf_src" and stores the
200  * encoded information in the destination buffer "buf_dst". The elements are
201  * of primary data type which include uint8_t - u64 or similar. This
202  * function returns the number of bytes of encoded information.
203  *
204  * Return: The number of bytes of encoded information.
205  */
qmi_encode_basic_elem(void * buf_dst,const void * buf_src,uint32_t elem_len,uint32_t elem_size)206 static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src,
207 				 uint32_t elem_len, uint32_t elem_size)
208 {
209 	uint32_t i, rc = 0;
210 
211 	for (i = 0; i < elem_len; i++) {
212 		QMI_ENCDEC_ENCODE_N_BYTES(buf_dst, buf_src, elem_size);
213 		rc += elem_size;
214 	}
215 
216 	return rc;
217 }
218 
219 /**
220  * qmi_encode_struct_elem() - Encodes elements of struct data type
221  * @ei_array: Struct info array descibing the struct element.
222  * @buf_dst: Buffer to store the encoded information.
223  * @buf_src: Buffer containing the elements to be encoded.
224  * @elem_len: Number of elements, in the buf_src, to be encoded.
225  * @out_buf_len: Available space in the encode buffer.
226  * @enc_level: Depth of the nested structure from the main structure.
227  *
228  * This function encodes the "elem_len" number of struct elements, each of
229  * size "ei_array->elem_size" bytes from the source buffer "buf_src" and
230  * stores the encoded information in the destination buffer "buf_dst". The
231  * elements are of struct data type which includes any C structure. This
232  * function returns the number of bytes of encoded information.
233  *
234  * Return: The number of bytes of encoded information on success or negative
235  * errno on error.
236  */
qmi_encode_struct_elem(struct qmi_elem_info * ei_array,void * buf_dst,const void * buf_src,uint32_t elem_len,uint32_t out_buf_len,int enc_level)237 static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array,
238 				  void *buf_dst, const void *buf_src,
239 				  uint32_t elem_len, uint32_t out_buf_len,
240 				  int enc_level)
241 {
242 	int i, rc, encoded_bytes = 0;
243 	struct qmi_elem_info *temp_ei = ei_array;
244 
245 	for (i = 0; i < elem_len; i++) {
246 		rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src,
247 				out_buf_len - encoded_bytes, enc_level);
248 		if (rc < 0) {
249 			LOGW("%s: STRUCT Encode failure\n", __func__);
250 			return rc;
251 		}
252 		buf_dst = (char*)buf_dst + rc;
253 		buf_src = (char*)buf_src + temp_ei->elem_size;
254 		encoded_bytes += rc;
255 	}
256 
257 	return encoded_bytes;
258 }
259 
260 /**
261  * qmi_encode_string_elem() - Encodes elements of string data type
262  * @ei_array: Struct info array descibing the string element.
263  * @buf_dst: Buffer to store the encoded information.
264  * @buf_src: Buffer containing the elements to be encoded.
265  * @out_buf_len: Available space in the encode buffer.
266  * @enc_level: Depth of the string element from the main structure.
267  *
268  * This function encodes a string element of maximum length "ei_array->elem_len"
269  * bytes from the source buffer "buf_src" and stores the encoded information in
270  * the destination buffer "buf_dst". This function returns the number of bytes
271  * of encoded information.
272  *
273  * Return: The number of bytes of encoded information on success or negative
274  * errno on error.
275  */
qmi_encode_string_elem(struct qmi_elem_info * ei_array,void * buf_dst,const void * buf_src,uint32_t out_buf_len,int enc_level)276 static int qmi_encode_string_elem(struct qmi_elem_info *ei_array,
277 				  void *buf_dst, const void *buf_src,
278 				  uint32_t out_buf_len, int enc_level)
279 {
280 	int rc;
281 	int encoded_bytes = 0;
282 	struct qmi_elem_info *temp_ei = ei_array;
283 	uint32_t string_len = 0;
284 	uint32_t string_len_sz = 0;
285 
286 	string_len = strlen(buf_src);
287 	string_len_sz = temp_ei->elem_len <= 256 ?
288 			sizeof(uint8_t) : sizeof(uint16_t);
289 	if (string_len > temp_ei->elem_len) {
290 		LOGW("%s: String to be encoded is longer - %d > %d\n",
291 		     __func__, string_len, temp_ei->elem_len);
292 		return -EINVAL;
293 	}
294 
295 	if (enc_level == 1) {
296 		if (string_len + TLV_LEN_SIZE + TLV_TYPE_SIZE >
297 		    out_buf_len) {
298 			LOGW("%s: Output len %d > Out Buf len %d\n",
299 			     __func__, string_len, out_buf_len);
300 			return -EINVAL;
301 		}
302 	} else {
303 		if (string_len + string_len_sz > out_buf_len) {
304 			LOGW("%s: Output len %d > Out Buf len %d\n",
305 			     __func__, string_len, out_buf_len);
306 			return -EINVAL;
307 		}
308 		rc = qmi_encode_basic_elem(buf_dst, &string_len,
309 					   1, string_len_sz);
310 		encoded_bytes += rc;
311 	}
312 
313 	rc = qmi_encode_basic_elem((char*)buf_dst + encoded_bytes, buf_src,
314 				   string_len, temp_ei->elem_size);
315 	encoded_bytes += rc;
316 
317 	return encoded_bytes;
318 }
319 
320 /**
321  * qmi_encode() - Core Encode Function
322  * @ei_array: Struct info array describing the structure to be encoded.
323  * @out_buf: Buffer to hold the encoded QMI message.
324  * @in_c_struct: Pointer to the C structure to be encoded.
325  * @out_buf_len: Available space in the encode buffer.
326  * @enc_level: Encode level to indicate the depth of the nested structure,
327  *             within the main structure, being encoded.
328  *
329  * Return: The number of bytes of encoded information on success or negative
330  * errno on error.
331  */
qmi_encode(struct qmi_elem_info * ei_array,void * out_buf,const void * in_c_struct,uint32_t out_buf_len,int enc_level)332 static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
333 		      const void *in_c_struct, uint32_t out_buf_len,
334 		      int enc_level)
335 {
336 	struct qmi_elem_info *temp_ei = ei_array;
337 	uint8_t opt_flag_value = 0;
338 	uint32_t data_len_value = 0, data_len_sz;
339 	uint8_t *buf_dst = (uint8_t *)out_buf;
340 	uint8_t *tlv_pointer;
341 	uint32_t tlv_len;
342 	uint8_t tlv_type;
343 	uint32_t encoded_bytes = 0;
344 	const void *buf_src;
345 	int encode_tlv = 0;
346 	int rc;
347 
348 	if (!ei_array)
349 		return 0;
350 
351 	tlv_pointer = buf_dst;
352 	tlv_len = 0;
353 	if (enc_level == 1)
354 		buf_dst = buf_dst + (TLV_LEN_SIZE + TLV_TYPE_SIZE);
355 
356 	while (temp_ei->data_type != QMI_EOTI) {
357 		buf_src = (char*)in_c_struct + temp_ei->offset;
358 		tlv_type = temp_ei->tlv_type;
359 
360 		if (temp_ei->array_type == NO_ARRAY) {
361 			data_len_value = 1;
362 		} else if (temp_ei->array_type == STATIC_ARRAY) {
363 			data_len_value = temp_ei->elem_len;
364 		} else if (data_len_value <= 0 ||
365 			    temp_ei->elem_len < data_len_value) {
366 			LOGW("%s: Invalid data length\n", __func__);
367 			return -EINVAL;
368 		}
369 
370 		switch (temp_ei->data_type) {
371 		case QMI_OPT_FLAG:
372 			rc = qmi_encode_basic_elem(&opt_flag_value, buf_src,
373 						   1, sizeof(uint8_t));
374 			if (opt_flag_value)
375 				temp_ei = temp_ei + 1;
376 			else
377 				temp_ei = skip_to_next_elem(temp_ei, enc_level);
378 			break;
379 
380 		case QMI_DATA_LEN:
381 			memcpy(&data_len_value, buf_src, temp_ei->elem_size);
382 			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
383 					sizeof(uint8_t) : sizeof(uint16_t);
384 			/* Check to avoid out of range buffer access */
385 			if ((data_len_sz + encoded_bytes + TLV_LEN_SIZE +
386 			    TLV_TYPE_SIZE) > out_buf_len) {
387 				LOGW("%s: Too Small Buffer @DATA_LEN\n",
388 				       __func__);
389 				return -EINVAL;
390 			}
391 			rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
392 						   1, data_len_sz);
393 			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
394 						encoded_bytes, tlv_len,
395 						encode_tlv, rc);
396 			if (!data_len_value)
397 				temp_ei = skip_to_next_elem(temp_ei, enc_level);
398 			else
399 				encode_tlv = 0;
400 			break;
401 
402 		case QMI_UNSIGNED_1_BYTE:
403 		case QMI_UNSIGNED_2_BYTE:
404 		case QMI_UNSIGNED_4_BYTE:
405 		case QMI_UNSIGNED_8_BYTE:
406 		case QMI_SIGNED_1_BYTE_ENUM:
407 		case QMI_SIGNED_2_BYTE_ENUM:
408 		case QMI_SIGNED_4_BYTE_ENUM:
409 			/* Check to avoid out of range buffer access */
410 			if (((data_len_value * temp_ei->elem_size) +
411 			    encoded_bytes + TLV_LEN_SIZE + TLV_TYPE_SIZE) >
412 			    out_buf_len) {
413 				LOGW("%s: Too Small Buffer @data_type:%d\n",
414 				     __func__, temp_ei->data_type);
415 				return -EINVAL;
416 			}
417 			rc = qmi_encode_basic_elem(buf_dst, buf_src,
418 						   data_len_value,
419 						   temp_ei->elem_size);
420 			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
421 						encoded_bytes, tlv_len,
422 						encode_tlv, rc);
423 			break;
424 
425 		case QMI_STRUCT:
426 			rc = qmi_encode_struct_elem(temp_ei, buf_dst, buf_src,
427 						    data_len_value,
428 						    out_buf_len - encoded_bytes,
429 						    enc_level + 1);
430 			if (rc < 0)
431 				return rc;
432 			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
433 						encoded_bytes, tlv_len,
434 						encode_tlv, rc);
435 			break;
436 
437 		case QMI_STRING:
438 			rc = qmi_encode_string_elem(temp_ei, buf_dst, buf_src,
439 						    out_buf_len - encoded_bytes,
440 						    enc_level);
441 			if (rc < 0)
442 				return rc;
443 			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
444 						encoded_bytes, tlv_len,
445 						encode_tlv, rc);
446 			break;
447 		default:
448 			LOGW("%s: Unrecognized data type\n", __func__);
449 			return -EINVAL;
450 		}
451 
452 		if (encode_tlv && enc_level == 1) {
453 			QMI_ENCDEC_ENCODE_TLV(tlv_type, tlv_len, tlv_pointer);
454 			encoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
455 			tlv_pointer = buf_dst;
456 			tlv_len = 0;
457 			buf_dst = buf_dst + TLV_LEN_SIZE + TLV_TYPE_SIZE;
458 			encode_tlv = 0;
459 		}
460 	}
461 
462 	return encoded_bytes;
463 }
464 
465 /**
466  * qmi_decode_basic_elem() - Decodes elements of basic/primary data type
467  * @buf_dst: Buffer to store the decoded element.
468  * @buf_src: Buffer containing the elements in QMI wire format.
469  * @elem_len: Number of elements to be decoded.
470  * @elem_size: Size of a single instance of the element to be decoded.
471  *
472  * This function decodes the "elem_len" number of elements in QMI wire format,
473  * each of size "elem_size" bytes from the source buffer "buf_src" and stores
474  * the decoded elements in the destination buffer "buf_dst". The elements are
475  * of primary data type which include uint8_t - u64 or similar. This
476  * function returns the number of bytes of decoded information.
477  *
478  * Return: The total size of the decoded data elements, in bytes.
479  */
qmi_decode_basic_elem(void * buf_dst,const void * buf_src,uint32_t elem_len,uint32_t elem_size)480 static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src,
481 				 uint32_t elem_len, uint32_t elem_size)
482 {
483 	uint32_t i, rc = 0;
484 
485 	for (i = 0; i < elem_len; i++) {
486 		QMI_ENCDEC_DECODE_N_BYTES(buf_dst, buf_src, elem_size);
487 		rc += elem_size;
488 	}
489 
490 	return rc;
491 }
492 
493 /**
494  * qmi_decode_struct_elem() - Decodes elements of struct data type
495  * @ei_array: Struct info array descibing the struct element.
496  * @buf_dst: Buffer to store the decoded element.
497  * @buf_src: Buffer containing the elements in QMI wire format.
498  * @elem_len: Number of elements to be decoded.
499  * @tlv_len: Total size of the encoded inforation corresponding to
500  *           this struct element.
501  * @dec_level: Depth of the nested structure from the main structure.
502  *
503  * This function decodes the "elem_len" number of elements in QMI wire format,
504  * each of size "(tlv_len/elem_len)" bytes from the source buffer "buf_src"
505  * and stores the decoded elements in the destination buffer "buf_dst". The
506  * elements are of struct data type which includes any C structure. This
507  * function returns the number of bytes of decoded information.
508  *
509  * Return: The total size of the decoded data elements on success, negative
510  * errno on error.
511  */
qmi_decode_struct_elem(struct qmi_elem_info * ei_array,void * buf_dst,const void * buf_src,uint32_t elem_len,uint32_t tlv_len,int dec_level)512 static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array,
513 				  void *buf_dst, const void *buf_src,
514 				  uint32_t elem_len, uint32_t tlv_len,
515 				  int dec_level)
516 {
517 	int i, rc, decoded_bytes = 0;
518 	struct qmi_elem_info *temp_ei = ei_array;
519 
520 	for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) {
521 		rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src,
522 				tlv_len - decoded_bytes, dec_level);
523 		if (rc < 0)
524 			return rc;
525 		buf_src = (char*)buf_src + rc;
526 		buf_dst = (char*)buf_dst + temp_ei->elem_size;
527 		decoded_bytes += rc;
528 	}
529 
530 	if ((dec_level <= 2 && decoded_bytes != tlv_len) ||
531 	    (dec_level > 2 && (i < elem_len || decoded_bytes > tlv_len))) {
532 		LOGW("%s: Fault in decoding: dl(%d), db(%d), tl(%d), i(%d), el(%d)\n",
533 		     __func__, dec_level, decoded_bytes, tlv_len,
534 		     i, elem_len);
535 		return -EFAULT;
536 	}
537 
538 	return decoded_bytes;
539 }
540 
541 /**
542  * qmi_decode_string_elem() - Decodes elements of string data type
543  * @ei_array: Struct info array descibing the string element.
544  * @buf_dst: Buffer to store the decoded element.
545  * @buf_src: Buffer containing the elements in QMI wire format.
546  * @tlv_len: Total size of the encoded inforation corresponding to
547  *           this string element.
548  * @dec_level: Depth of the string element from the main structure.
549  *
550  * This function decodes the string element of maximum length
551  * "ei_array->elem_len" from the source buffer "buf_src" and puts it into
552  * the destination buffer "buf_dst". This function returns number of bytes
553  * decoded from the input buffer.
554  *
555  * Return: The total size of the decoded data elements on success, negative
556  * errno on error.
557  */
qmi_decode_string_elem(struct qmi_elem_info * ei_array,void * buf_dst,const void * buf_src,uint32_t tlv_len,int dec_level)558 static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
559 				  void *buf_dst, const void *buf_src,
560 				  uint32_t tlv_len, int dec_level)
561 {
562 	int rc;
563 	int decoded_bytes = 0;
564 	uint32_t string_len = 0;
565 	uint32_t string_len_sz = 0;
566 	struct qmi_elem_info *temp_ei = ei_array;
567 
568 	if (dec_level == 1) {
569 		string_len = tlv_len;
570 	} else {
571 		string_len_sz = temp_ei->elem_len <= 256 ?
572 				sizeof(uint8_t) : sizeof(uint16_t);
573 		rc = qmi_decode_basic_elem(&string_len, buf_src,
574 					   1, string_len_sz);
575 		decoded_bytes += rc;
576 	}
577 
578 	if (string_len > temp_ei->elem_len) {
579 		LOGW("%s: String len %d > Max Len %d\n",
580 		     __func__, string_len, temp_ei->elem_len);
581 		return -EINVAL;
582 	} else if (string_len > tlv_len) {
583 		LOGW("%s: String len %d > Input Buffer Len %d\n",
584 		     __func__, string_len, tlv_len);
585 		return -EFAULT;
586 	}
587 
588 	rc = qmi_decode_basic_elem(buf_dst, (char*)buf_src + decoded_bytes,
589 				   string_len, temp_ei->elem_size);
590 	*((char *)buf_dst + string_len) = '\0';
591 	decoded_bytes += rc;
592 
593 	return decoded_bytes;
594 }
595 
596 /**
597  * find_ei() - Find element info corresponding to TLV Type
598  * @ei_array: Struct info array of the message being decoded.
599  * @type: TLV Type of the element being searched.
600  *
601  * Every element that got encoded in the QMI message will have a type
602  * information associated with it. While decoding the QMI message,
603  * this function is used to find the struct info regarding the element
604  * that corresponds to the type being decoded.
605  *
606  * Return: Pointer to struct info, if found
607  */
find_ei(struct qmi_elem_info * ei_array,uint32_t type)608 static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array,
609 				     uint32_t type)
610 {
611 	struct qmi_elem_info *temp_ei = ei_array;
612 
613 	while (temp_ei->data_type != QMI_EOTI) {
614 		if (temp_ei->tlv_type == (uint8_t)type)
615 			return temp_ei;
616 		temp_ei = temp_ei + 1;
617 	}
618 
619 	return NULL;
620 }
621 
622 /**
623  * qmi_decode() - Core Decode Function
624  * @ei_array: Struct info array describing the structure to be decoded.
625  * @out_c_struct: Buffer to hold the decoded C struct
626  * @in_buf: Buffer containing the QMI message to be decoded
627  * @in_buf_len: Length of the QMI message to be decoded
628  * @dec_level: Decode level to indicate the depth of the nested structure,
629  *             within the main structure, being decoded
630  *
631  * Return: The number of bytes of decoded information on success, negative
632  * errno on error.
633  */
qmi_decode(struct qmi_elem_info * ei_array,void * out_c_struct,const void * in_buf,uint32_t in_buf_len,int dec_level)634 static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
635 		      const void *in_buf, uint32_t in_buf_len,
636 		      int dec_level)
637 {
638 	struct qmi_elem_info *temp_ei = ei_array;
639 	uint8_t opt_flag_value = 1;
640 	uint32_t data_len_value = 0, data_len_sz = 0;
641 	uint8_t *buf_dst = out_c_struct;
642 	const uint8_t *tlv_pointer;
643 	uint32_t tlv_len = 0;
644 	uint32_t tlv_type;
645 	uint32_t decoded_bytes = 0;
646 	const void *buf_src = in_buf;
647 	int rc;
648 
649 	while (decoded_bytes < in_buf_len) {
650 		if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI)
651 			return decoded_bytes;
652 
653 		if (dec_level == 1) {
654 			tlv_pointer = buf_src;
655 			QMI_ENCDEC_DECODE_TLV(&tlv_type,
656 					      &tlv_len, tlv_pointer);
657 			buf_src = (uint8_t*)buf_src + (TLV_TYPE_SIZE + TLV_LEN_SIZE);
658 			decoded_bytes += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
659 			temp_ei = find_ei(ei_array, tlv_type);
660 			if (!temp_ei && tlv_type < OPTIONAL_TLV_TYPE_START) {
661 				LOGW("%s: Inval element info\n", __func__);
662 				return -EINVAL;
663 			} else if (!temp_ei) {
664 				UPDATE_DECODE_VARIABLES(buf_src,
665 							decoded_bytes, tlv_len);
666 				continue;
667 			}
668 		} else {
669 			/*
670 			 * No length information for elements in nested
671 			 * structures. So use remaining decodable buffer space.
672 			 */
673 			tlv_len = in_buf_len - decoded_bytes;
674 		}
675 
676 		buf_dst = (uint8_t*)out_c_struct + temp_ei->offset;
677 		if (temp_ei->data_type == QMI_OPT_FLAG) {
678 			memcpy(buf_dst, &opt_flag_value, sizeof(uint8_t));
679 			temp_ei = temp_ei + 1;
680 			buf_dst = (uint8_t*)out_c_struct + temp_ei->offset;
681 		}
682 
683 		if (temp_ei->data_type == QMI_DATA_LEN) {
684 			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
685 					sizeof(uint8_t) : sizeof(uint16_t);
686 			rc = qmi_decode_basic_elem(&data_len_value, buf_src,
687 						   1, data_len_sz);
688 			memcpy(buf_dst, &data_len_value, sizeof(uint32_t));
689 			temp_ei = temp_ei + 1;
690 			buf_dst = (uint8_t*)out_c_struct + temp_ei->offset;
691 			tlv_len -= data_len_sz;
692 			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
693 		}
694 
695 		if (temp_ei->array_type == NO_ARRAY) {
696 			data_len_value = 1;
697 		} else if (temp_ei->array_type == STATIC_ARRAY) {
698 			data_len_value = temp_ei->elem_len;
699 		} else if (data_len_value > temp_ei->elem_len) {
700 			LOGW("%s: Data len %d > max spec %d\n",
701 			     __func__, data_len_value, temp_ei->elem_len);
702 			return -EINVAL;
703 		}
704 
705 		switch (temp_ei->data_type) {
706 		case QMI_UNSIGNED_1_BYTE:
707 		case QMI_UNSIGNED_2_BYTE:
708 		case QMI_UNSIGNED_4_BYTE:
709 		case QMI_UNSIGNED_8_BYTE:
710 		case QMI_SIGNED_1_BYTE_ENUM:
711 		case QMI_SIGNED_2_BYTE_ENUM:
712 		case QMI_SIGNED_4_BYTE_ENUM:
713 			rc = qmi_decode_basic_elem(buf_dst, buf_src,
714 						   data_len_value,
715 						   temp_ei->elem_size);
716 			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
717 			break;
718 
719 		case QMI_STRUCT:
720 			rc = qmi_decode_struct_elem(temp_ei, buf_dst, buf_src,
721 						    data_len_value, tlv_len,
722 						    dec_level + 1);
723 			if (rc < 0)
724 				return rc;
725 			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
726 			break;
727 
728 		case QMI_STRING:
729 			rc = qmi_decode_string_elem(temp_ei, buf_dst, buf_src,
730 						    tlv_len, dec_level);
731 			if (rc < 0)
732 				return rc;
733 			UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
734 			break;
735 
736 		default:
737 			LOGW("%s: Unrecognized data type\n", __func__);
738 			return -EINVAL;
739 		}
740 		temp_ei = temp_ei + 1;
741 	}
742 
743 	return decoded_bytes;
744 }
745 
746 /**
747  * qmi_encode_message() - Encode C structure as QMI encoded message
748  * @type:	Type of QMI message
749  * @msg_id:	Message ID of the message
750  * @len:	Passed as max length of the message, updated to actual size
751  * @txn_id:	Transaction ID
752  * @ei:		QMI message descriptor
753  * @c_struct:	Reference to structure to encode
754  *
755  * Return: Buffer with encoded message, or negative ERR_PTR() on error
756  */
qmi_encode_message(struct qrtr_packet * pkt,int type,int msg_id,int txn_id,const void * c_struct,struct qmi_elem_info * ei)757 ssize_t qmi_encode_message(struct qrtr_packet *pkt, int type, int msg_id,
758 			   int txn_id, const void *c_struct,
759 			   struct qmi_elem_info *ei)
760 {
761 	struct qmi_header *hdr = pkt->data;
762 	ssize_t msglen = 0;
763 	int ret;
764 
765 	/* Check the possibility of a zero length QMI message */
766 	if (!c_struct) {
767 		ret = qmi_calc_min_msg_len(ei, 1);
768 		if (ret) {
769 			LOGW("%s: Calc. len %d != 0, but NULL c_struct\n",
770 			     __func__, ret);
771 			return -EINVAL;
772 		}
773 	}
774 
775 	if (pkt->data_len < sizeof(*hdr))
776 		return -EMSGSIZE;
777 
778 	/* Encode message, if we have a message */
779 	if (c_struct) {
780 		msglen = qmi_encode(ei, (char*)pkt->data + sizeof(*hdr), c_struct,
781 				    pkt->data_len - sizeof(*hdr), 1);
782 		if (msglen < 0)
783 			return msglen;
784 	}
785 
786 	hdr->type = type;
787 	hdr->txn_id = txn_id;
788 	hdr->msg_id = msg_id;
789 	hdr->msg_len = msglen;
790 
791 	pkt->type = QRTR_TYPE_DATA;
792 	pkt->data_len = sizeof(*hdr) + msglen;
793 
794 	return pkt->data_len;
795 }
796 
qmi_decode_header(const struct qrtr_packet * pkt,unsigned int * msg_id)797 int qmi_decode_header(const struct qrtr_packet *pkt, unsigned int *msg_id)
798 {
799 	const struct qmi_header *qmi = pkt->data;
800 
801 	if (qmi->msg_len != pkt->data_len - sizeof(*qmi)) {
802 		LOGW("[RMTFS] Invalid length of incoming qmi request\n");
803 		return -EINVAL;
804 	}
805 
806 	*msg_id = qmi->msg_id;
807 
808 	return 0;
809 }
810 
811 /**
812  * qmi_decode_message() - Decode QMI encoded message to C structure
813  * @buf:	Buffer with encoded message
814  * @len:	Amount of data in @buf
815  * @ei:		QMI message descriptor
816  * @c_struct:	Reference to structure to decode into
817  *
818  * Return: The number of bytes of decoded information on success, negative
819  * errno on error.
820  */
qmi_decode_message(void * c_struct,unsigned int * txn,const struct qrtr_packet * pkt,int type,int id,struct qmi_elem_info * ei)821 int qmi_decode_message(void *c_struct, unsigned int *txn,
822 		       const struct qrtr_packet *pkt,
823 		       int type, int id, struct qmi_elem_info *ei)
824 {
825 	const struct qmi_header *hdr = pkt->data;
826 
827 	if (!ei)
828 		return -EINVAL;
829 
830 	if (!c_struct || !pkt->data || !pkt->data_len)
831 		return -EINVAL;
832 
833 	if (hdr->type != type)
834 		return -EINVAL;
835 
836 	if (hdr->msg_id != id)
837 		return -EINVAL;
838 
839 	if (txn)
840 		*txn = hdr->txn_id;
841 
842 	return qmi_decode(ei, c_struct, (char*)pkt->data + sizeof(*hdr), pkt->data_len - sizeof(*hdr), 1);
843 }
844 
845 /* Common header in all QMI responses */
846 struct qmi_elem_info qmi_response_type_v01_ei[] = {
847 	{
848 		.data_type	= QMI_SIGNED_2_BYTE_ENUM,
849 		.elem_len	= 1,
850 		.elem_size	= sizeof(uint16_t),
851 		.array_type	= NO_ARRAY,
852 		.tlv_type	= QMI_COMMON_TLV_TYPE,
853 		.offset		= offsetof(struct qmi_response_type_v01, result),
854 		.ei_array	= NULL,
855 	},
856 	{
857 		.data_type	= QMI_SIGNED_2_BYTE_ENUM,
858 		.elem_len	= 1,
859 		.elem_size	= sizeof(uint16_t),
860 		.array_type	= NO_ARRAY,
861 		.tlv_type	= QMI_COMMON_TLV_TYPE,
862 		.offset		= offsetof(struct qmi_response_type_v01, error),
863 		.ei_array	= NULL,
864 	},
865 	{
866 		.data_type	= QMI_EOTI,
867 		.elem_len	= 0,
868 		.elem_size	= 0,
869 		.array_type	= NO_ARRAY,
870 		.tlv_type	= QMI_COMMON_TLV_TYPE,
871 		.offset		= 0,
872 		.ei_array	= NULL,
873 	},
874 };
875