TAIL OSv0.9.0

Installing TailOS on Raspberry Pi 3

Hardware Required

Item Notes
Raspberry Pi 3B or 3B+
MicroSD card (8 GB+)
USB-to-TTL serial adapter (3.3V) For serial console (FTDI, CP2102, etc.)
5V / 2.5A power supply Official RPi PSU recommended
Host Linux machine For building and flashing

Quick Start

# 1. Build TailOS and create the SD card image
make sd-image

# 2. Flash to SD card (replace /dev/sdX with your SD card device)
sudo dd if=tailos_sd.img of=/dev/sdX bs=4M status=progress
sync

# 3. Wire serial console, insert SD card, power on

Serial Console Wiring

Connect the USB-to-TTL serial adapter to the RPi3 GPIO header:

USB-TTL Adapter          RPi3 GPIO Header
+-----------+            +----------------+
|           |            |                |
|  TX  o----+----------->| Pin 10 (RXD)  |  GPIO 15
|           |            |                |
|  RX  o<---+-----------o| Pin 8  (TXD)  |  GPIO 14
|           |            |                |
|  GND o----+----------->| Pin 6  (GND)  |
|           |            |                |
+-----------+            +----------------+

Important: Do NOT connect the VCC/5V pin from the serial adapter to the RPi. Power the RPi from its own power supply.

Open the serial terminal on your host:

screen /dev/ttyUSB0 115200
# or
minicom -D /dev/ttyUSB0 -b 115200

SD Card Image Structure

The make sd-image command produces tailos_sd.img with the following layout:

+===========================================================================+
|                          tailos_sd.img (193 MiB)                          |
+===========================================================================+
|                                                                           |
|  Sector 0: MBR (Master Boot Record)                                      |
|    Partition 1: Boot  | FAT32 | 64 MiB                                   |
|    Partition 2: Data  | FAT32 | 128 MiB                                  |
|                                                                           |
|  Partition 1: BOOT                                                        |
|  +-----------------------------------------------------------------------+|
|  |  bootcode.bin .... RPi GPU 1st-stage bootloader                       ||
|  |  start.elf ....... RPi GPU firmware                                   ||
|  |  fixup.dat ....... RPi GPU memory fixup                               ||
|  |  config.txt ...... Boot configuration (arm_64bit=1, enable_uart=1)    ||
|  |  kernel8.img ..... TailOS (startup + kernel + drivers + servers + tsh)||
|  +-----------------------------------------------------------------------+|
|                                                                           |
|  Partition 2: DATA                                                        |
|  +-----------------------------------------------------------------------+|
|  |  /usr/bin/ls ..... Directory listing utility                          ||
|  |  /usr/bin/pidls .. Process listing utility                            ||
|  +-----------------------------------------------------------------------+|
|                                                                           |
+===========================================================================+

Boot Sequence

Power On
  |
  v
GPU ROM -> loads bootcode.bin from boot partition
  |
  v
bootcode.bin -> loads start.elf
  |
  v
start.elf -> reads config.txt, loads kernel8.img at 0x80000
  |
  v
TailOS startup (_start.S)
  |-- Switch EL3 -> EL1
  |-- Initialize MMU and caches
  |-- Jump to kernel
  v
TailOS kernel
  |-- Initialize process/thread/IPC subsystem
  |-- Load drivers from RFS (UART, SD)
  |-- Mount data partition via SD driver + FAT server
  |-- Start tsh shell
  v
/$ _   (serial console ready)

Build Details

The make sd-image target:

  1. Builds TailOS (make build-release)
  2. Downloads RPi3 firmware from raspberrypi/firmware (cached locally)
  3. Converts tail.rfs (ELF) to kernel8.img (raw binary) via objcopy -O binary
  4. Creates a two-partition FAT32 image with MBR
  5. Populates boot partition with firmware + kernel
  6. Populates data partition with user binaries from tail.build [disk] section

Offline Firmware

To use pre-downloaded firmware instead of auto-downloading:

python3 utility/host/deploy_disk/make_sd_image.py \
    ./tail.build \
    $TAIL_PREFIX/os_image/tail.rfs \
    $TAIL_PREFIX/target/bin \
    tailos_sd.img \
    --firmware-dir /path/to/firmware/

The firmware directory must contain: bootcode.bin, start.elf, fixup.dat. These can be obtained from https://github.com/raspberrypi/firmware/tree/master/boot.

config.txt Reference

The generated config.txt contains:

Setting Value Purpose
arm_64bit 1 Boot in AArch64 mode
kernel kernel8.img Kernel filename to load
disable_commandline_tags 1 Don't pass ATAGS (TailOS doesn't use them)
gpu_mem 16 Minimize GPU memory (TailOS doesn't use GPU)
dtoverlay disable-bt Free PL011 UART from Bluetooth
enable_uart 1 Enable serial console

The dtoverlay=disable-bt setting is critical: by default, the RPi3 maps the full PL011 UART to Bluetooth and provides only the mini UART on GPIO 14/15. TailOS uses PL011 (at address 0x3F201000), so Bluetooth must be disabled to make PL011 available on the GPIO pins.

Troubleshooting

No serial output:

  • Verify TX/RX wiring (they must be crossed: adapter TX -> RPi RX)
  • Ensure baud rate is 115200
  • Check that the SD card has config.txt with dtoverlay=disable-bt and enable_uart=1

RPi power LED on but no activity LED blinking:

  • The SD card may not be readable. Re-flash with dd and verify the boot partition contains bootcode.bin, start.elf, and kernel8.img

Kernel panic or hang after startup:

  • Connect via GDB if built with debug: make run-gdb (QEMU only)
  • Compare behavior with QEMU first: see install_qemu.md
Generated from doc/install_rpi3.md in the TAIL OS repository.