From ecdc34091d1603de70024ae6383bca532b1d9ec6 Mon Sep 17 00:00:00 2001 From: Jeremy Anderson Date: Fri, 24 Jul 2026 15:58:54 -0400 Subject: [PATCH] update 4.1 --- BTC.sh | 1348 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1348 insertions(+) create mode 100644 BTC.sh diff --git a/BTC.sh b/BTC.sh new file mode 100644 index 0000000..d259fa3 --- /dev/null +++ b/BTC.sh @@ -0,0 +1,1348 @@ +#!/bin/bash +# BTC.sh requires GNU Bash 4.0+ (not POSIX sh). It uses: +# - [[ ... ]] conditionals, == pattern matching, =~ regex, (( )) arithmetic +# - ${var^^} uppercase expansion, associative arrays, process substitution +# - set -euo pipefail for strict error handling +# BTC-0.4.0.sh - Build Tool Chain +# Identity: dcosnet / dcos.net | Multi-Arch Cross-Compilation Build Tool Chain +# Version: 0.4.1 | Persistence: /opt/BTC | Volatile: ramfs +# License: GNU AGPLv3 Mandatory Prominent Interactive Notice +# Copyright (C) 2012-2026 Jeremy Anderson (info@dcos.net) + +set -euo pipefail +export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES + +# ============================================================================ +# 1. AGPL INTERACTIVE LICENSE COMPLIANCE +# ============================================================================ +function f_agpl_header() { + clear + cat << 'EOF' +=========================================================================== + BTC-0.4.0.sh - Build Tool Chain (AGPLv3 PROTECTED) + Cross-Compilation Build Tool Chain +=========================================================================== +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License. + +REMOTE INTERACTION NOTICE: Per Section 13 of the GNU AGPLv3, if you modify +this script and offer its toolchain-building capabilities as a service over +a network, you MUST make your complete modified source code available. +=========================================================================== +EOF + if [[ ! -f /var/tmp/BTC-AGPL-ACCEPTED ]]; then + echo -n "Do you accept the network-sovereignty terms of the AGPLv3? (y/N): " + read -r reply + if [[ "${reply}" =~ ^[Yy]$ ]]; then + touch /var/tmp/BTC-AGPL-ACCEPTED + else + echo ">> Build aborted: AGPLv3 acceptance is mandatory for execution." + exit 1 + fi + fi + + # --- Signature Tier Selection --- + # Skip prompt if tier was already specified via CLI flags. + if [[ ${BTC_TPM_SEAL} -eq 0 && -z "${BTC_CLUSTER_JOIN:-}" && ! -f "${BTC_ARCHIVE:-/opt/BTC}/.btc-salt" && ! -f "${BTC_ARCHIVE:-/opt/BTC}/.btc-cluster-token" ]]; then + echo "" + echo ">> Select forensic signature tier:" + echo ">> 1) poly — Per-machine random salt (write-once, default)" + echo ">> 2) tpm — Hardware-bound PCR digest (singular deploys)" + echo ">> 3) cluster — Join existing cluster with shared token" + echo -n ">> Choice [1]: " + read -r sig_choice + case "${sig_choice:-1}" in + 2) + BTC_TPM_SEAL=1 + echo ">> [SIG] TPM seal selected." + ;; + 3) + echo -n ">> Enter cluster token: " + read -r cluster_tok + if [[ -n "${cluster_tok}" ]]; then + export BTC_CLUSTER_JOIN="${cluster_tok}" + echo ">> [SIG] Cluster join selected." + else + echo ">> [WARN] Empty token. Defaulting to poly." + fi + ;; + *) + echo ">> [SIG] Poly (per-machine salt) selected." + ;; + esac + echo "" + fi +} + +# ============================================================================ +# 2. CROSS-COMPILATION TARGET REGISTRY +# +# Architecture | Target ID | GCC march | ISA | C Library +# ------------- | ------------------- | ------------------ | ------ | ---------- +# x86_64 | haswell | haswell | AVX2 | glibc +# x86_64 | haswell-ep | haswell | AVX2 | glibc +# x86_64 | broadwell | broadwell | AVX2 | glibc +# x86_64 | broadwell-ep | broadwell | AVX2 | glibc +# x86_64 | skylake | skylake | AVX2 | glibc +# x86_64 | skylake-x | skylake-avx512 | AVX512 | glibc +# x86_64 | skylake-server | skylake-server | AVX512 | glibc +# x86_64 | znver1 | znver1 | AVX2 | glibc +# x86_64 | znver2 | znver2 | AVX2 | glibc +# x86_64 | znver3 | znver3 | AVX2 | glibc +# x86_64 | znver4 | znver4 | AVX512 | glibc +# x86_64 | apu-zn1 | znver1 | AVX2 | glibc +# x86_64 | apu-zn2 | znver1 | AVX2 | glibc +# x86_64 | apu-zn3 | znver2 | AVX2 | glibc +# x86_64 | apu-zn4 | znver3 | AVX2 | glibc +# x86_64 | atom-silvermont | silvermont | SSE4_2| glibc +# x86_64 | atom-goldmont | goldmont | SSE4_2| glibc +# x86_64 | atom-tremont | tremont | SSE4_2| glibc +# x86_64 | atom-sierraforest | sierraforest | SSE4_2| glibc +# mipsel | mipselr2 | mips32r2 | MIPS32 | musl +# arm | armv7 | armv7-a | NEON | musl +# tilegx | tilegx | tilegx | TILE | musl +# +# Host is always an average x86_64 system. All targets listed above +# are CROSS-COMPILATION targets (CROSS_MODE=1). The --native flag +# auto-probes the host silicon and builds without a target prefix. +# +# Cross targets use SYSROOT-based cross-compilation (CLFS / Buildroot style). +# ============================================================================ + +# Associative array: target_id → property string +# Format: "arch|cpu|march|isa|abi|clib|endian|family|desc|kernel_min|gcc_cfg_extra" +declare -A BTC_TARGETS + +# --- x86_64 Intel family --- +BTC_TARGETS[haswell]="x86_64|i686|haswell|AVX2|sysv|glibc|little|intel|Intel Haswell (Xeon E5 v3 / Core i7-4xxx)|4.19|" +BTC_TARGETS[haswell-ep]="x86_64|i686|haswell|AVX2|sysv|glibc|little|intel|Intel Haswell-EP X99 (Xeon E5 v3 / E7 v3)|4.19|" +BTC_TARGETS[broadwell]="x86_64|i686|broadwell|AVX2|sysv|glibc|little|intel|Intel Broadwell (Core i7-5xxx / Core i5-5xxx / Xeon E5 v4)|4.19|" +BTC_TARGETS[broadwell-ep]="x86_64|i686|broadwell|AVX2|sysv|glibc|little|intel|Intel Broadwell-EP (Xeon E5-2600 v4 / E7-4800 v4)|4.19|" +BTC_TARGETS[skylake]="x86_64|i686|skylake|AVX2|sysv|glibc|little|intel|Intel Skylake (Core i7-6xxx / Xeon v5)|4.19|" +BTC_TARGETS[skylake-x]="x86_64|i686|skylake-avx512|AVX512|sysv|glibc|little|intel|Intel Skylake-X X299 (Core i9-7xxx Xeon Scalable)|4.19|" +BTC_TARGETS[skylake-server]="x86_64|i686|skylake-server|AVX512|sysv|glibc|little|intel|Intel Skylake-Server (Xeon SP 1st/2nd Gen Platinum)|4.19|" + +# --- x86_64 AMD family --- +BTC_TARGETS[znver1]="x86_64|i686|znver1|AVX2|sysv|glibc|little|amd|AMD Zen1 Ryzen (Ryzen 1000 / EPYC Naples)|4.19|" +BTC_TARGETS[znver2]="x86_64|i686|znver2|AVX2|sysv|glibc|little|amd|AMD Zen2 Ryzen (Ryzen 3000 / EPYC Rome)|4.19|" +BTC_TARGETS[znver3]="x86_64|i686|znver3|AVX2|sysv|glibc|little|amd|AMD Zen3 Ryzen (Ryzen 5000 / EPYC Milan)|4.19|" +BTC_TARGETS[znver4]="x86_64|i686|znver4|AVX512|sysv|glibc|little|amd|AMD Zen4 Ryzen (Ryzen 7000 / EPYC Genoa)|4.19|" + +# --- x86_64 AMD APU family (mobile/embedded Zen, 15-54W TDP) --- +# APU series 1 (Raven Ridge, 2400GE/3200GE) = Zen 1, AVX2, Vega graphics +# APU series 2 (Picasso, 3250U/3500U) = Zen+, AVX2 (GCC march=znver1) +# APU series 3 (Renoir/Lucienne, 4500U/4700U)= Zen 2, AVX2 +# APU series 4 (Cezanne/Barcelo, 5500U/5700U) = Zen 3, AVX2 +# These are cross-compiled from an average x86_64 host for deployment +# on APU-based mini-PCs, laptops, and embedded nodes. +BTC_TARGETS[apu-zn1]="x86_64|i686|znver1|AVX2|sysv|glibc|little|amd-apu|AMD APU Series 1 Zen (Raven Ridge 2400GE / 3200GE Vega)|4.19|" +BTC_TARGETS[apu-zn2]="x86_64|i686|znver1|AVX2|sysv|glibc|little|amd-apu|AMD APU Series 2 Zen+ (Picasso 3250U / 3500U)|4.19|" +BTC_TARGETS[apu-zn3]="x86_64|i686|znver2|AVX2|sysv|glibc|little|amd-apu|AMD APU Series 3 Zen2 (Renoir 4500U / 4700U)|4.19|" +BTC_TARGETS[apu-zn4]="x86_64|i686|znver3|AVX2|sysv|glibc|little|amd-apu|AMD APU Series 4 Zen3 (Cezanne 5500U / 5700U)|4.19|" + +# --- x86_64 Intel Atom family (low-power embedded, 4-15W TDP) --- +# silvermont = Bay Trail (Z3000 series, E38xx) — in-order, SSE4.2 +# goldmont = Apollo Lake (x5-Z8350, N4200) — out-of-order, SSE4.2 +# tremont = Elkhart Lake (x6000E series) — improved OoO, SSE4.2 +# sierraforest= Sierra Forest (x7000RE, E-core) — hybrid, SSE4.2, GCC 14+ +# All Atom targets are cross-compiled for edge/IoT gateways, routers, +# and low-power cluster nodes where AVX is not available. +BTC_TARGETS[atom-silvermont]="x86_64|i686|silvermont|SSE4_2|sysv|glibc|little|atom|Intel Atom Silvermont (Bay Trail Z3000 / E38xx)|4.14|" +BTC_TARGETS[atom-goldmont]="x86_64|i686|goldmont|SSE4_2|sysv|glibc|little|atom|Intel Atom Goldmont (Apollo Lake x5-Z8350 / N4200)|4.14|" +BTC_TARGETS[atom-tremont]="x86_64|i686|tremont|SSE4_2|sysv|glibc|little|atom|Intel Atom Tremont (Elkhart Lake x6000E series)|5.4|" +BTC_TARGETS[atom-sierraforest]="x86_64|i686|sierraforest|SSE4_2|sysv|glibc|little|atom|Intel Atom Sierra Forest (x7000RE E-core cluster)|6.1|" + +# --- MIPS (little-endian, soft-float baseline) --- +# mips32r2 is the ISA baseline for mipselr2 — covers the MALTA-like +# embedded targets that are the closest thing to a "universal mips" +# reference platform. Uses musl because glibc MIPS support is +# fragmented across kernel versions and vendor patches. +BTC_TARGETS[mipselr2]="mipsel|mips|32r2|MIPS32|o32|musl|little|mips|MIPS32R2 Little-Endian (MALTA / embedded routers)|4.9|--with-arch=mips32r2 --with-float=soft --with-abi=32 --disable-libsanitizer" + +# --- ARMv7 (hard-float, Thumb-2, NEON) --- +# armv7-a with NEON and VFPv3-D16 is the "x86 baseline" of the ARM +# world — it covers Raspberry Pi 2/3 (32-bit), BeagleBone, Odroid, +# and virtually every Cortex-A7/A9/A15/A17 SoC. Uses musl for +# cross-compile portability; glibc armv7 is available as a future +# clib variant. +BTC_TARGETS[armv7]="arm|arm|armv7-a|NEON|eabihf|musl|little|arm|ARMv7-A Hard-Float NEON (Cortex-A7/A9/A15 RPi2/3 32b)|4.9|--with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --enable-target-optspace --disable-libsanitizer --with-abi=aapcs-linux" + +# --- TileGX (Tilera TILE-Gx72/Metor) --- +# The Tile architecture is a 64-bit VLIW mesh network processor. +# GCC upstream dropped mainline Tile-Gx support after GCC 11, so +# we pin GCC 10.3.0 for Tile-Gx targets. The tilegx triple uses +# linux-gnu-abi64. Uses musl as glibc has no Tile-Gx port. +BTC_TARGETS[tilegx]="tilegx|tilegx|tilegx|TILE|abi64|musl|little|tile|Tilera TILE-Gx (TILE-Gx72 / TilePro mesh VLIW)|4.14|--with-arch=tilegx --disable-libssp --disable-libquadmath --disable-libatomic" + +# --- Helper: list all registered targets --- +function f_list_targets() { + echo ">> BTC-0.4.0 Registered Cross-Compilation Targets:" + echo ">> ===============================================" + printf ">> %-16s %-10s %-18s %-8s %-6s %s\n" "TARGET_ID" "ARCH" "MARCH" "ISA" "CLIB" "DESCRIPTION" + printf ">> %-16s %-10s %-18s %-8s %-6s %s\n" "--------" "----" "-----" "---" "----" "-----------" + for tid in $(echo "${!BTC_TARGETS[@]}" | tr ' ' '\n' | sort); do + IFS='|' read -r arch cpu march isa abi clib endian family desc kern_min gcc_extra <<< "${BTC_TARGETS[${tid}]}" + printf ">> %-16s %-10s %-18s %-8s %-6s %s\n" "${tid}" "${arch}" "${march}" "${isa}" "${clib}" "${desc}" + done + echo "" + echo ">> Usage: BTC.sh Build cross-toolchain for target" + echo ">> BTC.sh --native Auto-probe host silicon and build native" + echo ">> BTC.sh --list Show this target table" + echo ">> BTC.sh --list-json Emit target table as JSON" +} + +function f_list_targets_json() { + echo '[' + local first=true + for tid in $(echo "${!BTC_TARGETS[@]}" | tr ' ' '\n' | sort); do + IFS='|' read -r arch cpu march isa abi clib endian family desc kern_min gcc_extra <<< "${BTC_TARGETS[${tid}]}" + if [[ "${first}" == "true" ]]; then first=false; else echo ','; fi + cat << TJSEP + { + "id": "${tid}", + "arch": "${arch}", + "cpu": "${cpu}", + "march": "${march}", + "isa": "${isa}", + "abi": "${abi}", + "clib": "${clib}", + "endian": "${endian}", + "family": "${family}", + "description": "${desc}", + "kernel_min": "${kern_min}", + "gcc_extra": "${gcc_extra}" + } +TJSEP + done + echo ']' +} + +# ============================================================================ +# 3. TARGET PROBE & SELECTION +# ============================================================================ + +# Resolved target properties (set by f_resolve_target) +BTC_T_ARCH="" +BTC_T_CPU="" +BTC_T_MARCH="" +BTC_T_ISA="" +BTC_T_ABI="" +BTC_T_CLIB="" +BTC_T_ENDIAN="" +BTC_T_FAMILY="" +BTC_T_DESC="" +BTC_T_KERN_MIN="" +BTC_T_GCC_EXTRA="" +BTC_T_ID="" +CROSS_MODE=0 # 0 = native, 1 = cross + +function f_resolve_target() { + local target_id="$1" + local spec="${BTC_TARGETS[${target_id}]:-}" + + if [[ -z "${spec}" ]]; then + echo ">> [ERROR] Unknown target: '${target_id}'" + echo ">> Run 'BTC.sh --list' for available targets." + exit 1 + fi + + IFS='|' read -r BTC_T_ARCH BTC_T_CPU BTC_T_MARCH BTC_T_ISA BTC_T_ABI BTC_T_CLIB BTC_T_ENDIAN BTC_T_FAMILY BTC_T_DESC BTC_T_KERN_MIN BTC_T_GCC_EXTRA <<< "${spec}" + BTC_T_ID="${target_id}" +} + +function f_silicon_probe() { + echo ">> Interrogating Core Topology and Instruction Extensions..." + + # Step-down dispatch: explicit target, explicit native, or default native + case "${BTC_TARGET_ID:-}" in + --native|'') + _probe_native + ;; + *) + f_resolve_target "${BTC_TARGET_ID}" + CROSS_MODE=1 + _configure_from_target + ;; + esac +} + +function _probe_native() { + local RAW_ARCH + RAW_ARCH=$(gcc -march=native -Q --help=target 2>/dev/null | grep -m1 "march=" | awk '{print $2}') || true + + if [[ -z "${RAW_ARCH}" || "${RAW_ARCH}" == "x86-64" ]]; then + RAW_ARCH="haswell" + fi + + # Try to match the probed microarch to a registered target + local probe_lower="${RAW_ARCH,,}" + local matched="${BTC_TARGETS[${probe_lower}]:-}" + if [[ -n "${matched}" ]]; then + matched="${probe_lower}" + else + # Select haswell as the deterministic default for unregistered microarchitectures + echo ">> [WARN] Probed microarch '${RAW_ARCH}' not in target registry. Selecting 'haswell'." + matched="haswell" + fi + + f_resolve_target "${matched}" + CROSS_MODE=0 + _configure_from_target +} + +function _configure_from_target() { + # Derive the target triple + case "${BTC_T_ARCH}" in + x86_64) + TARGET="x86_64-dcosnet-linux-gnu" + HOST_ARCH="x86_64-pc-linux-gnu" + ;; + mipsel) + TARGET="mipsel-dcosnet-linux-musl" + HOST_ARCH="x86_64-pc-linux-gnu" + ;; + arm) + TARGET="arm-dcosnet-linux-musleabihf" + HOST_ARCH="x86_64-pc-linux-gnu" + ;; + tilegx) + TARGET="tilegx-dcosnet-linux-gnu" + HOST_ARCH="x86_64-pc-linux-gnu" + ;; + *) + TARGET="${BTC_T_ARCH}-dcosnet-linux-gnu" + HOST_ARCH="x86_64-pc-linux-gnu" + ;; + esac + + # ISA tag for SYS_LABEL + ISA_TAG="${BTC_T_ISA}" + OPT_TAG="LTO" + SYS_LABEL="DCOSNET-${BTC_T_ID^^}-${ISA_TAG}-${OPT_TAG}" + + # Override SYS_LABEL for cross-compiles to include the arch family + if [[ "${CROSS_MODE}" -eq 1 ]]; then + SYS_LABEL="DCOSNET-${BTC_T_FAMILY^^}-${BTC_T_ID^^}-${ISA_TAG}-CROSS" + fi + + # Resource-Safe Threading: Allocate 2GB RAM per core floor to prevent LTO thrashing + local total_cpus + total_cpus=$(nproc) + local free_gb + free_gb=$(free -g | awk '/^Mem:/{print $7}') + local safe_threads=$(( free_gb / 2 )) + + if [[ ${safe_threads} -lt 1 ]]; then safe_threads=1; fi + if [[ ${safe_threads} -gt ${total_cpus} ]]; then safe_threads=${total_cpus}; fi + export v_threads="-j${safe_threads}" + + # Pin GCC version for Tile-Gx (upstream dropped after GCC 11) + if [[ "${BTC_T_FAMILY}" == "tile" ]]; then + v_gcc='gcc-10.3.0' + fi + + echo ">> [IDENTITY STAMP] ${SYS_LABEL}" + echo ">> [TARGET] ${BTC_T_ID} — ${BTC_T_DESC}" + echo ">> [TRIPLE] ${TARGET}" + echo ">> [C LIBRARY] ${BTC_T_CLIB}" + local mode_label="NATIVE" + if [[ "${CROSS_MODE}" -eq 1 ]]; then mode_label="CROSS-COMPILE"; fi + echo ">> [MODE] ${mode_label}" + echo ">> [THREAD ALLOCATION] Probed ${total_cpus} cores -> Throttled to ${v_threads} for LTO Safety." +} + +# ============================================================================ +# 4. SYSTEM PATHS & STAGING MATRIX +# ============================================================================ +export SOURCES_ACTIVE=/usr/src +export BTC_ARCHIVE=/opt/BTC +export SOURCE_CACHE=${BTC_ARCHIVE}/src +export RAMDISK_SIZE="12gb" + +# Upstream Production Matrices (defaults — can be overridden per-target) +v_linux='linux-7.1' +v_binutils='binutils-2.46.1' +v_gcc='gcc-15.3.0' +v_glibc='glibc-2.43' +v_libxcrypt='4.5.2' +v_gmp='gmp-6.3.0' +v_mpfr='mpfr-4.2.2' +v_mpc='mpc-1.4.0' +v_musl='musl-1.2.6' +v_linux_headers="${v_linux}" + +# These are set after f_resolve_target: +# NEWROOT, LOGS, HOST_ARCH, TARGET, TARGET_ARCH, GLOBAL_CFLAGS, GLOBAL_LDFLAGS + +function f_set_paths() { + export NEWROOT="${SOURCES_ACTIVE}/${SYS_LABEL}-cleanroom" + export LOGS="${BTC_ARCHIVE}/logs/${SYS_LABEL}" + + # Architecture-specific optimization flags + # For non-x86_64, march maps to the per-arch value from the target registry + local march_flag="${BTC_T_MARCH}" + + # ISA-specific extra flags (table-driven via case — SEI CERT CTR50-JP) + local isa_extra="" + case "${BTC_T_ISA}" in + AVX512) isa_extra=" -mavx512f -mavx512dq -mavx512vl -mavx512bw" ;; + AVX2) isa_extra=" -mavx2" ;; + SSE4_2) isa_extra=" -msse4.2" ;; + NEON) isa_extra=" -mfpu=neon -mfloat-abi=hard" ;; + MIPS32) isa_extra="" ;; + TILE) isa_extra="" ;; + esac + + # Unified CFLAGS: --sysroot points at NEWROOT for both glibc and musl targets + export GLOBAL_CFLAGS="-O3 -march=${march_flag}${isa_extra} -flto -ffat-lto-objects --sysroot=${NEWROOT} -pipe" + export GLOBAL_LDFLAGS="-Wl,-O1 -Wl,--as-needed -flto --sysroot=${NEWROOT}" + + # For native x86_64 builds, keep the i686 build cpu + if [[ "${CROSS_MODE}" -eq 0 && "${BTC_T_ARCH}" == "x86_64" ]]; then + TARGET_ARCH="${BTC_T_MARCH}" + else + TARGET_ARCH="${BTC_T_ID}" + fi +} + +# ============================================================================ +# 5. HARDWARE SENTINEL & TELEMETRY MODULES +# ============================================================================ +function f_guard() { + local max_temp=85 + local min_mem=800 + local cur_temp + local cur_mem + + # Thermal zones may not exist in containers; guard gracefully + if [[ -d /sys/class/thermal ]]; then + cur_temp=$(cat /sys/class/thermal/thermal_zone*/temp 2>/dev/null | head -n1 | awk '{print $1/1000}') || cur_temp=0 + else + cur_temp=0 + fi + cur_mem=$(free -m | awk '/^Mem:/{print $7}') + + if (( ${cur_temp%.*} > max_temp )); then + echo ">> [WARNING: THERMAL SPIKE] Temp at ${cur_temp}C. Throttling build for cooling phase..." + sleep 15 + fi + if [[ ${cur_mem} -lt ${min_mem} ]]; then + echo ">> [WARNING: MEMORY SATURATION] Free memory at ${cur_mem}MB. Yielding pipeline execution..." + sleep 20 + fi +} + +function f_entropy_shield() { + local min_entropy=1000 + local cur_entropy + if [[ -f /proc/sys/kernel/random/entropy_avail ]]; then + cur_entropy=$(< /proc/sys/kernel/random/entropy_avail) + if [[ ${cur_entropy} -lt ${min_entropy} ]]; then + echo ">> [ENTROPY DEFICIT] Pool dropped to ${cur_entropy}. Injecting safe hardware-jitter..." + find /bin /sbin -type f -exec ls -l {} + > /dev/null 2>&1 & + sleep 2 + kill $! 2>/dev/null || true + fi + fi +} + +function f_exec_log() { + local cmd="$1" + local log_base="$2" + + f_entropy_shield + f_guard + + echo ">> Executing: ${log_base}" + # Note: ${cmd} is sourced from internal build functions only (not user input). + # The trust boundary is the BTC.sh script itself — do not expose f_exec_log + # as a public API with externally-supplied command strings. + stdbuf -oL -eL bash -c "${cmd}" 2>&1 | \ + pv -t -r -b -N "${log_base}" | \ + tee -a "${LOGS}/${log_base}.log" > /dev/null +} + +function f_tmux_dashboard() { + if [[ -n "${TMUX:-}" ]]; then + echo ">> Active Tmux session identified. Splitting target tracking matrix..." + tmux split-window -h -p 35 "tail -F \"${LOGS}\"/*.log" || true + tmux split-window -v -p 50 "watch -n 2 'echo \"=== ENTROPY POOL ===\"; cat /proc/sys/kernel/random/entropy_avail; echo \"=== NETWORK BOUND MATRIX ===\"; ss -tunp | grep -v 127.0.0.1'" || true + tmux select-pane -t 0 || true + fi +} + +# ============================================================================ +# 6. POLY-SIGNATURE IDENTITY STAMPING LAYER +# +# Tier 1 — Cluster: Deterministic token from target+sysroot hash. +# Joins an existing cluster token if one is provided. +# Write-once per deployment; never drifts. +# Tier 2 — TPM: Binds signature to hardware PCR state via TPM 1.2/2.0. +# Singular-target deployments only. Gated behind --tpm-seal. +# Tier 3 — Poly: Per-machine random salt (write-once) folded into every +# binary stamp. Two independent machines produce different +# forensic signatures even for the same target. +# +# Selection priority: cluster-join > tpm-seal > poly (default). +# State files live under ${BTC_ARCHIVE}/ and persist across builds. +# ============================================================================ + +# Signature state (set once by f_sig_init, consumed by f_stamp_binary) +BTC_SIG_TIER="" +BTC_SIG_TOKEN="" +BTC_TPM_SEAL=0 + +function f_tpm_pcr_digest() { + # Attempt TPM 2.0 PCR read via tpm2-tools + if command -v tpm2_pcrread &>/dev/null; then + tpm2_pcrread sha256:0,1,2,3,4,5,6,7 2>/dev/null | \ + awk '/^[0-9]+:/{gsub(/[^0-9a-fA-F]/,"", $2); printf "%s", $2}' | \ + sha256sum | awk '{print $1}' + return 0 + fi + + # Attempt TPM 1.2 via sysfs PCR export + if [[ -d /sys/class/tpm/tpm0 ]]; then + sha256sum /sys/class/tpm/tpm0/pcrs 2>/dev/null | awk '{print $1}' + return 0 + fi + + # No TPM hardware detected + return 1 +} + +function f_sig_init() { + local salt_file="${BTC_ARCHIVE}/.btc-salt" + local cluster_file="${BTC_ARCHIVE}/.btc-cluster-token" + + # --- Tier 1: Cluster --- + # If a cluster token exists on disk, this machine has already joined. + # Honor it unconditionally — no drift, no re-roll. + if [[ -f "${cluster_file}" ]]; then + BTC_SIG_TOKEN=$(< "${cluster_file}") + BTC_SIG_TIER="cluster" + echo ">> [SIG] Tier 1 (cluster) — Adopting existing cluster token." + echo ">> [SIG] Token: ${BTC_SIG_TOKEN:0:16}..." + return 0 + fi + + # If a cluster join was requested via CLI, adopt the provided token. + if [[ -n "${BTC_CLUSTER_JOIN:-}" ]]; then + BTC_SIG_TOKEN="${BTC_CLUSTER_JOIN}" + BTC_SIG_TIER="cluster" + mkdir -p "${BTC_ARCHIVE}" + echo "${BTC_SIG_TOKEN}" > "${cluster_file}" + echo ">> [SIG] Tier 1 (cluster) — Joined cluster with provided token." + echo ">> [SIG] Token: ${BTC_SIG_TOKEN:0:16}..." + return 0 + fi + + # --- Tier 2: TPM --- + # Hardware-bound signature. Singular deployments only. + if [[ "${BTC_TPM_SEAL}" -eq 1 ]]; then + local pcr_digest + pcr_digest=$(f_tpm_pcr_digest) || true + if [[ -n "${pcr_digest}" ]]; then + BTC_SIG_TOKEN="tpm:${pcr_digest:0:32}" + BTC_SIG_TIER="tpm" + echo ">> [SIG] Tier 2 (tpm) — PCR digest sealed into signature." + echo ">> [SIG] Token: ${BTC_SIG_TOKEN:0:16}..." + return 0 + else + echo ">> [WARN] --tpm-seal requested but no TPM hardware detected. Stepping down to poly." + fi + fi + + # --- Tier 3: Poly (default) --- + # Per-machine random salt. Write-once; subsequent builds reuse it. + mkdir -p "${BTC_ARCHIVE}" + if [[ -f "${salt_file}" ]]; then + BTC_SIG_TOKEN=$(< "${salt_file}") + else + BTC_SIG_TOKEN=$(openssl rand -hex 16) + echo "${BTC_SIG_TOKEN}" > "${salt_file}" + fi + BTC_SIG_TIER="poly" + echo ">> [SIG] Tier 3 (poly) — Per-machine salt deployed." + echo ">> [SIG] Token: ${BTC_SIG_TOKEN:0:16}..." +} + +function f_stamp_binary() { + local target_bin="$1" + local log_base="$2" + + if [[ -f "${target_bin}" && ! -L "${target_bin}" ]]; then + # Select the assembler matching the build mode + local assembler + if [[ "${CROSS_MODE}" -eq 1 ]]; then + assembler="${TARGET}-gcc" + else + assembler="gcc" + fi + + # 1. Inject ELF Object Note with poly-signature token + # The .note.BTC payload now carries the active sig tier and token, + # making each deployment's forensic identity distinct. + # Note type 0xB7C is a vendor-specific identifier — it does NOT + # correspond to any standard ELF note type (NT_VERSION, etc.). + cat << EOF > btc_stamp.s +.section .note.BTC,"a",@note +.long 2f - 1f +.long 4f - 3f +.long 0xB7C +1: .asciz "DCOSNET" +2: .align 4 +3: .ascii "Org: dcos.net|K:${v_linux}|Arch:${BTC_T_ID}|Label:${SYS_LABEL}|Stage:${log_base}|SigTier:${BTC_SIG_TIER}|Sig:${BTC_SIG_TOKEN}" +4: .align 4 +EOF + ${assembler} -c btc_stamp.s -o btc_stamp.o + ${TARGET}-objcopy --add-section .note.BTC=btc_stamp.o "${target_bin}" 2>/dev/null || \ + objcopy --add-section .note.BTC=btc_stamp.o "${target_bin}" 2>/dev/null || true + rm -f btc_stamp.s btc_stamp.o + + # 2. Extended Filesystem Attributes — identity now includes sig tier and token + local bin_hash + bin_hash=$(sha256sum "${target_bin}" | awk '{print $1}') + setfattr -n user.btc.identity -v "BTC-${SYS_LABEL}-${v_linux}-${BTC_SIG_TIER}" "${target_bin}" 2>/dev/null || true + setfattr -n user.btc.hash -v "${bin_hash}" "${target_bin}" 2>/dev/null || true + setfattr -n user.btc.sig.tier -v "${BTC_SIG_TIER}" "${target_bin}" 2>/dev/null || true + setfattr -n user.btc.sig.token -v "${BTC_SIG_TOKEN}" "${target_bin}" 2>/dev/null || true + + # 3. Separate Debug Symbols & Create External Links + if [[ "${BTC_STRIP_MODE:-1}" -eq 1 ]]; then + mkdir -p "${BTC_ARCHIVE}/symbols/${SYS_LABEL}" + ${TARGET}-objcopy --only-keep-debug "${target_bin}" "${BTC_ARCHIVE}/symbols/${SYS_LABEL}/${log_base}.debug" 2>/dev/null || \ + objcopy --only-keep-debug "${target_bin}" "${BTC_ARCHIVE}/symbols/${SYS_LABEL}/${log_base}.debug" 2>/dev/null || true + ${TARGET}-strip --strip-unneeded "${target_bin}" 2>/dev/null || \ + strip --strip-unneeded "${target_bin}" 2>/dev/null || true + ${TARGET}-objcopy --add-gnu-debuglink="${BTC_ARCHIVE}/symbols/${SYS_LABEL}/${log_base}.debug" "${target_bin}" 2>/dev/null || \ + objcopy --add-gnu-debuglink="${BTC_ARCHIVE}/symbols/${SYS_LABEL}/${log_base}.debug" "${target_bin}" 2>/dev/null || true + fi + fi +} + +# ============================================================================ +# 7. SOURCE ACQUISITION (download / decompress / compress) +# ============================================================================ + +# Associative array: package stem -> upstream URL +# Only packages consumed by the build sequence are listed. +# URLs are canonical upstream mirrors — replace to point at a local mirror. +declare -A A_SRC_URL=( + [binutils]="https://ftp.gnu.org/gnu/binutils/${v_binutils}.tar.xz" + [linux]="https://cdn.kernel.org/pub/linux/kernel/v7.x/${v_linux}.tar.xz" + [linux-headers]="https://cdn.kernel.org/pub/linux/kernel/v7.x/${v_linux_headers}.tar.xz" + [gcc]="https://ftp.gnu.org/gnu/gcc/${v_gcc}/${v_gcc}.tar.xz" + [glibc]="https://ftp.gnu.org/gnu/glibc/${v_glibc}.tar.xz" + [libxcrypt]="https://github.com/besser82/libxcrypt/releases/download/v${v_libxcrypt}/libxcrypt-${v_libxcrypt}.tar.xz" + [gmp]="https://ftp.gnu.org/gnu/gmp/${v_gmp}.tar.xz" + [mpfr]="https://ftp.gnu.org/gnu/mpfr/${v_mpfr}.tar.xz" + [mpc]="https://ftp.gnu.org/gnu/mpc/${v_mpc}.tar.xz" + [musl]="https://musl.libc.org/releases/${v_musl}.tar.gz" +) + +function _archive_sane() { + # Quick integrity test: returns 0 if archive is valid, 1 if corrupt. + # Handles .tar.xz, .tar.gz, .tar.bz2, .tar.lz, .tar.lrz, .zip + local f="$1" + local ext="${f##*.}" + case "${ext}" in + xz|bz2|lz|gz) tar -tf "${f}" >/dev/null 2>&1 ;; + lrz) lrzip -t "${f}" >/dev/null 2>&1 ;; + zip) unzip -t "${f}" >/dev/null 2>&1 ;; + *) return 0 ;; + esac +} + +function f_download() { + # Fetch all upstream source tarballs into SOURCE_CACHE. + # Skips files already present AND integrity-verified (idempotent — safe to re-run). + # Corrupted/truncated files are deleted and re-fetched automatically. + # Produces per-file md5 and sha512 checksum manifests. + mkdir -p "${SOURCE_CACHE}" "${LOGS}/checksums" + cd "${SOURCE_CACHE}" + echo ">> [ACQUIRE] Downloading upstream source tarballs..." + + for key in "${!A_SRC_URL[@]}"; do + local url="${A_SRC_URL[$key]}" + local file="${url##*/}" + + if [[ -f "${file}" ]] && _archive_sane "${file}"; then + echo ">> [ACQUIRE] ${file} — present, skipping." + else + if [[ -f "${file}" ]]; then + echo ">> [ACQUIRE] ${file} — corrupt/truncated, re-fetching..." + rm -f "${file}" + else + echo ">> [ACQUIRE] ${file} — fetching..." + fi + wget -nc -O "${file}" "${url}" + # Post-download integrity check + if ! _archive_sane "${file}"; then + echo ">> [ACQUIRE] ${file} — FAILED integrity check after download!" + rm -f "${file}" + return 1 + fi + fi + + md5sum "${file}" >> "${LOGS}/checksums/${file}.md5" 2>/dev/null || true + sha512sum "${file}" >> "${LOGS}/checksums/${file}.sha512" 2>/dev/null || true + done + + echo ">> [ACQUIRE] Source acquisition complete." +} + +function f_decompress() { + # Auto-detect compression type from file extension and extract into + # SOURCES_ACTIVE (ramfs cleanroom). Accepts either a bare filename + # (looked up in SOURCE_CACHE) or a full path. + # + # Usage: f_decompress # uses SOURCE_CACHE + # f_decompress # absolute path + local in_file + case "$1" in + /*) in_file="$1" ;; + *) in_file="${SOURCE_CACHE}/$1" ;; + esac + + local ext="${in_file##*.}" + cd "${SOURCES_ACTIVE}" + + case "${ext}" in + xz) tar -axf "${in_file}" ;; + gz) tar -xzf "${in_file}" ;; + bz2) tar -xjf "${in_file}" ;; + lz) tar -axf "${in_file}" ;; + lrz) tar -x -I lrzip -f "${in_file}" ;; + zip) unzip -qo "${in_file}" ;; + *) echo ">> [WARN] f_decompress: unknown extension '.${ext}' for ${in_file}" ;; + esac +} + +function f_compress() { + # Compress the finished toolchain tarball using the specified algorithm. + # Step-down dispatch on USE_COMPRESSOR — SEI CERT CTR50-JP. + # Usage: f_compress + local out_file="$1" + case "${USE_COMPRESSOR:-xz}" in + xz) xz -z -e -9 "${out_file}" ;; + gz) gzip -9 "${out_file}" ;; + bz2) bzip2 -z9 "${out_file}" ;; + lrzip) lrzip -z -L9 -p${total_cpus:-1} -U "${out_file}" ;; + *) echo ">> [WARN] f_compress: unknown compressor '${USE_COMPRESSOR}', defaulting to xz"; xz -z -e -9 "${out_file}" ;; + esac +} + +# ============================================================================ +# 7b. CLEANROOM MATRIX CONFIGURATION +# ============================================================================ +function f_setup() { + echo ">> Preparing Virtualized Cleanroom Environment..." + mkdir -p "${SOURCE_CACHE}" "${LOGS}" "${BTC_ARCHIVE}/symbols/${SYS_LABEL}" + + if ! mountpoint -q "${SOURCES_ACTIVE}"; then + mount -t ramfs -o "size=${RAMDISK_SIZE}" ramfs "${SOURCES_ACTIVE}" + echo ">> Ramfs Cleanroom mounted at ${SOURCES_ACTIVE} with ceiling ${RAMDISK_SIZE}." + fi + + mkdir -p "${NEWROOT}" + cd "${NEWROOT}" + + # Create sysroot directory structure + mkdir -p bin etc lib lib64 sbin usr var include + + # Architecture-specific sysroot layout + case "${BTC_T_ARCH}" in + x86_64) + ln -sfv lib "${NEWROOT}/lib64" + ;; + arm) + # ARM EABI HF uses lib + lib/ld-linux-armhf.so.3 + ln -sfv lib "${NEWROOT}/lib32" 2>/dev/null || true + ;; + mipsel) + # MIPS o32 ABI: lib is the primary lib dir + ;; + tilegx) + # Tile-Gx 64-bit: lib64 for abi64 + ln -sfv lib "${NEWROOT}/lib64" 2>/dev/null || true + ;; + esac + + export PATH="${NEWROOT}/bin:${PATH}" +} + +# ============================================================================ +# 8. TOOLCHAIN BUILD FUNCTIONS +# ============================================================================ + +# --- 8a. Binutils (all architectures) --- +function f_binutils() { + cd "${SOURCES_ACTIVE}" + f_decompress "${v_binutils}.tar.xz" + mkdir -p "${v_binutils}-build" && cd "${v_binutils}-build" + + local configure_target="--target=${TARGET}" + + # Architecture-specific binutils configure patches + local binutils_extra="" + case "${BTC_T_ARCH}" in + arm) + binutils_extra="--enable-multilib --with-sysroot=${NEWROOT}" + ;; + mipsel) + binutils_extra="--enable-multilib --with-sysroot=${NEWROOT}" + ;; + tilegx) + binutils_extra="--disable-werror" + ;; + *) + binutils_extra="--enable-default-hash-style=gnu" + ;; + esac + + local build_cmd="../${v_binutils}/configure \ + --prefix=${NEWROOT} \ + --with-sysroot=${NEWROOT} \ + ${configure_target} \ + --disable-nls \ + --enable-gprofng=no \ + --disable-werror \ + ${binutils_extra}" + + f_exec_log "${build_cmd}" "binutils-configure" + f_exec_log "make ${v_threads}" "binutils-make" + f_exec_log "make install" "binutils-install" +} + +# --- 8b. Kernel Headers (all architectures) --- +function f_kernel_headers() { + cd "${SOURCES_ACTIVE}" + + # Use stable LTS headers for cross targets that may need older kernels + local kernel_src="${v_linux}" + if [[ "${BTC_T_FAMILY}" == "tile" ]]; then + kernel_src="${v_linux_headers}" + fi + + # For musl targets, we only need sanitized kernel headers (no full + # kernel source). For glibc targets we need the full headers. + f_decompress "${kernel_src}.tar.xz" + cd "${kernel_src}" + + f_exec_log "make mrproper" "kernel-headers-clean" + f_exec_log "make headers" "kernel-headers-generate" + + find usr/include -type f ! -name '*.h' -delete + mkdir -p "${NEWROOT}/usr/include" + cp -rv usr/include/* "${NEWROOT}/usr/include" +} + +# --- 8c. GCC Stage 1 (all architectures) --- +function f_gcc_p1() { + cd "${SOURCES_ACTIVE}" + rm -rf "${v_gcc}" + f_decompress "${v_gcc}.tar.xz" + cd "${v_gcc}" + + # Nesting Support Libraries internally for Stage-1 execution isolation + # f_decompress changes CWD to SOURCES_ACTIVE, so we must re-enter + # the gcc source tree and use absolute paths for the mv. + f_decompress "${v_gmp}.tar.xz" + f_decompress "${v_mpfr}.tar.xz" + f_decompress "${v_mpc}.tar.xz" + cd "${SOURCES_ACTIVE}/${v_gcc}" + rm -rf gmp mpfr mpc + mv -Tf "${SOURCES_ACTIVE}/${v_gmp}" gmp + mv -Tf "${SOURCES_ACTIVE}/${v_mpfr}" mpfr + mv -Tf "${SOURCES_ACTIVE}/${v_mpc}" mpc + + # Architecture-specific GCC source patches + case "${BTC_T_ARCH}" in + x86_64) + # Enforce 64-bit dynamic linker structural target pathing + # GCC >= 15 removed t-linux64; t-linux or config.gcc may carry m64= + if [[ -f gcc/config/i386/t-linux64 ]]; then + sed -e '/m64=/s/lib64/lib/' -i.bak gcc/config/i386/t-linux64 + elif [[ -f gcc/config/i386/t-linux ]]; then + sed -e '/m64=/s/lib64/lib/' -i.bak gcc/config/i386/t-linux + else + echo ">> [WARN] gcc/config/i386/t-linux64 not found in ${v_gcc}; skipping lib64->lib multilib patch (--disable-multilib is active)" + fi + ;; + arm) + # ARM: default to hard-float ABI + sed -e 's/#define DEFAULT_ABI_FLOAT SoftF/SoftF_HARDFP/' -i.bak gcc/config/arm/linux-eabi.h 2>/dev/null || true + ;; + mipsel) + # MIPS: default to o32 ABI, soft-float + ;; + tilegx) + # Tile-Gx: no special patches needed for GCC 10.3.0 + ;; + esac + + mkdir -p "${SOURCES_ACTIVE}/${v_gcc}-phase1" && cd "${SOURCES_ACTIVE}/${v_gcc}-phase1" + + # Base configure flags common to all targets + local gcc_base="--target=${TARGET} \ + --prefix=${NEWROOT} \ + --with-sysroot=${NEWROOT} \ + --with-newlib \ + --without-headers \ + --with-arch=${BTC_T_MARCH} \ + --with-cpu=${BTC_T_MARCH} \ + --enable-default-pie \ + --enable-default-ssp \ + --disable-nls \ + --disable-shared \ + --disable-threads \ + --disable-libatomic \ + --disable-libgomp \ + --disable-libquadmath \ + --disable-libssp \ + --disable-libvtv \ + --disable-libstdcxx \ + --enable-languages=c,c++" + + # Per-architecture configure adjustments + local gcc_arch_extra="" + case "${BTC_T_CLIB}" in + glibc) + # x86_64 glibc targets: set glibc version for compatibility checks + gcc_arch_extra="--with-glibc-version=${v_glibc#*-} --disable-multilib" + ;; + musl) + # Cross targets with musl: disable multilib by default, add arch-specific flags + gcc_arch_extra="--disable-multilib ${BTC_T_GCC_EXTRA}" + ;; + esac + + local build_cmd="../${v_gcc}/configure ${gcc_base} ${gcc_arch_extra}" + + f_exec_log "${build_cmd}" "gcc-p1-configure" + f_exec_log "make ${v_threads} all-gcc" "gcc-p1-make" + f_exec_log "make ${v_threads} all-target-libgcc" "gcc-p1-libgcc" + f_exec_log "make install-gcc" "gcc-p1-install" + f_exec_log "make install-target-libgcc" "gcc-p1-install-libgcc" +} + +# --- 8d. C Library (glibc or musl) --- +function f_clib() { + # Dispatch C library build; enforce architecture constraints at the gate + case "${BTC_T_CLIB}" in + glibc) + if [[ "${BTC_T_ARCH}" != "x86_64" ]]; then + echo ">> [ERROR] glibc does not support ${BTC_T_ARCH}. Select a musl-based target." + exit 1 + fi + f_glibc + ;; + musl) + f_musl + ;; + *) + echo ">> [ERROR] Unsupported C library: ${BTC_T_CLIB}" + exit 1 + ;; + esac +} + +function f_glibc() { + cd "${SOURCES_ACTIVE}" + f_decompress "${v_glibc}.tar.xz" + mkdir -p "${v_glibc}-build" && cd "${v_glibc}-build" + + local build_cmd="../${v_glibc}/configure \ + --prefix=/usr \ + --host=${TARGET} \ + --build=${HOST_ARCH} \ + --enable-kernel=${BTC_T_KERN_MIN} \ + --with-headers=${NEWROOT}/usr/include \ + --disable-profile \ + --enable-stack-protector=strong \ + --disable-werror \ + libc_cv_slibdir=/usr/lib" + + f_exec_log "${build_cmd}" "glibc-configure" + f_exec_log "make ${v_threads}" "glibc-make" + f_exec_log "make DESTDIR=${NEWROOT} install" "glibc-install" + + # Sanitize hardcoded host system configurations from dynamic script linkage + sed -i "s|${NEWROOT}||g" "${NEWROOT}/usr/bin/ldd" +} + +function f_libxcrypt() { + # libxcrypt is only used with glibc — musl has built-in crypt support + if [[ "${BTC_T_CLIB}" != "glibc" ]]; then + echo ">> [SKIP] libxcrypt: not needed for ${BTC_T_CLIB}" + return 0 + fi + + cd "${SOURCES_ACTIVE}" + f_decompress "libxcrypt-${v_libxcrypt}.tar.xz" + cd "libxcrypt-${v_libxcrypt}" + + # GCC >= 15 enforces stricter const-correctness (-Wcast-qual, -Wdiscarded-qualifiers). + # libxcrypt 4.5.2 has known issues in crypt-gost-yescrypt.c and crypt-sm3-yescrypt.c + # that trigger -Werror. Pass CFLAGS=-Wno-error to configure so it is baked into + # the generated Makefile. Automake places CFLAGS after WARN_CFLAGS on the compile + # line, so GCC processes -Werror first then -Wno-error (last wins). This survives + # Makefile regeneration and is the standard approach for building old deps with + # newer compilers. + local build_cmd="CFLAGS=\"-g -O2 -Wno-error\" ./configure \ + --prefix=/usr \ + --host=${TARGET} \ + --build=${HOST_ARCH} \ + --enable-hashes=strong,glibc \ + --enable-obsolete-api=no \ + --disable-static" + + f_exec_log "${build_cmd}" "libxcrypt-configure" + f_exec_log "make ${v_threads}" "libxcrypt-make" + f_exec_log "make DESTDIR=${NEWROOT} install" "libxcrypt-install" +} + +function f_musl() { + # musl: lightweight C library for cross-compilation + # Used by mipsel, armv7, and tilegx targets. + # Reference: CLFS (Cross Linux From Scratch) musl cross-compiler chapter. + cd "${SOURCES_ACTIVE}" + f_decompress "${v_musl}.tar.gz" + cd "${v_musl}" + + # Build a standalone musl cross-compiler that wraps our stage-1 GCC. + # This produces ${TARGET}-musl-gcc and the musl C library installed + # into the sysroot. + local musl_configure="./configure \ + --prefix=/usr \ + --host=${TARGET} \ + --build=${HOST_ARCH} \ + --disable-shared \ + --enable-static" + + # For some targets, musl needs additional architecture hints + case "${BTC_T_ARCH}" in + arm) + musl_configure="${musl_configure} CFLAGS=\"-O2 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16\"" + ;; + mipsel) + musl_configure="${musl_configure} CFLAGS=\"-O2 -march=mips32r2 -mabi=32 -msoft-float\"" + ;; + tilegx) + musl_configure="${musl_configure} CFLAGS=\"-O2 -march=tilegx\"" + ;; + esac + + # Pass cross-compiler tools inline to avoid polluting the caller's environment + local cross_env="CC=${NEWROOT}/bin/${TARGET}-gcc AR=${NEWROOT}/bin/${TARGET}-ar RANLIB=${NEWROOT}/bin/${TARGET}-ranlib" + + f_exec_log "${cross_env} CROSS_COMPILE=${TARGET}- ${musl_configure}" "musl-configure" + f_exec_log "${cross_env} make ${v_threads}" "musl-make" + f_exec_log "${cross_env} make DESTDIR=${NEWROOT} install" "musl-install" +} + +# --- 8e. GCC Stage 2 (final compiler) --- +function f_gcc_p2() { + cd "${SOURCES_ACTIVE}" + + # Decompress support libraries (f_decompress changes CWD to SOURCES_ACTIVE). + f_decompress "${v_gmp}.tar.xz" + f_decompress "${v_mpfr}.tar.xz" + f_decompress "${v_mpc}.tar.xz" + + # Re-enter gcc source tree and nest the extracted libraries where + # GCC's configure expects to find them (as gmp/, mpfr/, mpc/ subdirs). + cd "${SOURCES_ACTIVE}/${v_gcc}" + rm -rf gmp mpfr mpc + mv -Tf "${SOURCES_ACTIVE}/${v_gmp}" gmp + mv -Tf "${SOURCES_ACTIVE}/${v_mpfr}" mpfr + mv -Tf "${SOURCES_ACTIVE}/${v_mpc}" mpc + + mkdir -p "${SOURCES_ACTIVE}/${v_gcc}-phase2" && cd "${SOURCES_ACTIVE}/${v_gcc}-phase2" + + # Stage 2 final compiler — runs on BUILD host, targets the sysroot. + # CRITICAL: --host must be ${HOST_ARCH} (the machine the compiler + # executes on), NOT ${TARGET}. --target specifies what architecture + # the produced compiler generates code for. Using --host=${TARGET} + # caused configure to expect the build machine to be the custom + # triple, which made all compile-and-run checks fail instantly. + # + # --with-sysroot and --with-headers are in the base because both + # glibc and musl targets need the compiler to find C library + # headers and runtime in the sysroot. + local gcc_p2_base="--prefix=/usr \ + --build=${HOST_ARCH} \ + --host=${HOST_ARCH} \ + --target=${TARGET} \ + --with-sysroot=${NEWROOT} \ + --with-headers=${NEWROOT}/usr/include \ + --with-arch=${BTC_T_MARCH} \ + --with-cpu=${BTC_T_MARCH} \ + --enable-languages=c,c++ \ + --enable-default-pie \ + --enable-default-ssp \ + --enable-threads=posix \ + --disable-bootstrap" + + # Per-C-library configure adjustments + local gcc_p2_clib="" + case "${BTC_T_CLIB}" in + glibc) + gcc_p2_clib="--disable-multilib" + ;; + musl) + # musl targets: also point GCC at the musl library path. + gcc_p2_clib="--disable-multilib \ + --with-libs=${NEWROOT}/usr/lib \ + ${BTC_T_GCC_EXTRA}" + ;; + esac + + local build_cmd="../${v_gcc}/configure ${gcc_p2_base} ${gcc_p2_clib}" + + f_exec_log "${build_cmd}" "gcc-p2-configure" + f_exec_log "make ${v_threads}" "gcc-p2-make" + f_exec_log "make DESTDIR=${NEWROOT} install" "gcc-p2-install" +} + +# --- 8f. Kernel Binary (architecture-aware) --- +function f_kernel_binary() { + local kernel_src="${v_linux}" + if [[ "${BTC_T_FAMILY}" == "tile" ]]; then + kernel_src="${v_linux_headers}" + fi + + cd "${SOURCES_ACTIVE}/${kernel_src}" + + echo ">> Instantiating Silicon Optimized Monolithic Configuration Matrix for ${BTC_T_ARCH}..." + + # Select the correct defconfig for the target architecture + case "${BTC_T_ARCH}" in + arm) + # Multi-v7 is the universal ARMv7 defconfig (covers most Cortex-A SoCs) + make multi_v7_defconfig + ;; + mipsel) + # MALTA is the reference MIPS32 platform + make malta_defconfig + ;; + tilegx) + # Tile-Gx has its own defconfig + make tilegx_defconfig 2>/dev/null || make defconfig + ;; + *) + make defconfig + ;; + esac + + # Inject Custom Enterprise Swarm Labels & Architecture Parameters + sed -i "s/CONFIG_LOCALVERSION=\"\"/CONFIG_LOCALVERSION=\"-dcosnet-${SYS_LABEL}\"/" .config + + # Modern Hardening Optimization Suite Injection + sed -i "s/# CONFIG_MODULES is not set/CONFIG_MODULES=n/" .config || true + echo "CONFIG_MODULES=n" >> .config + echo "CONFIG_KALLSYMS=n" >> .config + echo "CONFIG_DEBUG_FS=n" >> .config + + # Cross-compile kernel for non-x86_64 targets + local kernel_make_vars="ARCH=${BTC_T_ARCH} CROSS_COMPILE=${TARGET}-" + + f_exec_log "make ${kernel_make_vars} olddefconfig" "kernel-bin-config-merge" + f_exec_log "make ${v_threads} ${kernel_make_vars} LOCALVERSION=-dcosnet-${SYS_LABEL}" "kernel-bin-make" + + # Install kernel image — path varies by architecture + mkdir -p "${NEWROOT}/boot" + case "${BTC_T_ARCH}" in + x86_64) + cp -v arch/x86/boot/bzImage "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" + ;; + arm) + cp -v arch/arm/boot/zImage "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" 2>/dev/null || \ + cp -v arch/arm/boot/Image "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" + # Also copy device tree blobs if built + find arch/arm/boot/dts -name '*.dtb' -exec cp -v {} "${NEWROOT}/boot/" \; 2>/dev/null || true + ;; + mipsel) + cp -v vmlinux "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" + ;; + tilegx) + cp -v arch/tile/boot/vmlinux "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" 2>/dev/null || \ + cp -v vmlinux "${NEWROOT}/boot/vmlinuz-${v_linux}-${SYS_LABEL}" + ;; + esac + + # Apply Forensic Identity Stamps to all toolchain binaries + while IFS= read -r bin; do + f_stamp_binary "${bin}" "$(basename "${bin}")" + done < <(find "${NEWROOT}/bin" "${NEWROOT}/usr/bin" -type f 2>/dev/null) || true +} + +# ============================================================================ +# 9. PACKAGING +# ============================================================================ +function f_package() { + echo ">> Packaging Production Golden Image Artifact Target Matrix..." + cd "${NEWROOT}" + + # --- Integration Manifest for sorcery-go and Fester --- + local manifest="${BTC_ARCHIVE}/${SYS_LABEL}-manifest.json" + # Derive mode label from dispatch state + local mode_label + case "${CROSS_MODE}" in + 1) mode_label="cross" ;; + *) mode_label="native" ;; + esac + + cat > "${manifest}" << MANIFEST_EOF +{ + "btc_version": "0.4.0", + "mode": "${mode_label}", + "cross_mode": ${CROSS_MODE}, + "sys_label": "${SYS_LABEL}", + "target_id": "${BTC_T_ID}", + "target_arch": "${BTC_T_ARCH}", + "target_cpu": "${BTC_T_CPU}", + "target_march": "${BTC_T_MARCH}", + "target_triple": "${TARGET}", + "host_arch": "${HOST_ARCH}", + "isa_tag": "${ISA_TAG}", + "opt_tag": "${OPT_TAG}", + "abi": "${BTC_T_ABI}", + "clib": "${BTC_T_CLIB}", + "endian": "${BTC_T_ENDIAN}", + "family": "${BTC_T_FAMILY}", + "description": "${BTC_T_DESC}", + "kernel_min": "${BTC_T_KERN_MIN}", + "kernel": "${v_linux}", + "binutils": "${v_binutils}", + "gcc": "${v_gcc}", + "glibc": "${v_glibc}", + "musl": "${v_musl}", + "libxcrypt": "libxcrypt-${v_libxcrypt}", + "golden_image": "${SYS_LABEL}-toolchain-golden.tar.xz", + "cflags": "${GLOBAL_CFLAGS}", + "ldflags": "${GLOBAL_LDFLAGS}", + "stamp_note": ".note.BTC", + "stamp_xattr_identity": "user.btc.identity", + "stamp_xattr_hash": "user.btc.hash", + "stamp_xattr_sig_tier": "user.btc.sig.tier", + "stamp_xattr_sig_token": "user.btc.sig.token", + "sig_tier": "${BTC_SIG_TIER}", + "sig_token_preview": "${BTC_SIG_TOKEN:0:16}...", + "org": "dcos.net", + "license": "AGPL-3.0-or-later", + "integrations": { + "sorcery-go": { + "config_key": "toolchain", + "config_value": "btc", + "env_btc_path": "SORCERY_GO_BTC_PATH", + "env_btc_root": "SORCERY_GO_BTC_ROOT", + "env_btc_syslabel": "SORCERY_GO_BTC_SYS_LABEL" + }, + "fester": { + "config_section": "btc", + "config_yaml_key": "btc.enabled / btc.root / btc.target" + } + } +} +MANIFEST_EOF + echo ">> [INTEGRATION] Manifest written to: ${manifest}" + + tar -cf - . | xz -9 -T 0 > "${BTC_ARCHIVE}/${SYS_LABEL}-toolchain-golden.tar.xz" + echo ">> [SUCCESS] Archive deployed cleanly to: ${BTC_ARCHIVE}/${SYS_LABEL}-toolchain-golden.tar.xz" + + # Generate SHA-256 checksums of the golden image for CAS integration. + local checksum_file="${BTC_ARCHIVE}/${SYS_LABEL}-toolchain-golden.sha256" + sha256sum "${BTC_ARCHIVE}/${SYS_LABEL}-toolchain-golden.tar.xz" > "${checksum_file}" + echo ">> [INTEGRATION] SHA-256 checksum written to: ${checksum_file}" +} + +# ============================================================================ +# 10. MAIN ENTRY RUNTIME MATRIX +# ============================================================================ +function f_main() { + [[ ${EUID} -ne 0 ]] && { echo ">> Error: Root privileges required."; exit 1; } + + # Parse command-line arguments (multi-flag pass) + # Flags that exit early are handled first; build flags accumulate. + local positional="" + while [[ $# -gt 0 ]]; do + case "$1" in + --list) + f_list_targets + exit 0 + ;; + --list-json) + f_list_targets_json + exit 0 + ;; + --help|-h) + echo "BTC-0.4.0.sh - Cross-Compilation Build Tool Chain" + echo "" + echo "Usage: BTC.sh [TARGET_ID | --native | --list | --list-json]" + echo " BTC.sh --tpm-seal [TARGET_ID]" + echo " BTC.sh --join-cluster=TOKEN [TARGET_ID]" + echo "" + echo " TARGET_ID Build cross-toolchain for the specified target" + echo " --native Auto-probe host silicon and build native toolchain" + echo " --list List all registered cross-compilation targets" + echo " --list-json Emit target registry as JSON" + echo " --tpm-seal Bind forensic signature to TPM PCR state (singular deploys)" + echo " --join-cluster=T Adopt cluster token T for unified identity" + echo "" + echo "Omitting an argument selects --native automatically." + echo "Signature tiers: cluster (joined) > tpm (hardware) > poly (per-machine salt)." + f_list_targets + exit 0 + ;; + --tpm-seal) + BTC_TPM_SEAL=1 + shift + ;; + --join-cluster=*) + export BTC_CLUSTER_JOIN="${1#*=}" + shift + ;; + --native) + positional="--native" + shift + ;; + *) + positional="$1" + shift + ;; + esac + done + + export BTC_TARGET_ID="${positional:-}" + + f_agpl_header + f_silicon_probe + f_set_paths + f_setup + f_download # Acquire all upstream source tarballs (idempotent) + f_sig_init + f_tmux_dashboard + + # Linear Build Execution Sequence + f_binutils + f_kernel_headers + f_gcc_p1 + f_clib # glibc OR musl (depending on target registry) + f_libxcrypt # glibc-only (skipped for musl targets) + f_gcc_p2 + f_kernel_binary + f_package + + # Clear volatile memory cleanrooms + cd / + umount -l "${SOURCES_ACTIVE}" 2>/dev/null || true + echo ">> [COMPLETE] Build Tool Chain Finished Successfully under AGPLv3 Framework." + echo ">> [TARGET] ${BTC_T_ID} (${BTC_T_DESC})" + echo ">> [LABEL] ${SYS_LABEL}" + echo ">> [IMAGE] ${BTC_ARCHIVE}/${SYS_LABEL}-toolchain-golden.tar.xz" +} + +f_main "$@" \ No newline at end of file