#!/bin/bash # Build linux system and generate ISO # Version: 0.5.0 # (C) Chris Dorman, 2014-2020 - GPLv3+ workdir=`pwd` freondir="/freon" corecount=25 # Common mirror (now self hosted) mainmirror="https://mirror.freonlinux.com/source" # Download mirrors syslinuxmirror="https://www.kernel.org/pub/linux/utils/boot/syslinux" kernelmirror="https://cdn.kernel.org/pub/linux/kernel/v5.x" busyboxmirror="http://busybox.net/downloads" libcmirror="http://ftp.gnu.org/gnu/libc" grubmirror="http://alpha.gnu.org/gnu/grub" xzmirror="https://tukaani.org/xz" dropbearmirror="https://matt.ucc.asn.au/dropbear/releases" zlibmirror="https://zlib.net" # endtag used for iso filename, and some rootfs configs endtag=`date +"%Y%m%d-%H%M"` hostbuild="Debian 10" # Source code filenames kernel="linux-5.9.1.tar.xz" syslinux="syslinux-6.03.tar.gz" busybox="busybox-1.32.0.tar.bz2" libc="glibc-2.28.tar.xz" grub="grub-2.02~rc2.tar.xz" xz="xz-5.2.4.tar.xz" dropbear="dropbear-2019.78.tar.bz2" zlib="zlib-1.2.11.tar.xz" # Source directory names kerneldir=${kernel//.tar.xz} busyboxdir=${busybox//.tar.bz2} syslinuxdir=${syslinux//.tar.gz} libcdir=${libc//.tar.xz} grubdir=${grub//.tar.xz} xzdir=${xz//.tar.xz} dropbearsrcdir=${dropbear//.tar.bz2} zlibsrcdir=${zlib//.tar.xz} # Echo colors NORMAL="\e[0m" RED="\e[0;31m" GREEN="\e[0;32m" BLUE="\e[0;34m" YELLOW="\e[1;33m" MAGENTA="\e[0;35m" CYAN="\e[0;36m" # function to check if errors occurred status() { local CHECK=$? echo -en "\033[68G" if [ $CHECK = 0 ] ; then echo -e "[ \e[0;32mOK\e[0m ]" else echo -e "[ \e[0;31mFAILED\e[0m ]" exit 1 fi } # same as above but doesn't output [ OK ] status_silent() { local CHECK=$? echo -en "\033[68G" if [ $CHECK != 0 ] ; then echo -e "[ \e[0;31mFAILED\e[0m ]" exit 1 fi } if [ "$(id -u)" != "0" ]; then echo -e "[$RED Error $NORMAL] This script needs to be executed by root." exit 1 fi if [ ! -d "src" ]; then echo -e "[$YELLOW Warning $NORMAL] No source directory!" echo -n "Creating source directory..." mkdir src > /dev/null 2>&1 status fi # check to see if source dir exists, if not create if [ ! -d src ]; then mkdir src status_silent fi # if called, print everything instead of hiding. Debugging purposes case $2 in --verbose|-v) verbose=1;; *) verbose=0; esac # Download source code get_files() { cd $workdir/src if [ -d "rootfs" ]; then echo -e "[$YELLOW Warning $NORMAL] Rootfs tree still exists." echo -n "Cleaning build tree..." rm -r rootfs > /dev/null 2>&1 status fi #echo " " # This is used to keep next echo from moving around echo -e "[$YELLOW Working $NORMAL] Downloading needed files..." if [ ! -f $kernel ]; then echo -n "$kernel..." wget $mainmirror/$kernel > /dev/null 2>&1 status fi if [ ! -f $busybox ]; then echo -n "$busybox..." wget $mainmirror/$busybox > /dev/null 2>&1 status fi if [ ! -f $syslinux ]; then echo -n "$syslinux..." wget $mainmirror/$syslinux > /dev/null 2>&1 status fi if [ ! -f $xz ]; then echo -n "$xz..." wget $mainmirror/$xz > /dev/null 2>&1 status fi if [ ! -f $libc ]; then echo -n "$libc..." wget $mainmirror/$libc > /dev/null 2>&1 status fi if [ ! -f $grub ]; then echo -n "$grub..." wget $mainmirror/$grub > /dev/null 2>&1 status fi } # Build linux kernel do_kernel() { cd $workdir/src echo -e "[$YELLOW Working $NORMAL] Configuring & building Linux kernel" if [ ! -d $kerneldir ]; then echo -n "Unpacking..." tar xf $kernel > /dev/null 2>&1 status fi echo -n "Configuring..." cd $kerneldir cp ../../files/$kerneldir.conf .config status echo -n "Building kernel base..." if [ "$verbose" == "1" ]; then make bzImage -j$corecount status else make bzImage -j$corecount > /dev/null 2>&1 status fi #echo -n "Building kernel modules..." #if [ "$verbose" == "1" ]; then # make modules -j20 # status #else # make modules -j20 > /dev/null 2>&1 # status #fi #echo -n "Installing kernel modules..." #make INSTALL_MOD_PATH=`pwd`/_pkg modules_install > /dev/null 2>&1 #status echo -n "Installing kernel headers..." make INSTALL_HDR_PATH=`pwd`/_hdr headers_install > /dev/null 2>&1 status cd .. } # Build busybox do_base() { echo -e "[$YELLOW Working $NORMAL] Configuring & building system utilities" cd $workdir/src if [ ! -d $busyboxdir ]; then echo -n "Unpacking..." tar xf $busybox > /dev/null 2>&1 status fi echo -n "Configuring..." cd $busyboxdir cp ../../files/$busyboxdir.conf .config status_silent make oldconfig > /dev/null 2>&1 status echo -n "Building..." if [ "$verbose" == "1" ]; then make -j$corecount status else make -j$corecount > /dev/null 2>&1 status fi if [ "$verbose" == "1" ]; then make install status else make install > /dev/null 2>&1 status fi echo -n "Finishing up..." chmod 4755 _install/bin/busybox cp -a _install/* /freon status cd $workdir cd system/ii make -j$corecount; make install status_silent cd ../chttpd cp inc/chttpd ../../rootfs/etc/init.d/chttpd make -j$corecount; make install status_silent cd ../sic make -j$corecount; make install status_silent cd $workdir } # Build system wide dependencies do_libc() { echo -e "[$YELLOW Working $NORMAL] Configuring & building libc" cd $workdir/src if [ ! -d $libcdir ]; then echo "Unpacking..." tar xf $libc > /dev/null 2>&1 status fi if [ ! -d rootfs ]; then mkdir rootfs cd rootfs/ echo -n "Laying out filesystem tree..." mkdir -p dev root etc home proc media mnt sys tmp var mkdir -p usr/{lib,local,share,games} \ var/{cache,lib,lock,log,games,run,spool,www} \ media/{cdrom,flash,usbdisk} \ etc/{init.d,conf.d} cd .. fi if [ ! -d $libcdir-build ]; then mkdir $libcdir-build fi if [ ! -d /freon/lib ]; then mkdir /freon/lib fi cd $libcdir-build echo -n "Configuring..." if [ "$verbose" == "1" ]; then `pwd`/../$libcdir/configure \ --prefix=$freondir \ --build=$MACHTYPE \ --host=x86_64-linux \ --target=x86_64-linux --with-headers=_hdr/include status else `pwd`/../$libcdir/configure \ --prefix=/freon \ --build=$MACHTYPE \ --host=x86_64-linux \ --target=x86_64-linux > /dev/null 2>&1 --with-headers=_hdr/include > /dev/null 2>&1 status fi echo -n "Building..." if [ "$verbose" == "1" ]; then make install-bootstrap-headers=yes install-headers status make -j$corecount csu/subdir_lib status install csu/crt1.o csu/crti.o csu/crtn.o /freon/lib status gcc \ -nostdlib \ -nostartfiles -shared -x c /dev/null -o $freondir/lib/libc.so status make -j$corecount status else make install-bootstrap-headers=yes install-headers > /dev/null 2>&1 status_silent make -j$corecount csu/subdir_lib > /dev/null 2>&1 status_silent install csu/crt1.o csu/crti.o csu/crtn.o $freondir/lib > /dev/null 2>&1 status_silent gcc \ -nostdlib \ -nostartfiles -shared -x c /dev/null -o $freondir/lib/libc.so 2>&1 status_silent make -j$corecount > /dev/null 2>&1 status fi echo -n "Copying to rootfs..." if [ "$verbose" == "1" ]; then make install status else make install > /dev/null 2>&1 status fi echo -n "Cleaning files..." #strip -v lib/* > /dev/null 2>&1 mkdir $workdir/src/rootfs/lib64 cd $workdir/src/rootfs/lib64 ln -s $freondir/lib/ld-2.28.so ld-linux-x86-64.so.2 status cd $freondir if [ ! -d "lib64" ]; then mkdir lib64 fi cd lib64 ln -s $freondir/lib/ld-2.28.so ld-linux-x86-64.so.2 cd $workdir } # Build grub legacy bootloader and install do_grub() { echo -e "[$YELLOW Working $NORMAL] Configuring & building bootloader" cd $workdir/src echo -n "Extracting..." if [ ! -d "$xzdir" ]; then tar xf $xz > /dev/null 2>&1 status_silent fi if [ ! -d "$grubdir" ]; then tar xf $grub > /dev/null 2>&1 status fi cd $grubdir echo -n "Configuring..." ./configure --prefix=`pwd`/../rootfs \ --disable-efiemu \ --disable-werror > /dev/null 2>&1 status_silent cd ../$xzdir ./configure --prefix=`pwd`/../rootfs \ --disable-static > /dev/null 2>&1 status cd ../$grubdir echo -n "Compiling..." make -j$corecount > /dev/null 2>&1 status_silent cd ../$xzdir make -j$corecount > /dev/null 2>&1 status cd ../$grubdir echo -n "Copying to rootfs..." make install > /dev/null 2>&1 status_silent cd ../$xzdir make install > /dev/null 2>&1 status cd ../$grubdir echo -n "Installing patched grub-mkconfig..." rm ../rootfs/sbin/grub-mkconfig > /dev/null 2>&1 status_silent cp ../../files/sbin/grub-mkconfig ../rootfs/sbin > /dev/null 2>&1 status cd ../rootfs #echo -n "Stripping grub..." #strip -s rootfs/bin/grub-* > /dev/null 2>&1 #strip -s rootfs/sbin/grub-* > /dev/null 2>&1 cd .. #status } # Install Freon utilities do_utilities() { echo -e "[$YELLOW Working $NORMAL] Installing Freon utilities" echo -n "Copying files..." cd $workdir/src cp -a ../files/bin/* rootfs/bin status } # Configure rootfs for live boot configure_system() { echo -e "[$YELLOW Working $NORMAL] Configuring root filesystem" echo -n "Linking init..." cd $workdir/src/rootfs if [ -f linuxrc ]; then rm linuxrc fi if [ ! -f init ]; then ln -s $freondir/bin/busybox init fi status echo -n "Filling /dev..." cp ../../files/bin/mkdevs $freondir/bin/mkdevs $freondir/bin/mkdevs dev > /dev/null 2>&1 status echo -n "Configuring networking..." echo "127.0.0.1 localhost" > etc/hosts echo "localhost 127.0.0.1" > etc/networks echo "linux" > etc/hostname echo "order hosts,bind" > etc/host.conf echo "multi on" >> etc/host.conf mkdir etc/network mkdir etc/network/if-up.d mkdir etc/network/if-down.d mkdir etc/network/if-pre-up.d mkdir etc/network/if-post-down.d echo "# loopback auto lo iface lo inet loopback # Ethernet // this is default and can be changed for per system auto eth0 iface eth0 inet dhcp " > etc/network/interfaces echo " # /etc/nsswitch.conf: GNU Name Service Switch config. # passwd: files group: files shadow: files hosts: files dns networks: files " > etc/nsswitch.conf status echo -n "Setting up default users and groups..." echo "root:x:0:0:root:/root:/bin/sh" > etc/passwd echo "root::13525:0:99999:7:::" > etc/shadow echo "root:x:0:" > etc/group echo "root:*::" > etc/gshadow chmod 640 etc/shadow chmod 640 etc/gshadow status #echo -n "Copying kernel modules..." #cp -a ../$kerneldir/_pkg/* . #status #echo -n "Copying kernel headers..." #cp -a ../$kerneldir/_hdr/* . #status echo -n "Compiling termtypes for core terminfo...." tic -o ./usr/share/terminfo ../../files/terminfo/termtypes > /dev/null 2>&1 status echo -n "Finishing up..." echo "# /etc/securetty: List of terminals on which root is allowed to login. # console # For people with serial port consoles ttyS0 # Standard consoles tty1 tty2 tty3 tty4 tty5 tty6 tty7" > etc/securetty echo "/bin/sh" > etc/shells echo "/bin/ash" >> etc/shells echo "Freon Linux $endtag \r \l" > etc/issue echo "" >> etc/issue echo "Welcome to _________ ___ ____/________________________ __ /_ __ ___/ _ \\ __ \\_ __ \\ _ __/ _ / / __/ /_/ / / / / /_/ /_/ \\___/\\____//_/ /_/ Compiled $endtag using $hostbuild" > etc/motd echo "[SUID] # Allow command to be run by anyone. su = ssx root.root passwd = ssx root.root loadkmap = ssx root.root mount = ssx root.root reboot = ssx root.root halt = ssx root.root" > etc/busybox.conf chmod 600 etc/busybox.conf echo "::sysinit:/etc/init.d/rc.init ::respawn:-/bin/sh tty2::askfirst:-/bin/sh ::ctrlaltdel:/bin/umount -a -r ::ctrlaltdel:/sbin/reboot" > etc/inittab echo "# /etc/profile: system-wide .profile file for the Bourne shells PATH=\"/freon/bin:/freon/sbin:/freon/usr/bin:/freon/usr/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/usr/local/sbin\" LD_LIBRARY_PATH=\"/freon/lib:/freon/lib64:/freon/usr/lib:/lib64:/usr/lib:/lib:/usr/local/lib\" TERM=\"xterm\" TERMINFO=\"/share/terminfo\" NORMAL=\"\\[\\e[0m\\]\" RED=\"\\[\\e[0;31m\\]\" GREEN=\"\\[\\e[0;32m\\]\" BLUE=\"\\[\\e[0;34m\\]\" YELLOW=\"\\[\\e[1;33m\\]\" MAGENTA=\"\\[\\e[0;35m\\]\" CYAN=\"\\[\\e[0;36m\\]\" if [ \"\`id -u\`\" -eq 0 ]; then PS1=\"$RED\\u$GREEN@$BLUE\\h [ $MAGENTA\\w$BLUE ]# \$NORMAL\" else PS1=\"$RED\\u$GREEN@$BLUE\\h [ $MAGENTA\\w$BLUE ]\\\$ \$NORMAL\" fi export PATH LD_LIBRARY_PATH PS1 DISPLAY ignoreeof umask 022 export G_FILENAME_ENCODING=iso8859-1 " > etc/profile echo "proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts defaults 0 0 tmpfs /dev/shm tmpfs defaults 0 0" > etc/fstab cp -a $workdir/files/etc/* etc cd share mkdir kmap cp -a $workdir/files/share/* . status_silent chmod +x udhcpc/default.script status_silent cd ../usr/share ln -s /share/udhcpc udhcpc cd ../.. # mkdir x86_64-linux-gnu # cd x86_64-linux-gnu # ln -s ../libm-2.22.so libm.so.6 # ln -s ../libc-2.22.so libc.so.6 status cd $workdir } # generate initramfs for live boot. gen_rootfs() { echo -e "[$YELLOW Working $NORMAL] Generating filesystem..." cd $workdir/src/rootfs cp -a $freondir . cd bin for f in /freon/bin/*; do ln -s $f . done cd ../sbin for f in /freon/sbin/*; do ln -s $f . done cd ../lib for l in /freon/lib/*.so; do ln -nsf $l . done for l in /freon/lib/*.so*; do ln -nsf $l . done for l in /freon/lib/*.o; do ln -nsf $l . done cd .. echo -n "Stripping build..." strip -s freon/lib/*.so > /dev/null 2>&1 strip -s freon/lib/*.so* > /dev/null 2>&1 strip -s freon/bin/busybox > /dev/null 2>&1 strip -s freon/sbin/chttpd > /dev/null 2>&1 rm freon/lib/*.a rm lib/*.a # In base-dev package rm usr/lib/*.a echo "#!/bin/sh exec /freon/bin/sh \$*" > bin/bash chmod +x bin/bash echo -n "Compressing filesystem..." find . -print | cpio -o -H newc | gzip -9 > ../rootfs.gz 2>&1 status cd $workdir } regen_rootfs_bare() { echo -e "[$YELLOW Working $NORMAL] Generating filesystem..." cd $workdir/src/rootfs cp -a $freondir . echo -n "Compressing filesystem..." find . -print | cpio -o -H newc | gzip -9 > ../rootfs.gz 2>&1 status cd $workdir } # setup bootloader for iso do_isolinux() { echo -e "[$YELLOW Working $NORMAL] Setting up bootloader." cd $workdir/src/ if [ ! -d $syslinuxdir ]; then echo -n "Unpacking $syslinuxdir..." tar -xzf $syslinux > /dev/null 2>&1 status fi if [ ! -d cdroot ]; then mkdir cdroot mkdir cdroot/boot fi cd $syslinuxdir echo -n "Copying isolinux files to iso..." cp bios/core/isolinux.bin ../cdroot cp bios/com32/elflink/ldlinux/ldlinux.c32 ../cdroot status echo -n "Generating isolinux config..." echo "Freon Linux $endtag Press to boot" > ../cdroot/display.txt echo "display display.txt default Freon label Freon kernel /boot/bzImage append initrd=/boot/rootfs.gz rw root=/dev/null vga=788 implicit 0 prompt 1 timeout 5" > ../cdroot/isolinux.cfg status cd $workdir } # generate complete iso ready for boot gen_iso() { echo -e -n "[$YELLOW Working $NORMAL] Generating bootable ISO image." cd $workdir/src cp rootfs.gz cdroot/boot cp $kerneldir/arch/x86/boot/bzImage cdroot/boot/bzImage genisoimage -R -o ../freon-$endtag.iso -b isolinux.bin \ -c boot.cat -no-emul-boot -boot-load-size 4 \ -V "Freon Linux" -input-charset iso8859-1 -boot-info-table cdroot > /dev/null 2>&1 status } do_refer() { echo -e "[$YELLOW Working $NORMAL] Reconfiguring root filesystem" cd $workdir/src/rootfs rm etc/init.d/* rm etc/conf.d/* cp -av ../../files/etc/* etc/ # Copy files/etc to filesystem (init scripts) cp -av ../../files/bin/* bin/ # Copy installer and package manager cp -av ../../files/share/* share/ # Stuffs cd $workdir } do_dropbear() { cd $workdir/src # Downloading dropbear source if [ ! -f "$dropbear" ]; then echo "Downloading Dropbear sources..." wget $dropbearmirror/$dropbear tar -xf $dropbear fi # Configure dropbear cd $dropbearsrcdir cp -v options.h options.h.backup sed -e "s@/dev/random@/dev/urandom@" options.h.backup > options.h ./configure --prefix=$workdir/src/rootfs # Compile make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" MULTI=1 make MULTI=1 PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install mkdir -pv $workdir/src/rootfs/etc/dropbear rm $workdir/src/rootfs/sbin/dropbear rm $workdir/src/rootfs/bin/{dropbearconvert,dropbearkey,scp,dbclient} cd $workdir/src/rootfs/bin ln -svf dropbearmulti dropbear ln -svf dropbearmulti dbclient ln -svf dropbearmulti dropbearkey ln -svf dropbearmulti dropbearconvert ln -svf dropbearmulti scp cd $workdir } do_zlib() { cd $workdir/src # Downloading zlib source if [ ! -f "$zlib" ]; then echo "Downloading zlib sources..." wget $zlibmirror/$zlib tar -xf $zlib fi # Confingure cd $zlibsrcdir ./configure --prefix=$freondir # Compile make -j$corecount make install # mv -v ../../src/rootfs/usr/lib/libz.so.* ../../src/rootfs/lib # ln -sfv ../../src/rootfs/lib/libz.so ../../src/rootfs/usr/lib/libz.so cd $workdir } case $1 in rootfs) get_files; do_libc; do_base; do_grub; do_zlib; do_dropbear; do_kernel; configure_system; do_utilities;; refer) do_refer; regen_rootfs_bare; do_isolinux; gen_iso;; full) get_files; do_libc; do_base; do_grub; do_zlib; do_dropbear; do_kernel; configure_system; do_utilities; gen_rootfs; do_isolinux; gen_iso;; *) echo "Unknown argument: ./build-freon [full|refer|rootfs]";; esac