boot2

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

mkrelease.sh (6947B)


      1 #!/bin/sh
      2 ## mkrelease.sh — package a per-arch boot2 release tarball.
      3 ##
      4 ## A release tarball is a self-contained bundle that lets anyone
      5 ## reproduce the full boot0..boot7 chain off the bundled inputs and
      6 ## byte-compare the outputs against a hash manifest. Layout:
      7 ##
      8 ##   boot2-<arch>[-<rev>].tar.gz
      9 ##     boot2-<arch>[-<rev>]/
     10 ##       README.md             extract + run instructions
     11 ##       verify.sh             drives boot0..boot7 + diffs manifests
     12 ##       INPUT_MANIFEST.txt    sha256 of every input under src/ + boot/
     13 ##       OUTPUT_MANIFEST.txt   sha256 of expected per-stage artifacts
     14 ##       TOOLCHAIN_MANIFEST.txt sha256 of every installed boot7 file
     15 ##       Both output manifests are driver-agnostic; the project's
     16 ##       seed-accept harness verifies podman vs seed equivalence.
     17 ##       src/                  the sealed source tree (from
     18 ##                             build/<arch>/src/, produced by prep-src.sh)
     19 ##       boot/                 boot0..boot7 stage drivers + libs +
     20 ##                             containers/Containerfile.*
     21 ##
     22 ## The output manifest is generated from the current build outputs in
     23 ## build/<arch>/<driver>/boot{0..7}/. mkrelease.sh does NOT rebuild;
     24 ## prereqs (`make all ARCH=<arch>`) must already have run.
     25 ##
     26 ## Usage: tools/mkrelease.sh <arch>
     27 ##   <arch> ∈ {aarch64, amd64, riscv64}
     28 ## Env:
     29 ##   DRIVER  podman (default) | seed   — which build tree to hash for the
     30 ##                                       output manifest. The manifest is
     31 ##                                       claimed driver-agnostic regardless.
     32 ##
     33 ## The tarball name is `boot2-<arch>.tar.gz` — deliberately rev-free, so
     34 ## the tarball's sha256 reflects content and nothing else. Provenance
     35 ## (git rev, build timestamp) lives in a sidecar produced by the
     36 ## validated mint path (tools/release.sh), not inside the tarball.
     37 
     38 set -eu
     39 
     40 ARCH=${1:-}
     41 case "$ARCH" in
     42     aarch64|amd64|riscv64) ;;
     43     *) echo "usage: $0 <aarch64|amd64|riscv64>" >&2; exit 2 ;;
     44 esac
     45 
     46 DRIVER=${DRIVER:-podman}
     47 case "$DRIVER" in
     48     podman|seed) ;;
     49     *) echo "[mkrelease] unknown DRIVER=$DRIVER (expected podman|seed)" >&2; exit 2 ;;
     50 esac
     51 
     52 ROOT=$(cd "$(dirname "$0")/.." && pwd)
     53 cd "$ROOT"
     54 
     55 case "$ARCH" in
     56     aarch64) KERNEL_NAME=Image ;;
     57     amd64)   KERNEL_NAME=kernel.elf ;;
     58     riscv64) KERNEL_NAME=kernel.elf ;;
     59 esac
     60 
     61 NAME=boot2-$ARCH
     62 
     63 SRC_TREE=build/$ARCH/src
     64 BUILD_TREE=build/$ARCH/$DRIVER
     65 REL_DIR=build/$ARCH/release
     66 STAGING=$REL_DIR/$NAME
     67 TARBALL=$REL_DIR/$NAME.tar.gz
     68 
     69 [ -d "$SRC_TREE" ]                || { echo "[mkrelease] missing $SRC_TREE — run bootprep/prep-src.sh $ARCH" >&2; exit 1; }
     70 [ -f "$BUILD_TREE/boot6/$KERNEL_NAME" ] || { echo "[mkrelease] missing $BUILD_TREE/boot6/$KERNEL_NAME — run 'make all ARCH=$ARCH DRIVER=$DRIVER'" >&2; exit 1; }
     71 [ -f "$BUILD_TREE/boot7/toolchain/MANIFEST.sha256" ] || { echo "[mkrelease] missing $BUILD_TREE/boot7/toolchain/MANIFEST.sha256 — run 'make all ARCH=$ARCH DRIVER=$DRIVER'" >&2; exit 1; }
     72 
     73 # Portable sha256. Use sha256sum if present; else shasum -a 256.
     74 if command -v sha256sum >/dev/null 2>&1; then
     75     sha256() { sha256sum "$1" | awk '{print $1}'; }
     76 else
     77     sha256() { shasum -a 256 "$1" | awk '{print $1}'; }
     78 fi
     79 
     80 echo "[mkrelease] staging -> $STAGING"
     81 rm -rf "$STAGING"
     82 mkdir -p "$STAGING"
     83 
     84 # ── (1) sealed source tree ────────────────────────────────────────────
     85 cp -R "$SRC_TREE" "$STAGING/src"
     86 
     87 # ── (2) boot drivers (boot/*.sh, lib-*.sh, containers/Containerfile.*) ─
     88 cp -R boot "$STAGING/boot"
     89 
     90 # ── (3) README + verify.sh templates ──────────────────────────────────
     91 cp tools/release/README.md "$STAGING/README.md"
     92 cp tools/release/verify.sh "$STAGING/verify.sh"
     93 chmod +x "$STAGING/verify.sh"
     94 
     95 # Substitute @ARCH@ / @KERNEL_NAME@ into shipped docs/scripts. No git
     96 # rev is embedded — content stays rev-free so sha256 reflects content.
     97 for f in "$STAGING/README.md" "$STAGING/verify.sh"; do
     98     sed -i.bak \
     99         -e "s/@ARCH@/$ARCH/g" \
    100         -e "s/@KERNEL_NAME@/$KERNEL_NAME/g" \
    101         "$f"
    102     rm -f "$f.bak"
    103 done
    104 
    105 # ── (4) INPUT_MANIFEST.txt ────────────────────────────────────────────
    106 echo "[mkrelease] input manifest"
    107 INMAN=$STAGING/INPUT_MANIFEST.txt
    108 tools/release/input-manifest.sh "$STAGING/src" "$STAGING/boot" "$INMAN"
    109 n_in=$(wc -l < "$INMAN" | tr -d ' ')
    110 
    111 # ── (5) OUTPUT_MANIFEST.txt ───────────────────────────────────────────
    112 # Per-stage key artifacts (mirrors the stamp-anchored declarations in
    113 # the top-level Makefile). Driver-agnostic.
    114 gen_outputs() {
    115     cat <<EOF
    116 boot0/hex2
    117 boot0/catm
    118 boot0/M0
    119 boot1/M1pp
    120 boot1/hex2pp
    121 boot2/catm
    122 boot2/scheme1
    123 boot3/tcc0
    124 boot3/libc.P1pp
    125 boot3/tcc.flat.P1pp
    126 boot4/tcc1
    127 boot4/tcc2
    128 boot4/hello
    129 boot4/crt1.o
    130 boot4/libc.a
    131 boot4/libtcc1.a
    132 boot5/libc.a
    133 boot5/crt1.o
    134 boot5/crti.o
    135 boot5/crtn.o
    136 boot5/hello
    137 boot6/$KERNEL_NAME
    138 boot7/toolchain/MANIFEST.sha256
    139 EOF
    140 }
    141 
    142 echo "[mkrelease] output manifest (from $BUILD_TREE)"
    143 OUTMAN=$STAGING/OUTPUT_MANIFEST.txt
    144 : > "$OUTMAN"
    145 rm -f "$OUTMAN.missing"
    146 gen_outputs | while read -r rel; do
    147     [ -n "$rel" ] || continue
    148     f=$BUILD_TREE/$rel
    149     if [ -e "$f" ]; then
    150         h=$(sha256 "$f")
    151         printf '%s  %s\n' "$h" "$rel" >> "$OUTMAN"
    152     else
    153         printf '%s\n' "$rel" >> "$OUTMAN.missing"
    154     fi
    155 done
    156 if [ -s "$OUTMAN.missing" ]; then
    157     echo "[mkrelease] FAIL: missing expected outputs under $BUILD_TREE:" >&2
    158     sed 's/^/  /' "$OUTMAN.missing" >&2
    159     echo "[mkrelease]   run 'make all ARCH=$ARCH DRIVER=$DRIVER' (and boot5) first" >&2
    160     rm -f "$OUTMAN.missing"
    161     exit 1
    162 fi
    163 n_out=$(wc -l < "$OUTMAN" | tr -d ' ')
    164 
    165 # ── (6) tarball — deterministic ──────────────────────────────────────
    166 # Keep detailed installed-tree hashes next to the concise per-stage
    167 # manifest. verify.sh compares this with boot7's regenerated manifest,
    168 # then checks every installed file named by it.
    169 TOOLMAN=$STAGING/TOOLCHAIN_MANIFEST.txt
    170 cp "$BUILD_TREE/boot7/toolchain/MANIFEST.sha256" "$TOOLMAN"
    171 n_tool=$(wc -l < "$TOOLMAN" | tr -d ' ')
    172 
    173 echo "[mkrelease] tar -> $TARBALL"
    174 TARBALL_ABS=$PWD/$TARBALL
    175 tools/release/tar-payload.sh "$STAGING" "$TARBALL_ABS"
    176 
    177 # Tarball digest (echoed for release notes; not embedded in the tar).
    178 TAR_SHA=$(sha256 "$TARBALL")
    179 printf '%s  %s\n' "$TAR_SHA" "$NAME.tar.gz" > "$REL_DIR/$NAME.tar.gz.sha256"
    180 
    181 bytes=$(wc -c < "$TARBALL" | tr -d ' ')
    182 echo "[mkrelease] OK"
    183 echo "[mkrelease]   tarball : $TARBALL  ($bytes bytes)"
    184 echo "[mkrelease]   sha256  : $TAR_SHA"
    185 echo "[mkrelease]   inputs  : $n_in files"
    186 echo "[mkrelease]   outputs : $n_out artifacts"
    187 echo "[mkrelease]   toolchain: $n_tool files"