The Linux penguin hitches a ride to the BeagleBone Black via the Yocto Project

How the Yocto Project Brings Linux to the BBB

Linux is an amazing operating system. I first encountered it 20 years ago in college, when I dual-booted my desktop computer to Linux to avoid spending more time in the computer science lab. Perhaps my inexperience at the time played a role, but I found running a Linux desktop to be a difficult endeavor. Since then, through my work as a professional, I have continually used Linux as a desktop and server operating system. In that time, Linux has gotten progressively easier to deploy and use – more so than my growth through experience can account for. Moreover, running Linux in a virtual machine is a breeze, especially with popular distros like Ubuntu or openSUSE. I have found the reliability of modern Linux to be fantastic, and I have administered servers that run for months on end without issue.

Linux has steamrolled from its success running servers, desktops, and virtual machines to become an operating system of choice for the new world of the Internet of Things (IoT). Linux is open source, and it can be deployed without royalty. It is a great choice for embedded systems.

Likewise to Linux, the BeagleBone Black (BBB) is an amazing reference design board. The BBB interfaces to a variety of hardware, has ethernet connectivity, supports HDMI displays, and, thankfully, comes with Linux preinstalled! The latest Linux firmware images for the BBB can be found at beagboard.org. These images are fantastic for learning and prototyping, and for many users these images are the best choice. There are, however, instances where customized firmware is warranted, and for that The Yocto Project (YP) excels.

Outline

“It’s not an embedded Linux Distribution. It creates a custom one for you.”

The Yocto Project tagline

The YP consolidates the critical components of embedded Linux management. When a project calls for a custom Linux firmware, the YP makes it easier to generate a compatible toolchain, bootloader, kernel, and root filesystem. The resulting image is built with packages (rpm or deb), and one can use a package manager to update the system at runtime.

The instructions herein aim not to instruct on the ins and outs of the YP; I’ll leave that job to the online documentation and to books like Mastering Embedded Linux Programming. Rather, I’ll run through just enough steps to get Linux on the BBB using the YP.

Prerequisites

Development Host

This guide uses Ubuntu Linux 20.04 desktop edition as the build host operating system. Refer to the YP documentation for information on other compatible Linux distributions.

I used a physical PC running Linux to maximize the performance of the build. Apple may consider it obsolete, but my old Mac Mini has new life as my BBB development host. Unfortunately, Apple’s onboard SD card reader wouldn’t work with Linux, but the USB card reader linked in the parts below was a cheap and easy plug-and-play add-on.

Parts

PartLinkQTYNotes
BeagleBone BlackAmazon1
+5V DC 2A Power SupplyAmazon1USB power is insufficient to flash the board – a brick is required.
microSDHC CardAmazon1SDXC is not compatible! Get a 32GB SDHC – affordable and spacious.
TTL Serial to USB CableAmazon1Purchase the 3.3V version only.
SD/microSDHC Card ReaderAmazon1Purchase if necessary.

Command Convention

To avoid confusion, I will prefix commands with either you@build-host or you@bbb. This is your indication whether a command is to be run on the Linux development host or the embedded target, in this case a BeagleBone Black. I will also include a working directory with this prefix, as a typical bash prompt would display.

Some parts of the guide involve commands run from the u-boot execution environment. These commands will be prefixed =>, to distinguish them from target commands intended for the Linux environment.

Build Host Setup

At the time of this writing, the YP build host packages specifies the following installations to configure an Ubuntu 20.04 build machine:

you@build-host:~$ sudo apt install gawk wget git diffstat unzip texinfo gcc 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 zstd liblz4-tool

Source

Recall that the YP is not an embedded Linux distribution, but rather a means to create your own. The best way to get started with that is to use the YP reference distribution, called Poky.

Poky is available as a git repository, and as such, is obtained via the git clone command. I recommend using the latest Long-Term Support (LTS) branch of this repository, which will be codenamed according to the Yocto Project Releases. When I reviewed the list, kirkstone was the codename of the latest LTS branch.

you@build-host:~$ mkdir demo && cd demo
you@build-host:~/demo$ git clone -b kirkstone git://git.yoctoproject.org/poky.git

The build host should now have a folder ~/demo/poky that contains all the layers and recipes and whatnot to make the reference distribution, Poky. The next step is to load up the shell with the build settings, which is done as follows:

