Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/audio/eq_iir/eq_iir.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ static int eq_iir_get_config(struct processing_module *mod,
return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size);
}

static int eq_iir_check_blob_size(struct comp_dev *dev, size_t size)
{
if (size < sizeof(struct sof_eq_iir_config) || size > SOF_EQ_IIR_MAX_SIZE) {
comp_err(dev, "invalid configuration blob, size %zu", size);
return -EINVAL;
}

return 0;
}

static int eq_iir_process(struct processing_module *mod,
struct input_stream_buffer *input_buffers, int num_input_buffers,
struct output_stream_buffer *output_buffers, int num_output_buffers)
Expand All @@ -119,7 +129,9 @@ static int eq_iir_process(struct processing_module *mod,

/* Check for changed configuration */
if (comp_is_new_data_blob_available(cd->model_handler)) {
cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
if (!cd->config || eq_iir_check_blob_size(mod->dev, cd->config_size) < 0)
return -EINVAL;
Comment on lines +132 to +134
ret = eq_iir_new_blob(mod, audio_stream_get_frm_fmt(source),
audio_stream_get_frm_fmt(sink),
audio_stream_get_channels(source));
Expand Down Expand Up @@ -158,7 +170,6 @@ static int eq_iir_prepare(struct processing_module *mod,
struct comp_dev *dev = mod->dev;
enum sof_ipc_frame source_format;
enum sof_ipc_frame sink_format;
size_t data_size;
int channels;
int ret = 0;

Expand All @@ -183,7 +194,7 @@ static int eq_iir_prepare(struct processing_module *mod,
source_format = audio_stream_get_frm_fmt(&sourceb->stream);
sink_format = audio_stream_get_frm_fmt(&sinkb->stream);

cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL);
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);

/* Initialize EQ */
comp_info(dev, "source_format=%d, sink_format=%d",
Expand All @@ -192,7 +203,9 @@ static int eq_iir_prepare(struct processing_module *mod,
eq_iir_set_passthrough_func(cd, source_format, sink_format);

/* Initialize EQ */
if (cd->config && data_size > 0) {
if (cd->config && cd->config_size > 0) {
if (eq_iir_check_blob_size(dev, cd->config_size) < 0)
return -EINVAL;
Comment on lines +206 to +208
ret = eq_iir_new_blob(mod, source_format, sink_format, channels);
if (ret)
return ret;
Expand Down
1 change: 1 addition & 0 deletions src/audio/eq_iir/eq_iir.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct comp_data {
struct comp_data_blob_handler *model_handler;
struct sof_eq_iir_config *config;
int32_t *iir_delay; /**< pointer to allocated RAM */
size_t config_size; /**< configuration size */
size_t iir_delay_size; /**< allocated size */
eq_iir_func eq_iir_func; /**< processing function */
};
Expand Down
78 changes: 72 additions & 6 deletions src/audio/eq_iir/eq_iir_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,20 +180,77 @@ void eq_iir_s32_default(struct processing_module *mod, struct input_stream_buffe
}
#endif /* CONFIG_FORMAT_S32LE */

static int eq_iir_blob_words_max(struct comp_dev *dev,
const struct sof_eq_iir_config *config,
uint32_t *coef_words_max)
{
size_t payload_bytes;

/* Compute the size of the coefficient area in int32_t words from the
* blob's self-declared size. The blob layout is:
* sizeof(*config) header bytes
* channels_in_config int32_t assign_response[]
* coefficient data[]
* channels_in_config is bounded above, so the multiply fits in size_t.
*/
if (config->size < sizeof(*config)) {
comp_err(dev, "config size %u too small", config->size);
return -EINVAL;
}
payload_bytes = config->size - sizeof(*config);
Comment on lines +196 to +200
if (payload_bytes % sizeof(int32_t) ||
payload_bytes < (size_t)config->channels_in_config * sizeof(int32_t)) {
comp_err(dev, "config size %u misaligned or too small", config->size);
return -EINVAL;
}
*coef_words_max = payload_bytes / sizeof(int32_t) - config->channels_in_config;
return 0;
}

static int eq_iir_init_response(struct comp_dev *dev, int idx,
int32_t *coef_data, uint32_t coef_words_max,
uint32_t *j, struct sof_eq_iir_header **eq_out)
{
struct sof_eq_iir_header *eq;
uint32_t header_end = *j + SOF_EQ_IIR_NHEADER;
uint32_t section_end;

/* Header must fit before reading num_sections */
if (header_end > coef_words_max) {
comp_err(dev, "response %d header out of bounds", idx);
return -EINVAL;
}
eq = (struct sof_eq_iir_header *)&coef_data[*j];
/* Bound num_sections so the multiply cannot overflow and the section
* data stays within the blob.
*/
section_end = header_end + (uint32_t)SOF_EQ_IIR_NBIQUAD * eq->num_sections;
if (eq->num_sections > SOF_EQ_IIR_BIQUADS_MAX || section_end > coef_words_max) {
comp_err(dev, "response %d num_sections %u out of bounds",
idx, eq->num_sections);
return -EINVAL;
}
*eq_out = eq;
*j = section_end;
return 0;
}

static int eq_iir_init_coef(struct processing_module *mod, int nch)
{
struct comp_data *cd = module_get_private_data(mod);
struct sof_eq_iir_config *config = cd->config;
struct iir_state_df1 *iir = cd->iir;
struct sof_eq_iir_header *lookup[SOF_EQ_IIR_MAX_RESPONSES];
struct sof_eq_iir_header *eq;
uint32_t coef_words_max;
int32_t *assign_response;
int32_t *coef_data;
int size_sum = 0;
int resp = 0;
int i;
int j;
uint32_t j;
int s;
int ret;

comp_info(mod->dev, "%u responses, %u channels, stream %d channels",
config->number_of_responses, config->channels_in_config, nch);
Expand All @@ -210,17 +267,21 @@ static int eq_iir_init_coef(struct processing_module *mod, int nch)
return -EINVAL;
}

ret = eq_iir_blob_words_max(mod->dev, config, &coef_words_max);
if (ret < 0)
return ret;

/* Collect index of response start positions in all_coefficients[] */
j = 0;
assign_response = ASSUME_ALIGNED(&config->data[0], 4);
coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config],
4);
coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config], 4);
for (i = 0; i < SOF_EQ_IIR_MAX_RESPONSES; i++) {
if (i < config->number_of_responses) {
eq = (struct sof_eq_iir_header *)&coef_data[j];
ret = eq_iir_init_response(mod->dev, i, coef_data,
coef_words_max, &j, &eq);
if (ret < 0)
return ret;
lookup[i] = eq;
j += SOF_EQ_IIR_NHEADER
+ SOF_EQ_IIR_NBIQUAD * eq->num_sections;
} else {
lookup[i] = NULL;
}
Expand Down Expand Up @@ -315,6 +376,11 @@ int eq_iir_setup(struct processing_module *mod, int nch)
struct comp_data *cd = module_get_private_data(mod);
int delay_size;

if (cd->config->size != cd->config_size) {
comp_err(mod->dev, "Incorrect configuration blob size");
return -EINVAL;
}
Comment thread
singalsu marked this conversation as resolved.
Comment on lines +379 to +382

/* Free existing IIR channels data if it was allocated */
eq_iir_free_delaylines(mod);

Expand Down
8 changes: 6 additions & 2 deletions src/math/iir_df1.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

int iir_delay_size_df1(struct sof_eq_iir_header *config)
{
int n = config->num_sections; /* One section uses two unit delays */
uint32_t n = config->num_sections; /* One section uses four unit delays */

if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1)
if (!n || n > SOF_EQ_IIR_BIQUADS_MAX)
return -EINVAL;

if (!config->num_sections_in_series ||
config->num_sections_in_series > n)
return -EINVAL;

return 4 * n * sizeof(int32_t);
Expand Down
8 changes: 6 additions & 2 deletions src/math/iir_df2t.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

int iir_delay_size_df2t(struct sof_eq_iir_header *config)
{
int n = config->num_sections; /* One section uses two unit delays */
uint32_t n = config->num_sections; /* One section uses two unit delays */

if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1)
if (!n || n > SOF_EQ_IIR_BIQUADS_MAX)
return -EINVAL;

if (!config->num_sections_in_series ||
config->num_sections_in_series > n)
return -EINVAL;

return 2 * n * sizeof(int64_t);
Expand Down
Loading