Introduction
To build an embedded Linux OS for a specific target board, it’s important to understand the main components of a Linux system:
- Compiler Toolchain (Cross-Compiler Toolchain)
- Bootloader
- Linux Kernel
- Root FileSystem
This first article of this series will focus on the first two components the Cross compiler and Bootloader.
Compiler Toolchain
Definition
A toolchain compiler is a tool that takes a source code as input and outputs a binary that can be executed on an OS.
When developing a custom embedded Linux system for a specific hardware, the first step is to build the corresponding toolchain compiler of the board’s processor. Because thanks to it, the Bootloader, the Kernel and the File System resources can be compiled. It is built in general on GNU/Linux workstation.
Note: The output binaries from the compiler available on a GNU/Linux can only be executed on the same workstation architectures. It’s called Native Toolchain Compiler.
The concerned toolchain to be built is a Cross-Compiler Toolchain. Which means it can be run on a GNU/Linux OS to compile a source code in order to have output binaries that can be executed on a different workstation architecture.

Toolchain Tuples
Since different systems are involved in a toolchain, they can be defined in a principle called ‘Target Triplets’ where each system is specified by a triplet in the form of ‘cpu-vendor-os’ knowing that vendor field can sometimes be left out and the os itself can sometimes be in two fields such as linux-gnu :
- Build (The machine where the toolchain is built eg. x86_64-linux-gnu for Intel 64-bit GNU/Linux)
- Host (The machine where the toolchain will be executed after it’s built eg. x86_64-linux-gnu for Intel 64-bit GNU/Linux)
- Target (The machine where the output binaries will be executed after compilation eg. arm-unknown-linux-gnueabi for ARM GNUeabi/Linux)
So the native and the cross-compiler are represented as shown bellow:
- native (build == host == target)
- cross (build == host != target)
Some toolchain examples:
- x86_64-unknown-linux-gnu (cpu=Intel 64bit, Vendor=unknown, OS=GNU/Linux)
- arm-unknown-none-eabi (cpu=arm, Vendor=unknown, OS=Bare-Metal with Embedded Application Binary Interface)
Tools to build Cross-Compiler Toolchain
A cross-compiler toolchain can be built using crosstool-ng or using automation tools such as Buildroot.
Bootloader
Definition
When building an embedded Linux OS the Bootloader comes in the second step because this is what is going to boot the system.
The bootloader can briefly be defined as a program that loads and executes another program after initializing needed hardware components. It can load an application software in case of Bare-Metal systems or a Kernel in case of operating systems. When talking about embedded Linux systems the bootloader will obviously load a Linux Kernel.
To understand how loading and executing a program are done, it’s essential to comprehend what is called the ‘Boot Sequence ‘ of a system.
The system boot sequence gathers all the steps (stages) executed on a system between the power-on action and the complete system start.
Boot sequence
The boot sequence and its stages are different from system to other. A generic three stages boot sequence can be summarized in figue 2 and following steps:
- After resetting the system, the first powered-on component is the CPU and the boot Rom Code located in it is executed. This is known as the first stage.
The role of the Rom Code is to initialize hardware components (SRAM…) needed for the second stage program (Bootstrap) and to load it from the storage media (SD Card or FLASH…) to SRAM then jump to it to launch it since the RAM is not yet initialized. - The second stage program is the Bootstrap. It will initialize hardware components (RAM…) needed for the third stage program (Bootloader) and load it from storage Media to the RAM then launch it by jumping to it.
- Once started the Bootloader will initialize some other devices needed for the Linux Kernel (Network, USB…) and load it with the Device Tree binary from network, USB flash drive or storage media to the RAM then execute it by jumping to it.
The kernel will then have complete control of the system.

Bootloader examples
Some bootloaders for embedded systems:
- U-Boot
- BAREBOX
Leave a Reply