Table of Contents
Where kernel loading fits in the boot chain
By the time “kernel loading” happens, a lot of work has already been done:
- Firmware (BIOS/UEFI) runs hardware initialization and finds the boot device.
- The bootloader (typically GRUB2 on Linux) is started from that device.
- The bootloader selects which kernel to boot and loads it (and its initramfs) into memory.
- Control is transferred from the bootloader to the kernel’s entry point.
This chapter covers steps 3 and 4: how the kernel image and initramfs are found, loaded, verified, and started.
You will see GRUB2 and firmware concepts mentioned, but their detailed behavior is covered in their own chapter. Here, focus on what specifically happens around the Linux kernel image itself.
Kernel images and their formats
Linux kernels are built into “images” that the bootloader can load into memory. The exact file and format depend on platform and distribution.
Common kernel image files
On x86 systems, you will most often see:
vmlinuz-*
Compressed, bootable Linux kernel image.
Typical paths:/boot/vmlinuz-6.8.0-xx-generic(Debian/Ubuntu-style)/boot/vmlinuz-linux(Arch-style)/boot/vmlinuz-<version>(generic pattern)bzImage(historical term)
The classic name for a “big zImage” — the compressed kernel format used on x86.
On modern distros, thevmlinuz-*file is typically abzImage.
On other architectures, names vary (e.g., Image, zImage, uImage), but the idea is the same: a self-contained binary that includes:
- Kernel code and data.
- A small decompressor stub.
- A boot-time header so the bootloader/firwmare knows how to jump into it.
Compressed vs uncompressed
A modern Linux kernel is large, so it is shipped in compressed form:
- Compression types:
gzip,bzip2,xz,zstd, etc. - Compression is rarely handled by the bootloader itself. Instead:
- Bootloader loads the compressed kernel image into memory.
- The kernel’s own decompressor runs first, uncompressing the image into its final location in RAM.
- Then the kernel proper starts.
This matters for:
- Boot speed (compression algorithm trade-offs).
- Memory layout (compressed vs decompressed size).
- Bootloader support (some firmware environments can load only certain formats).
What the bootloader does for kernel loading
Assuming GRUB2 (other bootloaders behave similarly), the kernel-loading role is:
- Locate the kernel image
GRUB uses a configuration file (commonly/boot/grub/grub.cfg) that specifies:
linux /boot/vmlinuz-6.8.0-31-generic root=UUID=... ro quiet splash
initrd /boot/initrd.img-6.8.0-31-genericlinux(orlinuxefion some UEFI setups) line points to the kernel image.initrdline points to the initramfs image.
- Load kernel and initramfs into memory
- Reads the kernel file from disk into memory at addresses chosen by the bootloader.
- Reads the initramfs file and places it in memory, then passes its location to the kernel through the boot protocol.
- Applies any required relocation to avoid overlaps with firmware or itself.
- Pass boot parameters (kernel command line)
The kernel command line (for example,root=... ro quiet) is passed as a string.
It affects: - Which root filesystem to mount.
- Boot mode flags (e.g.,
single,init=/bin/sh,nomodeset). - Debugging options and hardware quirks.
- Optionally verify signatures
In secure boot scenarios: - GRUB or the firmware may verify a signature on the kernel image and/or initramfs before loading or executing.
- If verification fails, boot is refused.
- Transfer control to the kernel
The bootloader calls the kernel entry point defined in the x86 boot protocol (or the equivalent on other architectures), handing over CPU control, registers, memory maps, and parameters.
Once that jump happens, the bootloader is out of the picture; the kernel takes over.
The Linux boot protocol (x86 perspective)
On x86, the interaction between bootloader and kernel is defined by the Linux boot protocol. You usually never touch this directly, but it explains what has to be prepared before the kernel can start.
Key things the bootloader must supply:
- Entry point
The kernel specifies a start address (a protected-mode entry on modern 32/64-bit systems). GRUB jumps there. - Boot parameters structure
A data structure containing: - Pointer to the command-line string.
- Pointer to the initramfs (if any) and its size.
- Memory map (list of usable and reserved RAM regions).
- Framebuffer/graphics information (for early console, splash, etc.).
- ACPI and other firmware tables.
- CPU mode and state
Typically: - 32-bit protected mode or 64-bit long mode enabled.
- Interrupts disabled.
- Some registers set per the protocol.
Other architectures (ARM, RISC-V, etc.) have their own conventions, but the idea is similar: bootloader loads the kernel at a given address, sets up basic CPU state, and calls a known entry point with some structure describing memory and firmware data.
From kernel entry to fully running kernel
From the moment the bootloader jumps into the kernel, the process is fully controlled by the kernel code.
1. Decompression and relocation
Steps:
- The small decompressor stub at the start of the image runs.
- It uncompresses the main kernel binary into its final location in memory:
- Ensures it does not overwrite the initramfs or firmware data.
- Deals with high memory vs low memory constraints.
- Control is passed to the uncompressed kernel’s early entry point.
Possible failure points here:
- “Decompressor failed” messages (corrupt or truncated kernel).
- Incompatible CPU features (kernel built for newer CPU than present).
2. Very early initialization (arch-specific)
This is still before init runs and before drivers are fully initialized:
- Set up basic page tables (virtual memory) and enable paging.
- Enable 64-bit long mode on x86-64 if not already active.
- Initialize per-CPU data structures.
- Parse early kernel parameters (e.g.,
earlyprintk,noapic, and some debug flags). - Map and store firmware tables (ACPI, SMBIOS, EFI tables).
If something goes wrong here, you see very early kernel panics or the system appears to “freeze” right after the “Loading Linux…” message.
3. Parsing the kernel command line
The kernel command line string provided by the bootloader is parsed to configure:
- Root filesystem choice:
root=UUID=...,root=/dev/sda1 - Read-only vs read-write:
roorrw - Alternative
initprogram:init=/bin/sh - Debugging options:
debug,loglevel=7 - Hardware parameters:
pci=nomsi,acpi=off, etc.
This affects later stages like root mounting and init selection, but the parsing itself is part of kernel loading and early boot.
4. Attaching the initramfs
If the bootloader provided an initramfs:
- Kernel knows:
- Start address in memory
- Length of the initramfs blob
- The initramfs is a compressed cpio or similar archive.
- Kernel unpacks it into a temporary root filesystem in RAM (usually
tmpfsorramfs).
At this point, the initial root filesystem is populated from the initramfs, and the kernel expects to find an init process inside it (e.g., /init or /sbin/init).
The details of what the initramfs does are covered in the initramfs chapter; here, the important point is: loading and attaching initramfs is part of the kernel’s early loading/initialization work.
Kernel loading in BIOS vs UEFI environments
The high-level idea is identical, but some details change depending on firmware type.
BIOS-style boot
Typical chain:
- BIOS loads the first-stage bootloader from the MBR.
- Bootloader eventually loads the full GRUB2 and its modules.
- GRUB2:
- Reads
/boot/grub/grub.cfgfrom a filesystem it understands. - Loads
/boot/vmlinuz-and/boot/initrd.img-into memory. - Switches CPU to protected/long mode if required.
- Calls the kernel’s entry point per the x86 boot protocol.
The kernel does not care that BIOS was used; it only sees the final CPU state and parameter structures.
UEFI-style boot
Typical chain:
- UEFI firmware loads an EFI executable from the EFI System Partition, such as:
shimx64.efi(often signed, used for Secure Boot)grubx64.efi(GRUB2 as an EFI application)- GRUB2 (EFI version):
- Runs as a UEFI application, using UEFI services to read disks.
- Loads the kernel and initramfs into memory.
- Prepares the boot parameters, including EFI-specific data (e.g., EFI system table pointer).
- Jumps to the kernel.
Alternatively, some setups use:
- EFISTUB: the kernel itself is an EFI application. UEFI loads the kernel directly without an external bootloader, passing command line and initramfs via EFI options. In this case, the kernel image must contain EFI headers.
From the kernel’s perspective:
- It can detect being booted via EFI vs BIOS.
- It accesses firmware data through different interfaces.
- But the basic loading sequence (image in memory, decompression, early init) is the same.
Initramfs: how it is loaded (from the kernel’s side)
Although initramfs has its own chapter, a couple of kernel-loading-specific points matter:
- The initramfs is typically not loaded by the initramfs itself; rather:
- Bootloader loads the compressed initramfs archive into memory.
- Kernel is given a pointer and size.
- During early boot, the kernel:
- Uncompresses the archive into a RAM-based filesystem.
- Treats it as the initial root filesystem.
- If no initramfs is provided:
- Kernel must be able to mount the real root filesystem directly using built-in drivers and compiled-in support.
- This places more requirements on the kernel configuration.
Problems in loading/initramfs at this stage often show as:
- “Cannot open root device” panics.
- “No init found. Try passing init= option to kernel.”
- Messages about missing
/initor root filesystem drivers.
Kernel parameters that influence loading and early boot
Some common kernel command-line parameters affect kernel loading directly or indirectly:
init=/path/to/program
Changes the first userspace program the kernel runs.root=...
Tells the kernel or initramfs where the real root filesystem resides.rootdelay=SECONDS
Delay before attempting to mount root (useful with slow storage).earlyprintk=.../loglevel=N
Control early logging and debugging output while the kernel is still in early initialization stages.noinitrd
Some bootloaders or configurations may use this to indicate there is no initramfs.kaslr/nokaslr
Enable/disable kernel address space layout randomization, affecting where the kernel is placed in memory. This influences memory layout already at loading time.
These are examples of how “kernel loading” is not just copying bytes into memory, but also configuring how and where the kernel will operate once it starts.
Troubleshooting issues in the kernel loading stage
Many boot problems appear just as (or shortly after) the kernel is being loaded. Common symptoms and where they likely occur:
- “Loading Linux …” and immediate freeze or reboot
- Kernel image corrupt or incompatible.
- Decompressor crashes (e.g., bad RAM, wrong CPU, broken image).
- Kernel panic with very few messages, no root filesystem mounted
- Problem with initramfs loading or parsing kernel parameters (e.g., wrong
root=). - “No such device” or “cannot open root device” right after kernel messages begin
- Initramfs did not contain the proper storage drivers or filesystem modules.
root=points to a wrong or missing device.
Tools/approaches that are specifically useful here:
- Edit the kernel command line at the bootloader menu to:
- Remove splash/quiet options and see full messages.
- Add
debugandloglevel=7to increase verbosity. - Boot an older kernel from the bootloader menu.
- Boot into a rescue environment and check:
/bootcontents (are kernel and initramfs files present and consistent?).- Bootloader configuration (do paths and versions match?).
Deeper recovery or configuration steps are covered in the boot troubleshooting chapter, but these are the kernel-loading-specific angles.
Summary of the kernel loading sequence
Putting it all together, the high-level flow during kernel loading is:
- Bootloader loads the compressed kernel image into memory.
- Bootloader loads the initramfs image into memory (if configured).
- Bootloader passes:
- Memory map
- Firmware tables
- Initramfs location and size
- Kernel command line
- CPU mode and entry point
- Bootloader jumps to the kernel entry point.
- Kernel decompressor unpacks the kernel into its final location.
- Kernel initializes early CPU and memory management.
- Kernel parses the command line and attaches/initramfs.
- Initial root filesystem (usually from initramfs) is ready, and the kernel proceeds to start the first userspace process.
Everything after that — init systems, services, and user login — sits on top of this kernel loading foundation.