#!/bin/sh
# =====================================================
# Armbian Radxa Dragon Q6A Custom Kernel Build Script
# RT + Low-latency config optimized for network router
# =====================================================
#
# Changes from original:
#   - Re-enabled PRINTK, BPF, KEYS, SECURITY, SECCOMP, COMPACTION
#     (required for a functional Armbian system)
#   - Removed x86-only configs (RETPOLINE, PTI, INTEL_IDLE)
#   - Added network router optimizations (nftables, conntrack, scheduling)
#   - Disabled all power management (actively cooled system)
#   - Added kernel boot parameters for RT + router tuning
#

set -e
export HOME_DIR="$HOME"
export BUILD_DIR="$HOME_DIR/armbian-build"
export BOARD="radxa-dragon-q6a"
export BRANCH="edge"
export USE_CCACHE="yes"

export NEEDRESTART_MODE=l
export DEBIAN_FRONTEND=noninteractive
apt-get purge needrestart -y

# ------------------------------
# 1. Install prerequisites
# ------------------------------
sudo apt update
sudo apt install -y git build-essential bc bison flex libssl-dev \
  libncurses-dev libelf-dev dwarves ccache wget rsync

# ------------------------------
# 2. Prepare build environment
# ------------------------------
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"

# ------------------------------
# 3. Clone Armbian build system
# ------------------------------
if [ ! -d "$BUILD_DIR/build" ]; then
    git clone https://github.com/armbian/build.git "$BUILD_DIR/build"
fi
cd "$BUILD_DIR/build"
git pull

# ------------------------------
# 4. Create custom kernel config
# ------------------------------
USERPATCH_DIR="userpatches"
mkdir -p "$USERPATCH_DIR"

BOARD_FAMILY=qcs6490
CONFIG_DEST="$USERPATCH_DIR/linux-${BOARD_FAMILY}-${BRANCH}.config"

cat << 'EOF' > "$CONFIG_DEST"
# ===========================================================
# RT Low-Latency Kernel Config — Network Router Profile
# PREEMPT_RT, reduced debug, safe optimizations for ARM64
# ===========================================================

# -----------------------------------------------------------
# RT / Preemption / Scheduling
# -----------------------------------------------------------
CONFIG_PREEMPT_RT=y
CONFIG_PREEMPT=y
#CONFIG_LOCALVERSION="-rt"
CONFIG_HZ_1000=y
CONFIG_NO_HZ_FULL=y
CONFIG_HIGH_RES_TIMERS=y

# RCU offloading — moves RCU callbacks off isolated cores
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_PRIORITY=1

# CPU isolation support (use isolcpus= boot param to activate)
CONFIG_CPU_ISOLATION=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_GENERIC_IRQ_MIGRATION=y

# -----------------------------------------------------------
# Network Stack — Router Optimizations
# -----------------------------------------------------------
# Core networking performance
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_XPS=y
CONFIG_RPS=y
CONFIG_BQL=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y

# Netfilter / nftables (required for routing/firewall)
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_NAT=y
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_NAT=y
CONFIG_NFT_MASQ=y
CONFIG_NFT_CT=y
CONFIG_NFT_COUNTER=y
CONFIG_NFT_LOG=y
CONFIG_NFT_LIMIT=y
CONFIG_NFT_REJECT=y
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_TFTP=m

# Traffic shaping / QoS
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_FQ_CODEL=y
CONFIG_NET_SCH_CAKE=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_MIRRED=y
CONFIG_NET_ACT_GACT=y

# VLAN, bridging, bonding
CONFIG_VLAN_8021Q=y
CONFIG_BRIDGE=y
CONFIG_BONDING=m

# TCP optimizations
CONFIG_TCP_CONG_BBR=y
CONFIG_DEFAULT_TCP_CONG="bbr"
CONFIG_TCP_CONG_CUBIC=y

# Modules — must be explicit for header packaging (Module.symvers)
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y

