Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ jobs:
repository: flooooooooooow/flow
path: flow

- name: Set up Flow Python environment
uses: ./flow/.github/actions/setup-python
- name: Set up Flow Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
cache: pip
cache-dependency-path: flow/requirements.lock

- name: Install Flow Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r flow/requirements.lock

- name: Install freestanding and boot-test toolchain
run: |
Expand All @@ -41,9 +50,15 @@ jobs:
lld \
grub-common \
grub-pc-bin \
mtools \
xorriso \
qemu-system-x86

- name: Validate Android runner scripts
run: |
bash -n android/termux-run.sh
bash -n android/termux-setup.sh

- name: Build freestanding x86_64 ELF
env:
FLOW: ${{ github.workspace }}/flow/flow
Expand All @@ -54,8 +69,8 @@ jobs:
bash x86_64/build.sh /tmp/flow-kernel-build
test -s /tmp/flow-kernel-build/flow-kernel.elf
grub-file --is-x86-multiboot2 /tmp/flow-kernel-build/flow-kernel.elf
llvm-readelf -h /tmp/flow-kernel-build/flow-kernel.elf
llvm-nm /tmp/flow-kernel-build/flow-kernel.elf | grep -F 'flow_export_kernel_main'
readelf -h /tmp/flow-kernel-build/flow-kernel.elf
nm /tmp/flow-kernel-build/flow-kernel.elf | grep -F 'flow_export_kernel_main'

- name: Build bootable GRUB image
run: |
Expand All @@ -65,17 +80,12 @@ jobs:
grub-mkrescue -o /tmp/flow-kernel.iso /tmp/flow-kernel-iso
test -s /tmp/flow-kernel.iso

- name: Boot smoke under QEMU
- name: Boot smoke through Android-compatible runner
run: |
set +e
timeout 10s qemu-system-x86_64 \
-machine accel=tcg \
-m 128M \
-cdrom /tmp/flow-kernel.iso \
-serial file:/tmp/flow-kernel-serial.log \
-display none \
-no-reboot \
-no-shutdown
timeout 10s env FLOW_KERNEL_QEMU=qemu-system-x86_64 \
bash android/termux-run.sh /tmp/flow-kernel.iso \
> /tmp/flow-kernel-serial.log 2>&1
rc=$?
set -e

Expand All @@ -88,6 +98,17 @@ jobs:
grep -F 'Flow kernel: entry' /tmp/flow-kernel-serial.log
grep -F 'Flow kernel: boot contract accepted' /tmp/flow-kernel-serial.log

- name: Package Android boot artifact
run: |
package=/tmp/flow-kernel-android-x86_64
mkdir -p "$package"
cp /tmp/flow-kernel.iso "$package/flow-kernel.iso"
cp android/termux-run.sh "$package/termux-run.sh"
cp android/termux-setup.sh "$package/termux-setup.sh"
cp android/README.md "$package/README.md"
(cd "$package" && sha256sum flow-kernel.iso > SHA256SUMS)
cat "$package/SHA256SUMS"

- name: Upload kernel artifacts
if: always()
uses: actions/upload-artifact@v4
Expand All @@ -99,3 +120,12 @@ jobs:
/tmp/flow-kernel-serial.log
if-no-files-found: warn
retention-days: 7

- name: Upload Android boot artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: flow-kernel-android-x86_64
path: /tmp/flow-kernel-android-x86_64/
if-no-files-found: warn
retention-days: 7
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ FLOW=../flow/flow bash x86_64/run.sh

That additionally requires `grub-mkrescue` and `qemu-system-x86_64`. Successful boot reaches the serial message `Flow kernel: boot contract accepted`.

## Boot on Android

The same x86_64 ISO can boot on a 64-bit Android phone through Termux and QEMU TCG without root or bootloader changes.

```bash
pkg update
pkg install x11-repo
pkg install qemu-system-x86-64
bash android/termux-run.sh /path/to/flow-kernel.iso
```

CI publishes a `flow-kernel-android-x86_64` artifact containing the ISO, Android runner, and checksum manifest. See [`android/README.md`](android/README.md) for the complete phone workflow.

## Roadmap

The next layers are Multiboot2 memory-map ingestion, a physical page allocator, interrupt/exception tables, timer-driven scheduling, syscall entry, virtual memory ownership, and then the eBPF verifier/interpreter/JIT hooks. eBPF should consume explicit kernel hook surfaces rather than becoming part of the boot substrate.

An `aarch64` architecture target is also planned so ARM64 Android devices can boot Flow under QEMU's `virt` machine without translating an x86_64 guest.
80 changes: 80 additions & 0 deletions android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Flow Kernel on Android

This boots the current x86_64 Multiboot2 Flow kernel inside QEMU TCG on a 64-bit Android device. It does not replace Android, unlock the bootloader, require root, or modify the phone kernel.

## 1. Install QEMU in Termux

Use a current Termux installation, then run:

```bash
bash termux-setup.sh
```

The setup helper enables the Termux X11 package repository and installs `qemu-system-x86-64`, which provides the `qemu-system-x86_64` binary used by the runner.

Equivalent manual commands are:

```bash
pkg update
pkg install x11-repo
pkg install qemu-system-x86-64
```

No X11 application is needed because Flow kernel output is carried over the emulated serial port.

## 2. Get the kernel image

Download the `flow-kernel-android-x86_64` artifact from a successful GitHub Actions run and extract it into a directory visible to Termux. The artifact contains:

```text
flow-kernel.iso
termux-run.sh
termux-setup.sh
README.md
SHA256SUMS
```

Verify the image before booting:

```bash
sha256sum -c SHA256SUMS
```

## 3. Boot Flow

From the extracted artifact directory:

