Microprocessors
Programs

Hacking Raspberry Pi 4 with Yocto: Downloading Yocto

5.0 My Setup

I am going to be building the Linux image on an Ubuntu 18.04 guest operating system running on a Mac OS X 10.14 host. The host should not make a difference for those of you following along. However, if you are using a different flavor of Linux, some commands and dependencies will differ for you.

5.1 Prequisites for Building Yocto

To start using Yocto/Poky/OpenEmbedded, we first need to install prerequisites. I would check here for the latest ones, but at the time of this writing, this is what I needed to install in order to get Yocto working:

$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat libsdl1.2-dev xterm python

5.2 Downloading Yocto: Zeus Branch

$ cd ~
$ mkdir Yocto
$ cd Yocto
$ git clone -b zeus http://git.yoctoproject.org/git/poky

This will set us up with the "zeus" branch of Yocto, which, at the time of writing, is the latest community version of Yocto. After we do this, we need to create our build directory and set up all the environmental variables, paths, etc. that bitbake will need in order to build an image. To do this, we source the oe-init-build-env script.

$ cd poky
$ source oe-init-build-env

5.3 Downloading the meta-raspberrypi Layer: Zeus Branch

To download the meta-raspberrypi layer that contains the board support package (bsp) we'll need for our Raspberry Pi 4, do the following:

$ cd ~/Yocto 
$ git clone -b zeus git://git.yoctoproject.org/meta-raspberrypi

5.4 Editing the bblayers.conf and local.conf Files

The two most important configuration files in a Yocto build are both located in the poky/build/ directory. They are bblayers.conf and local.conf. The former tells bitbake where the various layers are located and the latter is used to configure things like the target of a build and the location of the output products of that build.

5.4.1 bblayers.conf

The bblayers.conf file in ~/Yocto/poky/build should have the following contents for our build.

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

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

BBLAYERS ?= " \ 
  /home/lance/Yocto/poky/meta \ 
  /home/lance/Yocto/poky/meta-poky \ 
  /home/lance/Yocto/poky/meta-yocto-bsp \ 
  /home/lance/Yocto/meta-raspberrypi \ 
  /home/lance/Yocto/meta-rpilinux \
  " 

Obviously, the path to all those directories in the BBLAYERS section will have to be adjusted to your own system (unless you have a username of lance like me). These directories are where Yocto will look for recipes along with .bb and .bbappend files. Don't worry about the meta-rpilinux directory for now. We'll create that in the next section when we create our own custom layer.

5.4.2 local.conf

The next file is local.conf. This is a very powerful file. It allows us to specify where the output products are going to be stored, what sort of debugging utilities will be available in the image, and all kinds of other good stuff. For us, right now, the only concern is the target machine for the build. Look for the MACHINE ??= "qemux86-64" line in the file and change it to:

MACHINE ??= "raspberrypi4-64"

The file specified above is a configuration file that is provided in the meta-raspberrypi layer. That file is located in the meta-raspberrypi/conf/machine directory, along with the configuration files for all the other possible Raspberry Pi boards available. If you take a look inside this file, you'll see that it has directives that tell bitbake what type of image to build, what the kernel image name is, and what serial consoles are used.

Making the Build Go Much Faster!

Another very extremely useful set of directives that should be included in this file are the BB_NUMBER_THREADS and PARALLEL_MAKE. We can use these to specify the number of processor cores that bitbake uses during the build. And since the cross-compiling and cross-linking processors are highly parallelizable, it makes a HUGE difference to use all the cores you have available.

On my Mac-Mini 3.2 GHz Intel Core i7 processor, I have six cores. So in my local.conf file, I included the following lines just above the # Machine Selection section.

# Uncomment and set to allow bitbake to execute multiple tasks at once. 
# For a quadcore, BB_NUMBER_THREADS = "4", PARALLEL_MAKE = "-j 4" would 
# be appropriate. 
BB_NUMBER_THREADS = "6" 
# Also, make can be passed flags so it run parallel threads e.g.: 
PARALLEL_MAKE = "-j 6" 

You'll have to include these lines and adjust them accordingly for your hardware.

5.4.3 Raspberry Pi 4 Image: 64 vs. 32 Bit Architecture

You'll notice that in the MACHINE directive above, we told Yocto to use the raspberrypi4-64.conf file. As one might guess, this is the configuration that makes use of the fact that the Raspberry Pi 4 has a Broadcom BCM2711 System on Chip (SoC) with a 1.5 GHz 64-bit quad-core ARM Cortex-A72. One can still run 32-bit instructions on such a processor, but that's not really taking full advantage of what the Pi 4 is packing.

After we build the image, we'll look at some methods to determine what type of architecture the executable files we made are intended for. But at this point, it can be instructive to look at some of the binary files included in the repository we downloaded in Section 2.4. In case you don't feel like going back and reading that, you can obtain them by just doing a git clone https://https://github.com/raspberrypi/firmware.git.

Let's take a look at a few of the files in depth to see the difference between 32 and 64-bit. Interestingly enough, there are some major differences between the kernel.img files that are provided. We can run the file command on each to see what type of files they are.

$ file kernel8.img
kernel8.img: MS-DOS executable
$ file kernel7l.img
kernel7l.img: Linux kernel ARM boot executable zImage (little-endian)

The former is an "MS-DOS executable" while the latter is a "Linux kernel ARM boot executable zImage".

If you want to determine what type of architecture these MS-DOS executables—which is what we'll be building with Yocto—are intended for, you can run the command: hexdump [filename] -n 80. The latter will dump out the first 80 bytes of the file in hexidecimal format. If we look at kernel8.img, we see:

$ hexdump kernel8.img -n 80
0000000 5a4d 9100 ffff 1429 0000 0008 0000 0000
0000010 e000 00d4 0000 0000 000a 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 5241 644d 0040 0000
0000040 4550 0000 aa64 0002 0000 0000 0000 0000

If we take a look at the documentation for these MS-DOS executables, we see that the PE entry has an offset of 0x40 in the file. At 0x40, we see the string "PE" (0x4550 in Little Endian; you can see this more easily by running hexdump with the -c argument). This is followed by 0xaa64 at 0x44. The latter indicates that this kernel[].img file is inteded for a 64-bit architecture!



← Previous    ...    Next →