you@build-host:~/demo$ source poky/oe-init-build-env

The command above makes a folder called build, changes the working directory into that folder, and generates initial configuration files that can be edited to control the build.

Configuration

Poky is a reference distribution, and it targets reference development machines. One such machine is the the BBB, so in our case configuration is a one-line change. Edit the file ~/demo/build/conf/local.conf.

#
# Machine Selection
#
# You need to select a specific machine to target the build with. There are a selection
# of emulated machines available which can boot and run in the QEMU emulator:
#
#MACHINE ?= "qemuarm"
#MACHINE ?= "qemuarm64"
#MACHINE ?= "qemumips"
#MACHINE ?= "qemumips64"
#MACHINE ?= "qemuppc"
#MACHINE ?= "qemux86"
#MACHINE ?= "qemux86-64"
#
# There are also the following hardware board target machines included for
# demonstration purposes:
#
MACHINE ?= "beaglebone-yocto"
#MACHINE ?= "genericx86"
#MACHINE ?= "genericx86-64"
#MACHINE ?= "edgerouter"
#
# This sets the default machine to be qemux86-64 if no other machine is selected:
MACHINE ??= "qemux86-64"

By simply uncommenting the highlighted entry, for machine beaglebone-yocto, we have configured the build for the BBB.

Build

The next step is to run the build. The YP provides several example images. In a production environment, you are likely building your own image – that is what the YP is for. In this guide, I will build the provided example, core-image-x11.

you@build-host:~/demo/build$ bitbake core-image-x11

The task scheduler, bitbake, will get to work running the build as fast as the host can achieve it. On a first build, where nothing is cached, expect this to take considerable time – even on powerful workstations.

A man falls asleep on computer while building Linux.
Building a Linux distribution with the Yocto Project can take days to finish.

Target Preparation

WARNING: THESE INSTRUCTIONS CALL TO ERASE THE MEMORY ON THE BBB. DATA ON THE BBB WILL BE LOST.

The BeagleBone Black has both onboard eMMC memory and an SD card slot. For this guide, I will first demonstrate booting the BBB to an SD card imaged with the build result from the YP demo. Then, I will demonstrate flashing the BBB eMMC memory with the YP demo image. To begin, we will prepare the BBB by erasing the eMMC memory.

Remove any microSDHC card from the BBB. Attach the TTL serial cable and open a serial console. Apply power to the BBB with the +5V DC power supply. Press the spacebar, as prompted on the console, to interrupt the boot sequence. The BBB should be sitting on the u-boot command line.

Select the eMMC storage device.

=> mmc dev 1

Issue a command to erase the beginning portion of the card. The u-boot command line inputs numbers as hexadecimal. The number 0x20000 below, used positionally for the block count, is 131,072 in decimal format. With a typical SD card block size of 512 bytes, this call will erase 64 MiB of data from the beginning of the memory. Our aim is to overwrite the existing partition table and u-boot installation, and 64 MiB will surely get that job done.

=> mmc erase 0 20000

Now issue a call to reset the board.

=> reset

This will confirm we have successfully wiped the onboard memory. The initial boot loader should fail to find u-boot and will simply output an infinite series of the ‘C’ character.

resetting ...
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

Hold the power button on the BBB down until the board turns off.

SD Card Preparation

WARNING: THESE INSTRUCTIONS CALL TO ERASE THE SD CARD. ANY DATA ON THE CARD WILL BE LOST.

Insert the microSD card to the Host. You’ll need to identify the disk. I did this as follows:

you@build-host:~$ sudo fdisk -l | grep /dev/sd

From the output, I used the expected size of the microSD card to identify the disk:

Disk /dev/sda: 447.13 GiB, 480103981056 bytes, 937703088 sectors
/dev/sda1     2048   1050623   1048576   512M EFI System
/dev/sda2  1050624 937701375 936650752 446.6G Linux filesystem
Disk /dev/sdb: 931.53 GiB, 1000204886016 bytes, 1953525168 sectors
/dev/sdb1         40     409639     409600   200M EFI System
/dev/sdb2     409640  249846855  249437216   119G unknown
/dev/sdb3  250109952 1953261567 1703151616 812.1G Microsoft basic data
Disk /dev/sde: 29.74 GiB, 31914983424 bytes, 62333952 sectors

