@@ -211,6 +211,26 @@ static int eq_iir_blob_words_max(struct comp_dev *dev,
211211 return 0 ;
212212}
213213
214+ /**
215+ * @brief Parse one response header from the coefficient blob.
216+ *
217+ * Reads the response at word offset *j in @p coef_data, checks that both
218+ * the fixed header and the following biquad sections fit inside the
219+ * @p coef_words_max blob budget, and advances *j past this response so
220+ * the next call continues where this one left off. On success @p *eq_out
221+ * is set to point at the in-place header; callers that only want to walk
222+ * the blob for validation can discard that pointer.
223+ *
224+ * @param dev Component device, used for error logging.
225+ * @param idx Response index, used in error messages.
226+ * @param coef_data Base of the coefficient word array in the blob.
227+ * @param coef_words_max Total words available in @p coef_data.
228+ * @param j In/out cursor in words; advanced past this response.
229+ * @param eq_out Out; pointer to the parsed response header.
230+ *
231+ * @return 0 on success, -EINVAL if the header or sections would run off
232+ * the end of the blob or num_sections exceeds the platform limit.
233+ */
214234static int eq_iir_init_response (struct comp_dev * dev , int idx ,
215235 int32_t * coef_data , uint32_t coef_words_max ,
216236 uint32_t * j , struct sof_eq_iir_header * * eq_out )
@@ -239,59 +259,120 @@ static int eq_iir_init_response(struct comp_dev *dev, int idx,
239259 return 0 ;
240260}
241261
242- static int eq_iir_init_coef (struct processing_module * mod , int nch )
262+ /* Validate the config blob layout and, if lookup is non-NULL, populate it
263+ * with pointers to each response header. Pass lookup = NULL to validate only.
264+ */
265+ static int eq_iir_walk_config (struct comp_dev * dev ,
266+ struct sof_eq_iir_config * config ,
267+ size_t config_size ,
268+ struct sof_eq_iir_header * * lookup )
243269{
244- struct comp_data * cd = module_get_private_data (mod );
245- struct sof_eq_iir_config * config = cd -> config ;
246- struct iir_state_df1 * iir = cd -> iir ;
247- struct sof_eq_iir_header * lookup [SOF_EQ_IIR_MAX_RESPONSES ];
248270 struct sof_eq_iir_header * eq ;
249271 uint32_t coef_words_max ;
250- int32_t * assign_response ;
251272 int32_t * coef_data ;
252- int size_sum = 0 ;
253- int resp = 0 ;
273+ int ret ;
254274 int i ;
255275 uint32_t j ;
256- int s ;
257- int ret ;
258-
259- comp_info (mod -> dev , "%u responses, %u channels, stream %d channels" ,
260- config -> number_of_responses , config -> channels_in_config , nch );
261276
262- /* Sanity checks */
263- if (nch > PLATFORM_MAX_CHANNELS ||
264- config -> channels_in_config > PLATFORM_MAX_CHANNELS ||
277+ if (config -> channels_in_config > PLATFORM_MAX_CHANNELS ||
265278 !config -> channels_in_config ) {
266- comp_err (mod -> dev , "invalid channels count" );
279+ comp_err (dev , "invalid channels_in_config %u" , config -> channels_in_config );
267280 return - EINVAL ;
268281 }
269282 if (config -> number_of_responses > SOF_EQ_IIR_MAX_RESPONSES ) {
270- comp_err (mod -> dev , "# of resp exceeds max" );
283+ comp_err (dev , "# of resp %u exceeds max" , config -> number_of_responses );
271284 return - EINVAL ;
272285 }
273286
274- ret = eq_iir_blob_words_max (mod -> dev , config , cd -> config_size , & coef_words_max );
287+ ret = eq_iir_blob_words_max (dev , config , config_size , & coef_words_max );
275288 if (ret < 0 )
276289 return ret ;
277290
278- /* Collect index of response start positions in all_coefficients[] */
279291 j = 0 ;
280- assign_response = ASSUME_ALIGNED (& config -> data [0 ], 4 );
281292 coef_data = ASSUME_ALIGNED (& config -> data [config -> channels_in_config ], 4 );
282- for (i = 0 ; i < SOF_EQ_IIR_MAX_RESPONSES ; i ++ ) {
283- if (i < config -> number_of_responses ) {
284- ret = eq_iir_init_response (mod -> dev , i , coef_data ,
285- coef_words_max , & j , & eq );
286- if (ret < 0 )
287- return ret ;
293+ if (lookup )
294+ memset (lookup , 0 , SOF_EQ_IIR_MAX_RESPONSES * sizeof (* lookup ));
295+
296+ for (i = 0 ; i < config -> number_of_responses ; i ++ ) {
297+ /* Bounds-check response i, advance the walk cursor j past it,
298+ * and get a pointer to its in-place header. Stored in lookup[]
299+ * for later use, or discarded when we are walking the blob
300+ * only to validate it.
301+ */
302+ ret = eq_iir_init_response (dev , i , coef_data , coef_words_max , & j , & eq );
303+ if (ret < 0 )
304+ return ret ;
305+ if (lookup )
288306 lookup [i ] = eq ;
289- } else {
290- lookup [i ] = NULL ;
307+ }
308+
309+ return 0 ;
310+ }
311+
312+ int eq_iir_validate_config (struct comp_dev * dev , void * new_data , uint32_t new_data_size )
313+ {
314+ struct sof_eq_iir_config * config = new_data ;
315+ int32_t * assign_response ;
316+ int32_t resp ;
317+ int ret ;
318+ int i ;
319+
320+ if (new_data_size < sizeof (struct sof_eq_iir_config ) ||
321+ new_data_size > SOF_EQ_IIR_MAX_SIZE ) {
322+ comp_err (dev , "invalid configuration blob, size %u" , new_data_size );
323+ return - EINVAL ;
324+ }
325+
326+ ret = eq_iir_walk_config (dev , config , new_data_size , NULL );
327+ if (ret < 0 )
328+ return ret ;
329+
330+ /* Validate every assign_response[] entry that the per-channel loop in
331+ * eq_iir_init_coef() could pick up. Entries beyond channels_in_config
332+ * reuse the last assigned value, so checking [0, channels_in_config)
333+ * covers all reachable nch.
334+ */
335+ assign_response = ASSUME_ALIGNED (& config -> data [0 ], 4 );
336+ for (i = 0 ; i < config -> channels_in_config ; i ++ ) {
337+ resp = assign_response [i ];
338+ if (resp >= 0 && resp >= config -> number_of_responses ) {
339+ comp_err (dev , "assign_response[%d] = %d exceeds %u" ,
340+ i , resp , config -> number_of_responses );
341+ return - EINVAL ;
291342 }
292343 }
293344
345+ return 0 ;
346+ }
347+
348+ static int eq_iir_init_coef (struct processing_module * mod , int nch )
349+ {
350+ struct comp_data * cd = module_get_private_data (mod );
351+ struct sof_eq_iir_config * config = cd -> config ;
352+ struct iir_state_df1 * iir = cd -> iir ;
353+ struct sof_eq_iir_header * lookup [SOF_EQ_IIR_MAX_RESPONSES ];
354+ struct sof_eq_iir_header * eq ;
355+ int32_t * assign_response ;
356+ int size_sum = 0 ;
357+ int resp = 0 ;
358+ int i ;
359+ int s ;
360+ int ret ;
361+
362+ comp_info (mod -> dev , "%u responses, %u channels, stream %d channels" ,
363+ config -> number_of_responses , config -> channels_in_config , nch );
364+
365+ if (nch > PLATFORM_MAX_CHANNELS ) {
366+ comp_err (mod -> dev , "invalid stream channels %d" , nch );
367+ return - EINVAL ;
368+ }
369+
370+ ret = eq_iir_walk_config (mod -> dev , config , cd -> config_size , lookup );
371+ if (ret < 0 )
372+ return ret ;
373+
294374 /* Initialize 1st phase */
375+ assign_response = ASSUME_ALIGNED (& config -> data [0 ], 4 );
295376 for (i = 0 ; i < nch ; i ++ ) {
296377 /* Check for not reading past blob response to channel assign
297378 * map. The previous channel response is assigned for any
0 commit comments