diff --git a/apps/starry/README.md b/apps/starry/README.md index ce5a0567ef..ec21856503 100644 --- a/apps/starry/README.md +++ b/apps/starry/README.md @@ -76,6 +76,24 @@ cargo xtask starry app run -t gdb-smoke --arch riscv64 \ --qemu-config qemu-riscv64-gdbserver.toml ``` +## jcode + +The `jcode` case is an x86_64 QEMU app workflow that downloads the jcode AI coding +agent from GitHub releases, patches the glibc-linked binary for musl compatibility +using `patchelf`, builds a glibc stub shared library, and injects everything into +the app rootfs overlay. + +```bash +apps/starry/jcode/prepare_jcode_rootfs.sh +cargo xtask starry qemu \ + --arch x86_64 \ + --qemu-config apps/starry/jcode/qemu-x86_64.toml \ + --rootfs tmp/axbuild/rootfs/rootfs-x86_64-jcode.img +``` + +See `jcode/README.md` for interactive usage and troubleshooting. + + ## Orange Pi 5 Plus UVC The `orangepi-5-plus-uvc` case needs `/usr/bin/uvc-fps` to be installed in the diff --git a/apps/starry/jcode/README.md b/apps/starry/jcode/README.md new file mode 100644 index 0000000000..d2d42b9542 --- /dev/null +++ b/apps/starry/jcode/README.md @@ -0,0 +1,92 @@ +# StarryOS jcode Example + +这个目录提供在 StarryOS x86_64 QEMU 中运行 jcode(AI coding agent)的手动示例。它不是 `test-suit/starryos` 用例,也不会进入 CI;下载 jcode、glibc-to-musl 补丁、rootfs 注入都只会在用户显式执行本目录脚本时发生。 + +## 什么是 jcode + +jcode 是一个 Rust 编写的 AI coding agent harness,采用 TUI client + background server 双进程架构,通过 Unix domain socket 通信。项目地址: + +## Host 依赖 + +脚本需要以下 host 工具(Debian/Ubuntu): + +```bash +apt-get install -y patchelf binutils curl qemu-user-static +``` + +## 准备 jcode Rootfs + +先在 host 侧准备本地 rootfs。脚本会自动: + +1. 从 GitHub releases 下载 jcode linux-x86_64 二进制 +2. 下载 Alpine minirootfs 作为 staging 环境 +3. 使用 `patchelf` 将 glibc-linked 的 jcode 转换为 musl 兼容 +4. 编译 glibc stub 共享库(提供 `mallopt`、`__res_init` 等 glibc-only 符号) +5. 注入 jcode 二进制、SSL 库、Kerberos 依赖到 rootfs + +```bash +apps/starry/jcode/prepare_jcode_rootfs.sh +``` + +产物位于 `tmp/axbuild/rootfs/rootfs-x86_64-jcode.img`,是本地资产,不提交到仓库。 + +## 离线 Smoke 测试 + +验证 jcode 能在 StarryOS guest 中正常运行: + +```bash +cargo xtask starry qemu \ + --arch x86_64 \ + --qemu-config apps/starry/jcode/qemu-x86_64.toml \ + --rootfs tmp/axbuild/rootfs/rootfs-x86_64-jcode.img +``` + +期望输出包含: + +```text +STARRY_JCODE_SMOKE_PASSED +``` + +## 手动交互 + +准备 rootfs 后,可以直接启动 QEMU 进入 StarryOS shell: + +```bash +cargo xtask starry qemu \ + --arch x86_64 \ + --rootfs tmp/axbuild/rootfs/rootfs-x86_64-jcode.img +``` + +进入 `root@starry` 后: + +```sh +export HOME=/root +export USER=root +export SHELL=/bin/sh +export TERM=xterm-256color +export PATH=/usr/local/bin:/usr/bin:/bin:/sbin +export JCODE_NO_AUTO_UPDATE=1 + +# 配置 provider(需要网络和 API key) +jcode login --provider openai-compatible + +# 运行 jcode TUI +jcode +``` + +> **注意**:`JCODE_NO_AUTO_UPDATE=1` 必须设置。jcode 的自动更新会下载 glibc 版本的二进制,覆盖已打补丁的 musl 版本,导致 jcode 无法运行。如果误触发了自动更新,需要重新运行 `prepare_jcode_rootfs.sh`。 + + +## 内核修复 + +jcode 在 StarryOS 上运行需要以下内核修复(已合入 dev 分支): + +- ext4 文件系统块分配和 JBD2 superblock 修复 +- EPOLLET edge-triggered epoll 竞态修复 +- 非阻塞 socket waker 注册 +- ARP 队列扩容(32→256,TTL 60s→300s) +- TTY 终端 ANSI CPR 和 SIGWINCH 支持 + +## 边界 + +这个 example 只声明 x86_64 QEMU 下的手动演示流程。它不覆盖 jcode TUI 在线模式、CI 测试、或其他架构上的 jcode。 diff --git a/apps/starry/jcode/build-x86_64-unknown-none.toml b/apps/starry/jcode/build-x86_64-unknown-none.toml new file mode 100644 index 0000000000..1c8a2eeca2 --- /dev/null +++ b/apps/starry/jcode/build-x86_64-unknown-none.toml @@ -0,0 +1,5 @@ +target = "x86_64-unknown-none" +env = { AX_IP = "10.0.2.15", AX_GW = "10.0.2.2" } +log = "Warn" +features = ["qemu"] +plat_dyn = false diff --git a/apps/starry/jcode/prebuild.sh b/apps/starry/jcode/prebuild.sh new file mode 100755 index 0000000000..35318980ee --- /dev/null +++ b/apps/starry/jcode/prebuild.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_dir="${STARRY_APP_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}" +overlay_dir="${STARRY_OVERLAY_DIR:-}" +workspace="${STARRY_WORKSPACE:-$(cd "$app_dir/../../.." && pwd)}" + +require_env() { + local name="$1" value="$2" + if [[ -z "$value" ]]; then + echo "error: $name is required" >&2 + exit 1 + fi +} + +require_env STARRY_OVERLAY_DIR "$overlay_dir" + +# Download, patch, and build jcode assets. +"$app_dir/prepare_jcode_assets.sh" + +asset_dir="$workspace/target/jcode/assets" +for f in jcode.bin libglibc_stub.so jcode; do + [[ -f "$asset_dir/$f" ]] || { echo "error: missing asset: $f" >&2; exit 1; } +done + +# Populate overlay for the app runner to inject into rootfs. +install -Dm0755 "$asset_dir/jcode.bin" "$overlay_dir/usr/lib/jcode/jcode.bin" +install -Dm0755 "$asset_dir/libglibc_stub.so" "$overlay_dir/usr/lib/jcode/libglibc_stub.so" +install -Dm0755 "$asset_dir/jcode" "$overlay_dir/usr/bin/jcode" + +for f in "$asset_dir"/libssl.so* "$asset_dir"/libcrypto.so*; do + [[ -f "$f" ]] && install -Dm0755 "$f" "$overlay_dir/usr/lib/jcode/" +done + +for lib in libcom_err.so.2 libgssapi_krb5.so.2 libk5crypto.so.3 \ + libkeyutils.so.1 libkrb5.so.3 libkrb5support.so.0; do + [[ -f "$asset_dir/$lib" ]] && install -Dm0755 "$asset_dir/$lib" "$overlay_dir/usr/lib/" +done + +echo "jcode overlay ready in $overlay_dir" diff --git a/apps/starry/jcode/prepare_jcode_assets.sh b/apps/starry/jcode/prepare_jcode_assets.sh new file mode 100755 index 0000000000..348f7f78b5 --- /dev/null +++ b/apps/starry/jcode/prepare_jcode_assets.sh @@ -0,0 +1,256 @@ +#!/usr/bin/env bash +set -euo pipefail + +workspace="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +asset_dir="$workspace/target/jcode/assets" +cache_dir="$workspace/target/jcode/cache" + +ALPINE_VERSION="3.21" +ALPINE_PATCH="3.21.3" +ALPINE_MINIROOTFS_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION}/releases/x86_64/alpine-minirootfs-${ALPINE_PATCH}-x86_64.tar.gz" +ALPINE_MINIROOTFS_SHA256="1a694899e406ce55d32334c47ac0b2efb6c06d7e878102d1840892ad44cd5239" + +JCODE_VERSION="0.12.0" +JCODE_URL="https://github.com/1jehuang/jcode/releases/download/v${JCODE_VERSION}/jcode-linux-x86_64.tar.gz" +JCODE_SHA256="cc7fef26c348124af40db1793481b46945842e20a7b6c684fc66bea7b2524f0b" + +cleanup() { + rm -rf "${TMPDIR:-/tmp}/starry-jcode-assets.$$" 2>/dev/null || true +} +trap cleanup EXIT + +need_cmd() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "error: required command not found: $1" >&2 + echo " install with: apt-get install -y $2" >&2 + exit 1 + fi +} + +need_cmd curl curl +need_cmd tar tar +need_cmd install coreutils +need_cmd patchelf patchelf +need_cmd as binutils +need_cmd ld binutils +need_cmd qemu-x86_64-static qemu-user-static +need_cmd sha256sum coreutils + +verify_sha256() { + local expected="$1" path="$2" + local actual + actual="$(sha256sum "$path" | awk '{print $1}')" + if [[ "$actual" != "$expected" ]]; then + echo "error: SHA-256 mismatch for $path" >&2 + echo " expected: $expected" >&2 + echo " actual: $actual" >&2 + exit 1 + fi +} + +mkdir -p "$cache_dir" + +# Download jcode release tarball (cached). +jcode_tgz="$cache_dir/jcode-linux-x86_64.tar.gz" +if [[ ! -s "$jcode_tgz" ]]; then + echo "Downloading jcode v${JCODE_VERSION} from $JCODE_URL ..." + curl -fSL --retry 5 --retry-delay 3 --retry-all-errors --max-time 300 \ + "$JCODE_URL" -o "$jcode_tgz" +fi +verify_sha256 "$JCODE_SHA256" "$jcode_tgz" + +TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/starry-jcode-assets.$$.XXXXX")" +tar xzf "$jcode_tgz" -C "$TMPDIR" + +# Extract Alpine minirootfs as staging root. +alpine_tgz="$cache_dir/alpine-minirootfs-${ALPINE_PATCH}-x86_64.tar.gz" +if [[ ! -s "$alpine_tgz" ]]; then + echo "Downloading Alpine minirootfs ${ALPINE_VERSION} ..." + curl -fSL --retry 5 --retry-delay 3 --retry-all-errors --max-time 120 \ + "$ALPINE_MINIROOTFS_URL" -o "$alpine_tgz" +fi +verify_sha256 "$ALPINE_MINIROOTFS_SHA256" "$alpine_tgz" + +staging="$TMPDIR/staging" +mkdir -p "$staging" +tar xzf "$alpine_tgz" -C "$staging" + +# Install packages into staging root via qemu-user + apk. +# Unset LD_LIBRARY_PATH to prevent host tools from loading the staging musl libc. +( + unset LD_LIBRARY_PATH + MUSL_LD="$staging/lib/ld-musl-x86_64.so.1" + MUSL_LIBPATH="$staging/lib:$staging/usr/lib" + "$MUSL_LD" --library-path "$MUSL_LIBPATH" \ + "$staging/sbin/apk" \ + --root "$staging" --initdb --allow-untrusted --no-progress --no-scripts \ + add patchelf krb5-libs +) + +# Copy jcode binary into staging. +jcode_bin_name="jcode-linux-x86_64.bin" +if [[ ! -f "$TMPDIR/$jcode_bin_name" ]]; then + jcode_bin_name="$(ls "$TMPDIR"/*.bin 2>/dev/null | head -1)" +fi +[[ -f "$TMPDIR/$jcode_bin_name" ]] || { echo "error: jcode binary not found in tarball" >&2; exit 1; } +mkdir -p "$staging/usr/lib/jcode" +install -m 0755 "$TMPDIR/$jcode_bin_name" "$staging/usr/lib/jcode/jcode.bin" + +# Copy bundled SSL libs. +for f in "$TMPDIR"/libssl.so* "$TMPDIR"/libcrypto.so*; do + [[ -f "$f" ]] && cp "$f" "$staging/usr/lib/jcode/" +done + +# ── Patch jcode.bin via staging root's patchelf ───────────────────────────── +PATCHELF="$staging/usr/bin/patchelf" +QEMU_USER="/usr/bin/qemu-x86_64-static" +MUSL_INTERP="/lib/ld-musl-x86_64.so.1" +MUSL_LIBC="libc.musl-x86_64.so.1" +GLIBC_INTERP="ld-linux-x86-64.so.2" + +run_patchelf() { + "$QEMU_USER" -L "$staging" "$PATCHELF" "$@" +} + +run_patchelf \ + --set-interpreter "$MUSL_INTERP" \ + --set-rpath "/usr/lib/jcode" \ + --remove-needed "$GLIBC_INTERP" \ + --replace-needed "libc.so.6" "$MUSL_LIBC" \ + --remove-needed "libm.so.6" \ + --remove-needed "libdl.so.2" \ + --remove-needed "librt.so.1" \ + --remove-needed "libpthread.so.0" \ + "$staging/usr/lib/jcode/jcode.bin" + +# Patch bundled libssl and libcrypto. +for LIBSSL in "$staging/usr/lib/jcode"/libssl.so*; do + [[ -f "$LIBSSL" ]] || continue + run_patchelf \ + --set-rpath "/usr/lib/jcode:/usr/lib" \ + --replace-needed "libc.so.6" "$MUSL_LIBC" \ + --remove-needed "libdl.so.2" \ + "$LIBSSL" +done +for LIBCRYPTO in "$staging/usr/lib/jcode"/libcrypto.so*; do + [[ -f "$LIBCRYPTO" ]] || continue + run_patchelf \ + --set-rpath "/usr/lib/jcode:/usr/lib" \ + --replace-needed "libc.so.6" "$MUSL_LIBC" \ + --remove-needed "libdl.so.2" \ + "$LIBCRYPTO" +done + +# ── Build glibc stub shared library ────────────────────────────────────────── +# jcode.bin references glibc-specific symbols that don't exist in musl. +# Build a tiny .so that stubs them out. +STUB_ASM="$TMPDIR/glibc_stub.s" +STUB_OBJ="$TMPDIR/glibc_stub.o" +STUB_SO="$staging/usr/lib/jcode/libglibc_stub.so" + +/usr/bin/printf '%s\n' \ + '.text' \ + '.globl mallopt' \ + '.type mallopt, @function' \ + 'mallopt: mov $1, %eax; ret' \ + '' \ + '.globl malloc_trim' \ + '.type malloc_trim, @function' \ + 'malloc_trim: xor %eax, %eax; ret' \ + '' \ + '.globl __res_init' \ + '.type __res_init, @function' \ + '__res_init: xor %eax, %eax; ret' \ + '' \ + '.globl res_init' \ + '.type res_init, @function' \ + 'res_init: xor %eax, %eax; ret' \ + '' \ + '.globl __register_atfork' \ + '.type __register_atfork, @function' \ + '__register_atfork: xor %eax, %eax; ret' \ + '' \ + '.globl gnu_get_libc_version' \ + '.type gnu_get_libc_version, @function' \ + 'gnu_get_libc_version: lea .Lglibc_ver(%rip), %rax; ret' \ + '.section .rodata' \ + '.Lglibc_ver: .asciz "2.17"' \ + '' \ + '.text' \ + '.globl sdallocx' \ + '.type sdallocx, @function' \ + 'sdallocx: jmp free@PLT' \ + '' \ + '.globl __fprintf_chk' \ + '.type __fprintf_chk, @function' \ + '__fprintf_chk: mov %rdx, %rsi; mov %rcx, %rdx; jmp fprintf@PLT' \ + '' \ + '.globl __printf_chk' \ + '.type __printf_chk, @function' \ + '__printf_chk: mov %rsi, %rdi; mov %rdx, %rsi; jmp printf@PLT' \ + '' \ + '.globl __vfprintf_chk' \ + '.type __vfprintf_chk, @function' \ + '__vfprintf_chk: mov %rdx, %rsi; mov %rcx, %rdx; jmp vfprintf@PLT' \ + '' \ + '.globl __sprintf_chk' \ + '.type __sprintf_chk, @function' \ + '__sprintf_chk: mov %rdx, %rsi; mov %rcx, %rdx; jmp sprintf@PLT' \ + '' \ + '.globl __memcpy_chk' \ + '.type __memcpy_chk, @function' \ + '__memcpy_chk: jmp memcpy@PLT' \ + '' \ + '.globl __memset_chk' \ + '.type __memset_chk, @function' \ + '__memset_chk: jmp memset@PLT' \ + '' \ + '.globl __strcat_chk' \ + '.type __strcat_chk, @function' \ + '__strcat_chk: jmp strcat@PLT' \ + '' \ + '.globl __fread_chk' \ + '.type __fread_chk, @function' \ + '__fread_chk: mov %rdx, %rax; mov %rcx, %rdx; mov %r8, %rcx; mov %rax, %rsi; jmp fread@PLT' \ + '' \ + '.globl __syslog_chk' \ + '.type __syslog_chk, @function' \ + '__syslog_chk: mov %rdx, %rsi; mov %rcx, %rdx; jmp syslog@PLT' \ + > "$STUB_ASM" + +# Assemble with host 'as', link with host 'ld'. +as -o "$STUB_OBJ" "$STUB_ASM" +ld -shared -L "$staging/usr/lib" -L "$staging/lib" -lc -o "$STUB_SO" "$STUB_OBJ" +chmod 755 "$STUB_SO" + +# Replace glibc NEEDED with musl so the stub loads in the musl guest. +patchelf --replace-needed "libc.so.6" "$MUSL_LIBC" "$STUB_SO" + +# Inject stub as NEEDED into jcode.bin (must come before libc). +run_patchelf --add-needed "libglibc_stub.so" "$staging/usr/lib/jcode/jcode.bin" + +# Create launcher script. +LAUNCHER="$TMPDIR/jcode" +printf '#!/bin/sh\nexec /usr/lib/jcode/jcode.bin "$@"\n' > "$LAUNCHER" +chmod 755 "$LAUNCHER" + +# Collect assets. +rm -rf "$asset_dir" +mkdir -p "$asset_dir" +install -m 0755 "$staging/usr/lib/jcode/jcode.bin" "$asset_dir/jcode.bin" +install -m 0755 "$staging/usr/lib/jcode/libglibc_stub.so" "$asset_dir/libglibc_stub.so" +install -m 0755 "$LAUNCHER" "$asset_dir/jcode" +for f in "$staging/usr/lib/jcode"/libssl.so* "$staging/usr/lib/jcode"/libcrypto.so*; do + [[ -f "$f" ]] && install -m 0755 "$f" "$asset_dir/" +done +for lib in libcom_err.so.2 libgssapi_krb5.so.2 libk5crypto.so.3 \ + libkeyutils.so.1 libkrb5.so.3 libkrb5support.so.0; do + [[ -f "$staging/usr/lib/$lib" ]] && install -m 0755 "$staging/usr/lib/$lib" "$asset_dir/" +done + +# Verify. +for f in jcode.bin libglibc_stub.so jcode; do + [[ -f "$asset_dir/$f" ]] || { echo "error: missing asset: $f" >&2; exit 1; } +done + +echo "jcode assets ready in $asset_dir" diff --git a/apps/starry/jcode/prepare_jcode_rootfs.sh b/apps/starry/jcode/prepare_jcode_rootfs.sh new file mode 100755 index 0000000000..1368d00d08 --- /dev/null +++ b/apps/starry/jcode/prepare_jcode_rootfs.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +workspace="$(cd "$script_dir/../../.." && pwd)" +base_rootfs="$workspace/tmp/axbuild/rootfs/rootfs-x86_64-alpine.img" +output_rootfs="$workspace/tmp/axbuild/rootfs/rootfs-x86_64-jcode.img" + +usage() { + cat </dev/null 2>&1; then + echo "error: required command not found: $1" >&2 + exit 1 + fi +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --base-rootfs) + base_rootfs="$2" + shift 2 + ;; + --output-rootfs) + output_rootfs="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "error: unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +base_rootfs="$(cd "$workspace" && realpath -m "$base_rootfs")" +output_rootfs="$(cd "$workspace" && realpath -m "$output_rootfs")" + +need_cmd cp +need_cmd debugfs +need_cmd install +need_cmd mktemp +need_cmd stat + +if [[ ! -f "$base_rootfs" ]]; then + if [[ "$base_rootfs" == "$workspace/tmp/axbuild/rootfs/rootfs-x86_64-alpine.img" ]]; then + echo "Base rootfs not found; preparing the default x86_64 Alpine rootfs..." + (cd "$workspace" && cargo xtask starry rootfs --arch x86_64) + fi +fi + +if [[ ! -f "$base_rootfs" ]]; then + echo "error: base rootfs not found: $base_rootfs" >&2 + exit 1 +fi + +# Prepare assets (downloads, patches, and builds jcode). +"$script_dir/prepare_jcode_assets.sh" + +asset_dir="$workspace/target/jcode/assets" +for f in jcode.bin libglibc_stub.so jcode; do + if [[ ! -f "$asset_dir/$f" ]]; then + echo "error: jcode asset missing after prepare_jcode_assets.sh: $f" >&2 + exit 1 + fi +done + +mkdir -p "$(dirname "$output_rootfs")" +tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/starry-jcode-rootfs.XXXXXX")" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT + +# Build overlay tree. +overlay="$tmp_dir/overlay" +mkdir -p "$overlay/usr/lib/jcode" "$overlay/usr/bin" + +install -m 0755 "$asset_dir/jcode.bin" "$overlay/usr/lib/jcode/jcode.bin" +install -m 0755 "$asset_dir/libglibc_stub.so" "$overlay/usr/lib/jcode/libglibc_stub.so" +install -m 0755 "$asset_dir/jcode" "$overlay/usr/bin/jcode" + +# Copy SSL libs. +for f in "$asset_dir"/libssl.so* "$asset_dir"/libcrypto.so*; do + [[ -f "$f" ]] && install -m 0755 "$f" "$overlay/usr/lib/jcode/" +done + +# Copy Kerberos dependency libs. +for lib in libcom_err.so.2 libgssapi_krb5.so.2 libk5crypto.so.3 \ + libkeyutils.so.1 libkrb5.so.3 libkrb5support.so.0; do + [[ -f "$asset_dir/$lib" ]] && install -m 0755 "$asset_dir/$lib" "$overlay/usr/lib/" +done + +# Copy base rootfs and inject overlay. +tmp_rootfs="$tmp_dir/rootfs.img" +cp --reflink=auto "$base_rootfs" "$tmp_rootfs" 2>/dev/null || cp "$base_rootfs" "$tmp_rootfs" + +debugfs_script="$tmp_dir/inject.debugfs" +{ + find "$overlay" -type d | sort | while IFS= read -r dir; do + rel="${dir#"$overlay"}" + [[ -z "$rel" ]] && continue + printf 'mkdir %s\n' "$rel" + done + find "$overlay" -type f | sort | while IFS= read -r file; do + rel="${file#"$overlay"}" + mode="$(stat -c '%a' "$file")" + printf 'rm %s\n' "$rel" + printf 'write %s %s\n' "$file" "$rel" + printf 'sif %s mode 0100%s\n' "$rel" "$mode" + done + printf 'quit\n' +} > "$debugfs_script" + +debugfs_log="$tmp_dir/debugfs.log" +if ! debugfs -w -f "$debugfs_script" "$tmp_rootfs" >"$debugfs_log" 2>&1; then + cat "$debugfs_log" >&2 + exit 1 +fi +mv "$tmp_rootfs" "$output_rootfs" + +display_rootfs="$output_rootfs" +case "$display_rootfs" in + "$workspace"/*) + display_rootfs="${display_rootfs#"$workspace"/}" + ;; +esac + +echo "jcode example rootfs ready:" +echo " $output_rootfs" +echo +echo "Run the offline smoke test with:" +echo " cargo xtask starry qemu --arch x86_64 \\" +echo " --qemu-config apps/starry/jcode/qemu-x86_64.toml \\" +echo " --rootfs $display_rootfs" +echo +echo "For interactive use:" +echo " cargo xtask starry qemu --arch x86_64 \\" +echo " --rootfs $display_rootfs" diff --git a/apps/starry/jcode/qemu-x86_64.toml b/apps/starry/jcode/qemu-x86_64.toml new file mode 100644 index 0000000000..ee7b81e77f --- /dev/null +++ b/apps/starry/jcode/qemu-x86_64.toml @@ -0,0 +1,40 @@ +# Example only: this is not part of the StarryOS test-suit or CI. +args = [ + "-machine", + "q35", + "-nographic", + "-m", + "2G", + "-device", + "virtio-blk-pci,drive=disk0", + "-drive", + "id=disk0,if=none,format=raw,file=${workspace}/tmp/axbuild/rootfs/rootfs-x86_64-jcode.img", + "-device", + "virtio-net-pci,netdev=net0", + "-netdev", + "user,id=net0", + "-snapshot", +] +uefi = false +to_bin = false +shell_prefix = "root@starry:" +shell_init_cmd = ''' +export HOME=/root +export USER=root +export SHELL=/bin/sh +export TERM=xterm-256color +export PATH=/usr/local/bin:/usr/bin:/bin:/sbin +export JCODE_NO_AUTO_UPDATE=1 +set -e + +jcode --version +echo "STARRY_JCODE_SMOKE_PASSED" +''' +success_regex = ["(?m)^STARRY_JCODE_SMOKE_PASSED\\s*$"] +fail_regex = [ + "(?i)\\bpanic(?:ked)?\\b", + "(?i)page fault", + "(?i)segmentation fault", + "(?m)^/bin/sh:.*not found", +] +timeout = 60