Installing OpenAMP Firmware Into EDF Yocto Linux Images

This page describes how to build EDF Yocto disk images that include OpenAMP auxiliary-processor firmware, such as RPMsg firmware running on an RPU, and have that firmware deployed into the Linux root filesystem during a normal bitbake invocation.

The selected MACHINE drives the workflow. In most production deployments the entire build is a single bitbake call against a board-specific MACHINE. The split-machine flow that uses a prebuilt common-MACHINE root filesystem alongside a separate firmware build is treated as a special case.

This page is intentionally limited to the OpenAMP-specific pieces: the packaging recipes, multiconfig dependencies, and image integration flow. For the generic EDF image-variant background, see Linux-only and Platform Image Variants.

Overview

EDF Linux images can include OpenAMP firmware binaries built as part of the same Yocto build that produces the Linux user space. These are typically payloads targeted at an auxiliary execution environment such as Zephyr or FreeRTOS on a Cortex-R RPU core.

The integration is implemented with Yocto Project multiconfig support. A “Linux-side” packaging recipe (for example, openamp-zephyr-demo) declares a multiconfig dependency on a firmware build target with FW_MCDEPENDS (or do_install[mcdepends]). When the Linux image is built:

  • The firmware recipe is built under its own multiconfig (typically mc::${MACHINE}-${FW_MACHINE}-${FW_OS}).

  • The firmware do_deploy task publishes the binary into the multiconfig deploy directory.

  • The Linux-side recipe copies the deployed binary into /lib/firmware/ inside the rootfs. For the current Versal Gen 1 and Kria SoM OpenAMP examples, this is a board-specific hierarchy under /lib/firmware/xilinx/<board>/rpu/0/<firmware>.elf.

The critical requirement is that the selected MACHINE must define every multiconfig that the firmware recipes depend on. If a required multiconfig is not present in BBMULTICONFIG, the firmware recipe skips itself (bb.parse.SkipRecipe) and the Linux-side recipe fails to find the deployed binary.

The reference recipes used as templates throughout this page live in the meta-xilinx Yocto layer. The directory layout of meta-xilinx-standalone-sdt/recipes-applications/openamp-fw/ is:

