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
Part | Link | QTY | Notes |
---|---|---|---|
BeagleBone Black | Amazon | 1 | |
+5V DC 2A Power Supply | Amazon | 1 | USB power is insufficient to flash the board – a brick is required. |
microSDHC Card | Amazon | 1 | SDXC is not compatible! Get a 32GB SDHC – affordable and spacious. |
TTL Serial to USB Cable | Amazon | 1 | Purchase the 3.3V version only. |
SD/microSDHC Card Reader | Amazon | 1 | Purchase 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.

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

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!