How to cross-compile Embedded Linux (Part 3): Buildroot
Audio : Listen to This Blog.
This is the continuation of series of blogs about cross compiling, loading bootloader, Linux kernel and filesystem into an embedded development platform. Please check the previous blog for the target hardware and setup that is needed.
In short, the embedded development platform is beaglebone black with MicroSD card. We have already partitioned the card in the first blog and please look into it for more info
So far we have compiled U-Boot, Linux kernel and then loaded the builded images into the target hardware which is beaglebone black. At the end of the Linux kernel bootup log we got an error like “No working init found”. What it actually means is that it is not able to find the init binary which can be executed. Init in *nix based machines is the parent of all the processes except the kernel threads.
Basically to solve this issue we need a filesystem which provides us the init binary.
Buildroot
Buildroot is free and open-source software, maintained by Peter Korsgaard and licensed under version 2 or later of the GNU General Public License (GPL). It is a group of Makefiles and build script files which simplifies and automates the process of building a complete embedded Linux environment. For cross compiling to different target processor it can automatically build the required cross compilation toolchain. It has the support to create bootloader, Linux kernel and a root filesystem. It builds these independently also depending upon the user input.
It is primarily intended to be used with small or embedded systems based on various computer architectures including x86, ARM, MIPS and PowerPC.Numerous architectures and it also supports their variants. It also comes with default configurations for several development platforms such as Raspberry Pi, Cubieboard, etc. It is used as the basis for many third party projects and by many product development teams as it makes the process simple. It is organized as automatically downloaded packages which contain the source code of various userspace applications, libraries and system utilities. Root file system images, which are the final results, may be built using various file systems, including cramfs, JFFS2, romfs, SquashFS and UBIFS.
kasi@kasi-desktop:~/git$ git clone git://git.buildroot.net/buildroot
Configure the Buildroot
kasi@kasi-desktop:~/git$ cd buildroot/
The following command shows the list of files that is provided by buildroot.
kasi@kasi-desktop:~/git/buildroot$ ls -l/
Now execute the following command:
kasi@kasi-desktop:~/git/buildroot$ make menuconfig/
We need to select “Target options” here.
In the following image (figure 2), architecture is shown as i386 by default target.
We need to change that to ARM little endian as in the following image:
Next we need to move to the Target Architecture variant option. After choosing target architecture we can see that the Target Architecture variant is set to arm926t.
Check the following image.
Beagle bone black is actually based on Cortex-A8 variant and it is exactly what we need to choose.
After choosing these two parameters we need to save this config file and start the build. There are a lot of other options like choosing which C library to use and various packages selection options, for the moment let us save the config file as below.
configuration written to /home/kasi/git/buildroot/.config
*** End of the configuration.
*** Execute ‘make’ to start the build or try ‘make help'[/vc_column_text]
Build
As with other blogs we now need to give ‘make’ command to start the compilation process.
kasi@kasi-desktop:~/git/buildroot$ make
We need to wait for 15 to 20 minutes depending upon the build machine hardware specs and network bandwidth available for the build to complete.
Final Steps
Generating root filesystem image rootfs.tar rm -f /home/kasi/git/buildroot/output/build/_fakeroot.fs rm -f /home/kasi/git/buildroot/output/target/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM rm -f /home/kasi/git/buildroot/output/build/_users_table.txt echo '#!/bin/sh' > /home/kasi/git/buildroot/output/build/_fakeroot.fs echo "set -e" >> /home/kasi/git/buildroot/output/build/_fakeroot.fs echo "chown -h -R 0:0 /home/kasi/git/buildroot/output/target" >> /home/kasi/git/buildroot/output/build/_fakeroot.fs printf ' \n' >> /home/kasi/git/buildroot/output/build/_users_table.txt PATH="/home/kasi/git/buildroot/output/host/bin:/home/kasi/git/buildroot/output/host/sbin:/home/kasi/git/buildroot/output/host/usr/bin:/home/kasi/git/buildroot/output/host/usr/sbin:/home/kasi/git/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/bin:/home/kasi/bin:/home/kasi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" /home/kasi/git/buildroot/support/scripts/mkusers /home/kasi/git/buildroot/output/build/_users_table.txt /home/kasi/git/buildroot/output/target >> /home/kasi/git/buildroot/output/build/_fakeroot.fs cat system/device_table.txt > /home/kasi/git/buildroot/output/build/_device_table.txt printf ' /bin/busybox f 4755 0 0 - - - - -\n /dev/console c 622 0 0 5 1 - - -\n\n' >> /home/kasi/git/buildroot/output/build/_device_table.txt echo "/home/kasi/git/buildroot/output/host/usr/bin/makedevs -d /home/kasi/git/buildroot/output/build/_device_table.txt /home/kasi/git/buildroot/output/target" >> /home/kasi/git/buildroot/output/build/_fakeroot.fs printf ' tar -cf /home/kasi/git/buildroot/output/images/rootfs.tar --numeric-owner -C /home/kasi/git/buildroot/output/target .\n' >> /home/kasi/git/buildroot/output/build/_fakeroot.fs chmod a+x /home/kasi/git/buildroot/output/build/_fakeroot.fs PATH="/home/kasi/git/buildroot/output/host/bin:/home/kasi/git/buildroot/output/host/sbin:/home/kasi/git/buildroot/output/host/usr/bin:/home/kasi/git/buildroot/output/host/usr/sbin:/home/kasi/git/gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabihf/bin:/home/kasi/bin:/home/kasi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" /home/kasi/git/buildroot/output/host/usr/bin/pseudo-wrapper -- /home/kasi/git/buildroot/output/build/_fakeroot.fs rootdir=/home/kasi/git/buildroot/output/target table='/home/kasi/git/buildroot/output/build/_device_table.txt' /usr/bin/install -m 0644 support/misc/target-dir-warning.txt /home/kasi/git/buildroot/output/target/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM kasi@kasi-desktop:~/git/buildroot$
The build is completed and the zipped file system is available in the following location:
kasi@kasi-desktop:~/git/buildroot$ ls output/images/ rootfs.tar kasi@kasi-desktop:~/git/buildroot$
We need to untar this file and copy the contents into the Micro SD card’s fs partition (ext4 partition with size more than 4GB).
kasi@kasi-desktop:~/git/buildroot$ cd output/images/ kasi@kasi-desktop:~/git/buildroot/output/images$ ls rootfs.tar kasi@kasi-desktop:~/git/buildroot/output/images$ mount /dev/sdc2 on /media/kasi/fs type ext4 (rw,nosuid,nodev,relatime,data=ordered,uhelper=udisks2) /dev/sdc1 on /media/kasi/BOOT type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2) kasi@kasi-desktop:~/git/buildroot/output/images$
It is a better idea to copy the zip file into the Micro SD card’s fs partition and unzip it there.
kasi@kasi-desktop:~/git/buildroot/output/images$ sudo cp rootfs.tar /media/kasi/fs/ [sudo] password for kasi: kasi@kasi-desktop:~/git/buildroot/output/images$ sync kasi@kasi-desktop:~/git/buildroot/output/images$ cd /media/kasi/fs kasi@kasi-desktop:/media/kasi/fs$ ls lost+found rootfs.tar kasi@kasi-desktop:/media/kasi/fs$ sudo tar xf rootfs.tar kasi@kasi-desktop:/media/kasi/fs$ ls -l total 1488 drwxr-xr-x 2 root root 4096 Nov 18 16:48 bin drwxr-xr-x 4 root root 4096 Nov 18 16:48 dev drwxr-xr-x 5 root root 4096 Nov 18 16:48 etc drwxr-xr-x 2 root root 4096 Nov 18 16:48 lib lrwxrwxrwx 1 root root 3 Nov 18 16:38 lib32 -> lib lrwxrwxrwx 1 root root 11 Nov 18 16:47 linuxrc -> bin/busybox drwx------ 2 root root 16384 Nov 5 18:53 lost+found drwxr-xr-x 2 root root 4096 Nov 18 16:22 media drwxr-xr-x 2 root root 4096 Nov 18 16:22 mnt drwxr-xr-x 2 root root 4096 Nov 18 16:22 opt drwxr-xr-x 2 root root 4096 Nov 18 16:22 proc drwx------ 2 root root 4096 Nov 18 16:22 root -rw-r--r-- 1 root root 1443840 Nov 22 11:39 rootfs.tar drwxr-xr-x 2 root root 4096 Nov 18 16:22 run drwxr-xr-x 2 root root 4096 Nov 18 16:48 sbin drwxr-xr-x 2 root root 4096 Nov 18 16:22 sys drwxrwxrwt 2 root root 4096 Nov 18 16:22 tmp drwxr-xr-x 6 root root 4096 Nov 18 16:47 usr drwxr-xr-x 4 root root 4096 Nov 18 16:48 var kasi@kasi-desktop:/media/kasi/fs$
The Micro SD card now contains all the needed images/binaries to boot up a complete embedded Linux machine. Remove the Micro SD card from the build machine and by following the boot procedure to boot using Micro SD card we should now be able to get the shell prompt.
Sample Log from Target
U-Boot SPL 2016.11-rc3-00044-g38cacda-dirty (Nov 14 2016 - 13:02:35) ############################ ##### MSYS Technologies #### ##### We were here #### ############################ Trying to boot from MMC1 reading uboot.env ** Unable to read "uboot.env" from mmc0:1 ** Using default environment reading u-boot.img reading u-boot.img reading u-boot.img reading u-boot.img U-Boot 2016.11-rc3-00044-g38cacda-dirty (Nov 14 2016 - 13:02:35 +0530) CPU : AM335X-GP rev 2.0 Model: TI AM335x BeagleBone Black DRAM: 512 MiB NAND: 0 MiB MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1 reading uboot.env ** Unable to read "uboot.env" from mmc0:1 ** Using default environment not set. Validating first E-fuse MAC Net: Could not get PHY for ethernet@4a100000: addr 0 eth0: ethernet@4a100000 Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0 is current device SD/MMC found on device 0 reading boot.scr ** Unable to read file boot.scr ** reading uEnv.txt 193 bytes read in 3 ms (62.5 KiB/s) Loaded env from uEnv.txt Importing environment from mmc0 ... Running uenvcmd ... reading uImage 3852896 bytes read in 251 ms (14.6 MiB/s) reading am335x-boneblack.dtb 34185 bytes read in 8 ms (4.1 MiB/s) ## Booting kernel from Legacy Image at 80008000 ... Image Name: Linux-4.8.7 Created: 2016-11-15 9:57:37 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3852832 Bytes = 3.7 MiB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 88008000 Booting using the fdt blob at 0x88008000 Loading Kernel Image ... OK Loading Device Tree to 8fff4000, end 8ffff588 ... OK Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] ################################## [ 0.000000] ###### MSYS Technologies ###### [ 0.000000] ###### We were here too ###### [ 0.000000] ################################## [ 0.000000] Linux version 4.8.7 (kasi@kasi-desktop) (gcc version 6.1.1 20160711 (Linaro GCC 6.1-2016.08) ) #3 SMP Tue Nov 15 15:27:26 IST 2016 [ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c5387d [ 1.850061] EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities [ 1.873734] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null) [ 1.882582] VFS: Mounted root (ext4 filesystem) readonly on device 179:2. [ 1.892735] devtmpfs: mounted [ 1.898228] Freeing unused kernel memory: 1024K (c0b00000 - c0c00000) [ 2.005862] EXT4-fs (mmcblk0p2): warning: mounting fs with errors, running e2fsck is recommended [ 2.018977] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered Starting logging: OK Initializing random number generator... done. Starting network: OK ##### MSYS Technologies -- Welcome to Buildroot ##### ##### We are everywhere ##### buildroot login: root # uname -a Linux buildroot 4.8.7 #3 SMP Tue Nov 15 15:27:26 IST 2016 armv7l GNU/Linux
We are able reach the shell prompt with the file system we have created.
Hope this series of blogs helps you to bring up an embedded device based on Linux.