boot2

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

build.sh (4925B)


      1 #!/bin/sh
      2 ## build.sh — build a P1v2 .P1 source into a runnable aarch64 ELF binary.
      3 ##
      4 ## Mirrors the Makefile's PROG=m1m pipeline but targets the P1v2 DEFINE
      5 ## table at build/p1v2/aarch64/p1_aarch64.M1.
      6 ##
      7 ## Usage: m1pp/build.sh <source.P1> <output_binary>
      8 ##
      9 ## Pipeline (mirrors Makefile PROG=m1m):
     10 ##   1. lint   — assert every P1v2 op token in source.P1 is defined
     11 ##   2. prune  — strip DEFINEs the source doesn't reference
     12 ##   3. catm   — pruned defs ++ source.P1 -> combined.M1
     13 ##   4. M1     — combined.M1 -> .hex2
     14 ##   5. catm   — ELF header ++ .hex2 -> linked.hex2
     15 ##   6. hex2   — linked.hex2 -> raw ELF
     16 ##   7. chmod 0700, deposit at <output_binary>
     17 ##
     18 ## Default mode uses native-compiled mescc-tools M1/hex2 on the host:
     19 ## ~150× faster than the bootstrap M0/hex2-0 on the linux/arm64 VM (the
     20 ## bootstrap tools do one syscall per byte; mescc-tools uses buffered
     21 ## stdio). Output is byte-exact — verified against the bootstrap chain
     22 ## with --little-endian on both tools.
     23 ##
     24 ## This is a dev-loop convenience. It does not alter the bootstrap chain
     25 ## itself: the stage0 M0/hex2-0 binaries under build/$ARCH/tools remain
     26 ## the source of truth. Set M1PP_BOOTSTRAP_TOOLS=1 to force the original
     27 ## container-based path (verification, or when mescc-tools is unavailable).
     28 ##
     29 ## Intermediates land in build/m1pp/<basename>.* for later inspection.
     30 
     31 set -eu
     32 
     33 if [ "$#" -ne 2 ]; then
     34     echo "usage: $0 <source.P1> <output_binary>" >&2
     35     exit 2
     36 fi
     37 
     38 SRC=$1
     39 OUT=$2
     40 
     41 REPO=$(cd "$(dirname "$0")/.." && pwd)
     42 ARCH=aarch64
     43 PLATFORM=linux/arm64
     44 IMAGE=localhost/distroless-busybox:latest
     45 CONTAINERFILE=Containerfile.busybox
     46 
     47 P1_DEFS=build/p1v2/$ARCH/p1_$ARCH.M1
     48 TOOLS=build/$ARCH/tools
     49 ELF_HDR=build/upstream/AArch64/ELF-aarch64.hex2
     50 BASE_ADDR=0x600000  ## must match the load address encoded in $ELF_HDR
     51 
     52 NATIVE_TOOLS_DIR=build/native-tools
     53 NATIVE_M1=$NATIVE_TOOLS_DIR/M1
     54 NATIVE_HEX2=$NATIVE_TOOLS_DIR/hex2
     55 
     56 cd "$REPO"
     57 
     58 for f in "$P1_DEFS" "$ELF_HDR" lint.sh "$SRC"; do
     59     if [ ! -e "$f" ]; then
     60         echo "build.sh: missing dependency: $f" >&2
     61         exit 1
     62     fi
     63 done
     64 
     65 NAME=$(basename "$SRC" .P1)
     66 WORK=build/m1pp/$NAME.work
     67 mkdir -p "$WORK" "$(dirname "$OUT")"
     68 
     69 PRUNED=$WORK/p1.pruned.M1
     70 
     71 ## Step 1: lint.
     72 sh lint.sh "$P1_DEFS" "$SRC"
     73 
     74 ## Step 2: prune. Same awk one-liner as Makefile — collect all whitespace-
     75 ## separated tokens from the source, keep only DEFINEs whose name appears.
     76 awk 'NR==FNR{for(i=1;i<=NF;i++)u[$i]=1;next} /^DEFINE /{if($2 in u)print;next} {print}' \
     77     "$SRC" "$P1_DEFS" > "$PRUNED"
     78 
     79 ## Steps 3-7: mode selection.
     80 if [ "${M1PP_BOOTSTRAP_TOOLS:-0}" = 1 ]; then
     81     ## Bootstrap mode: run stage0 M0/hex2-0 inside the container. Slow
     82     ## (~110s on 1 MB m1pp.P1) but exercises the same code path the
     83     ## seed/tcc-boot chain does. Stage through /tmp to dodge virtiofs.
     84     for f in "$TOOLS/M0" "$TOOLS/hex2-0" "$TOOLS/catm"; do
     85         if [ ! -e "$f" ]; then
     86             echo "build.sh: missing bootstrap dependency: $f" >&2
     87             exit 1
     88         fi
     89     done
     90     if ! podman image exists "$IMAGE"; then
     91         podman build -f "$CONTAINERFILE" -t "$IMAGE" .
     92     fi
     93     podman run --rm --pull=never --platform "$PLATFORM" \
     94         -v "$REPO":/work \
     95         -w /work \
     96         "$IMAGE" sh -ec "
     97             set -eu
     98             cp $PRUNED /tmp/p1.M1
     99             cp $SRC /tmp/prog.M1
    100             $TOOLS/catm   /tmp/combined.M1 /tmp/p1.M1 /tmp/prog.M1
    101             $TOOLS/M0     /tmp/combined.M1 /tmp/prog.hex2
    102 
    103             cp $ELF_HDR /tmp/elf.hex2
    104             $TOOLS/catm   /tmp/linked.hex2 /tmp/elf.hex2 /tmp/prog.hex2
    105             $TOOLS/hex2-0 /tmp/linked.hex2 /tmp/prog
    106             chmod 0700 /tmp/prog
    107 
    108             cp /tmp/combined.M1 $WORK/combined.M1
    109             cp /tmp/prog.hex2   $WORK/prog.hex2
    110             cp /tmp/linked.hex2 $WORK/linked.hex2
    111             cp /tmp/prog        $WORK/prog
    112         "
    113 else
    114     ## Native mode (default): host-compiled mescc-tools M1/hex2. The
    115     ## bootstrap chain is not invoked. Flags are chosen to make the
    116     ## emitted aarch64 ELF bit-exact with the bootstrap build:
    117     ##   M1:   --little-endian (default is big-endian; --architecture
    118     ##         aarch64 does NOT override that — see M1-macro.c:786).
    119     ##   hex2: --little-endian and --base-address matches $ELF_HDR.
    120     if [ ! -x "$NATIVE_M1" ] || [ ! -x "$NATIVE_HEX2" ]; then
    121         sh m1pp/build-native-tools.sh
    122     fi
    123 
    124     ## catm on the bootstrap side is just multi-file concat → shell cat
    125     ## is equivalent.
    126     cat "$PRUNED" "$SRC" > "$WORK/combined.M1"
    127     "$NATIVE_M1" --architecture "$ARCH" --little-endian \
    128         -f "$WORK/combined.M1" -o "$WORK/prog.hex2"
    129     cat "$ELF_HDR" "$WORK/prog.hex2" > "$WORK/linked.hex2"
    130     "$NATIVE_HEX2" --architecture "$ARCH" --little-endian \
    131         --base-address "$BASE_ADDR" \
    132         -f "$WORK/linked.hex2" -o "$WORK/prog"
    133     chmod 0700 "$WORK/prog"
    134 fi
    135 
    136 cp "$WORK/prog" "$OUT"
    137 chmod 0700 "$OUT"