A single script to build a minimal live Linux operating system from source code that runs Doom on boot.
./DoomLinux.shThis command will create an iso of DoomLinux which is bootable from USB stick.
- Downloads Linux Kernel 5.4.3 source and compiles it with a minimal configuration
- Downloads Busybox 1.35.0 source and compiles it statically.
- Downloads FBDoom and compiles it statically.
- Creates rootfs for linux kernel.
- Generates grub configuration
- Creates a bootable live Linux iso that runs Doom on boot.
sudo apt install wget make gawk gcc bc bison flex unzip rsync mtools xorriso libelf-dev libssl-dev grub-commonWe need to create some folders for managing the codes
mkdir -p rootfs mkdir -p staging mkdir -p iso/boot- rootfs - It is the root file system of DoomLinux.
rootfs ├── bin (Busybox and fbdoom binaries) ├── dev (All the available devices) ├── mnt (Mount point for temporary external media) ├── proc (Different information of currently running kernel) ├── sys (Directory for virtual filesystem) └── tmp (Directory for temporary files required during runtime) - staging - Here all the source codes are downloaded and compiled.
- iso - It is the folder structure for grub to make a bootable iso. In boot folder we will place grub.cfg
iso └── boot ├── bzImage (Compiled Linux Kernel) ├── grub │ └── grub.cfg (Grub Configuration) ├── rootfs.gz (Compressed root file system) └── System.map (System map that is compiled with kernel) Setting variables to make things easy
KERNEL_VERSION=5.4.3 BUSYBOX_VERSION=1.35.0 SOURCE_DIR=$PWD ROOTFS=$SOURCE_DIR/rootfs STAGING=$SOURCE_DIR/staging ISO_DIR=$SOURCE_DIR/isoWe need to download the required source codes in staging folder and extract them.
- Linux kernel 5.4.3
- Busybox 1.35.0 - For creating minimum shell environment.
- FBDoom - A port of Doom original source code for Linux framebuffer.
- Doom shareware - The shareware version of Doom. You can use other versions if you want.
cd $STAGING wget -nc -O kernel.tar.xz http://kernel.org/pub/linux/kernel/v5.x/linux-${KERNEL_VERSION}.tar.xz wget -nc -O busybox.tar.bz2 http://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2 wget -nc -O fbDOOM-master.zip https://github.com/maximevince/fbDOOM/archive/refs/heads/master.zip wget -nc -O doom1.wad https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad tar -xvf kernel.tar.xz tar -xvf busybox.tar.bz2 unzip fbDOOM-master.zipChange directory to kernel source.
cd $STAGING cd linux-${KERNEL_VERSION}Creating a config file for kernel. You can use either of the following
make -j$(nproc) defconfig # Creates a ".config" file with default options from current architecture make -j$(nproc) menuconfig # Menu-driven user interface for configuring kernel make -j$(nproc) xconfig # GUI based user interface for configuring kernel-j$(nproc) flag sets the number of jobs to the number of CPU cores/threads available. It make things compile faster.
Now we will make a couple of changes in the .config file to make our kernel size smaller. It will also reduce the compile time.
Use xz kernel compression instead of gzip
sed -i "s|.*# CONFIG_KERNEL_XZ is not set.*|CONFIG_KERNEL_XZ=y|" .config sed -i "s|.*CONFIG_KERNEL_GZIP=y.*|# CONFIG_KERNEL_GZIP is not set|" .configDisable sound drivers.
sed -i "s|.*CONFIG_SOUND=y.*|# CONFIG_SOUND is not set|" .configDisable network drivers.
sed -i "s|.*CONFIG_NET=y.*|# CONFIG_NET is not set|" .configDisable EFI stubs.
sed -i "s|.*CONFIG_EFI=y.*|# CONFIG_EFI is not set|" .config sed -i "s|.*CONFIG_EFI_STUB=y.*|# CONFIG_EFI_STUB is not set|" .configDisable kernel debug.
sed -i "s/^CONFIG_DEBUG_KERNEL.*/\\# CONFIG_DEBUG_KERNEL is not set/" .configOptimize for size.
sed -i "s|.*CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y.*|# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set|" .config sed -i "s|.*# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set.*|CONFIG_CC_OPTIMIZE_FOR_SIZE=y|" .configChange host name
sed -i "s|.*CONFIG_DEFAULT_HOSTNAME=*|CONFIG_DEFAULT_HOSTNAME=\"DoomLinux\"|" .configEnable Bochs dispi vga interface for QEMU
sed -i "s|.*# CONFIG_DRM_BOCHS is not set*|CONFIG_DRM_BOCHS=y|" .configNow compile the kernel and copy the binaries.
make -j$(nproc) bzImage cp arch/x86/boot/bzImage $SOURCE_DIR/iso/boot/bzImage cp System.map $SOURCE_DIR/iso/boot/System.mapcd $STAGING cd busybox-${BUSYBOX_VERSION} make defconfig LDFLAGS="--static" make busybox install -j$(nproc) cd _install cp -r ./ $ROOTFS/ cd $ROOTFS rm -f linuxrcThese commands will statically compile busybox. The default installation folder for busybox is _install. We will copy the compiled binaries from there to our rootfs.
cd $STAGING cd fbDOOM-master/fbdoom sed -i "s|CFLAGS+=-ggdb3 -Os|CFLAGS+=-ggdb3 -Os -static|" Makefile sed -i "s|ifneq (\$(NOSDL),1)|ifeq (\$(LINK_SDL),1)|" Makefile make -j$(nproc) cp fbdoom $ROOTFS/bin/fbdoom cp $STAGING/doom1.wad $ROOTFS/bin/doom1.wadWe need to statically compile FBDoom to work it in our system with minimal dependencies. The above commands will do that for us and it will also copy the doom1.wad in our root folder.
We will create additional folders so that Linux kernel can use them on runtime.
cd $ROOTFS mkdir -p dev proc sys mnt tmpNow we will create a init file for our kernel.
echo '#!/bin/sh' > initSuppress all messages from the kernel except panic messages.
echo 'dmesg -n 1' >> initMount dev folder to devtmpfs
echo 'mount -t devtmpfs none /dev' >> initMount proc folder to proc
echo 'mount -t proc none /proc' >> initMount sys folder to sysfs
echo 'mount -t sysfs none /sys' >> initRun doom right after booting the kernel. After that we will run busybox with cttyhack to stop kernel panic if we want to exit busybox. It will open another shell instead.
echo 'fbdoom -iwad /bin/doom1.wad' >> init echo 'setsid cttyhack /bin/sh' >> initWe must have to make the init file executable.
chmod +x initNow archive the rootfs with cpio.
cd $ROOTFS find . | cpio -R root:root -H newc -o | gzip > $SOURCE_DIR/iso/boot/rootfs.gzCreate a grub configuration file in iso/boot directory.
cd $SOURCE_DIR/iso/boot mkdir -p grub cd grub cat > grub.cfg << EOF set default=0 set timeout=30 # Menu Colours set menu_color_normal=white/black set menu_color_highlight=white/green root (hd0,0) menuentry "DoomLinux" { linux /boot/bzImage initrd /boot/rootfs.gz } EOFThese are the location of our compiled kernel and archived rootfs.
linux /boot/bzImage initrd /boot/rootfs.gz Finally create DoomLinux bootable iso
cd $SOURCE_DIR grub-mkrescue --compress=xz -o DoomLinux.iso isoYou can now write the iso in your USB stick and play Doom.
The final iso should be around 20 MB in size depending on the architecture. For my x86_64 CPU the compiled kernel size is 4.1 MB and the iso is 17.9 MB.
Write the iso image on USB stick and boot it from BIOS menu.
To run on QEMU :
qemu-system-x86_64 DoomLinux.isoThis project is made just for those who wants to learn how basic linux systems works. Under no circumstances shall the author be liable for any damage.
Licensed under the MIT License.
