Firmware Initialization & Boot Architecture#
The Firmware Initialization & Boot subsystem in Sound Open Firmware (SOF) governs the complete sequence through which the audio Digital Signal Processor (DSP) transitions from an unpowered or quiescent hardware state into a fully initialized, real-time audio computing engine.
Operating as an embedded real-time system across diverse silicon architectures (Intel CAVS/ACE, NXP i.MX, AMD ACP, and embedded microcontrollers like ESP32 and Teensy), SOF couples low-level hardware bootstrap sequences with the Zephyr RTOS kernel lifecycle, multi-tier platform hardware bringup, host driver synchronization handshakes, and multi-core power restoration.
This guide provides a comprehensive, high-level architectural walkthrough of the firmware initialization and boot framework without delving into low-level C code.
—
1. End-to-End Boot & Initialization Lifecycle#
Bringing an audio DSP from host power-on to active audio stream processing spans multiple distinct execution domains: host operating system orchestration, DSP hardware boot ROM, Zephyr RTOS kernel initialization, SOF primary core initialization, application thread startup, and host-firmware synchronization.
The Five Architectural Phases of Boot#
Host Driver Pre-Boot Staging: The host operating system (e.g., Linux mainline ALSA/ASoC driver) parses the signed firmware ELF binary, inspects embedded metadata headers, allocates host DMA buffers (or Isolated Memory Regions / IMR), programs DSP base address registers (BARs), and deasserts the hardware DSP core reset latch.
DSP Hardware Boot ROM Execution: The DSP’s embedded on-chip ROM begins executing on Core 0. The ROM powers up internal SRAM banks, configures early clock trees, validates cryptographic signatures and hash manifests, configures DSP memory management page tables, copies the firmware image from host memory into DSP SRAM, and vectors execution to the operating system entry point (
_start).Zephyr RTOS Kernel Bringup: The Zephyr operating system initializes processor registers, zeroes BSS, unpacks initialized data sections, initializes architectural exception vectors, and progresses through deterministic kernel initialization stages (
EARLY,PRE_KERNEL_1,PRE_KERNEL_2, andPOST_KERNEL).SOF Core & Platform Subsystem Initialization: Registered at Zephyr’s
POST_KERNELstage, SOF’s entry function (sof_init()) executes on Core 0. It sets up logging and DMA trace buffers, initializes system-wide notifiers, configures runtime power management, invokes platform-specific peripheral drivers (clocks, DMACs, IPC mailboxes, audio schedulers), and unpacks secondary core storage manifests.Application Main Handoff & Host Ready Handshake: Zephyr transitions execution to the application main thread (
sof_app_main()). SOF verifies library integrity (such as dynamically restored LLEXT components), writes firmware status and ABI details to the hardware mailbox, asserts the host interrupt, and transitions to the active running state, awaiting host IPC audio pipeline commands.
Figure 42 End-to-End SOF Boot Flow & System Lifecycle from Host Driver Staging to Audio Readiness#
—
2. Extended Firmware Manifest & Host Pre-Boot Discovery#
Before the DSP hardware is taken out of reset, the host operating system must discover firmware capabilities, ABI compatibility constraints, memory window geometries, and debugging parameters.
SOF accomplishes this via the Extended Firmware Manifest, an embedded data structure placed directly into the dedicated .fw_metadata section of the compiled firmware ELF binary (implemented in src/init/ext_manifest.c).
Manifest Structure & Header Elements#
The extended manifest consists of a contiguous sequence of self-describing structured elements. Each element begins with a standard header (ext_man_elem_header) containing an element type identifier and a total element payload byte length:
Firmware Version (``ext_man_fw_version``): Exposes the major, minor, micro, build tag, and cryptographic Git commit hash of the compiled firmware binary. The host uses this to verify driver compatibility before downloading.
Compiler & Toolchain Version (``ext_man_cc_version``): Contains the compiler name, toolchain version, and build timestamp (e.g., LLVM/Clang or Cadence XCC) used to build the image.
Extraction Probe Support (``ext_man_probe_support``): Informs the host driver whether live trace probe DMA extraction points are enabled and provides buffer sizing limits for real-time telemetry streaming.
Debug ABI Specification (``ext_man_dbg_abi``): Declares the user-space debugger and probe ABI version (such as dictionary-based log extraction schemas used by
smexandsof-logger).Configuration Dictionary (``ext_man_config_data``): A key-value array of hardware and build configuration constants, including maximum IPC message sizes (
SOF_IPC_MSG_MAX_SIZE), memory window offsets, and platform capabilities.
Figure 43 Extended Manifest (.fw_metadata) Binary Layout and Pre-Boot Host Parsing Flow#
Because the host driver inspects this manifest directly from the binary file prior to downloading code into the DSP, mismatched firmware builds or incompatible ABI revisions are intercepted immediately, preventing kernel panics or DSP hangs.
—
3. Zephyr RTOS Multi-Stage Initialization#
Sound Open Firmware is natively constructed upon the Zephyr RTOS. Zephyr utilizes a deterministic, multi-level initialization table where drivers, core kernel primitives, and application subsystems are systematically registered and executed using the SYS_INIT() macro.
Deterministic Initialization Levels#
Zephyr defines five sequential initialization levels:
EARLY: Low-level platform hardware initialization executed before any OS abstractions exist. No kernel structures or memory allocators are available.
PRE_KERNEL_1: Core CPU architecture features, basic interrupt controllers, and essential hardware console devices are brought online. No thread scheduling or kernel synchronization primitives exist.
PRE_KERNEL_2: High-resolution hardware system timers, memory management units (MMU/MPU), and hardware clock trees are initialized.
POST_KERNEL: The Zephyr kernel is fully operational. Dynamic memory allocators, thread creation, semaphores, and inter-thread messaging primitives are ready. Device drivers and middleware services initialize during this level.
APPLICATION: Executed after all kernel and device driver subsystems are ready, immediately prior to invoking the main application thread.
Figure 44 Zephyr RTOS Multi-Stage Initialization Pipeline and SOF SYS_INIT Integration#
The Rationale for POST_KERNEL, 99#
SOF explicitly binds its primary initialization entry point via:
/* Registered in src/init/init.c */
SYS_INIT(sof_init, POST_KERNEL, 99);
Selecting POST_KERNEL at priority level 99 (the lowest priority within that stage) guarantees that:
All hardware buses, DMA controllers, and interrupt routing controllers registered by Zephyr drivers have finished their initialization.
The Zephyr kernel heap allocator is fully operational, allowing SOF to dynamically allocate its global context structures and buffer descriptors.
Zephyr thread creation and synchronization APIs (such as
k_work_queueandk_thread) are ready for SOF’s deferred IPC handler and real-time audio schedulers.The SOF initialization code runs synchronously to completion on Core 0 before Zephyr switches execution to user application threads.
—
4. Primary Core Platform Initialization (primary_core_init)#
When Zephyr invokes sof_init(), control transitions immediately to primary_core_init() in src/init/init.c. This function orchestrates the deterministic bringup of SOF’s internal audio subsystem and invokes hardware-specific platform initializers.
Primary Core Initialization Stages#
Figure 45 Primary Core (primary_core_init) Execution Flow & Platform Subsystem Bringup Sequence#
Global Context Setup: Allocates and binds the singleton
struct soffirmware context, which anchors pointers to memory pools, platform configurations, and audio schedulers.Logging, Timestamps, and Trace Buffering: Configures Zephyr’s logging timestamp source to the high-resolution hardware cycle counter (
k_cycle_get_32()or 64-bit system ticks). Initializes the circular DMA trace buffer (trace_init()) and prints the official firmware ABI, build hash, and version banner.System Notifiers & Runtime Power Management: Initializes the asynchronous system notification bus (
init_system_notify()) used for inter-component messaging (such as clock changes and audio underrun broadcasts). Brings up runtime power management (pm_runtime_init()) to prepare low-power idle policies.Platform Hardware Bringup (``platform_init()``): Calls the platform-specific hardware initialization routine (e.g.,
src/platform/intel/ace/platform.corcavs/platform.c): - Clocks & KCPS: Configures DSP clock frequencies and initializes the kilo-cycles-per-second (KCPS) dynamic frequency scaling budget. - Audio Schedulers: Instantiates the Earliest Deadline First (EDF) scheduler, the Low-Latency (LL) timer domain, the Data Processing (DP) preemptive thread scheduler, and the Thread With Budget (TWB) scheduler. - System Agent: Configures periodic background health monitors (sa_init()) and hardware watchdog timers. - Audio DMACs: Initializes host and peripheral DMA controllers (HD-Audio DMA, GPDMA). - Host IPC & IDC: Allocates shared SRAM mailbox windows (Windows 0 to 3) and configures Inter-Domain Communication (IDC) for multi-core DSPs.AltBootManifest Unpacking (``lp_sram_unpack()``): On platforms where secondary cores lack hardware boot ROMs, the primary core parses the linker-generated
AltBootManifestto copy secondary core executable code and read-only data into Low-Power SRAM (LP-SRAM), followed by data cache write-back flushing.Component Registry & Pipeline Setup: Registers built-in processing modules (Volume, Mixer, SRC, EQ) into the component factory table (
sys_comp_init()) and initializes stream position tracking structures.
—
5. Host-Firmware Boot Synchronization & FW Ready Handshake#
Once the primary core completes internal hardware bringup, it must formally notify the host operating system that the DSP is operational and ready to accept audio stream commands. The host and firmware synchronize through the hardware mailbox and doorbell interrupt registers.
Protocol Generational Differences: IPC3 vs IPC4#
The handshake mechanism differs fundamentally between protocol generations:
Figure 46 Host-Firmware Boot Synchronization & FW Ready Handshake (IPC3 vs IPC4)#
IPC3 Handshake Protocol: 1. The DSP constructs a structured
sof_ipc_fw_readymessage containing ABI major/minor versions, build tags, and an array of memory window descriptors (defining the base offsets and lengths of Windows 0, 1, 2, and 3). 2. The DSP writes this message directly into Mailbox Window 0 (the Outbox) and rings the host doorbell interrupt. 3. The host driver’s ISR reads Window 0, verifies ABI compatibility, records mailbox memory geometries, clears its boot watchdog timer, and proceeds to parse and download the monolithic topology binary.IPC4 Handshake Protocol: 1. The DSP writes the ABI version of the firmware register layout into the
abi_verfield of the firmware status structure within Mailbox Window 0. 2. The DSP updates the firmware status register toSOF_IPC4_FW_STATUS_READY. 3. The host driver detects this state transition (via either an interrupt or status register polling), cancels the boot timeout, and issues an initial IPC4GLB_GET_FW_VERSIONor capabilities query to dynamically discover audio pipeline and module parameters.
Boot Timeout Protection#
During boot, the host driver starts a hardware boot timeout monitor (typically 2 to 5 seconds). If the DSP boot ROM, cryptographic validation, or firmware initialization encounters a fatal crash:
The DSP writes panic code dumps, exception vectors, and stack frames into Mailbox Window 0 before halting.
If the DSP hangs completely without writing to the mailbox, the host boot timer expires.
The host driver logs a boot failure error, captures the DSP register dump, triggers a hardware power-cycle or reset sequence, and prevents sound card registration from hanging the host operating system.
—
6. Multi-Core Initialization & Secondary Core Boot#
Modern audio DSPs (such as Intel cAVS 2.5, ACE 1.5, ACE 2.0, and ACE 3.0) feature multi-core symmetric multiprocessing (SMP) clusters (Dual-Core, Quad-Core, or Octa-Core). To conserve power, secondary cores are kept in low-power power-gated states during early boot and are powered up on demand.
The Secondary Core Boot Flow#
When an audio pipeline requires processing capacity beyond Core 0, the host or primary core powers up secondary cores (Core 1, Core 2, Core 3):
Power Domain Activation: Core 0 writes to the platform power management control registers to ungated clocks and energize the secondary core’s power well.
Zephyr SMP Core Bringup: The secondary core vectors out of reset into Zephyr’s secondary CPU startup stub.
State Assessment (``check_restore()``): The secondary core executes
secondary_core_init()insrc/init/init.c. It immediately evaluates whether this boot is a Cold Boot or a Power Restore (e.g., resuming from low-power D0ix retention where memory remained energized): - If persistent structures (schedulers, notifiers, IDC contexts) are already present in shared memory,check_restore()returns true, invokingsecondary_core_restore(). This bypasses re-allocation, preventing memory leaks and preserving pipeline state. - If memory was unpowered, the core proceeds with a full cold boot initialization.
Figure 47 Secondary Core Boot, Power State Assessment (check_restore), and Dynamic Activation Flow#
Cold Boot Subsystem Configuration#
During a cold boot, the secondary core configures its own local resources:
Local Core Notifiers: Registers local core notification queues for intra-core event handling.
Independent Low-Latency (LL) Domain: Sets up dedicated per-core timer domains and DMA domains, allowing the secondary core to drive real-time audio tasks without lock contention with Core 0.
Local Data Processing (DP) Scheduler: Initializes preemptive thread pools for compute-heavy audio algorithms.
Inter-Domain Communication (IDC): Binds hardware doorbell interrupts between Core 0 and the secondary core, allowing Core 0 to forward host IPC commands and synchronize audio scheduling across cores.
Dynamic KCPS Budget: Adjusts core clock frequencies to match its active processing workload.
—
7. Power State Lifecycles & Wake Transitions#
Firmware initialization occurs not only during system power-on, but also across runtime power state transitions. SOF coordinates with the host operating system to optimize energy efficiency through dynamic power management.
Power States & Transition Topologies#
The DSP transitions across three principal operational states:
D3 (Cold / Powered Off): The entire DSP power well is severed. All internal SRAM contents, registers, and cache lines are completely lost. Waking from D3 requires a complete cold boot: host binary download, DSP ROM cryptographic validation, Zephyr initialization, and full SOF platform bringup.
D0 (Active / Operational): The DSP is fully powered. Core 0 and optional secondary cores actively execute audio pipelines, process DMA interrupts, and handle host IPC transactions.
D0ix (Low-Power Idle / Retention): When no audio streams are active (or when streams enter extended pause), the DSP transitions into low-power idle. High-Performance SRAM (HP-SRAM) banks are dynamically powered down, and essential context is preserved in Low-Power SRAM (LP-SRAM) or Host DRAM. Secondary cores are powered off. Waking from D0ix bypasses full image download, executing a fast-restore path that re-enables clocks and restores execution in microseconds.
Figure 48 Power State Lifecycle Transitions, Wake Sequences, and Context Preservation#
LLEXT Dynamic Library Restoration#
When waking from low-power states where HP-SRAM banks were powered down, dynamically loaded Linkable Loadable Extension (LLEXT) modules must be preserved without requiring the host to re-download shared libraries over PCIe.
SOF’s LLEXT manager (llext_manager_restore_from_dram()) caches module text and data sections in host-backed DRAM or non-volatile LP-SRAM. During the wake sequence, the manager automatically verifies image checksums and restores the module code directly into DSP execution memory before the host ready handshake is signaled, ensuring seamless audio playback resumption.
—