lib-arch.sh (7188B)
1 # lib-arch.sh — single source for arch + driver setup shared by 2 # boot/boot.sh, boot/boot{0..6}.sh, lib-pipeline.sh, lib-runscm.sh. 3 # 4 # Public entry points (call in this order from a bootN.sh): 5 # 6 # bootlib_init <stage> <arch> # validate <arch>, cd to repo root, 7 # # set ARCH/PLATFORM/KERNEL_NAME/ 8 # # MUSL_ARCH/DRIVER/BOOT_STAGE/BOOT_TAG. 9 # driver_init [<image-kind>] # set OUT/STAGE; podman: build IMAGE 10 # # if missing (image-kind ∈ busybox| 11 # # empty; default busybox); seed: 12 # # verify boot6 kernel exists. 13 # require_src # die if build/$ARCH/src/ missing. 14 # require_prev <dir> <name>... # die if any <dir>/<name> is 15 # # missing or non-executable. 16 # require_file <path> [<hint>] # die if <path> missing; print a 17 # # uniform diagnostic with hint. 18 # 19 # After bootlib_init, the following shell vars are set/exported: 20 # ARCH input architecture token (aarch64|amd64|riscv64) 21 # ROOT repo root (cwd is set to ROOT) 22 # DRIVER podman|seed (defaults to podman) 23 # PLATFORM linux/<arm64|amd64|riscv64> for podman --platform 24 # KERNEL_NAME Image (aarch64) | kernel.elf (amd64,riscv64) 25 # MUSL_ARCH aarch64 | x86_64 | riscv64 26 # BOOT_TAG "<stage>/<driver>/<arch>" for log prefixes 27 # BOOT_STAGE stage name as passed in (boot0|boot1|...) 28 # 29 # After driver_init (boot stages only — prep-* skip it): 30 # OUT build/$ARCH/$DRIVER/$BOOT_STAGE (stage output dir) 31 # STAGE build/$ARCH/$DRIVER/.$BOOT_STAGE-stage (scratch staging dir) 32 # podman: IMAGE 33 # seed: KERNEL_IMAGE, EXTRACT, SEED_ARCH 34 35 bootlib_init() { 36 _stage=$1; _arch=${2:-} 37 [ -n "$_stage" ] || { echo "lib-arch: bootlib_init: stage required" >&2; exit 2; } 38 case "$_arch" in 39 aarch64|amd64|riscv64) ;; 40 *) echo "usage: $0 <aarch64|amd64|riscv64>" >&2; exit 2 ;; 41 esac 42 ARCH=$_arch 43 ROOT=$(cd "$(dirname "$0")/.." && pwd) 44 cd "$ROOT" 45 DRIVER=${DRIVER:-podman} 46 case "$DRIVER" in 47 podman|seed) ;; 48 *) echo "[$_stage/$DRIVER/$ARCH] unknown DRIVER=$DRIVER (expected podman|seed)" >&2; exit 2 ;; 49 esac 50 BOOT_STAGE=$_stage 51 BOOT_TAG="$_stage/$DRIVER/$ARCH" 52 BOOT_T0=$(date +%s) 53 case "$ARCH" in 54 aarch64) PLATFORM=linux/arm64; KERNEL_NAME=Image; MUSL_ARCH=aarch64 ;; 55 amd64) PLATFORM=linux/amd64; KERNEL_NAME=kernel.elf; MUSL_ARCH=x86_64 ;; 56 riscv64) PLATFORM=linux/riscv64; KERNEL_NAME=kernel.elf; MUSL_ARCH=riscv64 ;; 57 esac 58 export ARCH ROOT DRIVER PLATFORM KERNEL_NAME MUSL_ARCH BOOT_TAG BOOT_STAGE BOOT_T0 59 trap _bootlib_finish EXIT 60 } 61 62 # _bootlib_finish — EXIT trap installed by bootlib_init. Prints 63 # `[$BOOT_TAG] done in Xs (cum Ys)` (or `failed after Xs` on error). 64 # On success, records the elapsed time so later stages can sum the 65 # chain. Cumulative = sum of all per-stage .timing files relevant to 66 # the current $ARCH/$DRIVER. 67 _bootlib_finish() { 68 _exit=$? 69 [ -n "${BOOT_T0:-}" ] || return 0 70 _elapsed=$(( $(date +%s) - BOOT_T0 )) 71 if [ "$_exit" != 0 ]; then 72 echo "[$BOOT_TAG] failed after ${_elapsed}s (exit=$_exit)" >&2 73 return 0 74 fi 75 # Record this stage's time. Boot stages have OUT (set by driver_init); 76 # the orchestrator (BOOT_STAGE=boot) doesn't write — its time would 77 # double-count. Other stages without OUT (prep-src) write 78 # to a per-arch sidecar dir. 79 if [ "$BOOT_STAGE" != boot ]; then 80 if [ -n "${OUT:-}" ] && [ -d "$OUT" ]; then 81 echo "$_elapsed" > "$OUT/.timing" 82 elif [ -d "build/$ARCH" ]; then 83 mkdir -p "build/$ARCH/.timings" 84 echo "$_elapsed" > "build/$ARCH/.timings/$BOOT_STAGE" 85 fi 86 fi 87 # Cumulative: sum boot-stage timings for this driver + driver- 88 # independent prep timings. Glob may not match — guard each path. 89 _cum=0 90 for _f in \ 91 "build/$ARCH/$DRIVER"/*/.timing \ 92 "build/$ARCH/.timings"/* 93 do 94 [ -f "$_f" ] || continue 95 _v=$(cat "$_f" 2>/dev/null) || continue 96 case "$_v" in *[!0-9]*|'') continue ;; esac 97 _cum=$((_cum + _v)) 98 done 99 echo "[$BOOT_TAG] done in ${_elapsed}s (cum ${_cum}s)" 100 } 101 102 driver_init() { 103 _image_kind=${1:-busybox} 104 case "$_image_kind" in 105 busybox|empty) ;; 106 *) echo "[$BOOT_TAG] driver_init: image-kind must be busybox|empty (got $_image_kind)" >&2; exit 2 ;; 107 esac 108 OUT=build/$ARCH/$DRIVER/$BOOT_STAGE 109 STAGE=build/$ARCH/$DRIVER/.$BOOT_STAGE-stage 110 export OUT STAGE 111 case "$DRIVER" in 112 podman) 113 IMAGE=boot2-$_image_kind:$ARCH 114 if ! podman image exists "$IMAGE"; then 115 echo "[$BOOT_TAG] building $IMAGE" 116 # Containerfile.empty drops /etc resolver state etc.; no-cache 117 # avoids a stale layer surviving an upstream tag bump. 118 _no_cache= 119 [ "$_image_kind" = empty ] && _no_cache=--no-cache 120 podman build $_no_cache --platform "$PLATFORM" -t "$IMAGE" \ 121 -f boot/containers/Containerfile.$_image_kind boot/containers/ 122 fi 123 export IMAGE 124 ;; 125 seed) 126 # DRIVER=seed always consumes the podman-built boot6 kernel — 127 # tcc3 is platform-agnostic but we settled on a single canonical 128 # build location to reduce surface area. 129 KERNEL_IMAGE=$ROOT/build/$ARCH/podman/boot6/$KERNEL_NAME 130 EXTRACT=$ROOT/seed-kernel/scripts/extract-blk.sh 131 [ -f "$KERNEL_IMAGE" ] || { 132 echo "[$BOOT_TAG] missing $KERNEL_IMAGE — run ./boot/boot.sh $ARCH (default DRIVER=podman) first" >&2 133 exit 1 134 } 135 export KERNEL_IMAGE EXTRACT 136 export SEED_ARCH=$ARCH 137 ;; 138 esac 139 } 140 141 require_prev() { 142 _dir=$1; shift 143 for _n in "$@"; do 144 [ -x "$_dir/$_n" ] || { 145 _stage_name=$(basename "$_dir") 146 case "$_stage_name" in 147 boot*) _hint="run boot/$_stage_name.sh $ARCH" ;; 148 *) _hint="rebuild $_dir" ;; 149 esac 150 echo "[$BOOT_TAG] missing prerequisite: $_dir/$_n ($_hint)" >&2 151 exit 1 152 } 153 done 154 } 155 156 # require_src — assert build/$ARCH/src/ exists (the canonical generated 157 # source tree built by bootprep/prep-src.sh). Every bootN.sh needs it. 158 require_src() { 159 [ -d "build/$ARCH/src" ] || { 160 echo "[$BOOT_TAG] missing build/$ARCH/src — run bootprep/prep-src.sh $ARCH" >&2 161 exit 1 162 } 163 } 164 165 # require_file <path> [<hint>] — assert <path> exists; print a uniform 166 # "[$BOOT_TAG] missing <path> — <hint>" diagnostic on failure. 167 require_file() { 168 _path=$1; _hint=${2:-} 169 [ -e "$_path" ] || { 170 if [ -n "$_hint" ]; then 171 echo "[$BOOT_TAG] missing $_path — $_hint" >&2 172 else 173 echo "[$BOOT_TAG] missing $_path" >&2 174 fi 175 exit 1 176 } 177 }