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