TUI/CLI tool for managing device tree overlays at runtime. Go + Bubble Tea, single static binary, zero runtime dependencies.
Works on any Linux distro (Ubuntu, Debian, Buildroot, etc.) with U-Boot overlay support.
┌─────────────────────────────────────────────────────────┐ │ User runs: sudo ovtree │ │ ↓ │ │ overlays.ini ──(read/write)── TUI / CLI │ │ ↓ │ │ .ubootenv ──(auto-generated on save)── │ │ ↓ │ │ U-Boot boot ──(reads .ubootenv)── loads *.dtbo │ └─────────────────────────────────────────────────────────┘
All files live in /boot/overlays/:
/boot/overlays/ ├── overlays.ini ← single source of truth (human-editable) ├── .ubootenv ← auto-generated (U-Boot reads this) ├── example-dsi.dtbo ← compiled overlay binaries └── example-spi.dtbo /usr/local/bin/ └── ovtree ← the tool
This tool is distro-agnostic and can be integrated into any Rockchip Linux SDK. You need three things:
Your U-Boot must include an overlay loader that reads /boot/overlays/.ubootenv from the rootfs partition and applies the listed .dtbo files to the device tree at boot.
The .ubootenv format is simple:
# auto-generated — do not edit
overlays=your-overlay-a.dtbo your-overlay-b.dtbo
Reference implementation: u-boot/arch/arm/mach-rockchip/overlay_loader.c
Key constants your loader should match:
| Item | Value |
|---|---|
| Config file path | /boot/overlays/.ubootenv |
| DTBO directory | /boot/overlays/ |
| Config format | overlays=<name1>.dtbo <name2>.dtbo ... |
| Max overlays | 128 |
| Max DTBO size | 256 KB |
Create a device-tree-overlays/ directory alongside your board DTS files:
kernel/arch/arm64/boot/dts/<vendor>/device-tree-overlays/ ├── Makefile ├── overlays.ini └── overlays/ ├── your-board-dsi-screen.dts └── your-board-spi-device.dts
The Makefile compiles .dts → .dtbo using the kernel's dtc:
DTC ?= dtc
CPP ?= cpp
KERNEL_DIR ?= $(shell cd ../../../.. && pwd)
DTS_CPPFLAGS = -nostdinc -undef -D__DTS__ -x assembler-with-cpp
DTS_INCLUDE = -I$(KERNEL_DIR)/include \
-I$(KERNEL_DIR)/arch/arm64/boot/dts \
-I$(KERNEL_DIR)/arch/arm64/boot/dts/rockchip
SRCS = $(wildcard overlays/*.dts)
DTBOS = $(SRCS:.dts=.dtbo)
.PHONY: overlays clean
overlays: $(DTBOS)
%.dtbo: %.dts.tmp
$(DTC) -@ -I dts -O dtb -o $@ $<
%.dts.tmp: %.dts
$(CPP) $(DTS_CPPFLAGS) $(DTS_INCLUDE) -o $@ $<
clean:
rm -f overlays/*.dtbo overlays/*.dts.tmp
Three steps need to happen during your SDK build:
Step A — Compile overlays + TUI tool (during kernel build):
# Compile .dts → .dtbo
make -C "$OVERLAY_DIR" overlays DTC="kernel/scripts/dtc/dtc"
# Copy outputs
mkdir -p "$OUTPUT_DIR/overlays/overlays"
cp "$OVERLAY_DIR/overlays.ini" "$OUTPUT_DIR/overlays/overlays/"
cp "$OVERLAY_DIR/overlays/"*.dtbo "$OUTPUT_DIR/overlays/overlays/"
# Build TUI tool (requires Go 1.21+)
cd app/ovtree
INSTALL_DIR="$OUTPUT_DIR/overlays" ./scripts/build.sh
Step B — Install to rootfs (post-rootfs hook, runs for all distros):
# Install DTBO files + config
mkdir -p "$TARGET_ROOTFS/boot/overlays"
cp overlays/*.dtbo "$TARGET_ROOTFS/boot/overlays/"
cp overlays/overlays.ini "$TARGET_ROOTFS/boot/overlays/"
# Generate .ubootenv from overlays.ini (parse enabled=true sections)
# ... see post-dts-overlays.sh for the full parser
# Install TUI binary
install -m 755 ovtree "$TARGET_ROOTFS/usr/local/bin/"
Step C — Verify (on target board):
ls /boot/overlays/ # should have *.dtbo + overlays.ini + .ubootenv
which ovtree # should be in PATH
sudo ovtree # should launch TUI
/boot/overlays/.ubootenv and loads listed .dtbo files.dts overlay sources to .dtbooverlays.ini is deployed to /boot/overlays/ on the rootfs.ubootenv is generated from overlays.ini during buildovtree binary is installed to /usr/local/bin/# Mutex group — only one overlay in a group can be enabled at a time
[group:dsi-display]
type = group
name_zh = DSI 显示屏
name_en = DSI Display
desc_zh = 同一时间只能使用一个 DSI 屏幕
desc_en = Only one DSI display can be active at a time
# Overlay entry — section name must match the .dtbo filename
[your-board-dsi-screen.dtbo]
enabled = false
name_zh = 10.1寸 MIPI 屏幕
name_en = 10.1" MIPI Display
desc_zh = 800x1280, 4-lane MIPI, GT9xx 触控
desc_en = 800x1280, 4-lane MIPI, GT9xx Touch
group = dsi-display
| Field | Required | Description |
|---|---|---|
enabled | Yes | true or false |
name_zh | Yes | Chinese display name |
name_en | Yes | English display name |
desc_zh | No | Chinese description |
desc_en | No | English description |
group | No | Mutex group name (empty = no constraint) |
sudo ovtree # language selection first
sudo ovtree --lang=zh # skip to Chinese
sudo ovtree --lang=en # skip to English
sudo ovtree list # JSON list of all overlays
sudo ovtree status # show enabled overlays
sudo ovtree enable your-overlay.dtbo # enable one
sudo ovtree disable your-overlay.dtbo # disable one
sudo ovtree disable-all # disable all
scp your-overlay.dtbo root@board:/boot/overlays/
sudo ovtree # select "Add New Overlay" in TUI
# Auto-detect/install Go, cross-compile arm64, install binary
./scripts/build.sh
# Or with custom install directory
INSTALL_DIR=/path/to/output ./scripts/build.sh
# Or via Makefile
make build # cross-compile arm64
make build-host # native build (for testing)
make INSTALL=/custom/path install
Requirements: Go 1.21+ (auto-installed by build.sh if missing)
ovtree/ ├── main.go # entry point ├── embed.go # go:embed default overlays.ini ├── defaults/ │ └── overlays.ini # embedded fallback config ├── cmd/ # CLI commands (root, list, enable, disable, status, disable-all) ├── engine/ # config load/save, mutex check, dtbo validation, .ubootenv sync ├── i18n/ # bilingual strings (zh/en) ├── tui/ # Bubble Tea pages (lang select, menu, group config, confirm, etc.) ├── scripts/build.sh # auto-install Go + cross-compile + install └── Makefile
GPL-2.0+