# BPF — required for nftables, tc, systemd cgroups
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_HAVE_BPF_JIT=y
CONFIG_CGROUP_BPF=y

# -----------------------------------------------------------
# Power management — fully disabled (actively cooled system)
# CPU runs at max clock permanently, no idle states
# -----------------------------------------------------------
CONFIG_CPU_IDLE=n
#CONFIG_ARM_PSCI_CPUIDLE=n
CONFIG_CPU_FREQ=n
CONFIG_CPUFREQ_DT=n
CONFIG_ARM_SCMI_CPUFREQ=n
#CONFIG_ARM_QCOM_CPUFREQ_HW=n
CONFIG_ENERGY_MODEL=n
#CONFIG_THERMAL=n
#CONFIG_QCOM_TSENS=n
#CONFIG_QCOM_SPMI_TEMP_ALARM=n
#CONFIG_ARM_SCMI_POWER_DOMAIN=n
#CONFIG_QCOM_RPMPD=n
#CONFIG_QCOM_RPMHPD=n
CONFIG_PM_SLEEP=n
CONFIG_PM_AUTOSLEEP=n
CONFIG_PM_WAKELOCKS=n
CONFIG_SUSPEND=n
CONFIG_HIBERNATION=n

# -----------------------------------------------------------
# Disable debug — safe subset only
# Keep PRINTK (kernel logs are essential for any system)
# -----------------------------------------------------------
CONFIG_PRINTK=y
CONFIG_DYNAMIC_DEBUG=n

CONFIG_DEBUG_KERNEL=n
CONFIG_DEBUG_MISC=n
CONFIG_DEBUG_INFO=n
CONFIG_DEBUG_INFO_DWARF4=n
CONFIG_DEBUG_INFO_DWARF5=n
CONFIG_DEBUG_INFO_BTF=n
CONFIG_DEBUG_INFO_BTF_MODULES=n
CONFIG_GDB_SCRIPTS=n
CONFIG_PROVE_LOCKING=n
CONFIG_LOCKDEP=n
CONFIG_DEBUG_SPINLOCK=n
CONFIG_DEBUG_MUTEXES=n
CONFIG_DEBUG_RWSEMS=n
CONFIG_DEBUG_ATOMIC_SLEEP=n
CONFIG_SCHED_DEBUG=n
CONFIG_SCHEDSTATS=n
CONFIG_GENERIC_IRQ_DEBUGFS=n

# Disable tracers (significant RT overhead)
# Note: TRACING and EVENT_TRACING must stay enabled — BPF_SYSCALL
# depends on event tracing infrastructure in kernel 6.18+.
# Only the actual tracer frontends are disabled; the base infra
# adds negligible overhead when no tracer is active.
CONFIG_FTRACE=n
CONFIG_FUNCTION_TRACER=n
CONFIG_FUNCTION_GRAPH_TRACER=n
CONFIG_IRQSOFF_TRACER=n
CONFIG_PREEMPT_TRACER=n
CONFIG_KPROBES=n
CONFIG_UPROBES=n

# Disable runtime memory debuggers
CONFIG_SLUB_DEBUG=n
CONFIG_PAGE_POISONING=n
CONFIG_DEBUG_PAGEALLOC=n
CONFIG_KASAN=n
CONFIG_KFENCE=n
CONFIG_UBSAN=n

# -----------------------------------------------------------
# Security — keep functional, disable only heavy runtime checks
# -----------------------------------------------------------
# These MUST stay enabled for a working Armbian system
CONFIG_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
CONFIG_AUDIT=n

# -----------------------------------------------------------
# Memory management — safe RT optimizations
# -----------------------------------------------------------
CONFIG_TRANSPARENT_HUGEPAGE=n
CONFIG_KSM=n
CONFIG_ZSWAP=n
CONFIG_COMPACTION=y

# -----------------------------------------------------------
# ARM64 Spectre/Meltdown mitigations
# Disabled for lower latency — acceptable on isolated routers
# behind a firewall, NOT for multi-user/container hosts
# -----------------------------------------------------------
CONFIG_ARM64_SSBD=n
CONFIG_ARM64_SPECTRE_V2=n
CONFIG_HARDEN_BRANCH_PREDICTOR=n
CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=n
CONFIG_ARM64_MTE=n

CONFIG_OF=y
CONFIG_OF_PARTITION
CONFIG_OF_OVERLAY=y
CONFIG_DTC=y
# Note: CONFIG_RETPOLINE, CONFIG_PAGE_TABLE_ISOLATION,
# CONFIG_INTEL_IDLE are x86-only and have been removed.
EOF

echo "[INFO] Custom kernel config created at $CONFIG_DEST"

# ------------------------------
# 5. Boot parameters (apply on target after install)
# ------------------------------
# These go into /boot/armbianEnv.txt on the target system
BOOT_PARAMS_REF="$BUILD_DIR/armbianEnv-rt-router.txt"
cat << 'BOOTEOF' > "$BOOT_PARAMS_REF"
# RT and router-optimized boot parameters
# Add this line to /boot/armbianEnv.txt on the target system
# Adjust isolcpus/nohz_full/rcu_nocbs based on your core layout
# QCS6490 has 8 cores: 0-3 (Cortex-A55) + 4-7 (Cortex-A78)
extraargs=mitigations=off threadirqs nohz_full=2-7 rcu_nocbs=2-7 irqaffinity=0-1 net.core.busy_read=50 net.core.busy_poll=50
BOOTEOF

echo "[INFO] Reference boot params created at $BOOT_PARAMS_REF"
echo "[INFO] Copy extraargs line to /boot/armbianEnv.txt on target after install"

# Auto-restart services on upgrade
sudo mkdir -p /etc/needrestart/conf.d
echo "\$nrconf{restart} = 'a';" | sudo tee /etc/needrestart/conf.d/autorestart.conf > /dev/null

# ------------------------------
# 6. Enable ccache
# ------------------------------
export CCACHE_DIR="$HOME_DIR/.ccache"
mkdir -p "$CCACHE_DIR"
export USE_CCACHE=yes

# ------------------------------
# 7. Build kernel
# ------------------------------
echo "[INFO] Starting custom kernel build..."
./compile.sh kernel \
    BOARD="$BOARD" \
    BRANCH="$BRANCH" \
    RELEASE=trixie \
    KERNEL_BTF=no \
    KERNEL_CONFIGURE=no \
    SKIP_EXTERNAL_MODULES="yes"

# ------------------------------
# 8. Copy resulting .deb packages
# ------------------------------
DEB_OUTPUT="$BUILD_DIR/debs"
mkdir -p "$DEB_OUTPUT"
cp output/debs/linux-image-*.deb "$DEB_OUTPUT/" 2>/dev/null || true
cp output/debs/linux-headers-*.deb "$DEB_OUTPUT/" 2>/dev/null || true
cp output/debs/linux-dtb-*.deb "$DEB_OUTPUT/" 2>/dev/null || true
( cd $DEB_OUTPUT && tar cvf $HOME/rt.tar * )

echo ""
echo "======================================================"
echo "[INFO] Custom Armbian RT kernel build finished!"
echo "======================================================"
echo "Debs:    $DEB_OUTPUT"
echo "CCACHE:  $CCACHE_DIR"
echo ""
echo "Install on target with:"
echo "  sudo dpkg -i $DEB_OUTPUT/linux-*.deb"
echo ""
echo "Then add boot params on target:"
echo "  Edit /boot/armbianEnv.txt and add the extraargs line from:"
echo "  $BOOT_PARAMS_REF"
echo ""
echo "Post-install tuning (run on target):"
echo "  # Increase conntrack table for router use"
echo "  sudo sysctl -w net.netfilter.nf_conntrack_max=262144"
echo "  sudo sysctl -w net.core.netdev_max_backlog=8192"
echo "  sudo sysctl -w net.core.somaxconn=4096"
echo "======================================================"
