#!/bin/sh
# Builds the BeagleY-AI boot chain (tiboot3.bin, tispl.bin, u-boot.img) and
# kernel (Image, DTB, overlays, modules) in the BQ2 seed, with no Python,
# flex or bison: cleave-kconfig, cleave-dtc, cleave-optee and cleave-binman
# stand in for them.
#
#   tools/build-beagley-ai-bsp.sh fetch WORK  sources into WORK/src, patched
#                                             (outside the seed: git, curl, tar)
#   tools/build-beagley-ai-bsp.sh build WORK  build in the seed; results in WORK/out
#   tools/build-beagley-ai-bsp.sh job WORK    fetch, then build in the seed entered
#                                             with bubblewrap (an aarch64 host)
#
# Versions are those of bsp/beagley-ai/manifest.md. The seed's LLVM has only
# the AArch64 target, so the first stage builds the same LLVM (18.1.7) with
# ARM too, for the R5 SPL, and the llvm-objcopy, llvm-readelf and llvm-strip
# the seed lacks. Each stage is skipped when its result is already there.
set -eu

here=$(cd "$(dirname "$0")/.." && pwd)
cmd=${1:?usage: $0 fetch|build|job WORK}
work=$(mkdir -p "${2:?usage: $0 fetch|build|job WORK}" && cd "$2" && pwd)
src=$work/src
bsp=$here/bsp/beagley-ai

SEED_URL=https://dl.beagle.cc/images/bq2-rootfs-0.4.0-arm64.tar.gz
SEED_SHA256=b655bbc5c721a0c712b275cd78fc3a1af80f68702d4c9b30e9ac5b19d57e77b1
LLVM_URL=https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-18.1.7.tar.gz
LLVM_SHA256=b60df7cbe02cef2523f7357120fb0d46cbb443791cde3a5fb36b82c335c0afc9
# Wi-Fi userspace: wpa_supplicant and the two libnl libraries it uses
LIBNL_URL=https://github.com/thom311/libnl/releases/download/libnl3_11_0/libnl-3.11.0.tar.gz
LIBNL_SHA256=2a56e1edefa3e68a7c00879496736fdbf62fc94ed3232c0baba127ecfa76874d
WPA_URL=https://w1.fi/releases/wpa_supplicant-2.11.tar.gz
WPA_SHA256=912ea06f74e30a8e36fbb68064d6cdff218d8d591db0fc5d75dee6c81ac7fc0a
# CC33xx firmware 1.7.0.316 (SDK 1.0.2.10), which the kernel's cc33xx driver
# expects; ti-linux-firmware still has the 2024 firmware, whose
# cc33xx-conf.bin the driver rejects. BeagleBoard.org's package source.
CC33XX_FW_URL='https://repos.rcn-ee.com/debian-arm64/pool/main/b/bbb.io-cc33xx-1.0.2.10-firmware/bbb.io-cc33xx-1.0.2.10-firmware_1.20260901.0-0~noble+20260901.tar.gz'
CC33XX_FW_SHA256=0c711f6bf54cbc067ae685e1bc5e5de288ab23a6d8069105f3c6e058a78937f4
# The wireless regulatory database, signed: cfg80211 loads regulatory.db and
# checks regulatory.db.p7s against the keys built into the kernel (wens.hex
# signs this release). Its sha256 is kernel.org's, from sha256sums.asc.
REGDB_URL=https://mirrors.edge.kernel.org/pub/software/network/wireless-regdb/wireless-regdb-2026.09.03.tar.gz
REGDB_SHA256=5803f25172c8668434faf95844e1ef98315adeece49b444562712e2efb1faf62

stage() {
	echo "== $* ($(date -u +%H:%M:%S))"
}

# failed LOG: the error lines of a parallel build's log, then its end
failed() {
	echo "-- errors in $1:"
	grep -n -E "error:|Error [0-9]|undefined reference|No such file|not found" "$1" | head -40
	echo "-- end of $1:"
	tail -15 "$1"
	exit 1
}

