diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index 643de03b0cd9..18f20311e147 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -118,17 +118,15 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, } /* namespace system */ } /* namespace intel_adsp */ -#ifdef __cplusplus -extern "C" { -#endif /* The create_instance_f is a function call type known in IADK module. The module entry_point * points to this type of function which starts module creation. */ typedef int (*create_instance_f)(uint32_t module_id, uint32_t instance_id, uint32_t core_id, void *mod_cfg, void *parent_ppl, void **mod_ptr); -void* system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t instance_id, - uint32_t core_id, uint32_t log_handle, void* mod_cfg) +int system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t instance_id, + uint32_t core_id, uint32_t log_handle, void* mod_cfg, + void **adapter) { uint32_t ret; SystemAgent system_agent(module_id, instance_id, core_id, log_handle); @@ -137,13 +135,11 @@ void* system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t inst create_instance_f ci = (create_instance_f)(entry_point); ret = ci(module_id, instance_id, core_id, mod_cfg, NULL, &system_agent_p); - return system_agent_p; + IadkModuleAdapter* module_adapter = reinterpret_cast(system_agent_p); + *adapter = module_adapter; + return ret; } -#ifdef __cplusplus -} -#endif - extern "C" void __cxa_pure_virtual() __attribute__((weak)); void __cxa_pure_virtual() diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 9ad88d5a5bb7..690f111fb0bc 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -59,7 +59,8 @@ static int modules_init(struct processing_module *mod) const struct comp_driver *const drv = dev->drv; const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; const struct comp_ipc_config *config = &dev->ipc_config; - void *system_agent; + void *adapter; + int ret; uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, src_cfg); @@ -81,16 +82,20 @@ static int modules_init(struct processing_module *mod) .size = md->cfg.size >> 2, }; - system_agent = system_agent_start(module_entry_point, module_id, instance_id, 0, log_handle, - &mod_cfg); + ret = system_agent_start(module_entry_point, module_id, instance_id, 0, log_handle, + &mod_cfg, &adapter); + if (ret) { + comp_info(dev, "System agent failed"); + return ret; + } - module_set_private_data(mod, system_agent); + module_set_private_data(mod, adapter); md->mpd.in_buff_size = src_cfg->ibs; md->mpd.out_buff_size = src_cfg->obs; mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; - return iadk_wrapper_init(system_agent); + return iadk_wrapper_init(adapter); } /** diff --git a/src/include/sof/audio/module_adapter/iadk/api_version.h b/src/include/sof/audio/module_adapter/iadk/api_version.h index bd05e49d7239..4d6be24e461d 100644 --- a/src/include/sof/audio/module_adapter/iadk/api_version.h +++ b/src/include/sof/audio/module_adapter/iadk/api_version.h @@ -19,4 +19,10 @@ #define IADK_MODULE_API_CURRENT_VERSION MODULE_API_VERSION_ENCODE(IADK_MODULE_API_MAJOR_VERSION, \ IADK_MODULE_API_MIDDLE_VERSION, IADK_MODULE_API_MINOR_VERSION) +/* Defines the size of the space reserved within ModuleHandle for SOF to store its private data. + * This size comes from the IADK header files and must match the IADK API version. + * Please do not modify this value! + */ +#define IADK_MODULE_PASS_BUFFER_SIZE 320 + #endif /* __MODULE_ADAPTER_IADK_API_VERSION_H__ */ diff --git a/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h b/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h index b14cf169c909..67ac69f46d08 100644 --- a/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h +++ b/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -112,6 +114,8 @@ namespace dsp_fw intel_adsp::ProcessingModuleInterface &processing_module_; }; +STATIC_ASSERT(sizeof(IadkModuleAdapter) <= IADK_MODULE_PASS_BUFFER_SIZE, IadkModuleAdapter_too_big); + } /* namespace dsp_fw */ } /* extern "C" */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_agent.h b/src/include/sof/audio/module_adapter/iadk/system_agent.h index ff2dcfbc9b5e..65afd2f82c14 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_agent.h +++ b/src/include/sof/audio/module_adapter/iadk/system_agent.h @@ -72,8 +72,43 @@ namespace system #ifdef __cplusplus extern "C" { #endif -void *system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t instance_id, - uint32_t core_id, uint32_t log_handle, void *mod_cfg); +/* + * The process of loading a IADK module is quite complicated. The function call stack is as follows: + * + * 1. IADK module adapter initialization function (modules_init) pass module entry point to the + * system_agent_start function. + * + * 2. system_agent_start: This function creates an instance of the SystemAgent class on the stack + * and then calls the module entry point function (ModuleEntryPoint) passing a pointer to the + * SystemAgent object as a parameter. + * + * 3. ModuleEntryPoint(system_agent): Creates a ModuleFactory object of the module on the stack + * (inheriting from ProcessingModuleFactoryInterface) and then calls the + * LoadableModuleMain(system_agent, module_factory, placeholder) function, which is the default + * entry point for all IADK modules. Placeholder is part of the .bss section intended for + * a given module instance, with its address is determined based on the instance ID. + * + * 4. LoadableModuleMain(system_agent, module_factory, placeholder): Calls the CheckIn method + * (variant with 7 parameters) of the SystemAgent class. + * + * 5. SystemAgent.CheckIn(7): Calls the Create method from the ModuleFactory object. + * + * 6. ModuleFactory.Create(system_agent, placeholder): Creates an instance of the module class + * (inheriting from ProcessingModule) at the address pointed to by placeholder. + * The ProcessingModule class contains a module_handle field, which reserves an area in memory + * of size IADK_MODULE_PASS_BUFFER_SIZE bytes. The constructor of this class calls the CheckIn + * method (the variant with 3 parameters) from the SystemAgent class, passing a pointer to self + * and a pointer to module_handle. + * + * 7. SystemAgent.CheckIn(3): Stores the address of module_handle in a private variable and + * creates an instance of the IadkModuleAdapter class in this location. + * + * The saved address of the module_handle (the adapter's IADK instance) is returned in the CheckIn + * method (the variant with 7 parameters) via a parameter that initially contained the address to + * the agent system. The system_agent_start function returns it in the variable adapter. + */ +int system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t instance_id, + uint32_t core_id, uint32_t log_handle, void *mod_cfg, void **adapter); #ifdef __cplusplus } #endif