lib: qmi: Add api to verify maximum length of a QMI message

The new API is added to verify the maximum length of a QMI message
embedded inside the message descriptor matches the expected maximum
length of the concerned QMI message. The expected maximum length of
the QMI message is calculated using the message descriptor which
describes all the elements in the structure.

Change-Id: I09602df410d9891d60f1502245ad055653f8f0f7
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
This commit is contained in:
Karthikeyan Ramasubramanian 2013-01-08 17:21:53 -07:00
parent 887a9bbbb0
commit 0714f1b72b
2 changed files with 89 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -150,6 +150,15 @@ int qmi_kernel_encode(struct msg_desc *desc,
int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct,
void *in_buf, uint32_t in_buf_len);
/**
* qmi_verify_max_msg_len() - Verify the maximum length of a QMI message
* @desc: Pointer to structure descriptor.
*
* @return: true if the maximum message length embedded in structure
* descriptor matches the calculated value, else false.
*/
bool qmi_verify_max_msg_len(struct msg_desc *desc);
#else
static inline int qmi_kernel_encode(struct msg_desc *desc,
void *out_buf, uint32_t out_buf_len,
@ -164,6 +173,11 @@ static inline int qmi_kernel_decode(struct msg_desc *desc,
{
return -EOPNOTSUPP;
}
static inline bool qmi_verify_max_msg_len(struct msg_desc *desc)
{
return false;
}
#endif
#endif

View File

@ -89,6 +89,71 @@ static int _qmi_kernel_decode(struct elem_info *ei_array,
void *in_buf, uint32_t in_buf_len,
int dec_level);
/**
* qmi_calc_max_msg_len() - Calculate the maximum length of a QMI message
* @ei_array: Struct info array describing the structure.
* @level: Level to identify the depth of the nested structures.
*
* @return: expected maximum length of the QMI message or 0 on failure.
*/
static int qmi_calc_max_msg_len(struct elem_info *ei_array,
int level)
{
int max_msg_len = 0;
struct elem_info *temp_ei;
if (!ei_array)
return max_msg_len;
for (temp_ei = ei_array; temp_ei->data_type != QMI_EOTI; temp_ei++) {
/* Flag to identify the optional element is not encoded */
if (temp_ei->data_type == QMI_OPT_FLAG)
continue;
if (temp_ei->data_type == QMI_DATA_LEN) {
max_msg_len += (temp_ei->elem_size == sizeof(uint8_t) ?
sizeof(uint8_t) : sizeof(uint16_t));
continue;
} else if (temp_ei->data_type == QMI_STRUCT) {
max_msg_len += qmi_calc_max_msg_len(temp_ei->ei_array,
(level + 1));
} else {
max_msg_len += (temp_ei->elem_len * temp_ei->elem_size);
}
/*
* Type & Length info. not prepended for elements in the
* nested structure.
*/
if (level == 1)
max_msg_len += (TLV_TYPE_SIZE + TLV_LEN_SIZE);
}
return max_msg_len;
}
/**
* qmi_verify_max_msg_len() - Verify the maximum length of a QMI message
* @desc: Pointer to structure descriptor.
*
* @return: true if the maximum message length embedded in structure
* descriptor matches the calculated value, else false.
*/
bool qmi_verify_max_msg_len(struct msg_desc *desc)
{
int calc_max_msg_len;
if (!desc)
return false;
calc_max_msg_len = qmi_calc_max_msg_len(desc->ei_array, 1);
if (calc_max_msg_len != desc->max_msg_len) {
pr_err("%s: Calc. len %d != Passed len %d\n",
__func__, calc_max_msg_len, desc->max_msg_len);
return false;
}
return true;
}
/**
* qmi_kernel_encode() - Encode to QMI message wire format
* @desc: Pointer to structure descriptor.
@ -103,6 +168,7 @@ int qmi_kernel_encode(struct msg_desc *desc,
void *in_c_struct)
{
int enc_level = 1;
int ret, calc_max_msg_len;
if (!desc || !desc->ei_array)
return -EINVAL;
@ -113,8 +179,14 @@ int qmi_kernel_encode(struct msg_desc *desc,
if (desc->max_msg_len < out_buf_len)
return -ETOOSMALL;
return _qmi_kernel_encode(desc->ei_array, out_buf,
in_c_struct, out_buf_len, enc_level);
ret = _qmi_kernel_encode(desc->ei_array, out_buf,
in_c_struct, out_buf_len, enc_level);
if (ret == -ETOOSMALL) {
calc_max_msg_len = qmi_calc_max_msg_len(desc->ei_array, 1);
pr_err("%s: Calc. len %d != Out buf len %d\n",
__func__, calc_max_msg_len, out_buf_len);
}
return ret;
}
EXPORT_SYMBOL(qmi_kernel_encode);