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