Dev/Embedded/FromScratch
Introduction
First of all, building your own system image for your board is a good idea.
This may feel a little bit confusing or difficult at first, but you'll find most information here and across this Wiki. It may not be exhaustive or up-to-date, but you'll have all the basics.
Building your own images is really important.
It means that :
- You have access to all the sources
- You do not depend on others to get what you want, update, or fix your system
- You will learn a lot
External requirements
In order to build your own system image you will need a few things :
- A system running a Linux based distribution. It will be your "host" or "development" system. (Well, the "Linux based" is not mandatory, but it's the one I use). I'm using a Devuan GNU/Linux system running on a x86_64 computer, but there are alternatives out there, for the distribution as well as for the hardware. It's best if it has some powerfull processors and plenty of available RAM and storage, but even the smallest system will do the job, it will only take more time.
- A (cross-)compiler toolchain. You'll find (most of) the information related to this part on my page dedicated to cross-compilation.
- A way to fetch the sources of course.
- A target system to run the binaries you'll build. Well you certainly have one, or you'll not be here, though it is also possible to use an emulator on your development system.
- A way to connect to your target's serial console. It may be possible to do it differently, but it's way easier to have a serial link to connect to the system console (UART), and I'll consider you are using this solution.
- Access to the sources and documentations for your hardware system and it's components. Though you won't need the documentation of all the parts, or even none of them if your system is already fully supported, it's always better if they are not black-boxes.
- Some time, curiosity and will. It's not very difficult, but you may enconter some problem as the systems you'll use are in constant evolution and may not behave the same as when I wrote these lines.
System content
All system images can be split in three parts :
- The bootloader
- The Linux kernel
- The userspace
These three parts may be split further, but it's the basics.
Bootloader
The bootloader is a small piece of software which is the first thing to run when the system is powered up.
The role of the Bootloader is to setup the hardware so that it can execute a bigger system : the Linux Kernel in our case.
Depending on your target hardware you may need more than one boatloader before you can get your Linux Kernel running. This is usually due to technical reasons, such as available memory or hardware security protections.
In most cases, the very first boatloader is a part you have no control over, and is usually called a "ROM bootloader" (or RBL), and is integrated in the ROM of the processor. This one will load your first stage bootloader from a given source, depending (most of the time) on the state of some configuration pins (boot selection or boot configuration) or internal fuses (e-fuses, which may be one-time programmable or not).
Depending on the hardware you'll use, this first stage bootloader can be :
- The only bootloader you'll need
- A smaller version of your bootloader : some processor will load the bootloader in the instruction cache of the processor, which may be too small for a full featured bootloader (tough if you manage to get everything you need in the available space, then you can get rid of the second stage bootloader and use only this one).
- A specific piece of firmware required for the processor, provided as source or binary : many recent ARM targets require an "ARM trusted firmware", now called "Trusted Firmware-A (TF-A)". Other may need other hadware specific bootloader to start.
When the first stage bootloader (sometimes called "Secondary Program Loader" (SPL)) is not the only required one, it will load your second stage bootloader (sometimes called "next stage" bootloader). Most of the time the second stage bootloader is from the same project as the first stage one (both u-boot, or both barebox for example), and when your board is supported the compilation is made in one go, both binaries being bundled in a single image.
In order to know what can and cannot be done with a specific board you will need the board's documentation or schematics (and the processor's documentation).
U-Boot (and Arm Trusted Firmware)
Most boards make use of U-Boot as bootloader.
Detailed information will be found on the page dedicated to U-Boot.
Other bootloaders
Some boards make use of barebox (https://www.barebox.org/) as bootloader (which is an u-boot derivative, and for some boards you may have the choice between different solutions.
Currently I always sticked to the bootloader advertised by the board vendor, and used barebox only on industrial boards not sold to the public, so I won't add any more information here.
Linux Kernel
On all my systems (embedded and PC) I'm using Linux based systems.
By definition, these use Linux as the kernel for the system, whatever the bootloader or the user-space part.
The Linux kernel can run on almost any processor you can find which has an MMU and two separate execution modes, tough it has even been ported on MMU-less systems and micro-controllers with a single execution mode.
It's purpose is to handle the hardware and provide an unified interface to the user-space programs. As such, it has to be taillored to the effective hardware present on your system.
Detailed information will be found on the page dedicated to the Linux Kernel.
Userspace
The "last" part you'll need to get a running system is the "userspace", which is simply all the binaries (executables), the libraries, the configuration files, the scripts, and all the other files and directories required by the system and your application.
This "userspace" is usually split in two parts : the "base system", and your application(s).
The "base system" is the part you get from an external source (or many), while the "application" part is pretty obvious : it's your own code and data.
Note that there are many confusions out there : some call the "base system" the "rootfs", others even add the application, though the "rootfs" can be either all (base + app) or only a subpart (not even whole base).
The rootfs is the part which the kernel is looking for in order to mount it as the root ("/") of the filesystems stack/tree, and where it will need to find your init binary. It can be reduced to an initramfs file containing a single init binary file.
Chose a solution for your base system
To build the base part of your userspace you have a few options :
- Build everything from scratch (follow Linux From Scratch instructions, I will not explain it on this Wiki)
- Use BusyBox : recommended for space constrained systems. Get more information for this choice on the BusyBox dedicated page.
- Use a GNU/Linux distribution : the easy way (I'm using Devuan GNU/Linux, but many other distribution may fit, just avoid those targeting only desktop or those making stupid choices). Also get more information for this choice on the Devuan dedicated page.
- Use an image provided from a third party (well, I'll never trust any of these, but it's up to you)
- Use an image builder tool (there's some unusable ones out there, Yocto may be the most popular, but I strongly advise against these "solutions")