# git_at URL REF DIR COMMIT [clone options]: a shallow clone, checked
git_at() {
	url=$1 ref=$2 dir=$3 commit=$4
	shift 4
	if [ ! -d "$dir/.git" ]; then
		git -c advice.detachedHead=false clone -q --depth 1 --branch "$ref" "$@" "$url" "$dir"
	fi
	got=$(git -C "$dir" rev-parse HEAD)
	if [ "$got" != "$commit" ]; then
		echo "$dir: $ref is $got, not $commit" >&2
		exit 1
	fi
}

# patch_once DIR PATCH...: applied once, remembered in DIR/.cleave-patched
patch_once() {
	dir=$1
	shift
	for p in "$@"; do
		name=$(basename "$p")
		grep -qx "$name" "$dir/.cleave-patched" 2>/dev/null && continue
		# (patch is more lenient than git apply, as BQ2's applier is)
		git -C "$dir" apply "$p" 2>/dev/null || patch -d "$dir" -p1 -s < "$p"
		echo "$name" >> "$dir/.cleave-patched"
	done
}

download() {
	url=$1 file=$2 sha=$3
	if [ ! -f "$file" ]; then
		curl -sSfL -o "$file.part" "$url"
		mv "$file.part" "$file"
	fi
	echo "$sha  $file" | sha256sum -c - >/dev/null
}

