diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index 18f20311e147..860d5b1b279b 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -124,9 +124,9 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, 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); -int system_agent_start(uint32_t entry_point, uint32_t module_id, uint32_t instance_id, +int system_agent_start(uintptr_t entry_point, uint32_t module_id, uint32_t instance_id, uint32_t core_id, uint32_t log_handle, void* mod_cfg, - void **adapter) + const void **adapter) { uint32_t ret; SystemAgent system_agent(module_id, instance_id, core_id, log_handle); diff --git a/src/audio/module_adapter/library/native_system_agent.c b/src/audio/module_adapter/library/native_system_agent.c index 9704da50739e..9a93af6f3565 100644 --- a/src/audio/module_adapter/library/native_system_agent.c +++ b/src/audio/module_adapter/library/native_system_agent.c @@ -19,17 +19,24 @@ typedef void* (*native_create_instance_f)(void *mod_cfg, void *parent_ppl, struct native_system_agent native_sys_agent; -void *native_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 native_system_agent_start(uintptr_t entry_point, uint32_t module_id, uint32_t instance_id, + uint32_t core_id, uint32_t log_handle, void *mod_cfg, + const void **iface) { native_sys_agent.module_id = module_id; native_sys_agent.instance_id = instance_id; native_sys_agent.core_id = core_id; native_sys_agent.log_handle = log_handle; + const void *ret; void *system_agent_p = &native_sys_agent; native_create_instance_f ci = (native_create_instance_f)entry_point; - return ci(mod_cfg, NULL, &system_agent_p); + ret = ci(mod_cfg, NULL, &system_agent_p); + if (!ret) + return -EINVAL; + + *iface = ret; + return 0; } diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 47fd8af6b217..c7a22f372e3d 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -56,46 +55,16 @@ static int modules_init(struct processing_module *mod) { struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; - 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 *adapter; - int ret; - - uintptr_t module_entry_point = lib_manager_allocate_module(config, src_cfg); - - if (module_entry_point == 0) { - comp_err(dev, "modules_init(), lib_manager_allocate_module() failed!"); - return -EINVAL; - } /* At this point module resources are allocated and it is moved to L2 memory. */ comp_info(dev, "modules_init() start"); - const uint32_t module_id = IPC4_MOD_ID(config->id); - const uint32_t instance_id = IPC4_INST_ID(config->id); - const uint32_t log_handle = (uint32_t)drv->tctx; - - byte_array_t mod_cfg = { - .data = (uint8_t *)md->cfg.init_data, - /* Intel modules expects DW size here */ - .size = md->cfg.size >> 2, - }; - - 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, 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(adapter); + return iadk_wrapper_init(module_get_private_data(mod)); } /** diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 45dab7b02e19..71cb80970172 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -34,12 +34,31 @@ LOG_MODULE_REGISTER(module_adapter, CONFIG_SOF_LOG_LEVEL); * \param[in] drv - component driver pointer. * \param[in] config - component ipc descriptor pointer. * \param[in] spec - passdowned data from driver. + * \param[in] mod_priv - Pointer to private data for processing module. * * \return: a pointer to newly created module adapter component on success. NULL on error. */ struct comp_dev *module_adapter_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) + const struct comp_ipc_config *config, const void *spec) +{ + return module_adapter_new_ext(drv, config, spec, NULL); +} + +/* + * \brief Create a module adapter component. + * \param[in] drv - component driver pointer. + * \param[in] config - component ipc descriptor pointer. + * \param[in] spec - passdowned data from driver. + * \param[in] mod_priv - Pointer to private data for processing module. + * + * \return: a pointer to newly created module adapter component on success. NULL on error. + * + * Note: Use the ext version if you need to set the module's private data before calling + * the create method. + */ +struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec, + void *mod_priv) { int ret; struct comp_dev *dev; @@ -79,6 +98,7 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv, dst = &mod->priv.cfg; + module_set_private_data(mod, mod_priv); mod->dev = dev; dev->mod = mod; 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 65afd2f82c14..a0470167c796 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_agent.h +++ b/src/include/sof/audio/module_adapter/iadk/system_agent.h @@ -107,8 +107,8 @@ extern "C" { * 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); +int system_agent_start(uintptr_t entry_point, uint32_t module_id, uint32_t instance_id, + uint32_t core_id, uint32_t log_handle, void *mod_cfg, const void **adapter); #ifdef __cplusplus } #endif diff --git a/src/include/sof/audio/module_adapter/library/native_system_agent.h b/src/include/sof/audio/module_adapter/library/native_system_agent.h index 7faf802debe1..657bc6ac643d 100644 --- a/src/include/sof/audio/module_adapter/library/native_system_agent.h +++ b/src/include/sof/audio/module_adapter/library/native_system_agent.h @@ -11,6 +11,10 @@ #include #include +typedef int (*system_agent_start_fn)(uintptr_t entry_point, uint32_t module_id, + uint32_t instance_id, uint32_t core_id, uint32_t log_handle, + void *mod_cfg, const void **adapter); + struct native_system_agent { struct system_service system_service; uint32_t log_handle; @@ -20,7 +24,23 @@ struct native_system_agent { uint32_t module_size; }; -void *native_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); +/** + * @brief Starts the native system agent. + * + * This function initializes and starts the native system agent with the provided parameters. + * + * @param[in] entry_point - The module entry point function address. + * @param[in] module_id - The identifier for the module. + * @param[in] instance_id - The instance identifier of the module. + * @param[in] core_id - Core on which the module will run. + * @param[in] log_handle - The handle for logging purposes. + * @param[in] mod_cfg - Pointer to the module configuration data. + * @param[out] iface - Pointer to the module interface. + * + * @return Returns 0 on success or an error code on failure. + */ +int native_system_agent_start(uintptr_t entry_point, uint32_t module_id, uint32_t instance_id, + uint32_t core_id, uint32_t log_handle, void *mod_cfg, + const void **iface); #endif /* __NATIVE_SYSTEM_AGENT_H__ */ diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index bff6aa420629..9baa118a6c06 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -209,6 +209,9 @@ int module_unbind(struct processing_module *mod, struct bind_info *unbind_data); struct comp_dev *module_adapter_new(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec); +struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec, + void *mod_priv); int module_adapter_prepare(struct comp_dev *dev); int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params); int module_adapter_copy(struct comp_dev *dev); diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 24e5b7bddb52..f9b7f16c0b0c 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -63,6 +63,8 @@ #define __SOF_LIB_MANAGER_H__ #include +#include +#include #include #if CONFIG_LIBRARY_AUTH_SUPPORT #include @@ -71,9 +73,9 @@ #define LIB_MANAGER_MAX_LIBS 16 #define LIB_MANAGER_LIB_ID_SHIFT 12 -#define LIB_MANAGER_LIB_NOTIX_MAX_COUNT 4 +#define LIB_MANAGER_LIB_NOTIX_MAX_COUNT 4 -#define LIB_MANAGER_GET_LIB_ID(module_id) ((module_id) >> LIB_MANAGER_LIB_ID_SHIFT) +#define LIB_MANAGER_GET_LIB_ID(module_id) (((module_id) & 0xF000) >> LIB_MANAGER_LIB_ID_SHIFT) #define LIB_MANAGER_GET_MODULE_INDEX(module_id) ((module_id) & 0xFFF) #ifdef CONFIG_LIBRARY_MANAGER @@ -184,21 +186,6 @@ int lib_manager_register_module(const uint32_t component_id); */ const struct sof_man_fw_desc *lib_manager_get_library_manifest(int module_id); -struct processing_module; -struct comp_ipc_config; -/* - * \brief Allocate module - * - * param[in] drv - component driver - * param[in] ipc_config - audio component base configuration from IPC at creation - * param[in] ipc_specific_config - ipc4 base configuration - * - * Function is responsible to allocate module in available free memory and assigning proper address. - * (WIP) These feature will contain module validation and proper memory management. - */ -uintptr_t lib_manager_allocate_module(const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config); - /* * \brief Free module * diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index beca55af22f1..c153c61a308b 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -142,8 +143,7 @@ static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_ return sys_mm_drv_update_region_flags((__sparse_force void *)vma, size, flags); } -static int lib_manager_load_module(const uint32_t module_id, - const struct sof_man_module *const mod) +static int lib_manager_load_module(const uint32_t module_id, const struct sof_man_module *const mod) { struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); const uintptr_t load_offset = POINTER_TO_UINT(ctx->base_addr); @@ -325,22 +325,25 @@ static int lib_manager_free_module_instance(uint32_t instance_id, const struct s return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); } -uintptr_t lib_manager_allocate_module(const struct comp_ipc_config *ipc_config, - const void *ipc_specific_config) +/* + * \brief Allocate module + * + * param[in] mod - module manifest + * param[in] ipc_config - audio component base configuration from IPC at creation + * param[in] ipc_specific_config - ipc4 base configuration + * + * Function is responsible to allocate module in available free memory and assigning proper address. + */ +static uintptr_t lib_manager_allocate_module(const struct sof_man_module *mod, + const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) { - const struct sof_man_module *mod; const struct ipc4_base_module_cfg *base_cfg = ipc_specific_config; const uint32_t module_id = IPC4_MOD_ID(ipc_config->id); int ret; tr_dbg(&lib_manager_tr, "mod_id: %#x", ipc_config->id); - mod = lib_manager_get_module_manifest(module_id); - if (!mod) { - tr_err(&lib_manager_tr, "failed to get module descriptor"); - return 0; - } - if (module_is_llext(mod)) return llext_manager_allocate_module(ipc_config, ipc_specific_config); @@ -480,6 +483,88 @@ const struct sof_man_module *lib_manager_get_module_manifest(const uint32_t modu SOF_MAN_MODULE_OFFSET(entry_index)); } +/** + * \brief Starts system agent and returns module interface into agent_interface variable. + * + * \param[in] drv - Pointer to the component driver structure. + * \param[in] component_id - Identifier of the component. + * \param[in] args - Pointer to components' ipc configuration arguments. + * \param[in] module_entry_point - Entry point address of the module. + * \param[in] agent - Function pointer to the system agent start function. + * \param[out] agent_interface - Pointer to store the module interface returned by the system agent. + * + * \return Error code returned by the system agent, 0 on success. + */ +static int lib_manager_start_agent(const struct comp_driver *drv, const uint32_t component_id, + const struct ipc_config_process *args, + const uintptr_t module_entry_point, + const system_agent_start_fn agent, + const void **agent_interface) +{ + const uint32_t module_id = IPC4_MOD_ID(component_id); + const uint32_t instance_id = IPC4_INST_ID(component_id); + const uint32_t log_handle = (uint32_t)drv->tctx; + byte_array_t mod_cfg; + int ret; + + mod_cfg.data = (uint8_t *)args->data; + /* Intel modules expects DW size here */ + mod_cfg.size = args->size >> 2; + + ret = agent(module_entry_point, module_id, instance_id, 0, log_handle, &mod_cfg, + agent_interface); + if (ret) + tr_err(&lib_manager_tr, "System agent start failed %d!", ret); + + return ret; +} + +enum buildinfo_mod_type { MOD_TYPE_INVALID, MOD_TYPE_IADK, MOD_TYPE_LMDK, MOD_TYPE_LLEXT }; + +/** + * \brief Get module type based on its build information. + * + * \param[in] desc - Pointer to the firmware descriptor containing module information. + * \param[in] mod - Pointer to the module manifest structure. + * + * \return The type of the module as an enum value. + */ +static enum buildinfo_mod_type lib_manager_get_module_type(const struct sof_man_fw_desc *const desc, + const struct sof_man_module *mod) +{ + const struct sof_module_api_build_info *const build_info = + (const struct sof_module_api_build_info *)((const char *)desc - + SOF_MAN_ELF_TEXT_OFFSET + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + /* + * llext modules store build info structure in separate section which is not accessible now. + */ + if (module_is_llext(mod)) + return MOD_TYPE_LLEXT; + + tr_info(&lib_manager_tr, "Module API version: %u.%u.%u, format: 0x%x", + build_info->api_version_number.fields.major, + build_info->api_version_number.fields.middle, + build_info->api_version_number.fields.minor, + build_info->format); + + /* Check if module is IADK */ + if (IS_ENABLED(CONFIG_INTEL_MODULES) && + build_info->format == IADK_MODULE_API_BUILD_INFO_FORMAT && + build_info->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { + return MOD_TYPE_IADK; + } else { + /* Check if module is NOT native */ + if (build_info->format != SOF_MODULE_API_BUILD_INFO_FORMAT || + build_info->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, "Unsupported module API version"); + return MOD_TYPE_INVALID; + } + + return MOD_TYPE_LMDK; + } +} + /* * \brief Load module code, allocate its instance and create a module adapter component. * \param[in] drv - component driver pointer. @@ -492,50 +577,74 @@ static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec) { + const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(config->id); const struct ipc_config_process *args = (struct ipc_config_process *)spec; - const uint32_t module_id = IPC4_MOD_ID(config->id); - const uint32_t instance_id = IPC4_INST_ID(config->id); - const uint32_t log_handle = (uint32_t)drv->tctx; - byte_array_t mod_cfg; - - /* - * Variable used by llext_manager to temporary store llext handle before creation - * a instance of processing_module. - */ + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(config->id); + const struct module_interface *ops = NULL; + const struct sof_man_module *mod; + system_agent_start_fn agent; + void *adapter_priv = NULL; + const void **agent_iface; struct comp_dev *dev; + int ret; - /* At this point module resources are allocated and it is moved to L2 memory. */ - const uint32_t module_entry_point = lib_manager_allocate_module(config, - args->data); - - if (!module_entry_point) { - tr_err(&lib_manager_tr, "lib_manager_allocate_module() failed!"); + tr_dbg(&lib_manager_tr, "start"); + if (!desc) { + tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.", + config->id); return NULL; } - tr_dbg(&lib_manager_tr, "start"); - mod_cfg.data = (uint8_t *)args->data; - /* Intel modules expects DW size here */ - mod_cfg.size = args->size >> 2; - - const struct module_interface *ops = native_system_agent_start(module_entry_point, - module_id, instance_id, - 0, log_handle, &mod_cfg); + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Entry index %u out of bounds.", entry_index); + return NULL; + } - if (!ops) { - lib_manager_free_module(module_id); - tr_err(&lib_manager_tr, "native_system_agent_start failed!"); + mod = (const struct sof_man_module *) + ((const uint8_t *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); + + switch (lib_manager_get_module_type(desc, mod)) { + case MOD_TYPE_LLEXT: + case MOD_TYPE_LMDK: + agent = &native_system_agent_start; + agent_iface = (const void **)&ops; + break; + case MOD_TYPE_IADK: + agent = &system_agent_start; + /* processing_module_adapter_interface is already assigned to drv->adapter_ops by + * the lib_manager_prepare_module_adapter function. + */ + agent_iface = (const void **)&adapter_priv; + break; + case MOD_TYPE_INVALID: return NULL; } - if (comp_set_adapter_ops(drv, ops) < 0) + const uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, args->data); + if (!module_entry_point) { + tr_err(&lib_manager_tr, "lib_manager_allocate_module() failed!"); return NULL; + } - dev = module_adapter_new(drv, config, spec); + /* At this point module resources are allocated and it is moved to L2 memory. */ + + ret = lib_manager_start_agent(drv, config->id, args, module_entry_point, agent, + agent_iface); + if (ret) + goto err; + + if (ops && comp_set_adapter_ops(drv, ops) < 0) + goto err; + + dev = module_adapter_new_ext(drv, config, spec, adapter_priv); if (!dev) - lib_manager_free_module(module_id); + goto err; return dev; + +err: + lib_manager_free_module(config->id); + return NULL; } static void lib_manager_module_free(struct comp_dev *dev) @@ -588,33 +697,25 @@ static void lib_manager_prepare_module_adapter(struct comp_driver *drv, const st int lib_manager_register_module(const uint32_t component_id) { - const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(component_id); - const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(component_id); - const struct sof_module_api_build_info *build_info; struct comp_driver_info *new_drv_info; struct comp_driver *drv = NULL; - const struct sof_man_module *mod; + const struct sof_man_module *mod = lib_manager_get_module_manifest(component_id); + const struct sof_uuid *uid = (struct sof_uuid *)&mod->uuid; int ret; - if (!desc) { + if (!mod) { tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.", component_id); return -ENOENT; } - if (entry_index >= desc->header.num_module_entries) { - tr_err(&lib_manager_tr, "Entry index %u out of bounds.", entry_index); - return -ENOENT; - } - /* allocate new comp_driver_info */ new_drv_info = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(struct comp_driver_info)); if (!new_drv_info) { tr_err(&lib_manager_tr, "failed to allocate comp_driver_info"); - ret = -ENOMEM; - goto cleanup; + return -ENOMEM; } drv = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, @@ -625,43 +726,8 @@ int lib_manager_register_module(const uint32_t component_id) goto cleanup; } - mod = (const struct sof_man_module *)((const uint8_t *)desc + - SOF_MAN_MODULE_OFFSET(entry_index)); - const struct sof_uuid *uid = (const struct sof_uuid *)&mod->uuid; - lib_manager_prepare_module_adapter(drv, uid); - /* - * llext modules store build info structure in separate section which is not accessible now. - */ - if (!module_is_llext(mod)) { - build_info = (const struct sof_module_api_build_info *)((const char *)desc - - SOF_MAN_ELF_TEXT_OFFSET + - mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); - - tr_info(&lib_manager_tr, "Module API version: %u.%u.%u, format: 0x%x", - build_info->api_version_number.fields.major, - build_info->api_version_number.fields.middle, - build_info->api_version_number.fields.minor, - build_info->format); - - /* Check if module is IADK */ - if (IS_ENABLED(CONFIG_INTEL_MODULES) && - build_info->format == IADK_MODULE_API_BUILD_INFO_FORMAT && - build_info->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { - /* Use module_adapter functions */ - drv->ops.create = module_adapter_new; - } else { - /* Check if module is NOT native */ - if (build_info->format != SOF_MODULE_API_BUILD_INFO_FORMAT || - build_info->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { - tr_err(&lib_manager_tr, "Unsupported module API version"); - ret = -ENOEXEC; - goto cleanup; - } - } - } - /* Fill the new_drv_info structure with already known parameters */ new_drv_info->drv = drv; new_drv_info->adapter_ops = &drv->adapter_ops;