boot4-gen-runscm.sh (6268B)
1 #!/bin/sh 2 ## boot4-gen-runscm.sh — emit run.scm driving boot4's tcc0→tcc1→tcc2 3 ## chain inside the seed kernel. Mirrors boot/boot4.sh's per-stage shell 4 ## emission; per-arch values resolved on the host so the .scm body is 5 ## straight-line (run …) calls. 6 ## 7 ## Reads use in/<name>; writes (intermediates and exports) use out/<name>. 8 ## 9 ## Usage: bootprep/boot4-gen-runscm.sh <arch> 10 ## Writes build/<arch>/src/run/boot4.scm. 11 12 set -eu 13 [ "$#" -eq 1 ] || { echo "usage: $0 <arch>" >&2; exit 2; } 14 ARCH=$1 15 OUT=build/$ARCH/src/run/boot4.scm 16 mkdir -p "$(dirname "$OUT")" 17 18 case "$ARCH" in 19 aarch64) LIB_HELPER_SRC=lib-arm64.c; LIB_HELPER_OBJ=lib-arm64.o 20 LIB_HELPER_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_ARM64=1" "-D" "TCC_TARGET_ARM=1"' 21 LIBTCC1_C_SRCS="lib-arm64.c" 22 LIBTCC1_C_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_ARM64=1" "-D" "TCC_TARGET_ARM=1"' 23 LIBTCC1_ASM_SRCS="" ;; 24 amd64) LIB_HELPER_SRC=va_list.c; LIB_HELPER_OBJ=va_list.o 25 LIB_HELPER_DEFS='"-D" "TCC_TARGET_X86_64=1"' 26 LIBTCC1_C_SRCS="libtcc1.c va_list.c" 27 LIBTCC1_C_DEFS='"-D" "TCC_TARGET_X86_64=1"' 28 LIBTCC1_ASM_SRCS="alloca86_64.S alloca86_64-bt.S" ;; 29 riscv64) LIB_HELPER_SRC=lib-arm64.c; LIB_HELPER_OBJ=lib-arm64.o 30 LIB_HELPER_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_RISCV64=1"' 31 LIBTCC1_C_SRCS="lib-arm64.c" 32 LIBTCC1_C_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_RISCV64=1"' 33 LIBTCC1_ASM_SRCS="" ;; 34 *) echo "boot4-gen: unknown arch $ARCH" >&2; exit 2 ;; 35 esac 36 37 # Per-arch link base for user binaries. tcc 0.9.26's riscv64-link.c 38 # defaults to ELF_START_ADDR=0x10000, which lives below the seed 39 # kernel's USER_VA_LO (0x200000). amd64 (0x400000) and aarch64 40 # (0x400000) defaults already sit inside the user window, so we leave 41 # them alone. Everywhere else in the chain (M0/hex2pp -B, boot6 42 # -Wl,-Ttext) we link riscv64 user binaries at 0x600000; do the same 43 # here so tcc-built outputs are loadable inside the seed kernel. 44 case "$ARCH" in 45 riscv64) LINK_TTEXT='"-Wl,-Ttext=0x600000"' ;; 46 *) LINK_TTEXT= ;; 47 esac 48 49 # emit_helpers — cc reads .S/.c sources from in/, writes .o to out/. 50 # cc_path is the cwd-relative path to the spawned compiler binary (in/tcc0 51 # for round B; out/tcc1, out/tcc2 in later rounds). 52 emit_helpers() { 53 cc_path=$1; tag=$2 54 cat <<EOF 55 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/start.o" "in/start.S") "$tag start.o") 56 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/sys_stubs.o" "in/sys_stubs.S") "$tag sys_stubs.o") 57 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/mem.o" "in/mem.c") "$tag mem.o") 58 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/libc.o" "in/libc.flat.c") "$tag libc.o") 59 (must (run "$cc_path" "-nostdlib" $LIB_HELPER_DEFS "-c" "-o" "out/$LIB_HELPER_OBJ" "in/$LIB_HELPER_SRC") "$tag $LIB_HELPER_OBJ") 60 EOF 61 } 62 63 # emit_archive — uses prefix to namespace output object names per stage. 64 # pfx="s1-"/"s2-" for stage C/D. The .o objects archived into libtcc1.a 65 # keep their bare basenames (lib-arm64.o, …) — tcc -ar stores basenames 66 # only, so this matches podman's archive members exactly. They overwrite 67 # the stage's helper-named .o files; nothing post-archive in the same 68 # stage reads them as standalone .o. 69 emit_archive() { 70 cc_path=$1; tag=$2; pfx=$3 71 echo "(must (run \"in/catm\" \"out/${pfx}crt1.o\" \"out/start.o\") \"copy crt1.o $pfx\")" 72 echo "(must (run \"$cc_path\" \"-ar\" \"rcs\" \"out/${pfx}libc.a\" \"out/sys_stubs.o\" \"out/mem.o\" \"out/libc.o\") \"$tag ${pfx}libc.a\")" 73 libtcc1_objs="" 74 for src in $LIBTCC1_C_SRCS; do 75 obj=${src%.c}.o 76 echo "(must (run \"$cc_path\" \"-nostdlib\" $LIBTCC1_C_DEFS \"-c\" \"-o\" \"out/${obj}\" \"in/$src\") \"$tag lt ${obj}\")" 77 libtcc1_objs="$libtcc1_objs \"out/${obj}\"" 78 done 79 for src in $LIBTCC1_ASM_SRCS; do 80 obj=${src%.S}.o 81 echo "(must (run \"$cc_path\" \"-nostdlib\" \"-c\" \"-o\" \"out/${obj}\" \"in/$src\") \"$tag lt ${obj}\")" 82 libtcc1_objs="$libtcc1_objs \"out/${obj}\"" 83 done 84 echo "(must (run \"$cc_path\" \"-ar\" \"rcs\" \"out/${pfx}libtcc1.a\"$libtcc1_objs) \"$tag ${pfx}libtcc1.a\")" 85 } 86 87 emit_link_tcc() { 88 cc_path=$1; tag=$2; pfx=$3; out=$4 89 echo "(must (run \"$cc_path\" \"-nostdlib\" $LINK_TTEXT \"out/${pfx}crt1.o\" \"in/tcc.flat.c\" \"out/${pfx}libc.a\" \"out/${pfx}libtcc1.a\" \"out/${pfx}libc.a\" \"-o\" \"out/$out\") \"$tag -> $out\")" 90 } 91 92 { 93 cat <<'PROLOGUE' 94 ;; boot4 run.scm — drive tcc0 -> tcc1 -> tcc2 inside seed kernel. 95 ;; Generated by bootprep/boot4-gen-runscm.sh; mirrors boot/boot4.sh's 96 ;; podman path stage-for-stage. Reads use in/; writes (intermediates and 97 ;; exports) use out/. tcc0 is staged as in/tcc0; tcc1/tcc2 are produced 98 ;; and exported under out/. 99 ;; 100 ;; Stages C and D use the SAME archive-based link line, so tcc0's output 101 ;; (tcc1) is directly comparable to tcc1's output (tcc2): once tcc0 is a 102 ;; faithful compilation of tcc.c, tcc1 == tcc2 is the fixed point. 103 104 (define (must r tag) 105 (if (and (car r) (= 0 (cdr r))) 106 r 107 (begin 108 (write-string stderr "boot4: step failed: ") 109 (write-string stderr tag) 110 (write-string stderr "\n") 111 (exit 1)))) 112 113 (write-string stdout "boot4: stage C (tcc0 -> tcc1)\n") 114 PROLOGUE 115 116 # Stage C: tcc0 builds helpers + archive, links tcc1 — same link line as 117 # stage D so tcc1 is directly comparable to tcc2. 118 emit_helpers in/tcc0 tcc0 119 emit_archive in/tcc0 tcc0 "s1-" 120 emit_link_tcc in/tcc0 tcc0 "s1-" tcc1 121 122 cat <<EOF 123 124 (write-string stdout "boot4: stage D (tcc1 -> tcc2)\n") 125 EOF 126 127 # Stage D: tcc1 rebuilds helpers + archive, links tcc2. tcc1 == tcc2 is 128 # the bootstrap fixed point (asserted host-side in boot4.sh). The s2- 129 # archives + crt1.o built here are boot4's exported deliverables. 130 emit_helpers out/tcc1 tcc1 131 emit_archive out/tcc1 tcc1 "s2-" 132 emit_link_tcc out/tcc1 tcc1 "s2-" tcc2 133 134 cat <<EOF 135 136 (write-string stdout "boot4: linking hello\n") 137 (must (run "out/tcc1" "-nostdlib" $LINK_TTEXT "out/s2-crt1.o" "in/hello.c" "out/s2-libc.a" "out/s2-libtcc1.a" "out/s2-libc.a" "-o" "out/hello") "tcc1 -> hello") 138 (write-string stdout "boot4: ALL-OK\n") 139 (exit 0) 140 EOF 141 } > "$OUT"