On my system, the SD card is recognized as /dev/sde. Substitute this device name with the proper device from your build host. Failure to do so can result in damage to your operating system.

As with the BBB’s onboard eMMC, I prefer to zero out the memory on the microSD card. To erase the first 64 MiB, issue the following command:

you@build-host:~$ sudo dd bs=64K count=1024 if=/dev/zero of=/dev/sde

Write the image created by the YP build to the SD card:

you@build-host:~$ sudo dd bs=64K if=~/demo/build/tmp/deploy/images/beaglebone-yocto/core-image-x11-beaglebone-yocto.wic of=/dev/sde

Have a look at the SD card:

you@build-host:~$ sudo fdisk -l /dev/sde

Note that there are 2 partitions. The first is the boot partition, and the second is the root filesystem. There is ample space left on the SD card!

Disk /dev/sde: 29.74 GiB, 31914983424 bytes, 62333952 sectors
Disk model: MassStorageClass
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1f5d25e0

Device     Boot Start     End Sectors   Size Id Type
/dev/sde1  *        8   65543   65536    32M  c W95 FAT32 (LBA)
/dev/sde2       65544 1133357 1067814 521.4M 83 Linux

Use the fdisk utility to expand the root filesystem partition to fill the remainder of the disk:

you@build-host:~$ sudo fdisk /dev/sde

The fdisk utility now runs interactively. Make selections to delete the second partition, then recreate it with the same starting sector. The last sector will default to the remainder of the disk, so accept that and proceed to verify the partition table and write the changes.

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk /dev/sde: 29.74 GiB, 31914983424 bytes, 62333952 sectors
Disk model: MassStorageClass
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1f5d25e0

Device     Boot Start     End Sectors   Size Id Type
/dev/sde1  *        8   65543   65536    32M  c W95 FAT32 (LBA)
/dev/sde2       65544 1133357 1067814 521.4M 83 Linux

Command (m for help): d
Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (65544-62333951, default 67584): 65544
Last sector, +/-sectors or +/-size{K,M,G,T,P} (65544-62333951, default 62333951):

Created a new partition 2 of type 'Linux' and of size 29.7 GiB.
Partition #2 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): p

Disk /dev/sde: 29.74 GiB, 31914983424 bytes, 62333952 sectors
Disk model: MassStorageClass
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1f5d25e0

Device     Boot Start      End  Sectors  Size Id Type
/dev/sde1  *        8    65543    65536   32M  c W95 FAT32 (LBA)
/dev/sde2       65544 62333951 62268408 29.7G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Command the build host operating system to re-read the SD card partition table.

you@build-host:~$ sudo partprobe

Check the SD card filesystem on the expanded partition.

you@build-host:~$ sudo e2fsck -f /dev/sde2

Expand the ext4 filesystem of the partition.

you@build-host:~$ sudo resize2fs /dev/sde2

Mount the partition on the build host.

you@build-host:~$ mkdir -p ~/demo/sdcard/p2
you@build-host:~$ sudo mount /dev/sde2 ~/demo/sdcard/p2

Copy the YP build result image to the SD card.

you@build-host:~$ sudo mkdir -p ~/demo/sdcard/p2/opt/backup
you@build-host:~$ sudo cp ~/demo/build/tmp/deploy/images/beaglebone-yocto/core-image-x11-beaglebone-yocto.wic ~/demo/sdcard/p2/opt/backup/

Unmount the SD card and remove it from the build host.

you@build-host:~$ sudo umount ~/demo/sdcard/p2

Boot and Flash the BBB

Put the SD card into the BBB and power the board. Login with root and no password. The YP image can now be flashed to the eMMC.

root@bbb:~# dd bs=64K if=/opt/backup/core-image-x11-beaglebone-yocto.wic of=/dev/mmcblk1

Shutdown.

root@bbb:~# shutdown -h now

Remove the SD card from the BBB. Power up again and confirm the board now boots up your custom Linux!

Expanding Root

Technically, the image is now flashed to the BBB and ready for use. However, this image is smaller than the physical eMMC storage of the BBB. To make full and efficient use of the BBB’s memory, we should extend the root filesystem partition to the maximum of physical space available.

There is a problem with doing this straightaway, though. The YP reference image is minimal – it lacks the partprobe, e2fsck, and resize2fs commands we used previously on the build host. We can work around that by temporarily using the debian firmware.

