Skip to content

Commit 3ced38d

Browse files
Alexander Wilhelmandersson
authored andcommitted
soc: qcom: QMI encoding/decoding for big endian
The QMI_DATA_LEN type may have different sizes. Taking the element's address of that type and interpret it as a smaller sized ones works fine for little endian platforms but not for big endian ones. Instead use temporary variables of smaller sized types and cast them correctly to support big endian platforms. Signed-off-by: Alexander Wilhelm <[email protected]> Fixes: 9b8a11e ("soc: qcom: Introduce QMI encoder/decoder") Reviewed-by: Dmitry Baryshkov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent b0123a8 commit 3ced38d

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

drivers/soc/qcom/qmi_encdec.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
304304
const void *buf_src;
305305
int encode_tlv = 0;
306306
int rc;
307+
u8 val8;
308+
u16 val16;
307309

308310
if (!ei_array)
309311
return 0;
@@ -338,7 +340,6 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
338340
break;
339341

340342
case QMI_DATA_LEN:
341-
memcpy(&data_len_value, buf_src, temp_ei->elem_size);
342343
data_len_sz = temp_ei->elem_size == sizeof(u8) ?
343344
sizeof(u8) : sizeof(u16);
344345
/* Check to avoid out of range buffer access */
@@ -348,8 +349,17 @@ static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
348349
__func__);
349350
return -ETOOSMALL;
350351
}
351-
rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
352-
1, data_len_sz);
352+
if (data_len_sz == sizeof(u8)) {
353+
val8 = *(u8 *)buf_src;
354+
data_len_value = (u32)val8;
355+
rc = qmi_encode_basic_elem(buf_dst, &val8,
356+
1, data_len_sz);
357+
} else {
358+
val16 = *(u16 *)buf_src;
359+
data_len_value = (u32)le16_to_cpu(val16);
360+
rc = qmi_encode_basic_elem(buf_dst, &val16,
361+
1, data_len_sz);
362+
}
353363
UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
354364
encoded_bytes, tlv_len,
355365
encode_tlv, rc);
@@ -523,14 +533,23 @@ static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array,
523533
u32 string_len = 0;
524534
u32 string_len_sz = 0;
525535
const struct qmi_elem_info *temp_ei = ei_array;
536+
u8 val8;
537+
u16 val16;
526538

527539
if (dec_level == 1) {
528540
string_len = tlv_len;
529541
} else {
530542
string_len_sz = temp_ei->elem_len <= U8_MAX ?
531543
sizeof(u8) : sizeof(u16);
532-
rc = qmi_decode_basic_elem(&string_len, buf_src,
533-
1, string_len_sz);
544+
if (string_len_sz == sizeof(u8)) {
545+
rc = qmi_decode_basic_elem(&val8, buf_src,
546+
1, string_len_sz);
547+
string_len = (u32)val8;
548+
} else {
549+
rc = qmi_decode_basic_elem(&val16, buf_src,
550+
1, string_len_sz);
551+
string_len = (u32)val16;
552+
}
534553
decoded_bytes += rc;
535554
}
536555

@@ -604,6 +623,9 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
604623
u32 decoded_bytes = 0;
605624
const void *buf_src = in_buf;
606625
int rc;
626+
u8 val8;
627+
u16 val16;
628+
u32 val32;
607629

608630
while (decoded_bytes < in_buf_len) {
609631
if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI)
@@ -642,9 +664,17 @@ static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
642664
if (temp_ei->data_type == QMI_DATA_LEN) {
643665
data_len_sz = temp_ei->elem_size == sizeof(u8) ?
644666
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));
667+
if (data_len_sz == sizeof(u8)) {
668+
rc = qmi_decode_basic_elem(&val8, buf_src,
669+
1, data_len_sz);
670+
data_len_value = (u32)val8;
671+
} else {
672+
rc = qmi_decode_basic_elem(&val16, buf_src,
673+
1, data_len_sz);
674+
data_len_value = (u32)val16;
675+
}
676+
val32 = cpu_to_le32(data_len_value);
677+
memcpy(buf_dst, &val32, sizeof(u32));
648678
temp_ei = temp_ei + 1;
649679
buf_dst = out_c_struct + temp_ei->offset;
650680
tlv_len -= data_len_sz;

0 commit comments

Comments
 (0)