title: [Writing an OS Kernel from Scratch] 335 – ARM Architecture Boot: From Power-On to Kernel
category: os
tag: [arm, boot, embedded, u-boot]
source: https://github.com/golang12306/os-kernel-from-scratch

[Writing an OS Kernel from Scratch] 335 – ARM Architecture Boot: From Power-On to Kernel

1. ARM Boot Sequence Overview

Embedded device boot is a layered relay race. To understand ARM architecture boot, first grasp the overall flow:

Bash
┌────────────────────────────────────────────────────────────┐
│                     ARM Boot Sequence                        │
│                                                             │
│  POR (Power-On Reset)                                       │
│       │                                                     │
│       ▼                                                     │
│  ┌─────────┐  ── ROM (iROM) ── Stage 1 Bootloader          │
│  │  BL1    │      (Hard-coded, vendor-wired)                │
│  └────┬────┘                                                │
│       │ copy to SRAM                                        │
│       ▼                                                     │
│  ┌─────────┐  ── SRAM ── Stage 2 Bootloader                 │
│  │  BL2    │      (Modifiable, usually U-Boot SPL)          │
│  └────┬────┘                                                │
│       │ jump to DRAM                                        │
│       ▼                                                     │
│  ┌─────────┐  ── DRAM ── U-Boot (full U-Boot)              │
│  │  U-Boot │      Load Kernel + DTB                         │
│  └────┬────┘                                                │
│       │ bootm / booti                                       │
│       ▼                                                     │
│  ┌─────────┐  ── DRAM ── Linux Kernel                       │
│  │  Kernel │      Decompress/self-extract, enter ARM Linux  │
│  └────┬────┘                                                │
│       │ start_kernel()                                      │
│       ▼                                                     │
│  ┌─────────┐  ── DRAM ── Init (PID 1)                     │
│  └─────────┘                                                │
└────────────────────────────────────────────────────────────┘

2. ARM Exception Vector and Reset

Bash
ARM exception vector table (located at address 0x00000000 or 0xFFFF0000):

  Offset  Exception               Handler
  0x00    Reset                   reset_handler
  0x04    Undefined Instruction   und_handler
  0x08    Software Interrupt (SWI) svc_handler
  0x0C    Prefetch Abort          pabt_handler
  0x10    Data Abort              dabt_handler
  0x14    Reserved                —
  0x18    IRQ (Interrupt)         irq_handler
  0x1C    FIQ (Fast Interrupt)    fiq_handler

On reset:
  1. CPU enters SVC (Supervisor) mode
  2. Disable interrupts (I and F bits in CPSR)
  3. Set PC (Program Counter) to reset vector address
  4. Start executing from reset_handler

3. Minimal ARM Boot Assembly

Bash
Typical ARM boot header (start.S):

.section .text.boot
.globl _start

_start:
    // 1. Enter SVC mode, disable interrupts
    mrs    r0, cpsr
    bic    r0, r0, #0x1F
    orr    r0, r0, #0xD3    // SVC mode + IRQ/FIQ disabled
    msr    cpsr, r0

    // 2. Initialize stack pointer
    ldr    r0, =_stack_top
    mov    sp, r0

    // 3. Clear BSS section
    ldr    r0, =__bss_start
    ldr    r1, =__bss_end
    mov    r2, #0
bss_clear_loop:
    cmp    r0, r1
    strne  r2, [r0], #4
    bne    bss_clear_loop

    // 4. Enable I-Cache and D-Cache (if applicable)
    mrc    p15, 0, r0, c1, c0, 0    // Read SCTLR
    orr    r0, r0, #(1 << 12)       // Enable I-Cache
    // D-Cache: enable after MMU is set up
    mcr    p15, 0, r0, c1, c0, 0    // Write SCTLR

    // 5. Jump to main()
    bl     main

    // Infinite loop (should never reach here)
hang:
    b      hang
Last modified: 2024年7月16日

Author

Comments

Write a Reply or Comment

Your email address will not be published.