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"