```bash
bash termux-run.sh flow-kernel.iso
```

A successful boot reaches:

```text
Flow kernel: entry
Flow kernel: boot contract accepted
```

QEMU is intentionally configured with TCG rather than KVM because the current guest is x86_64 while normal modern Android phones are ARM64.

Press `Ctrl+A`, then `X` to terminate QEMU if required.

## Environment overrides

The runner accepts these optional variables:

```bash
FLOW_KERNEL_ISO=/path/to/flow-kernel.iso
FLOW_KERNEL_QEMU=qemu-system-x86_64
FLOW_KERNEL_MEMORY=128M
```

For example:

```bash
FLOW_KERNEL_MEMORY=256M bash termux-run.sh flow-kernel.iso
```

## Next architecture target

This Android path deliberately validates the existing kernel unchanged. The next native-emulation target should be `aarch64` using QEMU's `virt` machine so ARM64 Android hosts no longer pay the x86_64 instruction-translation cost.
29 changes: 29 additions & 0 deletions android/termux-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail

ISO="${1:-${FLOW_KERNEL_ISO:-$PWD/flow-kernel.iso}}"
QEMU="${FLOW_KERNEL_QEMU:-qemu-system-x86_64}"
MEMORY="${FLOW_KERNEL_MEMORY:-128M}"

if ! command -v "$QEMU" >/dev/null 2>&1; then
echo "flow-kernel: $QEMU is not installed" >&2
echo "flow-kernel: on Termux run: pkg install x11-repo && pkg install qemu-system-x86-64" >&2
exit 1
fi

if [[ ! -r "$ISO" ]]; then
echo "flow-kernel: ISO not found or unreadable: $ISO" >&2
echo "usage: $0 /path/to/flow-kernel.iso" >&2
exit 1
fi

exec "$QEMU" \
-machine accel=tcg \
-m "$MEMORY" \
-cdrom "$ISO" \
-boot d \
-serial stdio \
-display none \
-monitor none \
-no-reboot \
-no-shutdown
17 changes: 17 additions & 0 deletions android/termux-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail

case "$(uname -m)" in
aarch64|arm64|x86_64)
;;
*)
echo "flow-kernel: a 64-bit Termux environment is required for the x86_64 QEMU target" >&2
exit 1
;;
esac

pkg update
pkg install -y x11-repo
pkg install -y qemu-system-x86-64

qemu-system-x86_64 --version
31 changes: 31 additions & 0 deletions x86_64/arch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <stdint.h>

static inline void flow_kernel_outb(uint16_t port, uint8_t value)
{
__asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
}

void flow_kernel_serial_init(void)
{
flow_kernel_outb(0x3f8 + 1, 0x00);
flow_kernel_outb(0x3f8 + 3, 0x80);
flow_kernel_outb(0x3f8 + 0, 0x03);
flow_kernel_outb(0x3f8 + 1, 0x00);
flow_kernel_outb(0x3f8 + 3, 0x03);
flow_kernel_outb(0x3f8 + 2, 0xc7);
flow_kernel_outb(0x3f8 + 4, 0x0b);
}

void flow_kernel_serial_write(const char *text)
{
while (*text != '\0') {
flow_kernel_outb(0x3f8, (uint8_t)*text++);
}
}

__attribute__((noreturn)) void flow_kernel_halt(void)
{
for (;;) {
__asm__ volatile ("cli; hlt");
}
}
40 changes: 29 additions & 11 deletions x86_64/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD="${1:-$HERE/build}"
FLOW="${FLOW:-$HERE/../../flow/flow}"
FREESTANDING="$HERE/freestanding"

if [[ ! -x "$FLOW" ]]; then
echo "Flow compiler not found or not executable: $FLOW" >&2
Expand All @@ -18,21 +19,36 @@ mkdir -p "$BUILD"
--export kernel_main kernel_abi_version kernel_page_size kernel_boot_magic_valid kernel_page_count \
-o "$BUILD/kernel.c"

COMMON_CFLAGS=(
-target x86_64-unknown-none-elf
-std=c11
-ffreestanding
-fno-builtin
-fno-stack-protector
-fno-pic
-fno-pie
-mno-red-zone
-ffunction-sections
-fdata-sections
-O2
-I "$FREESTANDING"
)

clang \
-target x86_64-unknown-none-elf \
-std=c11 \
-ffreestanding \
-fno-builtin \
-fno-stack-protector \
-fno-pic \
-fno-pie \
-mno-red-zone \
-ffunction-sections \
-fdata-sections \
-O2 \
"${COMMON_CFLAGS[@]}" \
-c "$BUILD/kernel.c" \
-o "$BUILD/kernel-flow.o"

clang \
"${COMMON_CFLAGS[@]}" \
-c "$HERE/arch.c" \
-o "$BUILD/arch.o"

clang \
"${COMMON_CFLAGS[@]}" \
-c "$FREESTANDING/runtime.c" \
-o "$BUILD/freestanding-runtime.o"

clang \
-target x86_64-unknown-none-elf \
-ffreestanding \
Expand All @@ -48,6 +64,8 @@ ld.lld \
-T "$HERE/linker.ld" \
"$BUILD/boot.o" \
"$BUILD/kernel-flow.o" \
"$BUILD/arch.o" \
"$BUILD/freestanding-runtime.o" \
-o "$BUILD/flow-kernel.elf"

if command -v grub-file >/dev/null 2>&1; then
Expand Down
4 changes: 4 additions & 0 deletions x86_64/freestanding/math.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#ifndef FLOW_KERNEL_FREESTANDING_MATH_H
#define FLOW_KERNEL_FREESTANDING_MATH_H

#endif
Loading
Loading