Build kernel and bootloader for your embedded board (PART 1)

Rhythm Chopra
5 min readOct 19, 2018

--

This is the first part of series, Libretech tritium Board Bringup.

There can be times when you wonder, what is the actual sequence of commands which initiates the boot-up process of a board, starting from bootloader till the filesystem once the board is powered on.
Well, after spending quiet a time searching and googling, I somewhat got an idea of that stuff. So, let’s see what I found.

So, here we’ll build bootloader and kernel(bare minimum) from source and boot the board using them.
The following commands and code-snippets have been tested on Ubuntu 18.04.

Following is the checklist before continuing

  1. An embedded board, (in my case, libretech all-h3-cc h2+)
  2. Serial to USB connector (with 3 volts output), with jumper cables, which will be used for debugging and executing commands on board.
  3. A formatted sdcard, to flash bootloader
  4. A USB, to power the board (pretty obvious, right?)

So, to run commands on board, we would need a serial terminal emulator (such as minicom), which can be installed as follows

sudo apt install minicom

If you don’t have git install, then run this

sudo apt install git

Install cross compiler toolchain and other dependencies

sudo apt install bison flex swig gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf

So, let’s start with bootloader(u-boot)

Cloning and building u-boot

git clone git://git.denx.de/u-boot.git u-boot

Now, lets build it. Move into cloned u-boot directory and continue.

Create build configuration

Configuration files for almost all the boards is found in u-boot/configs/, find corresponding defconfig file for your board and replace libretech_all_h3_cc_h2_plus_defconfig in following command.

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- libretech_all_h3_cc_h2_plus_defconfig

Change .config file generated for partition number

This one is something I had to do because, u-boot was unable to find kernel image on sdcard. You might or might not need it, but if you have same board as mine, you definitely should do this.

sed -i ‘s/CONFIG_ENV_FAT_DEVICE_AND_PART=.*/CONFIG_ENV_FAT_DEVICE_AND_PART=”0:auto”/g’ .config

Finally, build the bootloader

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

Flashing u-boot to sdcard

After the build is complete, you will see some new files in u-boot directory. But we need to focus on just 1 or maybe 2, depending on how you proceed to flash.

Connect sdcard to host computer/ laptop and flash u-boot

Depending upon how your sdcard is connected, your device name will change in following commands. If you have an sdcard slot in laptop, it’ll be something like `/dev/mmcblkX` (X can be 0, 1, 2…), and if you use sdcard reader, it’ll be `/dev/sdX` (X can be b, c, d…). So modify following command accordingly.

Run any of the following 2 command blocks
Flash SPL and u-boot together

sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8 status=progress

Flash SPL and u-boot separately

sudo dd if=spl/sunxi-spl.bin of=/dev/sdX bs=1024 seek=8 status=progress
sudo dd if=u-boot.img of=/dev/sdX bs=1024 seek=40 status=progress

Checking u-boot

Plug in sdcard in board’s sdcard slot.
Connect UART pins on board to Serial to USB connector. In following manner

GND — GNDRX — TXTX — RX

Configure minicom for ttyUSB0 port with baudrate 115200 and hardware flow control to NO. Plug in and start minicom.
Power up the board and you should get something like this in console

If there’s nothing on console, try swapping RT-TX on either of the ends.

Hit enter or any key to enter u-boot console. Here you can try all the commands u-boot supports. We will use this console to boot the board once we have the kernel image ready.

Now, lets head towards kernel

Cloning and building linux-kernel 4.18 and device-tree

git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git -b linux-4.18.y linux

Now, lets build it. We will build the bare minimum linux kernel with default configuration for now. Move into cloned linux directory and continue.

Create build configuration

Since we are building for an ARM device, required defconfig file can be found in arch/arm/configs/. Replace the one corresponding with your board in following command

make ARCH=arm sunxi_defconfig

Build kernel zImage

Based on the number of cpus in your computer, change the number after -j in following command

make -j 8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage

Now sit back and wait, this is gonna take some time…

Build device tree

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

Copy kernel image and device tree to sdcard

Considering you are following this guide from beginning, your sdcard should be having u-boot already flashed. Otherwise, flash u-boot before continuing

Mount sdcard, change your sdcard device accordingly

sudo mount /dev/sdX1 /mnt

Copy kernel Image

sudo cp arch/arm/boot/zImage /mnt/zImage

Copy device tree blob

Change the sun8i-h2-plus-libretech-all-h3-cc.dtb file, in case you have another board

sudo cp arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dtb /mnt/device_tree.dtb

Unmount sdcard

sudo umount /mnt

Testing kernel image

  1. Plug sdcard into the board
  2. Start minicom after connecting USB to serial connector
  3. Power up the board and hit any key to enter u-boot console as before
  4. Load kernel image and device tree into memory.

Finding memory addresses for kernel and device tree

Before loading kernel and device tree into memory, you need to find out the memory addresses allocated for kernel image and device tree for your board configuration.
Run following commands in u-boot terminal, to find expected memory addresses.

printenv

Now look for a key like kernel_addr_r in terminal output, that is the memory address for kernel image.
And look for a key like fdt_addr_r in output, that is the memory address for device tree.

Now load kernel and device tree into corresponding memory address as follows, you can change variables $kernel_addr_r and $fdt_addr_r to memory addresses found above.

mmc rescan
load mmc 0:1 $kernel_addr_r zImage
load mmc 0:1 $fdt_addr_r device_tree.dtb

Now finally boot with following command

bootz $kernel_addr_r — $fdt_addr_r

Now you will start seeing logs for Starting kernel, which will eventually get stuck at a kernel panic.

But it’s fine, as we haven’t build a filesystem for the kernel to continue.

So now you have build u-boot and kernel which are capable of booting up your board.

So, in the next one, we’ll build a filesystem image and use the bootloader and kernel build above to properly boot up the board.

Part 2 is available here

Cheers.

--

--

Rhythm Chopra

Tech Enthusiast | Software Engineer | Trying out new stuff