kei Building & Deploying

Overview

kei produces kei-kernel.bin — the ARM64-enabled Asterinas kernel. This guide covers building the kernel, testing in QEMU, and deploying to physical hardware.

Build Pipeline

mermaid

Prerequisites

Quick Build

bash
1
2
3
4
5
6
7
8
9
10
11
# Stage the shared devtools recipes once (.just/ is gitignored)
just fetch

# One-time setup
just setup        # Configure git remotes

# Build for the NanoPi R3S
just build        # Builds kei-kernel.bin for aarch64/armv8

# Run QEMU boot tests
just test-all     # Boot-tests all supported architectures

Cross-Compilation

For cross-compiling from x86_64 to aarch64:

bash
1
2
3
4
5
6
7
8
9
10
11
# The ARM64 target is declared in rust-toolchain.toml, so rustup installs it with
# the toolchain; adding it by hand is:
rustup target add aarch64-unknown-none

# Install GCC cross-toolchain (distribution-dependent)
# Ubuntu / Debian:
sudo apt install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu

# Build. The kernel is produced through OSDK (it needs the initramfs packed and a
# nightly cargo on PATH), so use the build script rather than a bare `cargo build`:
python3 scripts/build.py nanopi-r3s

The kernel binary is a raw ARM64 Image (Linux boot protocol), not an ELF. It boots directly from U-Boot via the booti command.

QEMU Testing

Test the kernel in QEMU before deploying to hardware:

mermaid

Test Matrix

QEMU MachineCPURAMStatusCommand
virtcortex-a722GB✅ Primaryjust test
virtcortex-a722GB🔲 Planned—
virtmax4GB🔲 Planned—
sbsa-refmax4GB🔲 Planned—
bash
1
2
3
4
5
6
7
8
9
10
# Run the primary test target
just test

# Manual QEMU invocation
qemu-system-aarch64 \
  -machine virt,gic-version=3 \
  -cpu cortex-a72 \
  -m 2G \
  -kernel target/output/nanopi-r3s/kei-kernel.bin \
  -nographic

Physical Deployment

NanoPi R3S

Deploying kei to a physical NanoPi R3S:

mermaid

Flash to SD Card

bash
1
2
3
4
5
6
7
8
9
# Build the complete firmware image (includes kei-kernel.bin)
just build board nanopi-r3s

# Assemble the SD card image (borrows U-Boot + GPT from an Armbian reference)
just image ARMBIAN_IMG=/path/to/armbian.img

# Flash to SD card
sudo dd if=target/output/nanopi-r3s/sdcard.img of=/dev/sdX bs=4M status=progress
sync

No-Reflash Iteration

The one-time flash above is the last full flash required. The shipped boot.scr supports two iteration workflows that never touch the GPT or the U-Boot area:

TFTP netboot (recommended for bench work)

With kei_netboot=1 (default in armbianEnv.txt), U-Boot fetches the kernel, DTB and initramfs over TFTP and falls back to the SD copy when the server is unreachable.

One-time setup on the build host:

bash
1
2
3
# Serve /srv/tftp, e.g. with tftpd-hpa:
sudo apt install tftpd-hpa
sudo install -d -o "$USER" /srv/tftp/kei

Board-side settings (shipped as defaults in configs/board/nanopi-r3s/armbianEnv.txt):

text
1
2
3
kei_netboot=1
kei_tftp_prefix=kei
serverip=192.0.2.74   # build host running the TFTP server — adjust to your LAN

Iteration loop:

bash
1
2
3
python3 scripts/build.py nanopi-r3s   # rebuild kernel + DTB
scripts/push_netboot.sh               # copy artifacts into the TFTP root
# reset the board — U-Boot fetches kei over TFTP

To push to a remote TFTP server instead of a local directory:

bash
1
KEI_TFTP_DEST=user@host:/srv/tftp scripts/push_netboot.sh

In-place SD card update (offline)

When the board is not on the build LAN, refresh an existing card (or image) in place — only files under /boot/ are replaced:

bash
1
2
3
scripts/update_sdcard_kernel.sh --image target/output/nanopi-r3s/sdcard.img
# or, with the card in a reader on this host:
sudo scripts/update_sdcard_kernel.sh --device /dev/sdX

Boot Verification

After inserting the SD card and powering on, connect via USB-TTL serial (1500000 baud, 8N1):

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
U-Boot 2024.01 (Jan 01 2024 - 00:00:00 +0000)
...
## Loading kernel from mmc 0:1
   Image Name:   kei-kernel
   Image Type:   AArch64 Linux Kernel Image
   Data Size:    4194304 Bytes = 4 MiB
   Load Address: 00000000
   Entry Point:  00000000
## Flattened Device Tree blob at 44000000
   Booting using the fdt blob at 0x44000000

kei-kernel booting...
[KEI] initialising GICv3...
[KEI] initialising ARM Generic Timer...
[KEI] starting SMP...
[KEI] 4 cores online
...

Boot Order

mermaid

Troubleshooting

SymptomLikely CauseAction
No serial outputWrong baud rateUse 1500000, not 115200
GICv3 init failedQEMU machine typeUse virt,gic-version=3
SMP failedMissing PSCI in DTBCheck /cpus node in device tree
Kernel panicCode bug in arch layerAudit packages/ostd/src/arch/aarch64/
U-Boot can't find kernelWrong partition offsetVerify offset in boot.scr
TFTP times out, SD fallback bootsserverip wrong or server downCheck kei_netboot/serverip in armbianEnv.txt; verify tftpd serves the kei/ prefix
Old kernel boots despite netbootTFTP fetch failed silentlyWatch for [kei] netboot: lines on serial; check TFTP server logs
env import errors at bootCorrupt armbianEnv.txtRestore from configs/board/nanopi-r3s/armbianEnv.txt via update_sdcard_kernel.sh