fetch() {
	mkdir -p "$src"
	stage fetch
	git_at https://github.com/beagleboard/linux v6.12.49-ti-arm64-r56 "$src/linux" \
		8fb21420a704ea36aaf66df8288ed8ee9da2762d
	git_at https://github.com/beagleboard/u-boot v2025.07-am6232-pocketbeagle2 "$src/u-boot" \
		a2b9f59b4fa23266d014c8bf45baeaa189630355
	git_at https://github.com/TexasInstruments/arm-trusted-firmware 11.00.09 "$src/tfa" \
		b11beb2b6bd30b75c4bfb0e9925c0e72f16ca53f
	git_at https://github.com/OP-TEE/optee_os 4.6.0 "$src/optee_os" \
		71785645fa6ce42db40dbf5a54e0eaedc4f61591
	git_at https://github.com/TexasInstruments/ti-linux-firmware 11.02.15 "$src/ti-linux-firmware" \
		59351d453295295909a25a68b30f87e5c85a6e8a --filter=blob:none --sparse
	git -C "$src/ti-linux-firmware" sparse-checkout set ti-sysfw ti-dm/j722s
	download "$LLVM_URL" "$src/llvm-18.1.7.tar.gz" "$LLVM_SHA256"
	download "$LIBNL_URL" "$src/libnl-3.11.0.tar.gz" "$LIBNL_SHA256"
	download "$WPA_URL" "$src/wpa_supplicant-2.11.tar.gz" "$WPA_SHA256"
	download "$CC33XX_FW_URL" "$src/cc33xx-firmware-1.0.2.10.tar.gz" "$CC33XX_FW_SHA256"
	download "$REGDB_URL" "$src/wireless-regdb-2026.09.03.tar.gz" "$REGDB_SHA256"
	if [ ! -d "$src/llvm-project" ]; then
		tar -xzf "$src/llvm-18.1.7.tar.gz" -C "$src"
		mv "$src/llvm-project-llvmorg-18.1.7" "$src/llvm-project"
		git -C "$src/llvm-project" init -q
	fi

	stage patch
	patch_once "$src/linux" "$bsp"/patches/linux/*.patch
	cp "$bsp"/armbian/dt/* "$src/linux/arch/arm64/boot/dts/ti/"
	patch_once "$src/u-boot" "$bsp"/patches/u-boot/*.patch
	patch_once "$src/tfa" "$bsp"/patches/tf-a/*.patch
	patch_once "$src/optee_os" "$bsp"/patches/optee_os/*.patch
	patch_once "$src/llvm-project" "$bsp"/patches/llvm-project/*.patch
}

build() {
	jobs=${JOBS:-$(nproc)}
	b=$work/build
	out=$work/out
	llvm=$work/llvm
	bin=$work/bin
	mkdir -p "$b" "$out/boot/dtb/ti" "$bin"
	export SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-$(stat -c %Y "$src/linux/Makefile")}

	stage "llvm: clang and tools for AArch64 and ARM"
	if [ ! -x "$llvm/bin/clang" ]; then
		cmake -S "$src/llvm-project/llvm" -B "$b/llvm" -G "Unix Makefiles" \
			-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$llvm" \
			-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
			-DLLVM_ENABLE_PROJECTS=clang -DLLVM_TARGETS_TO_BUILD="AArch64;ARM" \
			-DLLVM_HOST_TRIPLE=aarch64-bq2-linux-musl \
			-DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-bq2-linux-musl \
			-DLLVM_INSTALL_TOOLCHAIN_ONLY=ON -DLLVM_ENABLE_LIBCXX=ON \
			-DCLANG_DEFAULT_RTLIB=compiler-rt -DCLANG_DEFAULT_UNWINDLIB=libunwind \
			-DCLANG_DEFAULT_CXX_STDLIB=libc++ \
			-DLLVM_ENABLE_PYTHON=OFF -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_LIBEDIT=OFF \
			-DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF \
			-DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF \
			-DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_UTILS=OFF -DLLVM_ENABLE_WARNINGS=OFF \
			-DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF \
			-DLLVM_ENABLE_PLUGINS=OFF -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=OFF \
			-DLLVM_TOOL_LTO_BUILD=OFF -DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF \
			-DCLANG_PLUGIN_SUPPORT=OFF -DCLANG_TOOL_LIBCLANG_BUILD=OFF \
			-DCLANG_TOOL_C_INDEX_TEST_BUILD=OFF >"$b/llvm-cmake.log" 2>&1 || failed "$b/llvm-cmake.log"
		make -C "$b/llvm" -j"$jobs" install >"$b/llvm-build.log" 2>&1 || failed "$b/llvm-build.log"
	fi
	for t in llvm-objcopy llvm-strip llvm-objdump llvm-size llvm-ar llvm-ranlib llvm-nm; do
		[ ! -e "$llvm/bin/$t" ] || ln -sf "$llvm/bin/$t" "$bin/$t"
	done
	# (llvm-readobj is readelf when called by that name)
	ln -sf "$llvm/bin/llvm-readobj" "$bin/llvm-readelf"
	"$llvm/bin/clang" --version | head -1

	stage "cleave tools"
	# (crystal links with $CC; the seed has clang, not cc)
	(cd "$here" && CC=clang shards build --release cleave-kconfig cleave-dtc cleave-optee cleave-binman cleave-oid-registry) >"$b/cleave.log" 2>&1 ||
		failed "$b/cleave.log"
	for t in cleave-kconfig cleave-dtc cleave-optee cleave-binman cleave-oid-registry; do
		ln -sf "$here/bin/$t" "$bin/$t"
	done
	export PATH="$bin:$PATH"

	stage "tf-a: bl31.bin"
	make -C "$src/tfa" -j"$jobs" BUILD_BASE="$b/tfa" CC=clang CROSS_COMPILE=aarch64-none-elf- \
		ARCH=aarch64 PLAT=k3 TARGET_BOARD=lite SPD=opteed LDFLAGS='-z notext' bl31 >"$b/tfa.log" 2>&1 ||
		failed "$b/tfa.log"
	bl31=$b/tfa/k3/lite/release/bl31.bin

	stage "op-tee: tee-pager_v2.bin"
	make -C "$src/optee_os" -j"$jobs" O="$b/optee" SHELL=/bin/sh PLATFORM=k3-am62x CFG_ARM64_core=y \
		COMPILER=clang CFG_BUILD_IN_TREE_TA=n CFG_USER_TA_TARGETS=ta_arm64 PYTHON3=false \
		CLEAVE_OPTEE=cleave-optee >"$b/optee.log" 2>&1 || failed "$b/optee.log"
	tee=$b/optee/core/tee-pager_v2.bin

	ln -sf "$bin/cleave-binman" "$src/u-boot/tools/binman/binman"
	printf '%s\n' '# CONFIG_TOOLS_MKEFICAPSULE is not set' > "$b/u-boot-cleave.config"
	# R5: only the SPL needs Thumb-2 (to fit 192 KB)
	printf '%s\n' '# CONFIG_SYS_THUMB_BUILD is not set' 'CONFIG_SPL_SYS_THUMB_BUILD=y' >> "$b/u-boot-cleave.config"
	# R5: checkpoints on main UART0 (the debug header) before the console
	# comes up; see patches/u-boot/0005
	printf '%s\n' CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_OMAP=y CONFIG_DEBUG_UART_BASE=0x2800000 \
		CONFIG_DEBUG_UART_CLOCK=48000000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_ANNOUNCE=y \
		>> "$b/u-boot-cleave.config"
	uboot "r5" am67a_beagley_ai_r5_defconfig ARCH=arm CROSS_COMPILE=arm-none-eabi- \
		CC="$llvm/bin/clang" "CPP=$llvm/bin/clang --target=arm-none-eabi -E"
	cp "$b/u-boot-r5/tiboot3-j722s-hs-fs-evm.bin" "$out/boot/tiboot3.bin"
	# (the A53 build links the compiler's runtime as libgcc; clang's is
	# compiler-rt, which the seed has for its own triple)
	printf '%s\n' '# CONFIG_TOOLS_MKEFICAPSULE is not set' > "$b/u-boot-cleave.config"
	# A53: name each initcall on the debug header; see patches/u-boot/0008
	printf '%s\n' CONFIG_DEBUG_UART=y CONFIG_DEBUG_UART_OMAP=y CONFIG_DEBUG_UART_BASE=0x2800000 \
		CONFIG_DEBUG_UART_CLOCK=48000000 CONFIG_DEBUG_UART_SHIFT=2 >> "$b/u-boot-cleave.config"
	uboot "a53" am67a_beagley_ai_a53_defconfig ARCH=arm CROSS_COMPILE=aarch64-none-elf- CC=clang \
		"CPP=clang --target=aarch64-none-elf -E" \
		BL31="$bl31" TEE="$tee" PLATFORM_LIBGCC=/usr/lib/clang/18/lib/aarch64-bq2-linux-musl/libclang_rt.builtins.a
	cp "$b/u-boot-a53/tispl.bin" "$b/u-boot-a53/u-boot.img" "$out/boot/"

	kernel
	ls -l "$out/boot" "$out/boot/dtb/ti"

	wifi

	stage "sd card image"
	rm -f "$out/sdcard.img" "$out/sdcard.img.xz"
	(cd "$here" && CC=clang WORK="$b/image" sh tools/build-beagley-ai-image.sh "$work/seed.tar.gz" "$out/boot" \
		"$out/sdcard.img" "$out/modules" "$out/wifi") >"$b/image.log" 2>&1 || failed "$b/image.log"
	tail -4 "$b/image.log"
}

# uboot NAME DEFCONFIG MAKE-ARGS...: configured with cleave-kconfig (doing
# what `make DEFCONFIG` and the include/config/%.conf rule do), then built
uboot() {
	name=$1 defconfig=$2
	shift 2
	stage "u-boot $name"
	o=$b/u-boot-$name
	cat "$src/u-boot/configs/$defconfig" "$b/u-boot-cleave.config" > "$b/$defconfig"
	# GCC_TOOLCHAIN= : U-Boot adds --gcc-toolchain=<where ld is>, which clang
	# 18 calls unused, failing every cc-option probe under -Werror (and with
	# them -mabi=aapcs-linux and -mno-movt)
	set -- O="$o" GCC_TOOLCHAIN= HOSTCC=clang LD=ld.lld OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump AR=llvm-ar NM=llvm-nm \
		STRIP=llvm-strip READELF=llvm-readelf DTC="$bin/cleave-dtc" NO_PYLIBFDT_CHECK=1 \
		PYTHON3=false BINMAN_INDIRS="$src/ti-linux-firmware" "$@"
	k="cleave-kconfig --dialect u-boot"
	make -C "$src/u-boot" "$@" --eval "cleave-defconfig: ; $k --defconfig=$b/$defconfig Kconfig && $k --syncconfig Kconfig && \$(MAKE) -f \$(srctree)/scripts/Makefile.autoconf __all && touch include/config/auto.conf" \
		cleave-defconfig >"$b/u-boot-$name.log" 2>&1 || failed "$b/u-boot-$name.log"
	make -C "$src/u-boot" -j"$jobs" "$@" >>"$b/u-boot-$name.log" 2>&1 ||
		failed "$b/u-boot-$name.log"
}

kernel() {
	stage "linux: Image, DTBs, modules"
	o=$b/linux
	mkdir -p "$o"
	# CC with ARM too (the 32-bit compat vDSO); host tools with the seed's
	# clang, whose resource directory has the compiler runtime
	set -- -C "$src/linux" O="$o" ARCH=arm64 LLVM=1 CC="$llvm/bin/clang" HOSTCC=/usr/bin/clang \
		HOSTCXX=/usr/bin/clang++ DTC="$bin/cleave-dtc" OID_REGISTRY="$bin/cleave-oid-registry"
	if [ ! -f "$o/include/config/auto.conf" ]; then
		cat "$bsp/armbian/linux-k3-beagle-vendor.config" "$bsp/kernel-jkembedded-audio.config" \
			"$bsp/kernel-bq2-seed.config" "$bsp/kernel-cleave-init.config" "$bsp/kernel-wifi.config" > "$o/.config"
		make "$@" --eval "cleave-syncconfig: ; cleave-kconfig --olddefconfig Kconfig && cleave-kconfig --syncconfig Kconfig" \
			cleave-syncconfig >"$b/linux.log" 2>&1 || failed "$b/linux.log"
	fi
	make "$@" -j"$jobs" Image modules ti/k3-am67a-beagley-ai.dtb \
		ti/k3-j722s-edgeai-apps.dtbo ti/k3-am67a-beagley-ai-csi0-imx219.dtbo >>"$b/linux.log" 2>&1 ||
		failed "$b/linux.log"
	rm -rf "$out/modules"
	# (busybox depmod ignores -b; modules.dep is made on the board)
	make "$@" INSTALL_MOD_PATH="$out/modules" INSTALL_MOD_STRIP=1 DEPMOD=true modules_install >>"$b/linux.log" 2>&1 ||
		failed "$b/linux.log"
	cp "$o/arch/arm64/boot/Image" "$out/boot/"
	cp "$o"/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dtb "$o"/arch/arm64/boot/dts/ti/k3-j722s-edgeai-apps.dtbo \
		"$o"/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai-csi0-imx219.dtbo "$out/boot/dtb/ti/"
	tar -C "$out/modules" -czf "$out/modules.tar.gz" lib
}

# Wi-Fi, as a root layer in WORK/out/wifi: wpa_supplicant and wpa_cli,
# linked statically with libnl-3 and libnl-genl-3, the CC33xx firmware, and
# the signed regulatory database. No cc33xx-nvs.bin: the driver reads only a
# MAC address from it, and without it takes the chip's own from its EFUSE.
# libnl's configure wants flex and bison, which only its route library
# uses: they are named false and that library is not built.
wifi() {
	stage "wifi: libnl, wpa_supplicant, CC33xx firmware, regulatory database"
	w=$out/wifi
	if [ ! -x "$w/usr/sbin/wpa_supplicant" ]; then
		rm -rf "$b/libnl" "$b/wpa" "$w"
		mkdir -p "$b/libnl" "$b/wpa"
		tar -xzf "$src/libnl-3.11.0.tar.gz" -C "$b/libnl" --strip-components=1
		# (the seed has no ar, ranlib or nm but LLVM's)
		(cd "$b/libnl" && CC=clang AR=llvm-ar RANLIB=llvm-ranlib NM=llvm-nm FLEX=false YACC=false ./configure --prefix=/usr --disable-shared \
			--enable-static --disable-cli --disable-debug &&
			make -j"$jobs" lib/libnl-3.la lib/libnl-genl-3.la) >"$b/libnl.log" 2>&1 || failed "$b/libnl.log"
		tar -xzf "$src/wpa_supplicant-2.11.tar.gz" -C "$b/wpa" --strip-components=1
		cp "$bsp/wpa_supplicant.config" "$b/wpa/wpa_supplicant/.config"
		# (--unwindlib=none: C needs no unwinder, and the seed's is shared only)
		make -C "$b/wpa/wpa_supplicant" -j"$jobs" CC="clang --unwindlib=none" LIBNL_INC="$b/libnl/include" \
			EXTRA_CFLAGS=-Os LDFLAGS="-L$b/libnl/lib/.libs -static" wpa_supplicant wpa_cli >"$b/wpa.log" 2>&1 ||
			failed "$b/wpa.log"
		for p in wpa_supplicant wpa_cli; do
			install -D -m 755 "$b/wpa/wpa_supplicant/$p" "$w/usr/sbin/$p"
			llvm-strip "$w/usr/sbin/$p"
		done
		mkdir -p "$w/lib/firmware/ti-connectivity"
		tar -xzf "$src/cc33xx-firmware-1.0.2.10.tar.gz" -C "$w/lib/firmware/ti-connectivity" --strip-components=2 \
			bbb.io-cc33xx-1.0.2.10-firmware-1.20260901.0/debian/cc33xx_fw.bin \
			bbb.io-cc33xx-1.0.2.10-firmware-1.20260901.0/debian/cc33xx_2nd_loader.bin \
			bbb.io-cc33xx-1.0.2.10-firmware-1.20260901.0/debian/cc33xx-conf.bin
	fi
	if [ ! -f "$w/lib/firmware/regulatory.db.p7s" ]; then
		mkdir -p "$w/lib/firmware"
		tar -xzf "$src/wireless-regdb-2026.09.03.tar.gz" -C "$w/lib/firmware" --strip-components=1 \
			wireless-regdb-2026.09.03/regulatory.db wireless-regdb-2026.09.03/regulatory.db.p7s
	fi
	ls -l "$w/usr/sbin" "$w/lib/firmware" "$w/lib/firmware/ti-connectivity"
}

# The seed, unpacked into WORK/seed, with the fixes it needs: the musl path
# for libunwind (see image/beagley-ai/README.md), and OP-TEE's clang target
# finding the compiler runtime under its own triple.
seed() {
	stage seed
	download "$SEED_URL" "$work/seed.tar.gz" "$SEED_SHA256"
	if [ ! -d "$work/seed/usr" ]; then
		mkdir -p "$work/seed"
		tar -xzf "$work/seed.tar.gz" -C "$work/seed" 2>/dev/null || true
		cp "$here/image/beagley-ai/rootfs/etc/ld-musl-aarch64.path" "$work/seed/etc/"
		rt=$work/seed/usr/lib/clang/18/lib
		ln -sfn aarch64-bq2-linux-musl "$rt/aarch64-unknown-linux-gnu"
		# The 0.4.0 seed's clang links the GCC runtime by default, which the
		# seed does not have (later seeds default to these, as BQ2 builds
		# LLVM now). Config files named for the seed's own triple apply to
		# its native builds only, not to --target cross builds.
		echo '--rtlib=compiler-rt --unwindlib=libunwind' > "$work/seed/usr/bin/aarch64-bq2-linux-musl-clang.cfg"
		echo '--rtlib=compiler-rt --unwindlib=libunwind -stdlib=libc++' > "$work/seed/usr/bin/aarch64-bq2-linux-musl-clang++.cfg"
		# and builds that call the compiler cc find clang
		ln -sf clang "$work/seed/usr/bin/cc"
		ln -sf clang++ "$work/seed/usr/bin/c++"
	fi
}

job() {
	fetch
	seed
	stage "entering the seed"
	bwrap --bind "$work/seed" / --bind "$work" /work --bind "$here" /cleave \
		--proc /proc --dev /dev --tmpfs /tmp --ro-bind /etc/resolv.conf /etc/resolv.conf \
		--unshare-user --uid 0 --gid 0 --setenv HOME /work --setenv PATH /usr/sbin:/usr/bin:/sbin:/bin \
		/bin/sh /cleave/tools/build-beagley-ai-bsp.sh build /work
	# (the seed's xz is busybox's, which only decompresses)
	stage "compressing the image"
	rm -f "$work/out/sdcard.img.xz"
	xz -T0 -6 "$work/out/sdcard.img"
	ls -l "$work/out/sdcard.img.xz" "$work/out/modules.tar.gz"
}

case $cmd in
fetch) fetch ;;
build) build ;;
job) job ;;
*) echo "usage: $0 fetch|build|job WORK" >&2; exit 2 ;;
esac