meta-xilinx-standalone-sdt/recipes-applications/openamp-fw/
|-- openamp-fw.inc
|-- openamp-fw-echo-testd.bb
|-- openamp-fw-mat-muld.bb
|-- openamp-fw-rpc-demo.bb
`-- openamp-zephyr-demo.bb

The openamp-fw-* recipes target FreeRTOS / bare-metal RPU firmware through the open-amp-xlnx recipe. The openamp-zephyr-demo recipe targets the Zephyr RPU port through zephyr-openamp-rpmsg-multi-srv. See the OpenAMP firmware recipes in the meta-xilinx Yocto layer for the in-tree sources.

Primary Workflow

The recommended workflow for production deployments is a single bitbake invocation against a board-specific MACHINE that already defines the firmware multiconfig targets. In that case:

  1. The platform disk image build starts.

  2. Each firmware-bearing image package (for example, openamp-zephyr-demo) is pulled into IMAGE_INSTALL and its multiconfig dependency is queued.

  3. The dependent firmware recipe builds under its multiconfig (for example, RPU0 cluster 0 running Zephyr) and produces a deployed binary.

  4. The Linux-side packaging recipe installs the binary into /lib/firmware/ inside the rootfs.

  5. edf-platform-disk-image assembles the final .wic image with the firmware already in place.

No manual firmware build, copy, or post-processing step is required beyond selecting the correct MACHINE and enabling the desired firmware package.

See Yocto Project Zephyr Build for the RPU-side multiconfig configuration (machine .conf files, Lopper transformations, and BBMULTICONFIG) that the firmware recipes consume.

Build Examples

Zephyr OpenAMP RPU Firmware

The Zephyr OpenAMP example currently runs on Versal Gen 2 boards; the worked example below uses the VEK385 RevB. A Versal Gen 2 -multidomain MACHINE already defines the cortexr52-0-zephyr multiconfig that openamp-zephyr-demo depends on, so the entire build is a single bitbake call. The -sdt-seg MACHINE on the same board has only the microblaze-pmc multiconfig and would trip the bb.parse.SkipRecipe failure mode flagged in the Overview.

  1. Build Yocto Project pre-requisites by following Operating System Integration and Development.

  2. Enable the firmware package by appending it to IMAGE_INSTALL in conf/local.conf:

    IMAGE_INSTALL:append = " openamp-zephyr-demo"
    
  3. Build the platform disk image against the VEK385 RevB -multidomain MACHINE:

    $ MACHINE=versal-2ve-2vm-vek385-revb-multidomain bitbake edf-platform-disk-image
    
  4. The build produces the disk image with the Zephyr RPU firmware already present under a board-specific directory tree rooted at /lib/firmware/xilinx/vek385-revb/rpu/ inside the rootfs. On RevA boards the same path is used, but without the -revb segment in the board name.

  5. Verify (pre-flash) that the firmware ELF made it into the rootfs tarball:

    $ tar tzf tmp/deploy/images/versal-2ve-2vm-vek385-revb-multidomain/edf-platform-disk-image-versal-2ve-2vm-vek385-revb-multidomain.rootfs.tar.gz \
          | grep '^lib/firmware/xilinx/vek385-revb/rpu/'
    lib/firmware/xilinx/vek385-revb/rpu/0/vek385-revb-r52-0-zephyr-openamp.elf
    

    An empty result means the firmware multiconfig was skipped (typically a missing cortexr52-0-zephyr entry in the board’s BBMULTICONFIG); see the Overview for the bb.parse.SkipRecipe failure mode.

The corresponding firmware-side recipe is zephyr-openamp-rpmsg-multi-srv, pulled in through the FW_MCDEPENDS declared by openamp-zephyr-demo.bb. No separate bitbake call is required for the firmware.

To boot the firmware from Linux user space at runtime, see Loading the prebuilt OpenAMP RPU firmware demos for the dfx-mgr-client and remoteproc walk-through that loads the deployed ELF.

FreeRTOS OpenAMP RPU Firmware

The FreeRTOS OpenAMP examples currently run on Versal Gen 1 boards (such as the VEK280, VCK190, VPK120, and VMK180) and on Kria SoM boards (such as the KR260, KV260, and KD240), which are based on Zynq UltraScale+ MPSoC. On all these boards the -multidomain MACHINEs define the cortexr5-0-baremetal and cortexr5-0-freertos multiconfigs used by the bare-metal and FreeRTOS variants of the OpenAMP demos. openamp-fw.inc emits one mcextend: variant per OS by expanding BBCLASSEXTEND over SUPPORTED_OS_LIST = "baremetal freertos" (giving mcextend:baremetal and mcextend:freertos); the variant the build needs has to be present in the board’s BBMULTICONFIG or the firmware recipe self-skips with bb.parse.SkipRecipe and the openamp-fw-* install step fails to find the deployed binary. The -sdt-seg MACHINEs on the same boards declare only the microblaze-pmc and microblaze-psm multiconfigs, so they cannot satisfy FW_MCDEPENDS for the FreeRTOS / bare-metal RPU recipes.

Versal Gen 1 Worked Example (VEK280)
  1. Build Yocto Project pre-requisites by following Operating System Integration and Development.

  2. Append one or more of the FreeRTOS demo packages to IMAGE_INSTALL in conf/local.conf:

    IMAGE_INSTALL:append = " openamp-fw-echo-testd \
                             openamp-fw-rpc-demo \
                             openamp-fw-mat-muld"
    
  3. Build the platform disk image against the board’s -multidomain MACHINE. For VEK280:

    $ MACHINE=versal-vek280-multidomain bitbake edf-platform-disk-image
    
  4. The build deploys the firmware ELFs into the rootfs under a board-specific directory tree rooted at /lib/firmware/xilinx/vek280/rpu/0/. The current FreeRTOS examples install the echo, matrix, and proxy firmware ELFs below that hierarchy.

  5. Verify (pre-flash) that all three firmware images made it into the rootfs tarball:

    $ tar tzf tmp/deploy/images/versal-vek280-multidomain/edf-platform-disk-image-versal-vek280-multidomain.rootfs.tar.gz \
          | grep '^lib/firmware/xilinx/vek280/rpu/'
    lib/firmware/xilinx/vek280/rpu/0/vek280-r5-0-echo-freertos.elf
    lib/firmware/xilinx/vek280/rpu/0/vek280-r5-0-matrix-freertos.elf
    lib/firmware/xilinx/vek280/rpu/0/vek280-r5-0-proxy-freertos.elf
    

    A missing entry means the corresponding firmware multiconfig was skipped (typically a missing cortexr5-0-baremetal or cortexr5-0-freertos entry in the board’s BBMULTICONFIG); see the Overview for the bb.parse.SkipRecipe failure mode.

To boot the firmware from Linux user space at runtime, see Loading the prebuilt OpenAMP RPU firmware demos for the dfx-mgr-client and remoteproc walk-through that loads the deployed ELF.

Kria SoM Worked Example (KR260)

The Kria SoM -multidomain MACHINEs (k26-smk-kr-sdt-multidomain for the KR260, k26-smk-kv-sdt-multidomain for the KV260, and k24-smk-kd-sdt-multidomain for the KD240, available from 2026.1) wire up the same cortexr5-0-freertos multiconfig the Versal Gen 1 boards use. The build flow is identical to the VEK280 example; only the MACHINE name and the resulting deploy / install paths differ.

  1. Build Yocto Project pre-requisites by following Operating System Integration and Development.

  2. Append one or more of the FreeRTOS demo packages to IMAGE_INSTALL in conf/local.conf exactly as for the Versal Gen 1 example above.

  3. Build the platform disk image against the board’s -multidomain MACHINE. For KR260:

    $ MACHINE=k26-smk-kr-sdt-multidomain bitbake edf-platform-disk-image
    
  4. The build deploys the firmware ELFs into the rootfs under /lib/firmware/xilinx/kr260/rpu/0/.

  5. Verify (pre-flash) that all three firmware images made it into the rootfs tarball:

    $ tar tzf tmp/deploy/images/k26-smk-kr-sdt-multidomain/edf-platform-disk-image-k26-smk-kr-sdt-multidomain.rootfs.tar.gz \
          | grep '^lib/firmware/xilinx/kr260/rpu/'
    lib/firmware/xilinx/kr260/rpu/0/k26-r5-0-echo-freertos.elf
    lib/firmware/xilinx/kr260/rpu/0/k26-r5-0-matrix-freertos.elf
    lib/firmware/xilinx/kr260/rpu/0/k26-r5-0-proxy-freertos.elf
    

    A missing entry means the corresponding firmware multiconfig was skipped (typically a missing cortexr5-0-freertos entry in the board’s BBMULTICONFIG); see the Overview for the bb.parse.SkipRecipe failure mode.

To boot the firmware from Linux user space at runtime, see Loading the prebuilt OpenAMP RPU firmware demos for the dfx-mgr-client and remoteproc walk-through that loads the deployed ELF.

How the Recipes Fit Together

This section traces the OpenAMP recipe chain only. For the generic EDF image-variant background, refer to Linux-only and Platform Image Variants.

Relevant Recipes

The OpenAMP packaging flow described on this page relies on the recipes under meta-xilinx-standalone-sdt/recipes-applications/openamp-fw/:

  • openamp-fw.inc - shared include for the FreeRTOS / bare-metal demos. Declares FW_MCDEPENDS, sets TARGET_MC per family, installs into ${nonarch_base_libdir}/firmware/, and uses BBCLASSEXTEND (expanded from SUPPORTED_OS_LIST = "baremetal freertos") to emit one mcextend: variant per OS.

  • openamp-fw-echo-testd.bb, openamp-fw-mat-muld.bb, openamp-fw-rpc-demo.bb - thin packaging recipes that require openamp-fw.inc and override OPENAMP_FW_NAME and OPENAMP_XLNX_RECIPE.

  • openamp-zephyr-demo.bb - the Zephyr equivalent. Sets FW_MCDEPENDS directly on zephyr-openamp-rpmsg-multi-srv rather than going through the open-amp-xlnx lineage used by the bare-metal / FreeRTOS demos.

The Firmware Recipe Chain

When the user adds a firmware-bearing recipe to IMAGE_INSTALL (for example, IMAGE_INSTALL:append = " openamp-fw-echo-testd"), bitbake walks the following dependency chain:

  1. openamp-fw-echo-testd.bb requires openamp-fw.inc, which sets:

    FW_MCDEPENDS = "mc::${MACHINE}-${TARGET_MC}:${OPENAMP_XLNX_RECIPE}-${FW_OS}:do_deploy"
    

    For a Versal board MACHINE this expands to:

    mc::<board>-cortexr5-0-${FW_OS}:open-amp-xlnx-echo-${FW_OS}:do_deploy
    
  2. ${FW_OS} is set by the mcextend: class extension to either baremetal or freertos (BBCLASSEXTEND in openamp-fw.inc emits both variants); whichever variant the user pulls into IMAGE_INSTALL selects the matching multiconfig.

  3. Bitbake checks that the multiconfig is in the board’s BBMULTICONFIG. If not, the firmware recipe self-skips with bb.parse.SkipRecipe("Requires multiconfig ...") and the do_install of the consumer (openamp-fw-*) fails to find the deployed ELF. This is the common first-time-setup failure mode flagged in the Overview.

  4. The firmware builds under its multiconfig, do_deploy copies the ELF into ${TMPDIR}-${MACHINE}-${TARGET_MC}/deploy/images/${MACHINE}/, and the consumer’s do_install reads it back from ${FW_DEPLOY_DIR} (computed from the same expression) and installs it into the rootfs under /lib/firmware/. For the current Versal Gen 1 and Kria SoM OpenAMP examples, the installed ELF lives in a board-specific hierarchy under /lib/firmware/xilinx/<board>/rpu/0/<firmware>.elf.

The Zephyr equivalent (openamp-zephyr-demo.bb) does not go through openamp-fw.inc; it sets FW_MCDEPENDS directly on the Zephyr build target (zephyr-openamp-rpmsg-multi-srv) and does not use BBCLASSEXTEND, so there is exactly one variant (cortexr52-0-zephyr on Versal Gen 2).

Split-Machine Workflow - Prebuilt Common MACHINE

The AMD Embedded Development Framework (EDF) also supports a split-machine flow. In this flow the rootfs is built against an EDF “common” MACHINE while the boot firmware and any auxiliary-processor firmware are built against a different board-specific MACHINE. This flow is intended primarily for the prebuilt demo and evaluation images that AMD CI publishes, and is not the recommended customer production path.

In this mode:

  • The Linux rootfs is built one time against an EDF common MACHINE (amd-cortexa78-mali-common, amd-cortexa72-common, amd-cortexa53-mali-common, amd-cortexa53-common). See Linux-only and Platform Image Variants for the variant matrix.

  • Firmware binaries are built under one or more board-specific MACHINEs that define the required multiconfigs.

  • The common-MACHINE image recipes pull in pre-packaged per-board firmware tarballs so the common rootfs can demonstrate the on-target OpenAMP flow without rebuilding the firmware.

The exact image contents for the Linux-only and platform image variants are documented in Linux-only and Platform Image Variants.

When To Use Which Workflow

  • Use the Primary Workflow for production deployments and any time the firmware is part of the product. The firmware and rootfs are built together, stay in sync, and version bumps to either side propagate through the same bitbake invocation.

  • Use the Split-Machine Workflow - Prebuilt Common MACHINE when consuming AMD-published prebuilt demo images, when iterating on the Linux user space without rebuilding the firmware on every change, or when reproducing the published EDF demo flow on a common MACHINE. Custom firmware on top of a common-MACHINE rootfs requires the manual integration described in Bringing Custom Firmware Into a Prebuilt Common Image.

Bringing Custom Firmware Into a Prebuilt Common Image

If the rootfs has to stay on a common MACHINE but the firmware payload must change (for example, a custom Zephyr application or a modified OpenAMP demo), the firmware build and the rootfs build have to run as two distinct bitbake invocations. There are two integration options.

On-Target Replacement (Development Iteration)

Useful for rapid iteration without rebuilding the rootfs:

  1. Build the firmware under a board-specific MACHINE that defines the required multiconfig. For example, for the Zephyr RPU demo:

    $ MACHINE=versal-2ve-2vm-vek385-revb-multidomain bitbake openamp-zephyr-demo
    
  2. Locate the deployed binary in ${TMPDIR}/deploy/images/<MACHINE>/ (the multiconfig copies the firmware ELF to the parent MACHINE’s deploy directory as part of do_deploy).

  3. Copy the binary onto the running system into the path expected by the OpenAMP runtime package. For the current Versal Gen 1 and Kria SoM examples, that is a board-specific hierarchy under /lib/firmware/xilinx/<board>/rpu/0/:

    $ scp <firmware>.elf amd-edf@<target>:/lib/firmware/xilinx/<board>/rpu/0/
    
  4. Boot the firmware through the existing remoteproc interface, as shown in Loading the prebuilt OpenAMP RPU firmware demos.

This path leaves the prebuilt common rootfs untouched but the change does not survive a re-flash of the disk image.

Packaging With a Thin Recipe (Build-Time Integration)

To make the change persist across rootfs builds, mirror the pattern used by the in-tree openamp-fw-* recipes:

  1. Create a thin packaging recipe that requires openamp-fw.inc and overrides the source / installed firmware names:

    require openamp-fw.inc
    
    OPENAMP_FW_SRC_NAME = "<your-firmware>.out"
    OPENAMP_FW_NAME     = "<runtime-expected-firmware-name>"
    

    For Zephyr-based firmware, instead model the recipe on openamp-zephyr-demo.bb and set FW_MCDEPENDS / TARGET_MC to the multiconfig that builds your firmware. For the current Versal Gen 1 and Kria SoM OpenAMP examples, keep the board-specific install layout under /lib/firmware/xilinx/<board>/rpu/0/<firmware>.elf aligned with the runtime package’s expected firmware path.

  2. Add the recipe to a layer and rebuild the disk image as in Primary Workflow, against a board MACHINE that defines the required multiconfig.

  3. If the rootfs has to remain a common-MACHINE build, generate the firmware tarball under the board MACHINE first, drop it into the common-MACHINE meta layer, and pull it into IMAGE_INSTALL of the common-MACHINE image (the same pattern that edf-image-common.inc uses for the per-board *-openamp-fw-examples tarballs).

This is the approach to use when a long-term production product needs custom firmware riding on top of an EDF common-MACHINE rootfs. It is intentionally more involved than the primary single-step flow, and that extra cost is the reason a board-specific MACHINE is preferred whenever the deployment permits it.

Summary

  • The recommended approach is a single-step Yocto build against a board-specific MACHINE that defines the firmware multiconfigs. The firmware is pulled into the rootfs automatically through FW_MCDEPENDS / do_install[mcdepends].

  • The selected MACHINE must define every multiconfig the firmware recipes depend on; otherwise the firmware recipe skips itself and the Linux-side recipe fails to find a deployed binary.

  • Prebuilt common-MACHINE images are supported for demo and evaluation. Custom firmware on top of a common rootfs requires the manual two-step integration described above.

  • For the RPU-side multiconfig configuration (machine .conf files, Lopper, Zephyr build settings) see Yocto Project Zephyr Build. For the image variant matrix and DISTRO feature gating, see Linux-only and Platform Image Variants.