331 – Android Bootloader: From Chip Power-On to Kernel Loading

Series Navigation: 330-Boot Overview | 332-init Process | 333-Zygote

In the previous article, we outlined the complete Android boot chain. This article focuses on the first software stage — the Bootloader.

The Bootloader is the first software code to run after hardware powers on (hard-coded in ROM/Flash). It is responsible for initializing hardware, loading the kernel, and verifying signatures. On Android devices, the Bootloader is often the most customized component and serves as each phone manufacturer’s “moat” — locking the bootloader is the first line of defense for system integrity.


The Bootloader’s Place

In embedded systems (phones, tablets, IoT devices), the Bootloader plays a similar role to a PC’s BIOS/UEFI, but with several key differences:

Dimension PC BIOS/UEFI Phone Bootloader
Storage location Motherboard SPI Flash SoC internal ROM + eMMC/UFS
Upgradable Usually upgradable BL1 cannot be changed, BL2 can be upgraded
Responsibilities Enumerate hardware, load GRUB Initialize DRAM, load kernel, verify signatures
Security UEFI Secure Boot (optional) Mandatory signature verification, DM-Verity

Memory layout after phone power-on:

Bash
0x00000000 ─┬─ ROM (Boot ROM, hard-coded in chip, unmodifiable)
            │   └─ BL1: Burned into CPU chip at factory, executed first after CPU reset
            │
0x00000000 ─┴─ SRAM (Chip internal high-speed memory, small capacity, for temporary data)
            │
0x10000000 ─┬─ DRAM (External memory, must be initialized by Bootloader before use)
            │   └─ Load Kernel + ramdisk (initramfs)
            │
0x00000000 ─┬─ eMMC/UFS (External storage)
                └─ BL2: Upgradable boot program (LK/ABOOT/U-Boot)

Bootloader Two-Stage Structure

Android device Bootloaders typically use a two-stage (or even three-stage) design:

Stage 1: BL1 (Boot ROM)

The first instruction executed after CPU reset. Hard-coded inside the chip.

Bash
CPU Reset → Boot ROM (BL1)
    → Initialize minimal hardware (MMU/cache/Stack)
    → Load BL2 from storage media into SRAM
    → Jump to BL2

BL1’s responsibilities are extremely streamlined — it only needs to load BL2 from persistent storage into memory. Since DRAM may not be initialized yet, many chips can only use SRAM.

Stage 2: BL2 (Little Kernel / ABOOT / U-Boot)

BL2 is the fully functional boot program that can be customized and upgraded.

Qualcomm devices commonly use LK (Little Kernel):

Bash
LK (BL2)
    → Initialize DRAM
    → Parse boot partition (kernel + ramdisk)
    → Signature verification
    → Load kernel into DRAM
    → Jump to execute kernel

Spreadtrum/MediaTek devices commonly use U-Boot:

Bash
U-Boot (BL2)
    → Initialize DRAM / NAND Flash
    → Set boot parameters (ATAG/DTB)
    → Load kernel
    → bootz or bootm

Bootloader Detailed Workflow

Bash
┌─────────────────────────────────────────────────────────────┐
│                    Chip Power-On / Reset                     │
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│  BL1: Boot ROM (CPU internal ROM)                           │
│  ┌──────────────────────────────────────────────────────────┐│
│  │ 1. CPU initial state:                                    ││
│  │    - Disable MMU, disable D-Cache                        ││
│  │    - Set stack pointer to SRAM top                       ││
│  │    - Configure clock/CRG (reset default)                  ││
│  │                                                          ││
│  │ 2. Minimal hardware init:                                ││
│  │    - Serial port (for debugging output)                  ││
│  │    - Clock/PLL (set CPU frequency)                       ││
│  │    - eMMC/NAND controller (basic init)                   ││
│  │                                                          ││
│  │ 3. Load BL2:                                             ││
│  │    - Read BL2 from boot partition (eMMC offset)          ││
│  │    - Verify BL2 signature (hash check)                    ││
│  │    - Copy BL2 to SRAM (or DRAM if already initialized)   ││
│  │    - Jump to BL2 entry point                              ││
│  └──────────────────────────────────────────────────────────┘│
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│  BL2: Little Kernel / U-Boot / ABOOT                        │
│  ┌──────────────────────────────────────────────────────────┐│
│  │ 1. Full hardware initialization:                         ││
│  │    - DDR controller + DRAM initialization (DRAM training) ││
│  │    - eMMC/UFS controller (full init)                     ││
│  │    - GPIO, I2C, SPI, UART, USB, display...                ││
│  │                                                          ││
│  │ 2. Load kernel + ramdisk:                                ││
│  │    - Parse boot.img header (Android boot image format)   ││
│  │    - Read kernel image (zImage/Image.gz)                 ││
│  │    - Read ramdisk (initramfs)                             ││
│  │    - Read DTB (Device Tree Blob)                         ││
│  │                                                          ││
│  │ 3. Signature verification (if bootloader locked):        ││
│  │    - Verify kernel hash against OEM public key            ││
│  │    - If locked and verification fails: stop boot         ││
│  │    - If unlocked: show warning (orange state)            ││
│  │                                                          ││
│  │ 4. Jump to kernel:                                       ││
│  │    - Setup boot parameters (ATAG or DTB pointer)          ││
│  │    - Set CPU to SVC mode (supervisor mode)                ││
│  │    - Turn off MMU, I/D-Cache                              ││
│  │    - Jump to kernel entry point (usually at 0x8000)      ││
│  └──────────────────────────────────────────────────────────┘│
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│  Linux Kernel Entry: start_kernel()                         │
└─────────────────────────────────────────────────────────────┘
Last modified: 2024年5月23日

Author

Comments

Write a Reply or Comment

Your email address will not be published.