Yocto for Cubieboard in QEMU

Yocto for Cubieboard in QEMU

Root filesystem options

The root filesystem is an important part of the BSP (Board Support Package), since it holds all of the applications, configuration files and kernel modules.

There are several ways to obtain root filesystem for an embedded Linux system

In the previous newsletter a prebuilt root filesystem from OpenWRT was used, and in the QEMU Board Emulation tutorials Ubuntu base was used as the root filesystem.

While using a prebuilt root filesystem is quick and easy, it also has some downsides:

  • not everyone has the same needs - there can be a lot of packages that are not used and need to be removed, and also a lot of packages can be missing, which would need to be installed somehow
  • fixed versions of packages - prebuilt root filesystem comes with certain, fixed versions of packages and it can be hard/impossible to change them
  • hard to maintain - once prebuilt image is customized to the needs, any future changes or improvements can be hard to handle, since everything has to be repackaged again

The prebuilt root filesystem can be an acceptable solution for rapid prototyping, or educational purposes, but it lacks the flexibility provided by the custom-built solutions.

In this post I will focus on Yocto, as a tool for guided/managed generation of custom-built root filesystem.

Yocto introduction

Yocto project provides tools and instructions used to build Board Support Package (BSP) and Linux distributions, especially for embedded targets. It is very configurable and provides fine grained control of output images.

Yocto builds everything, from native tools used to build the output products, cross-compiler and required libraries, to the final binary files and output image. This makes it also a reliable tool for reproducing builds.


A project in Yocto is organized into layers which contain configuration items and recipes for building applications and images. What is going to be build depends on image, machine and distribution that is selected, as well as local configuration parameters.

Yocto layers

In the picture above, there are three layers with recipes for different packages. As mentioned previously, the image, machine and distribution that are selected influence the recipes that will be built into the output image.

Recipe B is present in both layers 3 and 1, but since layer 3 has higher priority, recipe B from layer 3 will be used.

Yocto layers

The specification of available layers is contained in the file called bblayers.conf. That file holds list of paths to layers on the disk.

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "1"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  ${TOPDIR}/../sources/poky/meta \
  ${TOPDIR}/../sources/poky/meta-poky \
  ${TOPDIR}/../sources/poky/meta-yocto-bsp \
  ${TOPDIR}/../sources/meta-openembedded/meta-oe \
  ${TOPDIR}/../sources/meta-openembedded/meta-python \
  ${TOPDIR}/../sources/meta-sunxi \
"

The poky is the starting layer, or to be precise a collection of layers, which hold all the tools for building a Yocto distribution, as well as classes and recipes templates for building basic images.

The meta-openembedded layer has recipes for a lot of useful applications. It contains additional layers for python, networking, multimedia, etc.

The meta-sunxi layer contains machine definitions for the Allwinner-based Systems on Chip, as well as adaptations to some of the packages (like bootloader and Linux kernel, but also graphics support) so they are better suited for the Allwinner chips.

In this example we will use only layers and options provided by the standard available layers.

Local configuration

The local configuration can be used to define overall build-system behavior or to override certain configuration settings.

In the poky layer there is a default local.conf that will be used.

Building and running images in QEMU

Prerequisites

Before Yocto image can be built, several packages must be installed:

sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
  build-essential chrpath socat cpio python3 python3-pip python3-pexpect \
  xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa \
  libsdl1.2-dev pylint3 xterm python3-subunit mesa-common-dev

For details look at Yocto reference manual

Preparing environment

There are several ways to organize and maintain the Yocto build environment:

  • using google repo tool to manage the layers
  • using a standard git repository with layers as submodules

In this post we will use a third approach, where we will manually clone all needed repositories and prepare the bblayers.conf and local.conf files. This is done this way only for educational purposes, in a real use-case one of the two approaches listed above should be used.

Environment organization

The file structure we will use is sketched in the following block

.
├─ build/
│  └─ conf/
│     ├─ bblayers.conf
│     └─ local.conf
├─ downloads/
├─ sources/
│  ├─ meta-openembedded/
│  ├─ meta-sunxi/
│  └─ poky/
└─ sstate-cache/

The build and build/conf directories will be created automatically during the environment initialization, we just need to create the .conf layers inside it.

Besides the files and directories we have already mentioned, two additional directories will be created

  • downloads, where archives and git repositores with sources for packages are downloaded and kept,
  • sstate-cache, where intermediate build products for reuse will be stored during the build process.

The sstate-cache directory can speed up rebuilds, or different flavor builds, since packages that are not changed will be reused.

Initializing environment

We will start by downloading the layers

mkdir -p yocto/sources && cd yocto
git clone git://git.yoctoproject.org/poky -b kirkstone sources/poky
git clone https://github.com/openembedded/meta-openembedded -b kirkstone sources/meta-openembedded
git clone https://github.com/linux-sunxi/meta-sunxi -b kirkstone sources/meta-sunxi

After the layers have been downloaded, we can initialize the environment and create build/conf using

. ./sources/poky/oe-init-build-env build

This command will create the bblayers.conf and local.conf from templates and enter the build directory.

The conf/bblayers.conf should be edited to add the meta-openembedded and meta-sunxi layers. The final bblayers.conf file should look like

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  ${TOPDIR}/../sources/poky/meta \
  ${TOPDIR}/../sources/poky/meta-poky \
  ${TOPDIR}/../sources/poky/meta-yocto-bsp \
  ${TOPDIR}/../sources/meta-openembedded/meta-oe \
  ${TOPDIR}/../sources/meta-openembedded/meta-python \
  ${TOPDIR}/../sources/meta-sunxi \
"

We can also add two extra lines to the conf/local.conf, in order to make use of the downloads and sstate-cache directories.

cat >> conf/local.conf <<EOF
DL_DIR = "\${TOPDIR}/../downloads/"
SSTATE_DIR = "\${TOPDIR}/../sstate-cache/"
EOF

Building and running images

Before running a build, we need to enter the build directory,

The build is started using the following command

# build command
DISTRO=<selected_distribution> MACHINE=<selected_machine> bitbake <selected_image>

In our case, the MACHINE will be set to cubieboard, the DISTRO to poky, and we will use the core-image-minimal image, so the build command will be

DISTRO=poky MACHINE=cubieboard bitbake core-image-minimal

Important build products will be placed in ./tmp/deploy/images/cubieboard. The image file will have extension *.sunxi-sdimg. This is the SD card image which can be either copied (dd) to an SD card image created with qemu-img, or can be just resized using qemu-img to a power of 2 size. For instance

qemu-img resize ./tmp/deploy/images/cubieboard/core-image-minimal-cubieboard.sunxi-sdimg 1G

For instructions on using qemu-img instructions from QEMU Board Emulation tutorial can be used

Testing SD card boot

QEMU can be started using the following command

qemu-system-arm -M cubieboard -m 1G -nographic \
                -drive file=./tmp/deploy/images/cubieboard/core-image-minimal-cubieboard.sunxi-sdimg,format=raw,if=sd \
                -net nic -net tap,ifname=qemu-tap0,script=no
Poky (Yocto Project Reference Distro) 4.0.17 cubieboard /dev/ttyS0

cubieboard login:

The board went through the SPL -> U-Boot -> Linux boot process and waits for login. There is only the root account (without password) configured, so it can be used to login to the system.

The network connectivity can be enabled following instructions from QEMU Board Emulation Tutorial

For more details about the Yocto configuration, with more detailed example, the Cubieboard Yocto tutorial can be followed.

Subscribe
If you would like to get information as soon as new content is published, please subscribe to the "MistraSolutions newsletter".