boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit 21076563f70aed6d68f32a4a79d6ed992e2d552f
parent bd4fdff0302a2548ae7c5342c91ed819d244ae70
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed,  6 May 2026 19:46:47 -0700

containers: rename .scratch → .busybox; tests' .busybox → .busybox-test

The boot Containerfile bundles busybox via FROM scratch + COPY, so call
it that. Renames the tests-only image to boot2-busybox-test to free the
boot2-busybox tag for the boot image. Containerfile.empty (truly empty
rootfs) keeps its name.

Diffstat:
Mboot/boot0.sh | 2+-
Mboot/boot1.sh | 2+-
Mboot/boot2.sh | 2+-
Aboot/containers/Containerfile.busybox | 25+++++++++++++++++++++++++
Mboot/containers/Containerfile.empty | 2+-
Dboot/containers/Containerfile.scratch | 25-------------------------
Mboot/lib-arch.sh | 10+++++-----
Mbootprep/boot5-calibrate.sh | 4++--
Mdocs/MUSL.md | 2+-
Mtests/Makefile | 10+++++-----
Mtests/README.md | 2+-
Dtests/containers/Containerfile.busybox | 18------------------
Atests/containers/Containerfile.busybox-test | 18++++++++++++++++++
Mtests/run.sh | 2+-
14 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/boot/boot0.sh b/boot/boot0.sh @@ -20,7 +20,7 @@ set -eu . boot/lib-arch.sh bootlib_init boot0 "${1:-}" -driver_init scratch +driver_init busybox require_src . boot/lib-pipeline.sh diff --git a/boot/boot1.sh b/boot/boot1.sh @@ -24,7 +24,7 @@ set -eu . boot/lib-arch.sh bootlib_init boot1 "${1:-}" -driver_init scratch +driver_init busybox require_src BOOT0=build/$ARCH/$DRIVER/boot0 diff --git a/boot/boot2.sh b/boot/boot2.sh @@ -26,7 +26,7 @@ set -eu . boot/lib-arch.sh bootlib_init boot2 "${1:-}" -driver_init scratch +driver_init busybox require_src BOOT0=build/$ARCH/$DRIVER/boot0 diff --git a/boot/containers/Containerfile.busybox b/boot/containers/Containerfile.busybox @@ -0,0 +1,25 @@ +## Per-arch image used by the standalone bootN.sh entrypoints. +## Two stages: +## 1. pull busybox:musl as the build container (provides a single +## static /bin/busybox plus a tree of applet symlinks) +## 2. FROM scratch, copy the busybox binary + symlinks into a fresh +## empty rootfs +## +## The result is a per-arch image whose entire userland is +## statically-linked busybox. No libc, no resolver, no /etc. +## This is the only container the bootN.sh scripts ever exec into. +## +## Built per --platform; tag as boot2-busybox:<arch>. +## Multi-arch index pinned to the same digest the boot2-busybox-test image +## uses (tests/containers/Containerfile.busybox-test); per-arch entries within +## the index, fetched 2026-04-24: +## amd64 sha256:298efc24641ff8a1a285abdc555a0ce5ab7c42eb085e1be099f824188e069604 +## arm64 sha256:458a2ae4cb09bf96f8e24f135474b1552039738ed16ee470320a9c05c2da2004 +## riscv64 sha256:657f5a49af9288dc98d2bf45343e45c57c3caf3946aa9df436d05da320a8c863 + +FROM docker.io/library/busybox@sha256:19b646668802469d968a05342a601e78da4322a414a7c09b1c9ee25165042138 AS busybox + +FROM scratch +COPY --from=busybox /bin /bin +WORKDIR /work +CMD ["/bin/sh"] diff --git a/boot/containers/Containerfile.empty b/boot/containers/Containerfile.empty @@ -1,5 +1,5 @@ ## Per-arch image used by boot3/4/5.sh — fully empty rootfs (FROM scratch -## with no copy stages). Unlike boot/containers/Containerfile.scratch, this image +## with no copy stages). Unlike boot/containers/Containerfile.busybox, this image ## does not bundle busybox: boot3/4/5 invoke scheme1 directly via argv ## and run.scm spawns only staged binaries (catm, scheme1, M1pp, hex2pp, ## tcc), so no in-container shell, /bin/sh, or applet tree is needed. diff --git a/boot/containers/Containerfile.scratch b/boot/containers/Containerfile.scratch @@ -1,25 +0,0 @@ -## Per-arch image used by the standalone bootN.sh entrypoints. -## Two stages: -## 1. pull busybox:musl as the build container (provides a single -## static /bin/busybox plus a tree of applet symlinks) -## 2. FROM scratch, copy the busybox binary + symlinks into a fresh -## empty rootfs -## -## The result is a per-arch image whose entire userland is -## statically-linked busybox. No libc, no resolver, no /etc. -## This is the only container the bootN.sh scripts ever exec into. -## -## Built per --platform; tag as boot2-scratch:<arch>. -## Multi-arch index pinned to the same digest the boot2-busybox image -## uses (tests/containers/Containerfile.busybox); per-arch entries within the -## index, fetched 2026-04-24: -## amd64 sha256:298efc24641ff8a1a285abdc555a0ce5ab7c42eb085e1be099f824188e069604 -## arm64 sha256:458a2ae4cb09bf96f8e24f135474b1552039738ed16ee470320a9c05c2da2004 -## riscv64 sha256:657f5a49af9288dc98d2bf45343e45c57c3caf3946aa9df436d05da320a8c863 - -FROM docker.io/library/busybox@sha256:19b646668802469d968a05342a601e78da4322a414a7c09b1c9ee25165042138 AS busybox - -FROM scratch -COPY --from=busybox /bin /bin -WORKDIR /work -CMD ["/bin/sh"] diff --git a/boot/lib-arch.sh b/boot/lib-arch.sh @@ -7,8 +7,8 @@ # # set ARCH/PLATFORM/KERNEL_NAME/ # # MUSL_ARCH/DRIVER/BOOT_STAGE/BOOT_TAG. # driver_init [<image-kind>] # set OUT/STAGE; podman: build IMAGE -# # if missing (image-kind ∈ scratch| -# # empty; default scratch); seed: +# # if missing (image-kind ∈ busybox| +# # empty; default busybox); seed: # # verify boot6 kernel exists. # require_src # die if build/$ARCH/src/ missing. # require_prev <dir> <name>... # die if any <dir>/<name> is @@ -100,10 +100,10 @@ _bootlib_finish() { } driver_init() { - _image_kind=${1:-scratch} + _image_kind=${1:-busybox} case "$_image_kind" in - scratch|empty) ;; - *) echo "[$BOOT_TAG] driver_init: image-kind must be scratch|empty (got $_image_kind)" >&2; exit 2 ;; + busybox|empty) ;; + *) echo "[$BOOT_TAG] driver_init: image-kind must be busybox|empty (got $_image_kind)" >&2; exit 2 ;; esac OUT=build/$ARCH/$DRIVER/$BOOT_STAGE STAGE=build/$ARCH/$DRIVER/.$BOOT_STAGE-stage diff --git a/bootprep/boot5-calibrate.sh b/bootprep/boot5-calibrate.sh @@ -38,7 +38,7 @@ esac ROOT=$(cd "$(dirname "$0")/.." && pwd) cd "$ROOT" -IMAGE=boot2-scratch:$ARCH +IMAGE=boot2-busybox:$ARCH BOOT4=build/$ARCH/boot4 STAGE=build/$ARCH/.boot5-calibrate MUSL_TARBALL=vendor/musl/1.2.5.tar.gz @@ -58,7 +58,7 @@ SKIP_OUT=vendor/musl/skip-$ARCH.txt if ! podman image exists "$IMAGE"; then podman build --platform "$PLATFORM" -t "$IMAGE" \ - -f boot/containers/Containerfile.scratch boot/containers/ + -f boot/containers/Containerfile.busybox boot/containers/ fi rm -rf "$STAGE" diff --git a/docs/MUSL.md b/docs/MUSL.md @@ -6,7 +6,7 @@ static hello-world smoke binary. Supported architectures are `amd64`, `aarch64`, and `riscv64`; aarch64 is verified end-to-end every run, and the same recipe has previously been validated against amd64 and riscv64. -The build runs in `boot2-scratch:$ARCH` (scratch + busybox, no libc, no +The build runs in `boot2-busybox:$ARCH` (scratch + busybox, no libc, no `/etc`) and produces only static artifacts. Dynamic linking and `ldso/` are intentionally out of scope. diff --git a/tests/Makefile b/tests/Makefile @@ -42,7 +42,7 @@ boot3 = build/$(1)/$(TEST_DRIVER)/boot3 boot4 = build/$(1)/$(TEST_DRIVER)/boot4 boot5 = build/$(1)/$(TEST_DRIVER)/boot5 -# ── tests-only container images (boot2-busybox, boot2-alpine-gcc) ──────── +# ── tests-only container images (boot2-busybox-test, boot2-alpine-gcc) ── IMAGE_STAMP := build/$(ARCH)/.image IMAGE_STAMPS := $(foreach a,$(ALL_ARCHES),build/$(a)/.image) @@ -50,10 +50,10 @@ IMAGE_STAMPS := $(foreach a,$(ALL_ARCHES),build/$(a)/.image) .PHONY: image image: $(IMAGE_STAMP) -$(IMAGE_STAMPS): build/%/.image: tests/containers/Containerfile.busybox +$(IMAGE_STAMPS): build/%/.image: tests/containers/Containerfile.busybox-test mkdir -p $(@D) - podman build --platform $(PLATFORM_$*) -t boot2-busybox:$* \ - -f tests/containers/Containerfile.busybox tests/containers/ + podman build --platform $(PLATFORM_$*) -t boot2-busybox-test:$* \ + -f tests/containers/Containerfile.busybox-test tests/containers/ @touch $@ ALPINE_GCC_IMAGES := $(foreach a,$(ALL_ARCHES),build/$(a)/.image-alpine-gcc) @@ -68,7 +68,7 @@ $(ALPINE_GCC_IMAGES): build/%/.image-alpine-gcc: tests/containers/Containerfile. PODMAN = podman run --rm --pull=never --platform $(PLATFORM_$(1)) \ --tmpfs /tmp:size=512M \ -e ARCH=$(1) \ - -v $(CURDIR):/work -w /work boot2-busybox:$(1) + -v $(CURDIR):/work -w /work boot2-busybox-test:$(1) ALPINE_GCC = podman run --rm --pull=never --platform $(PLATFORM_$(1)) \ --tmpfs /tmp:size=128M \ diff --git a/tests/README.md b/tests/README.md @@ -41,7 +41,7 @@ make test SUITE=cc-libc ARCH=amd64 # one arch make test SUITE=tcc-cc ARCH=amd64 STAGE=2 # tcc-built test runners ``` -`make image` builds the per-arch `boot2-busybox` container used by all +`make image` builds the per-arch `boot2-busybox-test` container used by all podman-driven suites. ## Per-suite contract diff --git a/tests/containers/Containerfile.busybox b/tests/containers/Containerfile.busybox @@ -1,18 +0,0 @@ -## Minimal per-arch image used to run target-arch ELF (stage0 tools and -## final P1 programs). Built per --platform; tag as boot2-busybox:<arch>. -## -## docker.io/library/busybox:musl ships per-arch manifests for amd64, arm64 -## (aarch64), and riscv64. Pinning by index digest collapses to a single -## entry in the local store under multiple --platform pulls (the last wins), -## so we let `podman build --platform` pick the right per-arch manifest from -## the index and rely on per-arch tags (boot2-busybox:<arch>) to keep the -## resulting images distinct in the local store. -## -## Pinned to the busybox:musl index manifest (a multi-arch index, not a -## per-arch image). Per-arch entries within this index, fetched 2026-04-24: -## amd64 sha256:298efc24641ff8a1a285abdc555a0ce5ab7c42eb085e1be099f824188e069604 -## arm64 sha256:458a2ae4cb09bf96f8e24f135474b1552039738ed16ee470320a9c05c2da2004 -## riscv64 sha256:657f5a49af9288dc98d2bf45343e45c57c3caf3946aa9df436d05da320a8c863 - -FROM docker.io/library/busybox@sha256:19b646668802469d968a05342a601e78da4322a414a7c09b1c9ee25165042138 -CMD ["/bin/sh"] diff --git a/tests/containers/Containerfile.busybox-test b/tests/containers/Containerfile.busybox-test @@ -0,0 +1,18 @@ +## Minimal per-arch image used to run target-arch ELF (stage0 tools and +## final P1 programs). Built per --platform; tag as boot2-busybox-test:<arch>. +## +## docker.io/library/busybox:musl ships per-arch manifests for amd64, arm64 +## (aarch64), and riscv64. Pinning by index digest collapses to a single +## entry in the local store under multiple --platform pulls (the last wins), +## so we let `podman build --platform` pick the right per-arch manifest from +## the index and rely on per-arch tags (boot2-busybox-test:<arch>) to keep the +## resulting images distinct in the local store. +## +## Pinned to the busybox:musl index manifest (a multi-arch index, not a +## per-arch image). Per-arch entries within this index, fetched 2026-04-24: +## amd64 sha256:298efc24641ff8a1a285abdc555a0ce5ab7c42eb085e1be099f824188e069604 +## arm64 sha256:458a2ae4cb09bf96f8e24f135474b1552039738ed16ee470320a9c05c2da2004 +## riscv64 sha256:657f5a49af9288dc98d2bf45343e45c57c3caf3946aa9df436d05da320a8c863 + +FROM docker.io/library/busybox@sha256:19b646668802469d968a05342a601e78da4322a414a7c09b1c9ee25165042138 +CMD ["/bin/sh"] diff --git a/tests/run.sh b/tests/run.sh @@ -91,7 +91,7 @@ run_in_container() { -e "CC_DEBUG=${CC_DEBUG:-0}" \ -e "STAGE=${STAGE:-}" \ -v "$REPO":/work -w /work \ - "boot2-busybox:$arch" "$@" + "boot2-busybox-test:$arch" "$@" } if [ -z "$ARCH" ]; then