Recently, I started to dig into the topic of Linux kernel, especially from the embedded point of view. I got a chance to explore the operating system, its configuration and build process at Nokia, where I currently work. I decided to shift this exploration to a different kind of hardware. Since I've got two Raspberry Pi at home, I decided to make a mini project, where I would prepare the operating system myself.
At first, I thought about using Yocto, but since I don't need the out-of-the box package management provided by this build system, I ended up using Buildroot. What is more, it turned out that Buildroot prepares the image much faster than Yocto. The first one builds it in less than an hour, the second one uses more than 4 hours.
In the following sections, I will describe the steps needed to prepare a minimal image, which can be booted on the RPi. I will also show, how to access the freshly booted system without any network connection or external LCD.
I will not go into Buildroot details yet. The goal is to get the system up fast.
At the moment of writing this post, the latest stable buildroot version is 2016.02.
It's easy as a pie:
$ wget https://buildroot.org/downloads/buildroot-2016.02.tar.bz2 $ tar xvjf buildroot-2016.02.tar.bz2 $ cd buildroot-2016.02
Buildroot is now ready for initial configuration. There are few commands that can help:
$ make help $ make list-defconfigs
The first one will show all of the make commands that are available. After executing the second one, two interesting configurations can be found:
raspberrypi2_defconfig - Build for raspberrypi2 raspberrypi_defconfig - Build for raspberrypi
Since I'm using Raspberry Pi B, the choice is obvious:
$ make raspberrypi_defconfig
Which does not last too long:
real 0m1.252s user 0m0.868s sys 0m0.124s
Now, with a little bit of patience:
$ make all
Which takes (on a i5-3320M):
real 42m22.210s user 101m33.384s sys 7m20.732s
The first time I ran make all, there was a problem with downloading the mpfr library. www.mpfr.org was unavailable, causing wget to hang and retry connection. The solution was to switch source address in package/mpfr/mpfr.mk
#MPFR_SITE = http://www.mpfr.org/mpfr-$(MPFR_VERSION) MPFR_SITE = https://ftp.gnu.org/gnu/mpfr
Buildroot places the output files in:
And the most interesting at the moment is the sdcard.img
$ ls -al output/images/sdcard.img -h -rw-r--r-- 1 tekieli tekieli 84M 04-03 18:11 output/images/sdcard.img
The default image is only 84 megabytes, which is much less than a Raspbian. The image can be copied straight to the SD Card:
$ dd if=sdcard.img of=/dev/mmcblk0
Unfortunately, placing the SD card in the RPi is not enough. Since the default configuration does not set up any network, it is good to have some kind of control over the system. Serial console is the perfect answer.
Here is my setup:
To access serial connection:
$ minicom -b 115200 -D /dev/ttyUSB0
After connecting the serial adapter and powering up Pi, minicom shows:
"Uncompressing Linux... done, booting the kernel."
Great! Serial connections works, but nothing more, no logs, no login prompt. It turns out that the default arguments supplied to the kernel are:
Serial output needs to be enabled. To do this, cmdline.txt file needs to be modified. It is located on the first partition of the SD card.
console=ttyAMA0,115200 root=/dev/mmcblk0p2 rootwait
This will enable the log output during kernel startup. To enable the login prompt, so that we are able access the newly built system, a minor change needs to be done in the Buildroot configuration. To access the configuration, in the Buildroot top directory run:
$ make nconfig
Go to "System configuration" -> "Run a getty after boot" and set the "TTY port" to ttyAMA0, "Baudrate" to 115200 and "TERM environment variable" to vt100.
After exiting, run make all to rebuild the change. This time the build execution should take seconds, as all of the results of previous run are reused.
The change can be checked in:
$ cat output/target/etc/inittab ... ttyAMA0::respawn:/sbin/getty -L ttyAMA0 115200 vt100 # GENERIC_SERIAL ...
After copying the new image to the SD card, login through serial console will be enabled:
Welcome to Buildroot buildroot login:
Default login is root and password is not set.
# ls -al / total 31 drwxr-xr-x 18 root root 1024 Apr 3 2016 . drwxr-xr-x 18 root root 1024 Apr 3 2016 .. drwxr-xr-x 2 root root 3072 Apr 3 2016 bin drwxr-xr-x 7 root root 2580 Jan 1 00:00 dev drwxr-xr-x 5 root root 1024 Jan 1 00:00 etc drwxr-xr-x 4 root root 1024 Apr 3 2016 lib lrwxrwxrwx 1 root root 3 Apr 3 2016 lib32 -> lib lrwxrwxrwx 1 root root 11 Apr 3 2016 linuxrc -> bin/busybox drwx------ 2 root root 16384 Apr 3 2016 lost+found drwxr-xr-x 2 root root 1024 Mar 1 2016 media drwxr-xr-x 3 root root 1024 Jan 1 1970 mnt drwxr-xr-x 2 root root 1024 Mar 1 2016 opt dr-xr-xr-x 52 root root 0 Jan 1 00:00 proc drwx------ 2 root root 1024 Jan 1 00:00 root drwxr-xr-x 3 root root 140 Jan 1 00:00 run drwxr-xr-x 2 root root 1024 Apr 3 2016 sbin dr-xr-xr-x 11 root root 0 Jan 1 00:00 sys drwxrwxrwt 2 root root 60 Jan 1 00:00 tmp drwxr-xr-x 6 root root 1024 Apr 3 2016 usr drwxr-xr-x 4 root root 1024 Apr 3 2016 var
The system is now functional and ready for further customizations.