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