I. Step 1
In this first part, we had to set up the buildroot system basis.
Goals of this part are:
- Minimal buildroot configuration
- Copy the new firmware on RPi SD card
I.1. Base system specification
After downloaded the last release of buildroot, I prepared the build for Raspberry Pi 3 architecture.
In this interface “menuconfig”, I have to initiate the RAM filesystem:
Furthermore, as we can see in the picture above, I disabled the ext3/4 filesystem, it’s not necessary here.
I defined the root password:
I also changed the hash function, MD5 or SHA1 are deprecated.
The toolchain requested is Linario ARM, then I have to configure buildroot to use an external toolchain:
I.2. dd on the SD card
Now the build is ready for the Raspberry Pi 3, a little shot of dd on the SD card, and it’s done.
As mention above, the root filesystem is not required here, then I edited the “genimage-raspberrypi3.cfg” file, and remove this part. I saved the new file in “genimage-raspberrypi3-ENSIBS.cfg”.
Given that we modified the genimage name, I have to edit the “post-image.sh” file too (cf. Annexe 1 - Genimage ENSIBS & post-image.sh).
The firmware is ready, I have to build it, just make command in the buildroot root folder. When all dependencies are installed, I flashed the SD card:
II. Step 2
The step 2 consists to add the network layer in our firmware. As well as a path that allows us to edit configuration files in the firmware (it’s a overlays).
- Setting up an overlay
- Configuration of the network layer
II.1. Setting up on overlay
An overlay is a folder on the host system, it allows us to edit files in the firmware. Typically, we have to edit the interfaces file in /etc/network/ folder to setting up the network layer of our firmware. For this, I just have to create a directory and mention it in buildroot. For example, my path is:
In the first instance, the folder is empty, but at the end of the project, here is mine:
II.2. Network configuration
On the basis of the previous tree, we had to edit the interfaces and S40network file.
First of all, I noticed that the startup script for the ethernet interface (S40network) is triggered before the network card (hardware). I just add a 5 seconds sleep (cf. Annexe 2 - Sleep in S40Network file).
The “interface” file (cf. Annexe 3 - Static network configuration) allows the firmware to get a static address IP, a gateway, static network mask on a specific interface (i.e eth0 here). The firmware will have the IP address: 10.1.49.4⁄24 and the gateway will be my host system: 10.1.49.3.
II.3. Dropbear SSH installation
To install a known package in buildroot, it’s pretty easy. I just have to select it in the buildroot menuconfig:
Now, I must rebuild the firmware and flash again the SD card.
The default configuration of dropbear allows root connection, in our case, the only user on the firmware is the root user.
I will maybe add a hardening part later :D
Connection as root on the raspberry pi through SSH:
II.4. Update through network
The network connection is necessary to update (through SSH) the Raspberry Pi without unplugging the SD card from the Pi.
I made a little script (cf. Annexe 4 - Update script) to do this.
It following those steps:
- Copy the new firmware on the Pi (scp)
- Use the dd command to write the firmware on the SD card
- Restart the Raspberry Pi
This method works because the system is load in the RAM, so it won’t do any call to the SD card. By the way, we could remove the SD card from the raspberry pi during it operates, it will still work.
To improve my script, I could copy only the zImage file instead of the complete firmware (sdcard.img), for the V2! :p
III. Step 3
For this final step, I will install an external package (have to download sources, compile them and install, do the same thing with dependencies) and startup this package at boot.
- Install external package
- Check dependencies
- Start the package at boot
III.1. Install external package
The external package is: nInvaders. A Space Invaders for terminal! Very cool! :D
Tells to buildroot that we want to add an external package in the firmware, I have to add an entry Config.in (located in the root directory of buildroot). After that, the external package appears in the menuconfig of buildroot.
Then, create two files “Config.in”, “ninvaders.mk” in a folder called “ninvaders” (we have to create the folder).
- Config.in: This file tells to buildroot name of the external package, dependencies and help menu.
- ninvaders.mk: It’s a Makefile, it will build the package with all dependencies, but it’s not a standard Makefile, there is some environment variable and other settings manage by buildroot for the architecture (here it’s for Raspberry Pi 3).
Files are available in Annexe 5.
III.2. Check dependencies
NInvaders package needs ncurses dependancies. Fortunately, this package is easy to install and don’t need further dependencies.
In the file Config.in of nInvaders, there is the following line:
It will specify to buildroot that nInvaders needs ncurses.
To compile this dependency, we just need to add this line in our Makefile ninvaders.mk:
After a little make, the package nInvaders is successfully installed! Now, just connect to the Pi through SSH and execute ninvaders:
III.3. Start the package at boot
When the nInvaders package is successfully installed, we will execute it automatically when a session opens.
In our overlays, we need to add (at the end) the profile file in folder /etc of the firmware with the following lines:
Complete file is available in Annexe 6 - /etc/profile file.
The profile file will be executed when user shell is open. It’s quite like .bashrc with a bash shell.
To conclude this article, this project was very interesting, it’s a good introduction for people (like me) without knowledge of firmware building.
- Hardening part
- Update script
- Build more interesting (honeypot IoT ?)
Annexe 1 - Genimage ENSIBS & post-image.sh
Annexe 2 - Sleep in S40network file
Annexe 3 - Set static IP address
Annexe 4 - Update script
Annexe 5 - Config.in and ninvaders.mk
Annexe 6 - /etc/profile file