From 19fc74ff67e9c19527b3bf8e3e1b98d37ad41e37 Mon Sep 17 00:00:00 2001 From: Gaggery Tsai Date: Thu, 23 Jul 2026 11:02:00 -0700 Subject: [PATCH 01/10] audio: iadk: accept module API 4.5.2 Accept IADK module API 4.5.2 in addition to 4.5.0. Extend the detector and system-agent vtables and append the versioned system-service lookup slot without changing earlier slots. This only establishes the 4.5.2 ABI. Services unavailable in the base firmware return an error and clear the interface pointer. Signed-off-by: Gaggery Tsai --- src/audio/module_adapter/iadk/README.md | 6 ++++ .../module_adapter/iadk/system_agent.cpp | 31 ++++++++++++++++++- .../library/native_system_service.c | 18 +++++++++-- src/include/module/module/system_service.h | 6 +++- .../audio/module_adapter/iadk/api_version.h | 5 ++- .../iadk/processing_module_interface.h | 4 +++ .../audio/module_adapter/iadk/system_agent.h | 11 ++++++- .../iadk/system_agent_interface.h | 8 +++++ .../library/native_system_service.h | 12 +++++++ src/library_manager/lib_manager.c | 3 +- 10 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/audio/module_adapter/iadk/README.md b/src/audio/module_adapter/iadk/README.md index d04ea1924bd8..ba77e533dadd 100644 --- a/src/audio/module_adapter/iadk/README.md +++ b/src/audio/module_adapter/iadk/README.md @@ -50,6 +50,12 @@ classDiagram Because the actual module resides in an external binary, it requires a "System Agent" to correctly instantiate the C++ objects during the component's `init` phase. +The adapter accepts IADK API 4.5.0 and 4.5.2 binaries. API 4.5.2 +extends the detector interface with `WritePattern()`, adds +`SystemAgentInterface3::GetBssBase()`, and appends a versioned lookup +entry to the system service table. The existing table and vtable slots +keep their API 4.5.0 layout. + 1. The OS host driver sends an IPC `INIT_INSTANCE` command for the module. 2. The `system_agent_start()` function intercepts this, invokes the dynamic module's `create_instance` entry point (which invokes a `ModuleFactory`). 3. The `SystemAgent` deduces the pin count (interfaces) and initial pipeline configurations using `ModuleInitialSettingsConcrete`. diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index 7f5bc63a9559..390c56767fa2 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -24,6 +24,14 @@ #include #include +struct sof_man_module; +extern "C" const struct sof_man_module * +lib_manager_get_module_manifest(const uint32_t module_id); +extern "C" void +lib_manager_get_instance_bss_address(uint32_t instance_id, + const struct sof_man_module *mod, + void **va_addr, size_t *size); + using namespace intel_adsp; using namespace intel_adsp::system; using namespace dsp_fw; @@ -47,6 +55,7 @@ const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = { native_system_service_create_notification, native_system_service_send_notif_msg, native_system_service_get_interface, + native_system_service_get_interface_versioned, }; SystemAgent::SystemAgent(uint32_t module_id, @@ -79,6 +88,27 @@ void SystemAgent::CheckIn(ProcessingModuleInterface& processing_module, log_handle = reinterpret_cast(log_handle_); } +void SystemAgent::CheckInDetector(DetectorModuleInterface& processing_module, + ModuleHandle &module_handle, + LogHandle *&log_handle) +{ + CheckIn(static_cast(processing_module), + module_handle, log_handle); +} + +void *SystemAgent::GetBssBase(void) +{ + const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id_); + void *base = NULL; + size_t size = 0; + + if (!mod) + return NULL; + + lib_manager_get_instance_bss_address(instance_id_, mod, &base, &size); + return base; +} + int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, ModulePlaceholder *module_placeholder, size_t processing_module_size, @@ -155,4 +185,3 @@ extern "C" void __cxa_pure_virtual() __attribute__((weak)); void __cxa_pure_virtual() { } - diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c index 1c4688e885d0..dc917e34191d 100644 --- a/src/audio/module_adapter/library/native_system_service.c +++ b/src/audio/module_adapter/library/native_system_service.c @@ -158,9 +158,20 @@ AdspErrorCode native_system_service_send_notif_msg(enum notification_target noti AdspErrorCode native_system_service_get_interface(enum interface_id id, struct system_service_iface **iface) { - if (id < 0) + if (id < 0 || !iface) return ADSP_INVALID_PARAMETERS; - return ADSP_NO_ERROR; + + *iface = NULL; + return ADSP_INVALID_PARAMETERS; +} + +AdspErrorCode native_system_service_get_interface_versioned(enum interface_id id, + uint32_t version, + struct system_service_iface **iface) +{ + (void)version; + + return native_system_service_get_interface(id, iface); } const APP_TASK_DATA struct native_system_service native_system_service = { @@ -171,6 +182,7 @@ const APP_TASK_DATA struct native_system_service native_system_service = { .vec_memset = native_system_service_vec_memset, .notification_create = native_system_service_create_notification, .notification_send = native_system_service_send_notif_msg, - .get_interface = native_system_service_get_interface + .get_interface = native_system_service_get_interface, + .get_interface_versioned = native_system_service_get_interface_versioned } }; diff --git a/src/include/module/module/system_service.h b/src/include/module/module/system_service.h index 56f9712a67d5..4591ece2bada 100644 --- a/src/include/module/module/system_service.h +++ b/src/include/module/module/system_service.h @@ -85,7 +85,8 @@ enum interface_id { INTERFACE_ID_SDCA = 0x1002, /* See SdcaInterface */ INTERFACE_ID_ASYNC_MESSAGE_SERVICE = 0x1003, /* See AsyncMessageInterface */ INTERFACE_ID_AM_SERVICE = 0x1005, /* Reserved for ADSP system */ - INTERFACE_ID_KPB_SERVICE = 0x1006 /* See KpbInterface */ + INTERFACE_ID_KPB_SERVICE = 0x1006, /* See KpbInterface */ + INTERFACE_ID_TIMESTAMPING_SERVICE = 0x1007 /* See TimestampingInterface */ }; /* sub interface definition. @@ -115,5 +116,8 @@ struct system_service { uint32_t actual_payload_size); AdspErrorCode (*get_interface)(enum interface_id id, struct system_service_iface **iface); + + AdspErrorCode (*get_interface_versioned)(enum interface_id id, uint32_t version, + struct system_service_iface **iface); }; #endif /* MODULE_MODULE_SYSTEM_SERVICE_H */ 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 4d6be24e461d..d978d97565cb 100644 --- a/src/include/sof/audio/module_adapter/iadk/api_version.h +++ b/src/include/sof/audio/module_adapter/iadk/api_version.h @@ -14,11 +14,14 @@ #define IADK_MODULE_API_MAJOR_VERSION 4 #define IADK_MODULE_API_MIDDLE_VERSION 5 -#define IADK_MODULE_API_MINOR_VERSION 0 +#define IADK_MODULE_API_MINOR_VERSION 2 #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) +/* API 4.5.0 remains compatible with the extended interface tables. */ +#define IADK_MODULE_API_VERSION_4_5_0 MODULE_API_VERSION_ENCODE(4, 5, 0) + /* 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! diff --git a/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h b/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h index 3b725a23a095..8c41ebd3cabf 100644 --- a/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h +++ b/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h @@ -399,6 +399,10 @@ namespace intel_adsp virtual void OnStreamState(uint64_t counter, uint32_t stream_index, State state) = 0; + + /*! Write a pattern when an output stream resumes processing. */ + virtual void WritePattern(uint16_t stream_index, + OutputStreamBuffer *output_buffer) = 0; }; } /*namespace intel_adsp */ 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 e7aab98c748c..b390aef44855 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_agent.h +++ b/src/include/sof/audio/module_adapter/iadk/system_agent.h @@ -21,7 +21,7 @@ namespace system * A SystemAgent can only be delivered by the ADSP System. * Once registered, a ModuleHandle instance can be handled by the ADSP System. */ - class SystemAgent : public intel_adsp::SystemAgentInterface + class SystemAgent : public intel_adsp::SystemAgentInterface3 { public: SystemAgent(uint32_t module_id, @@ -34,6 +34,15 @@ namespace system intel_adsp::ModuleHandle & module_handle, intel_adsp::LogHandle * &log_handle) /*override*/; + /*! \brief Registers a detector module. */ + virtual void CheckInDetector( + DetectorModuleInterface & processing_module, + ModuleHandle & module_handle, + LogHandle * &log_handle) /*override*/; + + /*! \brief Returns the BSS base for the current module instance. */ + virtual void *GetBssBase(void) /*override*/; + /*! \return a value part of error code list defined within the adsp_error.h*/ virtual int CheckIn(intel_adsp::ProcessingModuleFactoryInterface & module_factory, intel_adsp::ModulePlaceholder * module_placeholder, diff --git a/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h b/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h index 3719c758ce23..58d04bf489ce 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h +++ b/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h @@ -134,6 +134,14 @@ namespace internal ) = 0; }; + class SystemAgentInterface3 : public SystemAgentInterface2 + { + public: + + /*! \brief Gets the BSS base for the current module instance. */ + virtual void *GetBssBase(void) = 0; + }; + } /* namespace intel_adsp */ #endif /* _ADSP_SYSTEM_AGENT_H_ */ diff --git a/src/include/sof/audio/module_adapter/library/native_system_service.h b/src/include/sof/audio/module_adapter/library/native_system_service.h index ab8188a2eca4..c684f5a56ef8 100644 --- a/src/include/sof/audio/module_adapter/library/native_system_service.h +++ b/src/include/sof/audio/module_adapter/library/native_system_service.h @@ -42,6 +42,18 @@ AdspErrorCode native_system_service_send_notif_msg(enum notification_target noti AdspErrorCode native_system_service_get_interface(enum interface_id id, struct system_service_iface **iface); +/** + * \brief Retrieve a versioned system service interface. + * + * \param id Service interface identifier. + * \param version Requested interface version. + * \param iface Location for the returned interface pointer. + * \return ADSP_INVALID_PARAMETERS if the interface is unavailable. + */ +AdspErrorCode native_system_service_get_interface_versioned(enum interface_id id, + uint32_t version, + struct system_service_iface **iface); + extern const struct native_system_service native_system_service; #ifdef __cplusplus diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 92fcbbad37de..da886405468c 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -635,7 +635,8 @@ static enum buildinfo_mod_type lib_manager_get_module_type(const struct sof_man_ /* 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) { + (build_info->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION || + build_info->api_version_number.full == IADK_MODULE_API_VERSION_4_5_0)) { return MOD_TYPE_IADK; } else { /* Check if module is NOT native */ From b4f0240737f35ebd0b55ef91a23b5cf2e267dad7 Mon Sep 17 00:00:00 2001 From: Gaggery Tsai Date: Thu, 23 Jul 2026 11:02:00 -0700 Subject: [PATCH 02/10] audio: iadk: resolve missing module placeholders The current loadable-module entry point calls the system agent with a null placeholder. Creating the module at that address corrupts memory before its adapter can register. Resolve a null placeholder to the instance BSS already allocated by the library manager. Also propagate factory errors and reject a module that did not register an adapter. Signed-off-by: Gaggery Tsai Signed-off-by: Adrian Bonislawski --- src/audio/module_adapter/iadk/README.md | 8 +++- .../module_adapter/iadk/system_agent.cpp | 43 +++++++++++++++---- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/audio/module_adapter/iadk/README.md b/src/audio/module_adapter/iadk/README.md index ba77e533dadd..7ea486046c06 100644 --- a/src/audio/module_adapter/iadk/README.md +++ b/src/audio/module_adapter/iadk/README.md @@ -58,8 +58,11 @@ keep their API 4.5.0 layout. 1. The OS host driver sends an IPC `INIT_INSTANCE` command for the module. 2. The `system_agent_start()` function intercepts this, invokes the dynamic module's `create_instance` entry point (which invokes a `ModuleFactory`). -3. The `SystemAgent` deduces the pin count (interfaces) and initial pipeline configurations using `ModuleInitialSettingsConcrete`. -4. The factory allocates the concrete algorithm and checks it back into SOF through `SystemAgent::CheckIn`. +3. If the entry point provides a null module placeholder, the `SystemAgent` + resolves it to the instance BSS allocated by the library manager after + verifying that the module object fits in that region. +4. The `SystemAgent` deduces the pin count (interfaces) and initial pipeline configurations using `ModuleInitialSettingsConcrete`. +5. The factory allocates the concrete algorithm and checks it back into SOF through `SystemAgent::CheckIn`. ```mermaid sequenceDiagram @@ -70,6 +73,7 @@ sequenceDiagram IPC->>SA: Trigger Mod Creation SA->>Fac: CI invokes create_instance + SA->>SA: Resolve instance BSS placeholder Fac->>Fac: Deduce BaseModuleCfgExt Fac->>Mod: operator new instantiate diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index 390c56767fa2..7ac5bcc4442d 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -24,13 +24,14 @@ #include #include +/* sof/lib_manager.h pulls C-only component headers into this C++ unit. */ struct sof_man_module; extern "C" const struct sof_man_module * lib_manager_get_module_manifest(const uint32_t module_id); extern "C" void lib_manager_get_instance_bss_address(uint32_t instance_id, const struct sof_man_module *mod, - void **va_addr, size_t *size); + void __sparse_cache **va_addr, size_t *size); using namespace intel_adsp; using namespace intel_adsp::system; @@ -46,6 +47,21 @@ namespace intel_adsp namespace system { +static void *system_agent_get_instance_bss(uint32_t module_id, + uint32_t instance_id, + size_t *size) +{ + const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id); + void __sparse_cache *base = NULL; + + *size = 0; + if (!mod) + return NULL; + + lib_manager_get_instance_bss_address(instance_id, mod, &base, size); + return reinterpret_cast(base); +} + /* Structure storing handles to system service operations */ const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = { native_system_service_log_message, @@ -98,15 +114,9 @@ void SystemAgent::CheckInDetector(DetectorModuleInterface& processing_module, void *SystemAgent::GetBssBase(void) { - const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id_); - void *base = NULL; size_t size = 0; - if (!mod) - return NULL; - - lib_manager_get_instance_bss_address(instance_id_, mod, &base, &size); - return base; + return system_agent_get_instance_bss(module_id_, instance_id_, &size); } int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, @@ -118,6 +128,20 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, void **obfuscated_modinst_p) { ErrorCode::Type error; + + if (!module_placeholder) { + size_t bss_size; + void *bss_base = system_agent_get_instance_bss(module_id_, instance_id_, + &bss_size); + + if (!bss_base || processing_module_size > bss_size) + return -ENOMEM; + + module_placeholder = reinterpret_cast(bss_base); + } + + module_size_ = processing_module_size; + IoPinsInfo pins_info; const dsp_fw::DwordArray& cfg_ipc_msg = *reinterpret_cast(obfuscated_mod_cfg); @@ -148,6 +172,9 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, if (error != ErrorCode::NO_ERROR) return -EINVAL; + if (!module_handle_) + return -EINVAL; + IadkModuleAdapter& module_adapter = *reinterpret_cast(module_handle_); *obfuscated_modinst_p = &module_adapter; reinterpret_cast(module_placeholder)->Init(); From 957d558a63ae44a73889efca54401d1b214b92f9 Mon Sep 17 00:00:00 2001 From: Gaggery Tsai Date: Thu, 23 Jul 2026 11:02:00 -0700 Subject: [PATCH 03/10] audio: iadk: initialize loadable modules once The system agent called Init() as soon as the module loaded. The module adapter called it again from framework-owned module_init(). That could allocate detector state and register services twice. Remove the early call and keep module_init() as the single owner. Its return value is propagated through iadk_wrapper_init(). Signed-off-by: Gaggery Tsai --- src/audio/module_adapter/iadk/system_agent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index 7ac5bcc4442d..c3de150b7131 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -177,7 +177,6 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, IadkModuleAdapter& module_adapter = *reinterpret_cast(module_handle_); *obfuscated_modinst_p = &module_adapter; - reinterpret_cast(module_placeholder)->Init(); return 0; } From 9d7cde8c3a2303cb22ec3239a14d5e42a982920a Mon Sep 17 00:00:00 2001 From: Gaggery Tsai Date: Thu, 23 Jul 2026 11:02:00 -0700 Subject: [PATCH 04/10] audio: module_adapter: support sinkless IADK modules Detector endpoints can consume input without a connected audio sink. Their process callback was skipped, prepare rejected the graph, and DP period calculation left the deadline at UINT_MAX. Allow sink/source modules without a sink, derive their DP period from the source IBS, and pass at most one IBS to each process call. A module without a sink still needs at least one connected source. Signed-off-by: Gaggery Tsai --- src/audio/module_adapter/README.md | 5 +++++ src/audio/module_adapter/iadk/README.md | 7 +++++- .../iadk/iadk_module_adapter.cpp | 8 +++++-- src/audio/module_adapter/module_adapter.c | 22 +++++++++++++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/audio/module_adapter/README.md b/src/audio/module_adapter/README.md index e87eda3f83cf..56923304116f 100644 --- a/src/audio/module_adapter/README.md +++ b/src/audio/module_adapter/README.md @@ -110,6 +110,11 @@ sequenceDiagram deactivate DP ``` +A sinkless DP module derives its period from the first source's +`min_available` value (its IBS) and audio format. This schedules input-only +detectors according to data arrival; a zero or otherwise invalid period is +rejected by the normal minimum-period check during prepare. + ## Error Handling and Memory Sandboxing * **Sandboxing (`mod_balloc_align`, `z_impl_mod_fast_get`, `z_impl_mod_free`)**: Since third-party DSP code is treated as semi-untrusted in memory lifetimes, module allocations grab slices from a dedicated component `dp_heap_user` heap instead of the global system heap (`mod_heap_info`). The wrapper automatically prunes leaked objects (`mod_free_all(mod)`) during teardown by keeping an `objpool` of all resource containers. diff --git a/src/audio/module_adapter/iadk/README.md b/src/audio/module_adapter/iadk/README.md index 7ea486046c06..b8ab90a80ea2 100644 --- a/src/audio/module_adapter/iadk/README.md +++ b/src/audio/module_adapter/iadk/README.md @@ -89,7 +89,12 @@ A significant task of `IadkModuleAdapter_Process` is converting SOF's underlying Instead of letting the module directly touch the SOF `comp_buffer` (which could change with SOF version updates), the adapter uses the abstraction APIs (`source_get_data` / `sink_get_buffer`) and wraps them: -1. Request raw continuous memory pointers from `source_get_data()`. +1. Limit each input to one source `min_available` portion (one IBS), then + request its continuous memory pointer from `source_get_data()`. 2. Construct an `intel_adsp::InputStreamBuffer` pointing to that continuous memory chunk. 3. Call the IADK `processing_module_.Process()`. 4. Release precisely the amount of consumed data using `source_release_data()`. + +Input-only detector endpoints are processed even when no audio sink is +connected. Their output descriptors remain empty, so the module can consume +and inspect each IBS without producing downstream audio. diff --git a/src/audio/module_adapter/iadk/iadk_module_adapter.cpp b/src/audio/module_adapter/iadk/iadk_module_adapter.cpp index f940f08fad4b..3264309bd958 100644 --- a/src/audio/module_adapter/iadk/iadk_module_adapter.cpp +++ b/src/audio/module_adapter/iadk/iadk_module_adapter.cpp @@ -46,7 +46,7 @@ int IadkModuleAdapter::IadkModuleAdapter_Process(struct sof_source **sources, { int ret = 0; - if ((num_of_sources > 0) && (num_of_sinks > 0)) { + if (num_of_sources > 0) { intel_adsp::InputStreamBuffer input_stream_buffers[INPUT_PIN_COUNT]; intel_adsp::OutputStreamBuffer output_stream_buffers[OUTPUT_PIN_COUNT]; for (int i = 0; i < (int)num_of_sources; i++) { @@ -55,6 +55,11 @@ int IadkModuleAdapter::IadkModuleAdapter_Process(struct sof_source **sources, intel_adsp::InputStreamFlags flags = {}; i_size = source_get_data_available(sources[i]); + size_t min_available = source_get_min_available(sources[i]); + + if (min_available && i_size > min_available) + i_size = min_available; + ret = source_get_data(sources[i], i_size, (const void **)&input, (const void **)&input_start, &input_end); if (ret != 0) @@ -255,4 +260,3 @@ void* operator new(size_t size, intel_adsp::OutputStreamBuffer* placeholder) thr return placeholder; } #endif - diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index cf1ee6aa0d1a..5bbfe1632af5 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -430,6 +430,18 @@ static void module_adapter_calculate_dp_period(struct comp_dev *dev) } + /* Sinkless modules derive their deadline from one input buffer. */ + if (period == UINT32_MAX && mod->num_of_sources > 0) { + size_t frame_bytes = source_get_frame_bytes(mod->sources[0]); + unsigned int rate = source_get_rate(mod->sources[0]); + + if (frame_bytes && rate) + period = 1000000ULL * source_get_min_available(mod->sources[0]) / + (frame_bytes * rate); + else + period = 0; + } + dev->period = period; } #endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ @@ -537,12 +549,18 @@ int module_adapter_prepare(struct comp_dev *dev) * Hence check for NULL. */ sink = comp_dev_get_first_data_consumer(dev); - if (!sink) { + if (!sink && !IS_PROCESSING_MODE_SINK_SOURCE(mod)) { comp_err(dev, "no sink present on period size calculation"); return -EINVAL; } - mod->period_bytes = audio_stream_period_bytes(&sink->stream, dev->frames); + /* A sinkless module still needs at least one source. */ + if (!sink && !comp_dev_get_first_data_producer(dev)) { + comp_err(dev, "no source or sink buffer connected"); + return -EINVAL; + } + + mod->period_bytes = sink ? audio_stream_period_bytes(&sink->stream, dev->frames) : 0; comp_dbg(dev, "got period_bytes = %u", mod->period_bytes); /* no more to do for sink/source mode */ From 83cd99781e270a5dfa753e25c279f08ab08a039f Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 13 Aug 2026 13:30:41 +0200 Subject: [PATCH 05/10] audio: iadk: define versioned system service lookup Add the public IADK interface version values and aliases used by current modules Signed-off-by: Adrian Bonislawski --- .../library/native_system_service.c | 13 +++++++---- src/include/module/iadk/adsp_error_code.h | 2 ++ src/include/module/module/system_service.h | 22 +++++++++++++++++++ .../library/native_system_service.h | 5 ++++- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c index dc917e34191d..f0f6c7fba89b 100644 --- a/src/audio/module_adapter/library/native_system_service.c +++ b/src/audio/module_adapter/library/native_system_service.c @@ -158,20 +158,25 @@ AdspErrorCode native_system_service_send_notif_msg(enum notification_target noti AdspErrorCode native_system_service_get_interface(enum interface_id id, struct system_service_iface **iface) { - if (id < 0 || !iface) + if (!iface) return ADSP_INVALID_PARAMETERS; + (void)id; *iface = NULL; - return ADSP_INVALID_PARAMETERS; + return ADSP_SERVICE_UNAVAILABLE; } AdspErrorCode native_system_service_get_interface_versioned(enum interface_id id, uint32_t version, struct system_service_iface **iface) { - (void)version; + if (!iface) + return ADSP_INVALID_PARAMETERS; - return native_system_service_get_interface(id, iface); + (void)id; + (void)version; + *iface = NULL; + return ADSP_SERVICE_UNAVAILABLE; } const APP_TASK_DATA struct native_system_service native_system_service = { diff --git a/src/include/module/iadk/adsp_error_code.h b/src/include/module/iadk/adsp_error_code.h index 4d3382de918a..96276e2c0111 100644 --- a/src/include/module/iadk/adsp_error_code.h +++ b/src/include/module/iadk/adsp_error_code.h @@ -35,6 +35,8 @@ typedef uint32_t AdspErrorCode; #define ADSP_INVALID_TARGET 142 /* Service is not supported on target platform. */ #define ADSP_SERVICE_UNAVAILABLE 143 +/* Service version is not supported on target platform. */ +#define ADSP_SERVICE_VERSION_UNAVAILABLE 145 /* SystemAgentInterface */ #define ADSP_MODULE_CREATION_FAILURE 16 diff --git a/src/include/module/module/system_service.h b/src/include/module/module/system_service.h index 4591ece2bada..2db65c93897e 100644 --- a/src/include/module/module/system_service.h +++ b/src/include/module/module/system_service.h @@ -89,6 +89,28 @@ enum interface_id { INTERFACE_ID_TIMESTAMPING_SERVICE = 0x1007 /* See TimestampingInterface */ }; +/* Public interface versions are opaque values used by the versioned GetInterface(). */ +enum interface_version { + INTERFACE_VERSION_GNA_V1 = 0x1000, + INTERFACE_VERSION_INFERENCE_SERVICE_V1 = 0x1000, + INTERFACE_VERSION_INFERENCE_SERVICE_V2 = 0x1001, + INTERFACE_VERSION_SDCA_V1 = 0x1000, + INTERFACE_VERSION_ASYNC_MESSAGE_SERVICE_V1 = 0x1000, + INTERFACE_VERSION_AM_SERVICE_V1 = 0x1000, + INTERFACE_VERSION_KPB_SERVICE_V1 = 0x1000, + INTERFACE_VERSION_KPB_SERVICE_V2 = 0x1001, + INTERFACE_VERSION_TIMESTAMPING_SERVICE_V1 = 0x1000, +}; + +/* Versions exposed to modules built against the current IADK headers. */ +#define INTERFACE_VERSION_GNA INTERFACE_VERSION_GNA_V1 +#define INTERFACE_VERSION_INFERENCE_SERVICE INTERFACE_VERSION_INFERENCE_SERVICE_V2 +#define INTERFACE_VERSION_SDCA INTERFACE_VERSION_SDCA_V1 +#define INTERFACE_VERSION_ASYNC_MESSAGE_SERVICE INTERFACE_VERSION_ASYNC_MESSAGE_SERVICE_V1 +#define INTERFACE_VERSION_AM_SERVICE INTERFACE_VERSION_AM_SERVICE_V1 +#define INTERFACE_VERSION_KPB_SERVICE INTERFACE_VERSION_KPB_SERVICE_V2 +#define INTERFACE_VERSION_TIMESTAMPING_SERVICE INTERFACE_VERSION_TIMESTAMPING_SERVICE_V1 + /* sub interface definition. * This type may contain generic interface properties like id or struct size if needed. */ diff --git a/src/include/sof/audio/module_adapter/library/native_system_service.h b/src/include/sof/audio/module_adapter/library/native_system_service.h index c684f5a56ef8..a3d4c991d8fb 100644 --- a/src/include/sof/audio/module_adapter/library/native_system_service.h +++ b/src/include/sof/audio/module_adapter/library/native_system_service.h @@ -48,7 +48,10 @@ AdspErrorCode native_system_service_get_interface(enum interface_id id, * \param id Service interface identifier. * \param version Requested interface version. * \param iface Location for the returned interface pointer. - * \return ADSP_INVALID_PARAMETERS if the interface is unavailable. + * \return ADSP_INVALID_PARAMETERS for invalid arguments. If the requested + * service has no provider, return ADSP_SERVICE_UNAVAILABLE without checking + * its version. A provider returns ADSP_SERVICE_VERSION_UNAVAILABLE when it + * exists but does not support the requested version. */ AdspErrorCode native_system_service_get_interface_versioned(enum interface_id id, uint32_t version, From c119089d72204a3ec70a179cc9c216e7bcda9f7e Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Tue, 18 Aug 2026 16:50:23 +0200 Subject: [PATCH 06/10] audio: iadk: pass instance BSS to system agent Pass the module instance BSS address and size from the library manager to the IADK system agent. Signed-off-by: Adrian Bonislawski --- .../module_adapter/iadk/system_agent.cpp | 45 ++++--------------- .../audio/module_adapter/iadk/system_agent.h | 6 ++- .../library/native_system_agent.h | 2 + src/library_manager/lib_manager.c | 6 +++ 4 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp index c3de150b7131..36722df3e117 100644 --- a/src/audio/module_adapter/iadk/system_agent.cpp +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -24,15 +24,6 @@ #include #include -/* sof/lib_manager.h pulls C-only component headers into this C++ unit. */ -struct sof_man_module; -extern "C" const struct sof_man_module * -lib_manager_get_module_manifest(const uint32_t module_id); -extern "C" void -lib_manager_get_instance_bss_address(uint32_t instance_id, - const struct sof_man_module *mod, - void __sparse_cache **va_addr, size_t *size); - using namespace intel_adsp; using namespace intel_adsp::system; using namespace dsp_fw; @@ -46,22 +37,6 @@ namespace intel_adsp { namespace system { - -static void *system_agent_get_instance_bss(uint32_t module_id, - uint32_t instance_id, - size_t *size) -{ - const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id); - void __sparse_cache *base = NULL; - - *size = 0; - if (!mod) - return NULL; - - lib_manager_get_instance_bss_address(instance_id, mod, &base, size); - return reinterpret_cast(base); -} - /* Structure storing handles to system service operations */ const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = { native_system_service_log_message, @@ -77,11 +52,15 @@ const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = { SystemAgent::SystemAgent(uint32_t module_id, uint32_t instance_id, uint32_t core_id, - uint32_t log_handle) : + uint32_t log_handle, + void *module_bss, + size_t module_bss_size) : log_handle_(log_handle), core_id_(core_id), module_id_(module_id), instance_id_(instance_id), + module_bss_(module_bss), + module_bss_size_(module_bss_size), module_handle_(NULL), module_size_(0) {} @@ -114,9 +93,7 @@ void SystemAgent::CheckInDetector(DetectorModuleInterface& processing_module, void *SystemAgent::GetBssBase(void) { - size_t size = 0; - - return system_agent_get_instance_bss(module_id_, instance_id_, &size); + return module_bss_; } int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, @@ -130,14 +107,10 @@ int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, ErrorCode::Type error; if (!module_placeholder) { - size_t bss_size; - void *bss_base = system_agent_get_instance_bss(module_id_, instance_id_, - &bss_size); - - if (!bss_base || processing_module_size > bss_size) + if (!module_bss_ || processing_module_size > module_bss_size_) return -ENOMEM; - module_placeholder = reinterpret_cast(bss_base); + module_placeholder = reinterpret_cast(module_bss_); } module_size_ = processing_module_size; @@ -194,7 +167,7 @@ int system_agent_start(const struct system_agent_params *params, { uint32_t ret; SystemAgent system_agent(params->module_id, params->instance_id, params->core_id, - params->log_handle); + params->log_handle, params->module_bss, params->module_bss_size); void* system_agent_p = reinterpret_cast(&system_agent); create_instance_f ci = (create_instance_f)(params->entry_point); 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 b390aef44855..206c44559433 100644 --- a/src/include/sof/audio/module_adapter/iadk/system_agent.h +++ b/src/include/sof/audio/module_adapter/iadk/system_agent.h @@ -27,7 +27,9 @@ namespace system SystemAgent(uint32_t module_id, uint32_t instance_id, uint32_t core_id, - uint32_t log_handle); + uint32_t log_handle, + void *module_bss, + size_t module_bss_size); /*! \brief Initializes a new instance of ModuleAdapter in the ModuleHandle buffer*/ virtual void CheckIn(intel_adsp::ProcessingModuleInterface & processing_module, @@ -69,6 +71,8 @@ namespace system uint32_t const core_id_; uint32_t module_id_; uint32_t instance_id_; + void * const module_bss_; + size_t const module_bss_size_; uint32_t module_size_; intel_adsp::ModuleHandle * module_handle_; 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 70c0f6b1aad1..96d8a519339f 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 @@ -18,6 +18,8 @@ struct system_agent_params { uint32_t core_id; /* Core on which the module will run. */ uint32_t log_handle; /* The handle for logging purposes. */ void *mod_cfg; /* Pointer to the module configuration data. */ + void *module_bss; /* Base of this module instance's BSS. */ + size_t module_bss_size; /* Size of this module instance's BSS. */ }; typedef int (*system_agent_start_fn)(const struct system_agent_params *params, diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index da886405468c..1e0a3c111587 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -556,6 +556,8 @@ static int lib_manager_start_agent(const struct comp_driver *drv, const struct module_interface **ops) { struct system_agent_params agent_params; + void __sparse_cache *module_bss; + size_t module_bss_size; byte_array_t mod_cfg; int ret = 0; @@ -571,6 +573,10 @@ static int lib_manager_start_agent(const struct comp_driver *drv, agent_params.log_handle = (uint32_t)drv->tctx; #endif agent_params.mod_cfg = &mod_cfg; + lib_manager_get_instance_bss_address(agent_params.instance_id, mod_manifest, + &module_bss, &module_bss_size); + agent_params.module_bss = (__sparse_force void *)module_bss; + agent_params.module_bss_size = module_bss_size; #if CONFIG_SOF_USERSPACE_PROXY /* If drv->user_heap is allocated, it means the module is userspace. */ From 25dbbcb77836a644379f5b7cda93c49e56080837 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Wed, 26 Aug 2026 10:49:43 +0200 Subject: [PATCH 07/10] audio: iadk: fix NotificationCreate Initialize the IPC notification envelope and propagate allocation failures when creating an IADK notification. Signed-off-by: Adrian Bonislawski --- .../library/native_system_service.c | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c index f0f6c7fba89b..56c68e08a06b 100644 --- a/src/audio/module_adapter/library/native_system_service.c +++ b/src/audio/module_adapter/library/native_system_service.c @@ -22,6 +22,8 @@ #include #define RSIZE_MAX 0x7FFFFFFF +#define IADK_NOTIFICATION_HEADER_SIZE 48 +#define IADK_NOTIFICATION_USER_VAL_2_MASK 0x3fffffffU /*! Module log level priority to sof log level conversion array */ const int log_priority_map[L_MAX] = { @@ -120,24 +122,42 @@ AdspErrorCode native_system_service_create_notification(struct notification_para uint32_t notification_buffer_size, struct notification_handle **handle) { - if ((params == NULL) || (notification_buffer == NULL) - || (notification_buffer_size <= 0) || (handle == NULL)) + union ipc4_notification_header header = { 0 }; + uint32_t payload_capacity; + struct ipc_msg *msg; + + if (!params || !notification_buffer || !notification_buffer_size || !handle) return ADSP_INVALID_PARAMETERS; - union ipc4_notification_header header; + *handle = NULL; + params->payload = NULL; + + if (notification_buffer_size < IADK_NOTIFICATION_HEADER_SIZE) + return ADSP_OUT_OF_MEMORY; + + payload_capacity = notification_buffer_size - IADK_NOTIFICATION_HEADER_SIZE; + if (params->max_payload_size > payload_capacity) + return ADSP_OUT_OF_MEMORY; + + if (params->type == NOTIFICATION_TYPE_MODULE_EVENT_NOTIFICATION && + params->max_payload_size < sizeof(struct module_event_notification)) + return ADSP_INVALID_PARAMETERS; header.r.notif_type = params->type; - header.r._reserved_0 = params->user_val_1; + header.r.rsvd0 = params->user_val_1; header.r.type = SOF_IPC4_GLB_NOTIFICATION; header.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; header.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; - struct ipc_msg *msg = lib_notif_msg_init((uint32_t)header.dat, notification_buffer_size); - if (msg) { - *handle = (struct notification_handle *)msg; - params->payload = msg->tx_data; - } + msg = lib_notif_msg_init(header.dat, params->max_payload_size); + if (!msg) + return ADSP_OUT_OF_MEMORY; + + msg->extension = params->user_val_2 & IADK_NOTIFICATION_USER_VAL_2_MASK; + params->payload = msg->tx_data; + params->max_payload_size = msg->tx_size; + *handle = (struct notification_handle *)msg; return ADSP_NO_ERROR; } From 16ba25ad4d3f06eafcd9b1eae4a1b440bf988445 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Wed, 26 Aug 2026 10:50:58 +0200 Subject: [PATCH 08/10] audio: iadk: honor NotificationSend payload size Allocate and transmit only the caller-provided payload size when sending an IADK notification. Signed-off-by: Adrian Bonislawski --- src/audio/module_adapter/library/native_system_service.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c index 56c68e08a06b..068a74146e89 100644 --- a/src/audio/module_adapter/library/native_system_service.c +++ b/src/audio/module_adapter/library/native_system_service.c @@ -166,11 +166,12 @@ AdspErrorCode native_system_service_send_notif_msg(enum notification_target noti struct notification_handle *message, uint32_t actual_payload_size) { - if ((message == NULL) || (actual_payload_size == 0)) - return ADSP_INVALID_PARAMETERS; - struct ipc_msg *msg = (struct ipc_msg *)message; + if (!msg || actual_payload_size > msg->tx_size) + return ADSP_INVALID_PARAMETERS; + + msg->tx_size = actual_payload_size; lib_notif_msg_send(msg); return ADSP_NO_ERROR; } From 522c6423d75d23875eb54920c038c7c9a9ae42ac Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Wed, 26 Aug 2026 10:51:25 +0200 Subject: [PATCH 09/10] audio: iadk: validate notification target Accept host-bound IADK notifications while rejecting unsupported notification targets. Signed-off-by: Adrian Bonislawski --- src/audio/module_adapter/library/native_system_service.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c index 068a74146e89..24091c1c3c91 100644 --- a/src/audio/module_adapter/library/native_system_service.c +++ b/src/audio/module_adapter/library/native_system_service.c @@ -168,6 +168,13 @@ AdspErrorCode native_system_service_send_notif_msg(enum notification_target noti { struct ipc_msg *msg = (struct ipc_msg *)message; + switch (notification_target) { + case NOTIFICATION_TARGET_DSP_TO_HOST: + break; + default: + return ADSP_INVALID_TARGET; + } + if (!msg || actual_payload_size > msg->tx_size) return ADSP_INVALID_PARAMETERS; From ac745eab293658f8236dedb5f85fa856757ffac4 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Tue, 13 Oct 2026 15:26:58 +0200 Subject: [PATCH 10/10] lib_manager: notification: reject oversized payloads Library notification payloads are allocated with SRAM_OUTBOX_SIZE bytes, but the requested size was copied to msg->tx_size without checking that capacity. An IADK module could therefore receive a payload pointer advertising more writable bytes than were allocated. Reject oversized requests before searching the notification pool or allocating a new message. This protects both fresh and reused buffers while keeping the IADK caller-buffer validation unchanged. Signed-off-by: Adrian Bonislawski --- src/library_manager/lib_notification.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/library_manager/lib_notification.c b/src/library_manager/lib_notification.c index 0feab9660c3e..0db5b2a08778 100644 --- a/src/library_manager/lib_notification.c +++ b/src/library_manager/lib_notification.c @@ -27,6 +27,9 @@ struct ipc_msg *lib_notif_msg_init(uint32_t header, uint32_t size) struct ext_library *ext_lib = ext_lib_get(); struct ipc_lib_msg *lib_notif = ext_lib->lib_notif_pool; + if (size > SRAM_OUTBOX_SIZE) + return NULL; + /* If list not empty search for free notification handle */ if (lib_notif && !list_is_empty(&lib_notif->list)) { struct list_item *list_elem;