Application Deployment using Yocto Recipes AMD Versal device portfolio

Application Deployment using Yocto Recipes AMD Versal device portfolio

This section of the getting started guide provides walk through style examples using the AMD Embedded Development Framework (EDF) covering applications deployment using Yocto Project™ recipes.

Once applications have been created, the Yocto Project build system can be used to package and manage deployment. This might mean integration into the image build or using a package stream or container store to enable over the air updates to the running system.

Table of Contents

Application Deployment using Yocto Recipes

image-20250328-112619.png

Software Application Deployment

This section describes building a simple "hello world" application using a basic Yocto recipe.

  1. Build the Yocto pre-requisites by following https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/3258089693/Operating+System+Integration+and+Development+AMD+Versal+device+portfolio#Yocto-Project-build-setup-instructions-for-EDF

  1. The following example is based on the hello-single example from meta-skelaton provided by the Yocto project.

  2. Copy the required files to sources/meta-amd-edf/recipes-apps/hello-simple - note that the source files could easily be moved to an external or local Git repo and cloned before they are built.

    File structure:

    /scratch/edf/sources/meta-amd-edf/recipes-apps/hello-simple $ tree . ├── files │  ├── hello-simple.c │  └── Makefile └── hello-simple_1.0.bb

    helloworld.c:

    #include <stdio.h> int main(void) { printf("Hello simple world!\n"); }

    Makefile:
    Note: in a Makefile, the indented lines must use a real tab and not a set of space characters!

    .PHONY: all install clean ALL = hello-simple all: $(ALL) install: $(ALL) mkdir -p $(DESTDIR)/usr/bin cp $(ALL) $(DESTDIR)/usr/bin clean: -$(RM) $(ALL) *.o

    hello-simple_1.0.bb:

    DESCRIPTION = "Simple helloworld application" SECTION = "examples" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = "file://hello-simple.c file://Makefile" S = "${WORKDIR}" EXTRA_OEMAKE = "DESTDIR=${D}" do_install() { oe_runmake install }
  3. Add the recipe to the image as shown below - the GP Linux image can be found in sources/meta-amd-edf/recipes-extended/*.bb

    local.conf:

    Note: the space before the word ‘hello’ is significant

    IMAGE_INSTALL:append = " hello-simple"
  4. In order to make the new application available on the system it will be necessary to rebuild the wic image and flash the SD card again or possibly copy the resulting .rpm file to a running system.

  5. On the running system the compiled binary can be found in the configured directory

    rootfs:

    /usr/bin/hello-simple

An example recipe for the autotools-based hello world application that we have compiled previously on target or using the application SDK can be found here https://web.git.yoctoproject.org/poky/plain/meta-skeleton/recipes-skeleton/hello-autotools/hello_2.10.bb

Kernel module

This section describes building a simple kernel module using a basic Yocto recipe.

For this example, we are writing a Yocto recipe for the same HDMI kernel module that we used in previous tutorials for the on-target and SDK-based development flow. The same template can be used for your own kernel module.

  1. Build Yocto pre-requisites by following https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/3258089693/Operating+System+Integration+and+Development+AMD+Versal+device+portfolio#Yocto-Project-build-setup-instructions-for-EDF

  2. Create a new recipe 'kernel-module-hdmi-test.bb' and place it under 'meta-amd-edf/recipes-kernel/hdmi-test'. It should look similar to the following:

SUMMARY = "Xilinx HDMI 2.1 FMC linux kernel module" DESCRIPTION = "Out-of-tree HDMI 2.1 FMC kernel modules provider for aarch64 devices" SECTION = "kernel/modules" LICENSE = "GPL-2.0-only" LIC_FILES_CHKSUM = "file://LICENSE.md;md5=eb723b61539feef013de476e68b5c50a"   inherit module   S = "${WORKDIR}/git"   SRC_BRANCH = "master" SRC_URI = "git://github.com/Xilinx/hdmi21-modules.git;protocol=https;branch=${SRC_BRANCH}" SRCREV = "089a930c5aef4ac7d3be59bbe55e6a270db1da68"   INHIBIT_PACKAGE_STRIP = "1"
  1. Add the recipe to the image as shown below.

local.conf:
Note: the space before the word ‘kernel’ is significant

IMAGE_INSTALL:append = " kernel-module-hdmi-test"
  1. Once images are built, kernel module files will be installed on target_rootfs:

rootfs:

/lib/modules/6.12.10-xilinx-gf28cb5f8491a/updates/xfmc/hdmi21-xfmc.ko

Firmware Bundle

This section describes how to create a simple firmware Yocto recipe.

Refer to the https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/3258188188 tutorial for generating the firmware artifacts used in this tutorial with Vivado

  1. Build Yocto pre-requisites by following https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/3258089693

  2. Create the recipes-firmware directory in the meta layer and copy the *_pld.pdi, .dtsi/dtbo, .json and .xclbin (optional) files to these directories.

    mkdir:

    $ mkdir -p <meta-layer>/recipes-firmware/<recipes-firmware-app>/files $ cp -r <path-to-files>/*.{bit or bin or pdi, dtsi or dtbo, shell.json or accel.json and .xclbin} <meta-layer>/recipes-firmware/<firmware-app-name>/files
  3. Now create the recipes for flat or static or partial firmware using recipetool.

    recipetool-create:

    $ recipetool create -o <meta-layer>/recipes-firmware/<firmware-app-name>/firmware-app-name.bb file:///<meta-layer>/recipes-firmware/<firmware-app-name>/files
  4. Modify the recipe and inherit the dfx_user_dts bbclass as shown below.

    recipetool-create:

    SUMMARY = "<firmware-app-name> Segemented Configuration(DFx Full) firmware using dfx_user_dts bbclass" DESCRIPTION = "<firmware-app-name> Segemented Configuration(DFx Full) firmware application" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"   inherit dfx_user_dts   SRC_URI = "\     file://shell.json \     file://<design_name>_pld.pdi \     file://pl.dtsi \     "   COMPATIBLE_MACHINE:<machine-name> = "${MACHINE}"

    Note: Instead of dtsi, you can alternatively provide a compiled dtbo file

  5. Add the firmware-recipe app to the image as shown below.

    local.conf:
    Note: the space before the word ‘firmware’ is significant

    IMAGE_INSTALL:append = " firmware-app-name"
  6. Once images are built, the firmware app files will be installed on target_rootfs. 

    rootfs:

    /lib/firmware/xilinx/firmware-app-name

Deploying a Container Image - Hello World Example

This section describes how to create a simple container image Yocto recipe which can be uploaded to a container registry or copied to a running system. 

The following “hello world“ example is based on the container-app-hello-world recipe from the meta-amd-edf layer. It builds on top of the container-app-base recipe from the meta-virtualization layer.

require recipes-extended/images/container-app-base.bb # Hello world example from meta-skeleton CONTAINER_APP = " hello" CONTAINER_APP_CMD = "hello"

CONTAINER_APP should contain the recipe(s) you need to install in the container

CONTAINER_APP_CMD is the (default) binary which the container runtime will execute when the container is run. This binary needs to be provided by one of the packages listed under CONTAINER_APP. For an interactive container this should be set to "sh" or similar (this default can be overwritten later).

Build:

To build the container image, run the following bitbake command. Set the MACHINE value to the desired target machine

$ MACHINE=amd-cortexa78-mali-common bitbake container-app-hello-world

The output can be found in the tmp/deploy/image/<MACHINE> folder, e.g.

build/tmp/deploy/images/amd-cortexa78-mali-common $ ls -l <snip> lrwxrwxrwx - user 18 Nov 17:12 container-app-hello-world-latest-oci -> container-app-hello-world-amd-cortexa78-mali-common.rootfs-20241118170958.rootfs-oci lrwxrwxrwx - user 18 Nov 17:12 container-app-hello-world-latest-oci-dir.tar -> container-app-hello-world-amd-cortexa78-mali-common.rootfs-20241118170958.rootfs-oci-dir.tar lrwxrwxrwx - user 18 Nov 17:12 container-app-hello-world-latest-oci.tar -> container-app-hello-world-amd-cortexa78-mali-common.rootfs-20241118170958.rootfs-oci.tar <snip>

The container image can either be pushed to a container registry such as dockerhub using a tool such as skopeo GitHub - containers/skopeo: Work with remote images registries - retrieving information, images, signing content (out of scope for this document) or the resulting rootfs tar ball can be copied to the target and imported using the docker command line.

Import a container image without a registry:

To get the full functionality from container images, they should be uploaded to a registry such as dockerhub as discussed previously. Alternatively, it is possible to copy the container image roofs to the host and run it as an image without relying on a registry. This can simplify the process of working with container images but comes at the cost of reduced functionality. By design, docker does not support directly importing OCI containers (the format generated by Yocto) on the command line as they only support importing containers in the docker format. 

It is possible to directly import a generated rootfs (tar.bz2) into docker and run it as a container - the caveat is that this will not contain any of the metadata (information or settings) that is stored in the container. For example, one known issue is that the container entry point is not available this way. You will have to specify the entry point as part of the docker run command yourself. Also, the repository and tag fields will not be populated when listing docker images. You have to pass the image ID to the run command instead of the name.

The generated rootfs can be found in tmp/deploy/images/<MACHINE> and should be scp'ed to the running system before being imported and run with docker. On the target, run the following commands:

amd-edf:~$ bunzip2 ./container-app-hello-world-amd-cortexa78-mali-common.rootfs-20241113140349.tar.bz2 amd-edf:~$ sudo docker import container-app-hello-world-amd-cortexa78-mali-common.rootfs-20241113140349.tar sha256:eaa826f05183f70b927a1245219f7f1ea0d89ebe6468ba91cb41e3c8795ac9ce amd-edf:~$ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> eaa826f05183 10 seconds ago 4.29MB amd-edf:~$ sudo docker run -it eaa826f05183 hello Hello, world!

Related Links

 

Trademarks

Yocto Project and all related marks and logos are trademarks of The Linux Foundation. This website is not, in any way, endorsed by the Yocto Project or The Linux Foundation.

Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.

© 2025 Advanced Micro Devices, Inc. Privacy Policy