DoomLinux
A single script to build a minimal live Linux operating system from source code that runs Doom on boot.
1
./DoomLinux.sh
This command will create a bootable iso of DoomLinux which is bootable from USB stick.
What it does
- 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.
Build Dependencies
1
sudo apt install wget make gawk gcc bc bison flex xorriso libelf-dev libssl-dev grub-common
Explanation
Creating folders and downloading the source codes
We need to create some folders for managing the codes
1
2
3
mkdir -p rootfs
mkdir -p staging
mkdir -p iso/boot
- rootfs - It is the root file system of DoomLinux.
1 2 3 4 5 6 7
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
1 2 3 4 5 6 7
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 ```bash 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/iso
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
We 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.
```bash
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.zip
Configuring the kernel and compile it
Change directory to kernel source.
1
2
cd $STAGING
cd linux-${KERNEL_VERSION}
Creating a config file for kernel. You can use either of the following
1
2
3
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
1
2
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|" .config
Disable sound drivers.
1
sed -i "s|.*CONFIG_SOUND=y.*|# CONFIG_SOUND is not set|" .config
Disable network drivers.
1
sed -i "s|.*CONFIG_NET=y.*|# CONFIG_NET is not set|" .config
Disable EFI stubs.
1
2
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|" .config
Disable kernel debug.
1
sed -i "s/^CONFIG_DEBUG_KERNEL.*/\\# CONFIG_DEBUG_KERNEL is not set/" .config
Optimize for size.
1
2
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|" .config
Change host name
1
sed -i "s|.*CONFIG_DEFAULT_HOSTNAME=*|CONFIG_DEFAULT_HOSTNAME=\"DoomLinux\"|" .config
Now compile the kernel and copy the binaries.
1
2
3
make -j$(nproc) bzImage
cp arch/x86/boot/bzImage $SOURCE_DIR/iso/boot/bzImage
cp System.map $SOURCE_DIR/iso/boot/System.map
Configuring busybox and compile it
1
2
3
4
5
6
7
8
9
cd $STAGING
cd busybox-${BUSYBOX_VERSION}
make defconfig
sed -i "s|.*CONFIG_STATIC.*|CONFIG_STATIC=y|" .config
make -j$(nproc) busybox install
cd _install
cp -r ./ $ROOTFS/
cd $ROOTFS
rm -f linuxrc
These commands will statically compile busybox. The default installation folder for busybox is _install. We will copy the compiled binaries from there to our rootfs.
Compile FBDoom statically
1
2
3
4
5
6
cd $STAGING
cd fbDOOM-master/fbdoom
sed -i "s|CFLAGS+=-ggdb3 -Os|CFLAGS+=-ggdb3 -Os -static|" Makefile
make -j$(nproc)
cp fbdoom $ROOTFS/bin/fbdoom
cp $STAGING/doom1.wad $ROOTFS/bin/doom1.wad
We 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.
Archive rootfs
We will create additional folders so that Linux kernel can use them on runtime.
1
2
cd $ROOTFS
mkdir -p dev proc sys mnt tmp
Now we will create a init file for our kernel.
1
echo '#!/bin/sh' > init
Suppress all messages from the kernel except panic messages.
1
echo 'dmesg -n 1' >> init
Mount dev folder to devtmpfs
1
echo 'mount -t devtmpfs none /dev' >> init
Mount proc folder to proc
1
echo 'mount -t proc none /proc' >> init
Mount sys folder to sysfs
1
echo 'mount -t sysfs none /sys' >> init
Run 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.
1
2
echo 'fbdoom -iwad /bin/doom1.wad' >> init
echo 'setsid cttyhack /bin/sh' >> init
We must have to make the init file executable.
1
chmod +x init
Now archive the rootfs with cpio.
1
2
cd $ROOTFS
find . | cpio -R root:root -H newc -o | gzip > $SOURCE_DIR/iso/boot/rootfs.gz
Using GRUB bootloader to boot DoomLinux
Create a grub configuration file in iso/boot directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
}
EOF
These are the location of our compiled kernel and archived rootfs.
1
2
linux /boot/bzImage
initrd /boot/rootfs.gz
Finally create DoomLinux bootable iso
1
2
cd $SOURCE_DIR
grub-mkrescue --compress=xz -o DoomLinux.iso iso