Most software engineers spend unnatural working hours writing code for enterprise problems which, to be honest, is an industry cliché. Yes, deriving solutions for complex business problems can be the reward but after doing it for a few years one might want to consider broadening their domain especially in the arena of embedded systems.
With IoT (Google it) creeping into the industry we now see a strong shift towards embedded systems and “smart” devices in the market. Just think about it, you walk into a high-end electronics store and a fridge would likely greet you and tell you what the weather is like. If you are paranoid about machines taking over the world *terminator music* then this series may not be for you, however, if you are curious and want to know how these tiny embedded systems actually work, then just maybe, this blog might come in handy.
Bootloader, what is it?
Bootloader, what is it? Well, the name more or less gives it away but for the sake of formalities – the purpose of the bootloader is to initialize the system to a very basic level and load the kernel, once the kernel is loaded the bootloader’s job is done and the memory is reclaimed. Typically, minimal resources such as a single CPU core and some on-chip static memory is used in the beginning, as the program executes it brings each of the systems into operation and finally, the kernel is loaded into the memory.
|RedBoot||ARM, MIPS, PowerPC|
|Barebox||ARM, MIPS, PowerPC, Nios II|
|Das U-Boot||ARC, ARM, Blackfin, MicroBlaze, MIPS, Nios II, OpenRice, PowerPC, SH|
|GRUB 2||x86, x86_64|
During the early days when life was simpler, NOR flash was used to place the bootloader but now it is done in phases that follow Universal Extensible Firmware Interface (UEFI) standards.
Phase 1 (The world of ROM code)
The code that is executed immediately after power-on is stored on a chip in the SoC and is commonly known as ROM code. The only RAM that the ROM code has access to is the small amount of static RAM available in most SoC designs. The ROM code loads a piece of code from preprogrammed locations such as the first sectors of an SD card into the SRAM. In some cases where the SRAM is not large enough to load the entire bootloader an intermediate secondary program loader known as SPL is used.
Phase 2 (Second stage/Secondary Program loader)
The secondary program loader also known as SPL sets up the memory controller and other system components to facilitate the loading of the third stage program loader into DRAM. At this stage, the SPL usually does not allow user inputs however you can read version details from the serial output during execution.
Phase 3 (Third stage program loader)
The third stage program loader known as TPL is essentially the bootloader that has the capacity to load the kernel into memory. During the TPL stage you can interrupt the bootloader process and execute maintenance commands without loading the kernel automatically. At the end of phase 3, the kernel is loaded and ready to fire.
When switching hands from the bootloader to the kernel, the bootloader does so with a parting gift. This gift essentially has zero human value but for the kernel this information is gold! The gold nuggets are essential information such as the architecture of the SoC, CPU clock speed, size of RAM, size and location of the device tree. We will discuss what a device tree is in another article but for now I shall sum it up as a road map of all the components available in a system.
Associate Tech Lead, Project Delivery
Mastering Embedded Linux Programming – Second Edition – Chris Simmonds
Embedded Programming with Android: Bringing Up an Android System from Scratch (Android Deep Dive) – Roger Ye