Insert the SD card on the build host. Zero out the memory.

you@build-host:~$ sudo dd bs=64K count=1024 if=/dev/zero of=/dev/sde

Download the latest console image from beagleboard.org. Verify the integrity with the posted checksum. Then unzip the image and write it to the SD card.

you@build-host:~$ wget https://debian.beagleboard.org/images/bone-debian-10.3-console-armhf-2020-04-06-1gb.img.xz
you@build-host:~$ sha256sum bone-debian-10.3-console-armhf-2020-04-06-1gb.img.xz > checksum.txt
you@build-host:~$ xz -d bone-debian-10.3-console-armhf-2020-04-06-1gb.img.xz
you@build-host:~$ sudo dd bs=64K if=bone-debian-10.3-console-armhf-2020-04-06-1gb.img of=/dev/sde

Now shutdown the BBB, insert the SD card, and boot it back up while holding the S2 button. Use the default username and password, debian/temppwd, to login. Then, proceed to resize the partition and filesystem of the eMMC.

debian@bbb:~$ sudo fdisk /dev/mmcblk1

Again, delete the second partition, then recreate it with the same starting sector. The last sector will default to the remainder of the disk, so accept that and proceed to verify the partition table and write the changes.

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk /dev/mmcblk1: 1.8 GiB, 1920991232 bytes, 3751936 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1f5d25e0

Device         Boot Start     End Sectors   Size Id Type
/dev/mmcblk1p1 *        8   65543   65536    32M  c W95 FAT32 (LBA)
/dev/mmcblk1p2      65544 1133357 1067814 521.4M 83 Linux

Command (m for help): d
Partition number (1,2, default 2):

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (2-4, default 2):
First sector (65544-3751935, default 67584): 65544
Last sector, +/-sectors or +/-size{K,M,G,T,P} (65544-3751935, default 3751935):

Created a new partition 2 of type 'Linux' and of size 1.8 GiB.
Partition #2 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): p

Disk /dev/mmcblk1: 1.8 GiB, 1920991232 bytes, 3751936 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x1f5d25e0

Device         Boot Start     End Sectors  Size Id Type
/dev/mmcblk1p1 *        8   65543   65536   32M  c W95 FAT32 (LBA)
/dev/mmcblk1p2      65544 3751935 3686392  1.8G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Reboot. (It is not necessary to hold S2 this time.)

debian@bbb:~$ sudo shutdown -r now

Now we proceed to check and resize the eMMC root filesystem.

debian@bbb:~$ sudo e2fsck -f /dev/mmcblk1p2
debian@bbb:~$ sudo resize2fs /dev/mmcblk1p2

Shutdown, remove the SD card, and boot the BBB again. Check the disk usage.

root@bbb:~# df -h

The root filesystem now utilizes the full remainder of eMMC memory.

Filesystem                Size      Used Available Use% Mounted on
/dev/root                 1.7G    228.6M      1.4G  14% /
devtmpfs                235.5M         0    235.5M   0% /dev
tmpfs                   244.0M    140.0K    243.8M   0% /run
tmpfs                   244.0M     72.0K    243.9M   0% /var/volatile
/dev/mmcblk1p1           31.9M      8.9M     23.0M  28% /boot

Closing Thoughts

A woman is frustrated her command was not found

Building a custom embedded Linux image is non-trivial, but is essential in many circumstances. Sometimes, there is no alternative, such as deploying Linux to custom-designed hardware. In other cases, performance or security constraints may force one to piece together an absolute minimal system. Additionally, enterprise development shops may look to a custom Linux for reliability and consistency with the toolchain. The YP gives practical structure to the complicated process of managing embedded Linux images. When circumstances call for a custom solution, the time invested to learn and maintain builds with the YP will pay dividends in productivity over the long run.

The YP supports the BBB hardware in the reference distribution, Poky, for good reason. The BBB is inexpensive, widely available, and built on an open-hardware design. This makes the BBB an excellent tool for anyone starting out with and learning the YP. The YP, however, is not a great tool for anyone starting out and learning the BBB. The debian firmware from beagleboard.org is designed for developers and makers to prototype and experiment rapidly. The aptitude package manager and the debian repositories make quick work of installing software and dependencies without the overhead of the YP recipes. For those reasons, I will be sticking with debian for now!

Leave a Reply

Scroll to Top
%d bloggers like this: