Fundamentals 9 min read

How Does the Linux Kernel Boot? A Deep Dive into Decompression and Initialization

This article explains the Linux kernel boot sequence, covering the decompression of a compressed kernel, the early startup code in head.S, the preparation steps performed by U-Boot, and the detailed initialization phases—including architecture setup, memory management, process creation, and the start_kernel routine.

Open Source Linux
Open Source Linux
Open Source Linux
How Does the Linux Kernel Boot? A Deep Dive into Decompression and Initialization

Linux Kernel Self-Decompression Process

After U-Boot finishes system boot, it executes the command stored in the bootm environment variable, loading the Linux kernel into memory and calling the do_bootm function. If the kernel is uncompressed, it starts directly; if compressed, a decompression routine in the kernel header is invoked.

The source file for the compressed kernel entry point is /kernel/arch/arm/boot/compressed/head.S. It calls decompress_kernel(), prints “Uncompressing Linux...done, booting the kernel”, then uses gunzip() (or unlz4(), bunzip2(), unlz()) to place the kernel at the designated address and start it.

Linux Kernel Startup Preparation Phase

The kernel link script /kernel/arch/arm/kernel/vmlinux.lds shows that the entry function is stext (defined in /kernel/arch/arm/kernel/head.S). After decompression, the code jumps to stext to begin execution.

ENTRY(stext)
setmodePSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode and irqs disabled
mrcp15, 0, r9, c0, c0 @ obtain processor ID into r9
bl __lookup_processor_type @ returns procinfo in r5, cpuid in r9
mov r10, r5 @ invalid processor (r5=0?)
beq __error_p @ error 'p' if unsupported
bl __lookup_machine_type @ returns machinfo in r5
mov r8, r5 @ invalid machine (r5=0?)
beq __error_a @ error 'a' if unsupported
bl __vet_atags @ verify ATAGS format from U-Boot
bl __create_page_tables @ create initial page tables
ldrr13, __switch_data @ address to jump to after preparation

(1) Disable IRQ/FIQ and switch to SVC mode via the setmode macro.

(2) Validate the processor ID; if unsupported, abort boot.

(3) Validate the machine code; if unsupported, abort boot.

(4) Verify the ATAGS format passed from U-Boot.

(5) Create a coarse page table used in early boot; a finer table will be rebuilt later.

(6) Jump to __switch_data, which calls __mmap_switched for final preparations.

1) Copy .data segment, clear .bss to set up C runtime environment.
2) Save processor ID, machine code, and ATAGS pointer.
3) Branch to start_kernel for kernel initialization.
__switch_data:
    .long __mmap_switched
    ...
__mmap_switched:
    adrr3, __switch_data + 4
    ldmiar3!, {r4, r5, r6, r7}
    cmp r4, r5 @ Copy data segment if needed
    ldrne fp, [r4], #4
    strne fp, [r5], #4
    bne 1b
    mov fp, #0 @ Clear BSS
    ...
    str r9, [r4] @ Save processor ID
    str r1, [r5] @ Save machine type
    str r2, [r6] @ Save ATAGS pointer
    bic r4, r0, #CR_A @ Clear A bit
    stmiar7, {r0, r4} @ Save control register values
    b start_kernel
ENDPROC(__mmap_switched)

Linux Kernel Initialization Phase

This phase starts with the start_kernel function, the entry point for all Linux platforms. It completes remaining hardware‑specific initialization, performs a series of kernel‑level setups, then launches the first user‑space process init, marking the end of kernel boot.

3.1 Main Work of start_kernel

start_kernel

performs several key initializations:

Architecture‑specific and generic configuration

Memory management setup

Process management setup

Scheduler initialization

Network subsystem initialization

Virtual file system setup

File system initialization

3.2 Key Functions in the start_kernel Flow

start_kernel flow diagram
start_kernel flow diagram

setup_arch(&command_line)

This architecture‑specific initialization handles processor parameter setup, early processing of the tagged list of boot parameters, and early memory subsystem initialization.

The command_line is the boot argument string passed from U‑Boot (environment variable bootargs). If empty, it defaults to the kernel’s built‑in command line defined by CONFIG_CMDLINE.

setup_command_line, parse_early_param, parse_args

These functions parse and store command‑line parameters. Example parsing result: console=ttySAC2,115200 – console device and baud rate root=/dev/mmcblk0p2 rw – root filesystem path init=/linuxrc – first user‑space process rootfstype=ext3 – filesystem type

sched_init

Initializes the scheduler, creates the run queue, and sets up the idle thread for the current task.

rest_init

Performs the final kernel startup steps:

1) Call kernel_thread to start two kernel threads: kernel_init and kthreadd.
   kernel_init mounts the root filesystem and invokes init_post to run the first user process (init).
   If the init path from command_line is invalid, fallback to /sbin/init, /etc/init, /bin/init, or /bin/sh.
2) Call schedule() to start the scheduler.
3) Call cpu_idle() to launch the idle process.

These steps complete the Linux kernel boot process.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KernelLinuxAssemblyInitializationbootU-Boot
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.