boot6-gen-runscm.sh (4344B)
1 #!/bin/sh 2 ## boot6-gen-runscm.sh — emit run.scm driving tcc3 to build seed-kernel. 3 ## 4 ## tcc3 -c each translation unit (kernel.S, kernel.c, mem.c) → .o, then 5 ## tcc3 links + emits a flat arm64 boot Image directly (no `ld -T 6 ## kernel.lds`, no objcopy). The link line is three tcc flags: 7 ## 8 ## -nostdlib -static freestanding link, no startfiles 9 ## -Wl,-Ttext=0x40080000 base address (arm64 RAM_BASE + 10 ## text_offset; QEMU's `-kernel` loads 11 ## us here) 12 ## -Wl,--oformat=binary flat-bytes output (objcopy -O binary 13 ## equivalent). Required because QEMU's 14 ## `-kernel <ELF>` path doesn't run the 15 ## arm64 boot wrapper that puts DTB in 16 ## x0 — only the flat-Image path does. 17 ## Detection is by `ARM\x64` magic at 18 ## file offset 0x38, which is in 19 ## kernel.S's Image header at the top of 20 ## `.text`. 21 ## 22 ## Everything else the kernel needs from the linker is supplied by 23 ## conventions tcc3 already honors: 24 ## 25 ## _start hard-coded entry symbol; kernel.S's arm64 Image 26 ## header is named `_start` (not `_head`) so this works 27 ## out of the box. 28 ## __bss_start auto-defined at the start of merged .bss via the 29 ## `bss-start-symbol` simple-patch. 30 ## _end auto-defined by stock tcc at the end of merged .bss 31 ## (tcc_add_linker_symbols). kernel.S uses it to 32 ## bracket the bss-zero loop and to compute the 33 ## Image-header `image_size` field; kernel.c uses it 34 ## to place the kernel heap above the loaded image. 35 ## 36 ## Usage: boot6-gen-runscm.sh <arch> <out.scm> 37 38 set -eu 39 [ "$#" -eq 2 ] || { echo "usage: $0 <arch> <out.scm>" >&2; exit 2; } 40 ARCH=$1; OUT=$2 41 42 # Per-arch link parameters. aarch64 alone needs --oformat=binary because 43 # QEMU's `-kernel <ELF>` path skips the arm64 boot wrapper that puts DTB 44 # in x0 — only the flat-Image path honors it (detected via the `ARM\x64` 45 # magic at file offset 0x38 in kernel.S's Image header). amd64/riscv64 46 # stay as ELF: QEMU's `-kernel` path on those arches consumes ELF 47 # directly (PVH note for amd64, OpenSBI for riscv64). 48 case "$ARCH" in 49 aarch64) TTEXT=0x40080000; OUT_FILE=Image; LINK_OFORMAT='"-Wl,--oformat=binary"' ;; 50 amd64) TTEXT=0x40000000; OUT_FILE=kernel.elf; LINK_OFORMAT= ;; 51 riscv64) TTEXT=0x80200000; OUT_FILE=kernel.elf; LINK_OFORMAT= ;; 52 *) echo "boot6-gen: unsupported arch '$ARCH'" >&2; exit 2 ;; 53 esac 54 55 # Kernel CFLAGS — freestanding, static, no host startfiles. We omit gcc's 56 # -mgeneral-regs-only (no tcc equivalent); kernel.S enables CPACR_EL1.FPEN 57 # in stext before the first `bl kmain`, so tcc's SIMD callee-saves in 58 # function prologues don't trap. 59 KCFLAGS='"-nostdlib" "-ffreestanding" "-static"' 60 61 cat > "$OUT" <<EOF 62 ;; boot6 run.scm — build seed-kernel ELF with tcc3. 63 ;; Generated by scripts/boot6-gen-runscm.sh; reads use in/, writes out/. 64 65 (define (must r tag) 66 (if (and (car r) (= 0 (cdr r))) 67 r 68 (begin 69 (write-string stderr "boot6: step failed: ") 70 (write-string stderr tag) 71 (write-string stderr "\n") 72 (exit 1)))) 73 74 (write-string stdout "boot6: tcc3 -c kernel.S\n") 75 (must (run "in/tcc3" $KCFLAGS "-c" "-o" "out/kernel-asm.o" "in/kernel.S") 76 "kernel.S -> kernel-asm.o") 77 78 (write-string stdout "boot6: tcc3 -c kernel.c\n") 79 (must (run "in/tcc3" $KCFLAGS "-Iin" "-c" "-o" "out/kernel.o" "in/kernel.c") 80 "kernel.c -> kernel.o") 81 82 (write-string stdout "boot6: tcc3 -c mmu.c\n") 83 (must (run "in/tcc3" $KCFLAGS "-Iin" "-c" "-o" "out/mmu.o" "in/mmu.c") 84 "mmu.c -> mmu.o") 85 86 (write-string stdout "boot6: tcc3 -c mem.c\n") 87 (must (run "in/tcc3" $KCFLAGS "-c" "-o" "out/mem.o" "in/mem.c") 88 "mem.c -> mem.o") 89 90 (write-string stdout "boot6: tcc3 link $OUT_FILE\n") 91 (must (run "in/tcc3" "-nostdlib" "-static" 92 "-Wl,-Ttext=$TTEXT" 93 $LINK_OFORMAT 94 "-o" "out/$OUT_FILE" 95 "out/kernel-asm.o" "out/kernel.o" "out/mmu.o" "out/mem.o") 96 "link $OUT_FILE") 97 98 (write-string stdout "boot6: ALL-OK\n") 99 (exit 0) 100 EOF