The ARM boot process refers to the sequence of steps that an ARM-based system goes through from the moment it is powered on until the operating system is up and running. This process is complex and involves coordination between hardware and software components.
When an ARM system is first powered on, the processor begins executing code starting from a hard-wired address in the ARM system’s memory map called the vector table. This table contains pointers to critical system startup code.
The first entry in the vector table is the reset vector, which points to the reset handler code. The reset handler initializes critical hardware components like DRAM and performs other low-level system setup.
Bootloader Stage 1
After the reset handler completes its tasks, it then jumps to the first-stage bootloader located in ROM or flash storage. This bootloader has a basic implementation that can read the next stage bootloader from storage into RAM.
The first-stage bootloader may perform tasks like:
- Initializing RAM
- Setting up stack pointer
- Enabling the MMU and caches
- Initializing simple serial debug output
Once its tasks are complete, the first-stage bootloader jumps to the second-stage bootloader that it loaded into RAM.
Bootloader Stage 2
The second-stage bootloader, also called the secondary program loader (SPL), has a more sophisticated implementation. It may be able to read file systems and supports loading images in formats like U-Boot and ARM Trusted Firmware.
Key tasks performed by SPL include:
- Advanced RAM initialization
- Initializing peripherals like GPIO, watchdogs, and timers
- Loading images like U-Boot into RAM
- Passing control to loaded images
SPL enables more advanced boot features like booting from storage devices, updating images, and booting alternative images for recovery.
Bootloader Stage 3
U-Boot is commonly used as the third-stage bootloader, though others like ARM Trusted Firmware can be used. This bootloader has a comprehensive environment with scripting and networking capabilities.
U-Boot provides functionality like:
- Booting images from different sources like flash, SD card, or network
- Command line interface for debugging and system control
- Loading Linux kernel, device tree, and ramdisk into RAM
- Configuring kernel parameters before booting
- Passing control to loaded kernel image
U-Boot offers complete control over the boot process and flexibility to handle different systems and boot scenarios.
Linux Kernel Initialization
U-Boot loads the Linux kernel image and optional ramdisk and device tree blobs into RAM, then passes control to the kernel entry point.
The kernel then goes through its initialization sequence:
- Set up low-level architecture specifics like stack and CPU mode
- Initialize early debugging output
- Parse command line arguments from U-Boot
- Initialize memory management unit and page tables
- Enable MMU and set up virtual memory layout
- Initialize rest of subsystems and core components
Once initialized, the kernel creates the first user space task which is usually the init process. This process runs initialization scripts that mount filesystems, launch background daemons, and start up core system services.
User Space Initialization
The init process executes scripts that perform essential user space setup steps like:
- Mounting necessary filesystems
- Configuring network interfaces
- Starting daemon processes like udev and crond
- Running rc scripts to launch services
- Starting login prompt or GUI environment
Once the user space is fully initialized, the system presents a login prompt or graphical environment to the user and normal operation begins.
ARM systems utilize multiple bootloader stages for modularity and flexibility. Each stage handles specific responsibilities.
The first-stage bootloader has minimal functionality but can initialize hardware and load the next stage. SPL adds platform and storage support and loads advanced bootloaders. U-Boot provides a rich environment to control the boot process before launching the kernel.
U-Boot is an open-source bootloader used across various ARM devices and boards. It is highly configurable and includes useful features:
- Support for loading images from flash, SD, USB, network, etc.
- Scripting capabilities to create boot scripts
- prebuilt configurations for many boards and SOCs
- Tools like mkimage to generate bootable images
- Active development community for support
U-Boot is a flexible choice as the final-stage bootloader before the kernel.
ARM Trusted Firmware
ARM Trusted Firmware provides a reference implementation of secure world software for ARMv8-A systems. It handles critical early initialization and provides abstraction between hardware and bootloader.
Key features include:
- Trusted boot capabilities using components like Trusted Board Boot
- Power, performance, and system error management
- Abstraction layer for hardware-specific operations
- Trusted services for additional security
Trusted Firmware can be used with U-Boot to support trusted boot flows.
There are several ways to control and modify the ARM Linux boot process:
- U-Boot environment variables – Used to select boot options and pass parameters to kernel.
- U-Boot scripts – Allow automating multi-step boot procedures.
- Kernel command line – Used to enable kernel features and select options.
- Device tree – Describes hardware details to kernel.
- initramfs – Bundle drivers and scripts needed for early user space startup.
- Systemd units – Control user space daemon and service startup order.
Multiple layers of configuration allow customizing ARM boots for specific hardware needs and use cases.
To protect against tampering and malware, ARM supports verified secure boot mechanisms:
- Signed bootloader images verified by ROM code before execution.
- Chain of trust established where each component verifies next.
- Device tree and kernel image also verified.
- Keys provisioned to device for verification.
- Failed verification can prevent boot.
This ensures boot components come from authorized source and haven’t been altered. ARM Trusted Firmware provides components to enable secure boot.
Boot Time Optimization
Boot time can be improved by:
- Speeding up storage by optimizing drivers, using faster media, etc.
- Optimizing U-Boot configuration by removing unneeded drivers, features, etc.
- Compressing kernel, ramdisk, and device tree.
- Removing unnecessary services, startup scripts, and daemons.
- Using a minimal ramdisk or initramfs.
- Launching fewer services at boot by disabling unused target runlevels.
Balancing boot speed with functionality allows optimizing boot time for a system’s particular use case.