From d1f3bcaffdd3382673f465f7d2dcb154c058acb0 Mon Sep 17 00:00:00 2001 From: Dinesh Talwadker <90450035+dinxsh@users.noreply.github.com> Date: Mon, 27 Apr 2026 03:58:57 +0530 Subject: [PATCH 1/2] docs: add WSL2 build path and troubleshooting section All 7 errors confirmed during a full build run on Ubuntu 24.04 WSL2 on Windows 11. WSL2 setup steps, error-specific fixes, and a note on reusing the rootfs image across build-images.sh runs without repeating the expensive rootfs build. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/README.md b/README.md index 4b09adc..2b42c1f 100644 --- a/README.md +++ b/README.md @@ -226,3 +226,107 @@ sudo rockusb write-bmap out/debian-.img.gz + +## Building on WSL2 (Windows) + +The build scripts work on Ubuntu 24.04 WSL2 with a few one-time setup steps. WSL2 does not pre-mount `binfmt_misc`, does not pre-create loop device nodes, and exposes `/dev/kvm` via Hyper-V even though `fakemachine` is not installed. Apply the following before running any build script. + +```bash +# Register ARM binary handlers (required for rootfs build) +mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true +update-binfmts --enable + +# Create loop device nodes (WSL2 does not create these automatically) +for i in $(seq 0 32); do + [ -b /dev/loop$i ] || mknod /dev/loop$i b 7 $i +done + +# Disable the fakemachine path - WSL2 exposes /dev/kvm but fakemachine is not installed +sed -i 's/if \[ -c \/dev\/kvm -a -w \/dev\/kvm \]/if false/' build-rootfs-img.sh build-images.sh + +# Keep IMG_OUT on the WSL2 virtual disk (ext4), not a Windows-mounted path +# NTFS does not support fallocate, which the image assembly step requires +export IMG_OUT=out +export TMPDIR=/root/build-tmp +mkdir -p "$TMPDIR" +``` + +Both `binfmt_misc` registration and the loop device creation need to be repeated after each WSL2 session restart (or added to `/etc/rc.local` to persist). + +## Troubleshooting + +### `execv(sh) failed: Exec format error` + +`binfmt_misc` is not mounted or ARM binary handlers are not registered. The rootfs build runs ARM binaries on the host and they fail immediately. + +```bash +mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc +update-binfmts --enable +``` + +### `lstat .../linux_tmp: no such file or directory` + +`IMG_OUT` is set to an absolute path. Internal scripts construct intermediate paths by appending relative suffixes, which breaks when the working directory changes mid-build. + +```bash +export IMG_OUT=out # relative to repo root +``` + +### `fallocate: fallocate failed: Operation not supported` + +`IMG_OUT` or `TMPDIR` points to an NTFS-backed path (e.g. `/mnt/c/...`). NTFS does not support `fallocate`. Keep both on a Linux ext4 filesystem: + +```bash +export IMG_OUT=out +export TMPDIR=/root/build-tmp && mkdir -p "$TMPDIR" +``` + +### `fakemachine: command not found` + +WSL2 exposes `/dev/kvm` via Hyper-V. The build script detects this and tries `fakemachine`, which is not installed. Patch the condition: + +```bash +sed -i 's/if \[ -c \/dev\/kvm -a -w \/dev\/kvm \]/if false/' build-rootfs-img.sh build-images.sh +``` + +### `bmaptool: image size X will not fit block device Y` + +`IMGSIZE` defaults differ between `build-rootfs-img.sh` and `build-images.sh`. Set it explicitly in both: + +```bash +sed -i 's/IMGSIZE:=4GiB/IMGSIZE:=8GiB/g' build-rootfs-img.sh build-images.sh +``` + +### `No space left on device` during kernel install + +The default 4 GiB rootfs is too small once kernel modules and headers are installed. Increase to 8 GiB: + +```bash +sed -i 's/^IMGSIZE=.*/IMGSIZE=8GiB/' build-rootfs-img.sh +``` + +Apply the same fix to `build-images.sh` to keep sizes consistent (see `bmaptool` error above). + +### `cp: Input/output error` copying the board image + +WSL2 kernel bug: a large file written through a loop device triggers EIO on a subsequent `cp`. The data is intact. Use `mv` instead: + +```bash +grep -n 'cp.*\.img' build-images.sh +# Replace cp with mv on that line (N): +sed -i 'Ns/\bcp\b/mv/' build-images.sh +``` + +`mv` is a rename and bypasses the page cache read path entirely. + +## Reusing the rootfs image + +`build-rootfs-img.sh` produces `out/debian-rootfs.img.zst`. This step installs all Debian packages and takes 20-40 minutes. `build-images.sh` consumes it to assemble the final board images and is much faster. + +**If `build-images.sh` fails, you do not need to rerun `build-rootfs-img.sh`.** Fix the error and rerun `build-images.sh` directly as long as `out/debian-rootfs.img.zst` exists: + +```bash +ls -lh out/debian-rootfs.img.zst # confirm it exists +zstd --test out/debian-rootfs.img.zst # verify it is not corrupted +./build-images.sh +``` From c76e98ea5328787767d3367b128338a2bdc17b98 Mon Sep 17 00:00:00 2001 From: Dinesh Talwadker <90450035+dinxsh@users.noreply.github.com> Date: Tue, 28 Apr 2026 08:26:43 +0530 Subject: [PATCH 2/2] docs: address alchark review comments on WSL2 section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace update-binfmts with qemu-user-binfmt package + systemd-binfmt.service - Remove fakemachine-not-installed premise (it is installed per base README prereqs) - Remove manual loop device mknod block (losetup creates them on demand) - Remove sed hack that disabled KVM/fakemachine detection (breaks non-root builds) - Remove redundant IMG_OUT=out (it is already the default) - Remove TMPDIR=/root/build-tmp (scripts use mktemp internally; /root breaks non-root) - Replace rc.local mention with systemd-binfmt.service for persistence - Remove lstat/linux_tmp troubleshooting entry (working directory error, not WSL2 bug) - Remove cp→mv workaround (cp is intentional; mv would break multi-board image loop) - Expand reuse section to cover all four build stages (kernel, U-boot, ospack, rootfs) Co-Authored-By: Claude Sonnet 4.6 --- README.md | 71 +++++++++++++------------------------------------------ 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 2b42c1f..9158db5 100644 --- a/README.md +++ b/README.md @@ -229,64 +229,32 @@ sudo rockusb write-bmap out/debian-.img.gz ## Building on WSL2 (Windows) -The build scripts work on Ubuntu 24.04 WSL2 with a few one-time setup steps. WSL2 does not pre-mount `binfmt_misc`, does not pre-create loop device nodes, and exposes `/dev/kvm` via Hyper-V even though `fakemachine` is not installed. Apply the following before running any build script. +If you followed the prerequisites above, `fakemachine` is already installed. On WSL2, ARM binary handlers for QEMU user-mode emulation must be registered before running the rootfs build. Install `qemu-user-binfmt` and activate its systemd unit: ```bash -# Register ARM binary handlers (required for rootfs build) -mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true -update-binfmts --enable - -# Create loop device nodes (WSL2 does not create these automatically) -for i in $(seq 0 32); do - [ -b /dev/loop$i ] || mknod /dev/loop$i b 7 $i -done - -# Disable the fakemachine path - WSL2 exposes /dev/kvm but fakemachine is not installed -sed -i 's/if \[ -c \/dev\/kvm -a -w \/dev\/kvm \]/if false/' build-rootfs-img.sh build-images.sh - -# Keep IMG_OUT on the WSL2 virtual disk (ext4), not a Windows-mounted path -# NTFS does not support fallocate, which the image assembly step requires -export IMG_OUT=out -export TMPDIR=/root/build-tmp -mkdir -p "$TMPDIR" +sudo apt install qemu-user-binfmt +sudo systemctl enable --now systemd-binfmt ``` -Both `binfmt_misc` registration and the loop device creation need to be repeated after each WSL2 session restart (or added to `/etc/rc.local` to persist). +This persists across WSL2 session restarts automatically. ## Troubleshooting ### `execv(sh) failed: Exec format error` -`binfmt_misc` is not mounted or ARM binary handlers are not registered. The rootfs build runs ARM binaries on the host and they fail immediately. +ARM binary handlers are not registered. The rootfs build runs ARM binaries on the host via QEMU and they fail immediately if the `binfmt_misc` entries are missing. ```bash -mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc -update-binfmts --enable -``` - -### `lstat .../linux_tmp: no such file or directory` - -`IMG_OUT` is set to an absolute path. Internal scripts construct intermediate paths by appending relative suffixes, which breaks when the working directory changes mid-build. - -```bash -export IMG_OUT=out # relative to repo root +sudo apt install qemu-user-binfmt +sudo systemctl enable --now systemd-binfmt ``` ### `fallocate: fallocate failed: Operation not supported` -`IMG_OUT` or `TMPDIR` points to an NTFS-backed path (e.g. `/mnt/c/...`). NTFS does not support `fallocate`. Keep both on a Linux ext4 filesystem: - -```bash -export IMG_OUT=out -export TMPDIR=/root/build-tmp && mkdir -p "$TMPDIR" -``` - -### `fakemachine: command not found` - -WSL2 exposes `/dev/kvm` via Hyper-V. The build script detects this and tries `fakemachine`, which is not installed. Patch the condition: +`IMG_OUT` points to an NTFS-backed path (e.g. `/mnt/c/...`). NTFS does not support `fallocate`. The default value `out` stores files on the WSL2 virtual disk (ext4) — unset any override: ```bash -sed -i 's/if \[ -c \/dev\/kvm -a -w \/dev\/kvm \]/if false/' build-rootfs-img.sh build-images.sh +unset IMG_OUT ``` ### `bmaptool: image size X will not fit block device Y` @@ -307,21 +275,16 @@ sed -i 's/^IMGSIZE=.*/IMGSIZE=8GiB/' build-rootfs-img.sh Apply the same fix to `build-images.sh` to keep sizes consistent (see `bmaptool` error above). -### `cp: Input/output error` copying the board image - -WSL2 kernel bug: a large file written through a loop device triggers EIO on a subsequent `cp`. The data is intact. Use `mv` instead: - -```bash -grep -n 'cp.*\.img' build-images.sh -# Replace cp with mv on that line (N): -sed -i 'Ns/\bcp\b/mv/' build-images.sh -``` +## Reusing build artifacts -`mv` is a rename and bypasses the page cache read path entirely. +Each build stage writes its output to a known location. If a stage's output already exists, the next stage skips it automatically. You can re-run any individual stage without repeating earlier ones: -## Reusing the rootfs image - -`build-rootfs-img.sh` produces `out/debian-rootfs.img.zst`. This step installs all Debian packages and takes 20-40 minutes. `build-images.sh` consumes it to assemble the final board images and is much faster. +| Stage | Output | How to skip | +|---|---|---| +| Kernel | `prebuilt/linux/` | `KEEP_SRC=yes ./build-kernel-*.sh` rebuilds without re-cloning | +| U-boot | `prebuilt/u-boot//` | `KEEP_SRC=yes ./build-uboot.sh` rebuilds without re-cloning | +| OS pack | `out/debian-ospack.tar.gz` | Skipped by `build-rootfs-img.sh` automatically if this file exists | +| Root filesystem | `out/debian-rootfs.img.zst` | Skipped by `build-images.sh` automatically if this file exists | **If `build-images.sh` fails, you do not need to rerun `build-rootfs-img.sh`.** Fix the error and rerun `build-images.sh` directly as long as `out/debian-rootfs.img.zst` exists: