#!/bin/bash # Builds a bootable floppy that contains a Linux OS acting as a router set -e +h if [ -z "${SCRIPT_DIR}" ]; then export SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) fi source "${SCRIPT_DIR}/.include.sh" source "${SCRIPT_DIR}/packages.conf" export BUILD_DIR="${SCRIPT_DIR}/build" export SOURCE_DIR="${SCRIPT_DIR}/src" export SYSROOT="${BUILD_DIR}/sysroot" export OUT_FILE="${SCRIPT_DIR}/boot-disk.img" export TARGET="i486-linux-musl" # Default to using as many cores for building software as your system has for "make" export MAKEFLAGS="${MAKEFLAGS:--j$(nproc)}" if [ ! -d "${SYSROOT}/dev" ]; then log "Creating basic directories and symlinks in target" test -d "${SYSROOT}" || mkdir -p "${SYSROOT}" || fail create target directory "${SYSROOT}" for DIR in /dev /proc /run /sys /usr/bin /usr/sbin /var/lib/misc /etc; do test -d "${SYSROOT}${DIR}" || mkdir -p "${SYSROOT}${DIR}" || fail create basic directory "${DIR}" in target done test -e "${SYSROOT}/var/run" || ln -s ../run "${SYSROOT}/var/run" || fail create basic symlink /var/run test -e "${SYSROOT}/bin" || ln -s usr/bin "${SYSROOT}/bin" || fail create basic symlink /bin test -e "${SYSROOT}/sbin" || ln -s usr/sbin "${SYSROOT}/sbin" || fail create basic symlink /sbin fi if [ ! -e "${SYSROOT}/dev/console" ]; then log "Creating basic device nodes" test -e "${SYSROOT}/dev/console" || \ $SUDO mknod -m 640 "${SYSROOT}/dev/console" c 5 1 || fail create console node test -e "${SYSROOT}/dev/null" || \ $SUDO mknod -m 664 "${SYSROOT}/dev/null" c 1 3 || fail create null node fi if [ ! -d "${BUILD_DIR}/musl-cross-toolchain" ]; then log "Build musl-cross-make toolchain" get_pkg_src "musl_cross_make" cd "${SOURCE_DIR}/musl-cross-make-${MUSL_CROSS_MAKE_VERSION}" echo "TARGET = ${TARGET}" > config.mak echo "OUTPUT = ${BUILD_DIR}/musl-cross-toolchain" >> config.mak make >/dev/null || fail build musl-cross-make toolchain make install >/dev/null || fail install musl-cross-make toolchain fi export PATH="$PATH:${BUILD_DIR}/musl-cross-toolchain/bin" if [ ! -e "${SYSROOT}/bin/busybox" ]; then log "Build BusyBox binary" get_pkg_src "busybox" if [ ! -e "${SOURCE_DIR}/busybox-${BUSYBOX_VERSION}/.config" ]; then cd "${SOURCE_DIR}/busybox-${BUSYBOX_VERSION}" cp "${SCRIPT_DIR}/configs/busybox.config" ".config" || fail copy BusyBox configuration sed "s#%%COMPPREFIX%%#${TARGET}-#" -i ".config" || fail Modify BusyBox compiler prefix sed "s#%%TARGET_DIR%%#${SYSROOT}#" -i ".config" || fail Modify BusyBox target directory fi make >/dev/null || fail build BusyBox make install >/dev/null || fail install BusyBox fi if [ ! -e "${SYSROOT}/usr/sbin/wg" ]; then log "Build Wireguard Tools" get_pkg_src "wireguard_tools" cd "${SOURCE_DIR}/wireguard-tools-${WIREGUARD_TOOLS_VERSION}/src" CC="${TARGET}-gcc" LD="${TARGET}-ld" CFLAGS="--static -static" LDFLAGS="-static" \ make >/dev/null || fail build Wireguard Tools "${TARGET}-strip" wg || fail strip Wireguard binary test -d "${SYSROOT}/usr/sbin" || mkdir -p "${SYSROOT}/usr/sbin" || fail create /usr/sbin in target cp wg "${SYSROOT}/usr/sbin/wg" || fail copy Wireguard binary to target fi if [ ! -e "${SYSROOT}/usr/sbin/iptables" ]; then log "Build IPtables" get_pkg_src iptables # When building IPtables statically, it includes all known extensions into the final binary # We only need a few of them, so here we copy only the necessary extensions into the source tree cd "${SOURCE_DIR}/iptables-${IPTABLES_VERSION}" test -d "extensions.orig" || mv "extensions" "extensions.orig" || fail move IPtables extensions directory test -d "extensions" || mkdir "extensions" || fail create new IPtables extensions directory while read -r FILE; do cp "extensions.orig/${FILE}" "extensions/" || fail copy IPtables extension file "${FILE}" done < "${SCRIPT_DIR}/configs/iptables-extension-files" builddir "iptables" CFLAGS="--static -static" LDFLAGS="-static" \ "${SOURCE_DIR}/iptables-${IPTABLES_VERSION}/configure" \ --prefix= \ --disable-nftables \ --disable-devel \ --disable-ipv6 \ --disable-largefile \ --enable-static \ --disable-shared \ --host="${TARGET}" >/dev/null || fail configure IPtables make >/dev/null || fail build IPtables make install DESTDIR="${BUILD_DIR}/iptables-install" >/dev/null || fail temporarily install IPtables "${TARGET}-strip" "${BUILD_DIR}/iptables-install/sbin/xtables-legacy-multi" || fail strip IPtables binary cp -a "${BUILD_DIR}/iptables-install/sbin/." "${SYSROOT}/usr/sbin" || fail copy IPtables binary to target fi if [ -d "${SCRIPT_DIR}/initramfs-source" ]; then log "Copying base files into target" cp -a "${SCRIPT_DIR}/initramfs-source/." "${SYSROOT}/" || fail copy initramfs base files into target fi log "Building Linux kernel" get_pkg_src "linux" cd "${SOURCE_DIR}/linux-${LINUX_VERSION}" if [ ! -e "${SOURCE_DIR}/linux-${LINUX_VERSION}/.config" ]; then cp "${SCRIPT_DIR}/configs/linux.config" ".config" || fail copy Linux configuration sed "s#%%INITRAMFS_SOURCE%%#${SYSROOT}#" -i ".config" || fail Modify Linux initramfs file source sed "s#%%BUILDER_UID%%#$(id -u)#" -i ".config" || fail Modify Linux building user ID sed "s#%%BUILDER_GID%%#$(id -g)#" -i ".config" || fail Modify Linux building user group ID fi make bzImage >/dev/null || fail build Linux kernel KERNEL_SIZE="$(stat -c "%s" "arch/x86/boot/bzImage")" if (( KERNEL_SIZE + 512 > 1024 * 1440 )); then fail "check kernel size, $(( 1024 * 1440 - 512 - KERNEL_SIZE )) bytes over" else log "Kernel size valid" fi log "Create bootable floppy image" get_pkg_src "tiny_floppy_bootloader" cp "${SCRIPT_DIR}/configs/tfb-build.sh" "${SOURCE_DIR}/tiny-floppy-bootloader-${TINY_FLOPPY_BOOTLOADER_VERSION}/" bash "${SOURCE_DIR}/tiny-floppy-bootloader-${TINY_FLOPPY_BOOTLOADER_VERSION}/tfb-build.sh" \ "${SOURCE_DIR}/linux-${LINUX_VERSION}/arch/x86/boot/bzImage" \ "${OUT_FILE}" log "Done! Your floppy image is at ${OUT_FILE}" log "To try it, run 'sudo bash run-qemu.sh $(basename "${OUT_FILE}")'"