Embedded Linux booting process

Prashant Divate
4 min readApr 7, 2021

This article will walk you through every step of the process of Embedded Linux booting. This is meant for engineers who are both new to working with embedded Linux, as well as those who are new to yocto project in general. No matter your current skill level, every step of the process is explained in detail

Full blog is quickly summarized in below video if you tired of reading 😄https://youtu.be/mTVtytWP9Sk

The Embedded Linux boot process involves the following steps:

figure. steps of booting process
  1. BOOT ROM

“Boot ROM” on chip includes code that the processor vendor develops and burns into the ROM. After a processor is reset, it executes ROM startup code. The ROM startup code initializes the CPU, memory controller, and on-chip devices, and it configures the memory map. It is also called as ROM Program Loader (RPL). The ROM code can load the SPL image from any of the following devices:

  • Memory booting with MMC
  • Peripheral booting with UART

2. SPL

The ROM copies content of “MLO” file (bootloader)to static static RAM. SRAM memory is limited (due to physical reasons), so we only have few KBs for bootloader. Usually regular bootloader (e.g. U-Boot) binary is bigger than that. So we need to create some additional bootloader, which will initialize regular RAM and copy regular bootloader from MMC to RAM, and then will jump to execute that regular bootloader. This additional bootloader is usually referred as uboot-SPL.

3. uboot

The bootloader decompresses the Linux kernel into RAM from Flash memory or a TFTP server transfer. It then executes a jump to the kernel’s first instruction. The kernel first configures microprocessor registers and then invokes start_kernel, which is the architecture-independent starting point.

Since embedded systems do not have a BIOS to perform the initial system configuration, the low level initialization of microprocessors, memory controllers, and other board-specific hardware varies from board to board and from CPU to CPU. These initializations must be performed before a Linux kernel image can execute.

4. Kernel

Now the kernel is loaded into memory and initialized. The initrd image is compiled and mounted into the memory. It serves as a temporary root file system and helps kernel to boot properly without mounting any root file system. Now that all the drivers are loaded into memory, and kernel has booted, kernel mounts the root filesystem in read only mode, and starts the first process.

5. init

‘init’ is the first process started by kernel (initialization process). It is parent of all processes. The PID (Process ID) of init process is always 1. This process persists till the computer halts. It is responsible for the whole state of system. The settings for this process are stored in its configuration file, /etc/inittab (system initialization table). Before diving deeper into the details of this file and proceeding any further with the boot process, let’s discuss about runlevels.

Runlevel is the state in which a system boots. It can boot in a single user mode, multiuser mode, with networking, and with graphics etc. Following are the default runlevels defined by Linux:

0: Halt or shutdown the system
1: Single user mode
2: Multi-user mode, without networking
3: Full multi user mode, with NFS (typical for servers)
4: Officially not defined; Unused
5: Full multi user with NFS and graphics (typical for desktops)
6: Reboot

The executing init process loads shared runtime libraries. init reads its configuration file, /etc/inittab, and executes scripts.

‘inittab’ file from recipe-sysvinit is:

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
# The default runlevel.
id:5:initdefault:

The general format of entries in this file is:

id:runlevel(s):action:process

Typically, init executes a startup script, /etc/rc.d/rcS, which configures and starts networking and other system services. After all these scripts have been executed, then finally “/etc/rc.local” script runs. init enters a runlevel where system duties can be performed or the login process can start, allowing for user sessions.

Don’t forget to like, comment, and subscribe to my youtube channel https://www.youtube.com/channel/UC0gLxk2vYC4LtbXyjBLy4sA for more tutorials on embedded systems and Linux.

--

--

Prashant Divate

An Embedded Software Engineer. Artist by nature and developer by passion, passionate learner. Open source lover and after all a wonderful human being.