Table of Contents

1. Linux Speedrun

I was able to build and boot this linux+busybox operating system in less than 15 minutes during presentation at work. The build was done in a podman container, and the kernel and rootfile system was booted in qemu outside the container. Based on the guide by chrisdone[0].

2. Run Fedora and install dependencies

We are going to use:

  • gcc — the compiler
  • make — the kernel's build system
  • bc — an arbitrary precision calculator language
  • flex — lexical analyser generator
  • bison — a parser generator
  • cmp — compare two files byte by byte
  • ncurses-devel — for menuconfig
  • cpio — for creating initramfs archive
  • elfutils-devel — for gelf.h headers
  • glibc-static — for building static busybox
  • git — to fetch sources.
ejo@fedora ~/r/t/einix> podman run -it fedora:latest /bin/bash
[root@2d1eb21fc48e linux]# dnf install gcc make flex bison bc cmp ncurses-devel cpio elfutils-devel glibc-static git

3. Download and build the kernel

Find the latest tag and shallow clone it. At the time of writing the latest release tag is v7.2

[root@2d1eb21fc48e /]# git ls-remote --tags https://github.com/torvalds/linux
[root@2d1eb21fc48e /]# git clone --branch=v7.2 --depth=1 https://github.com/torvalds/linux

Now configure the kernel by saying no to everything and build it using make, i use -j 14 because I have 14 CPU cores.

[root@2d1eb21fc48e /]# make allnoconfig # This generates the kernel config in the .config file
[root@2d1eb21fc48e /]# make -j14

Configure the follwoing using make menuconfig

[root@2d1eb21fc48e /]# make menuconfig

64-bit kernel ---> yes
General setup ---> Initial RAM filesystem and RAM disk (initramfs/initrd) support ---> yes
General setup ---> Configure standard kernel features ---> Enable support for printk ---> yes
Executable file formats / Emulations ---> Kernel support for ELF binaries ---> yes
Executable file formats / Emulations ---> Kernel support for scripts starting with #! ---> yes
Device Drivers ---> Generic Driver Options ---> Maintain a devtmpfs filesystem to mount at /dev ---> yes
Device Drivers ---> Generic Driver Options ---> Automount devtmpfs at /dev, after the kernel mounted the rootfs ---> yes
Device Drivers ---> Character devices ---> Enable TTY ---> yes
Device Drivers ---> Character devices ---> Serial drivers ---> 8250/16550 and compatible serial support ---> yes
Device Drivers ---> Character devices ---> Serial drivers ---> Console on 8250/16550 and compatible serial port ---> yes
File systems ---> Pseudo filesystems ---> /proc file system support ---> yes
File systems ---> Pseudo filesystems ---> sysfs file system support ---> yes

Build the kernel

[root@2d1eb21fc48e /]# make -j14
...
BUILD   arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready  (#2)

4. Build busybox core utils

Use menuconfig to enable static binary (no shared libs) and disable networking, network builds currently fail on newer versions of the Linux kernel. We want to build busybox as a static binary because then we avoid having to install any libraries, we can simply install the busybox binary as the root file system.

[root@2d1eb21fc48e /]# cd ..
[root@2d1eb21fc48e /]# git clone --depth=1 https://git.busybox.net/busybox 
[root@2d1eb21fc48e /]# cd busybox
[root@2d1eb21fc48e busybox]# make defconfig
[root@2d1eb21fc48e busybox]# make menuconfig

Build and install busybox

make -j14
make install

5. Create initial ramdisk root file system

[root@fc656f269d02 busybox]# cd ..
[root@fc656f269d02 /]# mkdir initramfs
[root@fc656f269d02 /]# cd initramfs/
[root@fc656f269d02 initramfs]# cp -r ../busybox/_install/* ./
[root@fc656f269d02 initramfs]# mkdir -p proc sys

Create init file using vi (paste the following into the file)

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys

cat <<!


Boot took $(cut -d' ' -f1 /proc/uptime) seconds

▓ ▄▄██   ██▓  █▄ ▄        ██▓ ▓▄▄   ▄▄▒
▓█   ▀  ▓▐█▒  ██ ▀█   █  ▓▐█▒ ▒▒ ▀ ▀ ▒░
▒█ █    ▒ █▒ ▓██  ▀█ ██▒ ▒ █▒ ░░      ░
▒▓█  ▄  ░▐ ░ ▓██▒  ▐ ██▒ ░▐ ░  ░ ▄ ▄ ▒
░▒████▒ ░▐█░ ▒██░   ▓██░ ░▐█░ ▓▀▀▒ ▒▀▀▒
░░ ▒░ ░ ░▓   ░ ▒░   ▒ ▓  ░▓   ▒▒ ░ ░▓ ░
 ░ ░  ░  ▒ ░ ░ ░░   ░ ▒░  ▒ ░ ░░   ░▒ ░
   ░     ▒ ░    ░   ░ ░   ▒ ░  ░    ░
   ░  ░  ░            ░   ░    ░    ░


Welcome to EINIX


!
exec /bin/sh

Make init script executable and create the ram file system

[root@2d1eb21fc48e initramfs]# chmod +x init
[root@2d1eb21fc48e initramfs]# find . -print0 | cpio --null -ov --format=newc   | gzip -9 > initramfs.cpio.gz

6. Copy files out of podman and run them in Qemu

[root@2d1eb21fc48e initramfs]# podman cp 2d1eb21fc48e:/linux/arch/x86/boot/bzImage ./
[root@2d1eb21fc48e initramfs]# podman cp 2d1eb21fc48e:initramfs.cpio.gz ./  

ejo@fedora ~> qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -nographic --append "console=ttyS0"
  ...
Freeing initrd memory: 2124K
Freeing unused kernel image (initmem) memory: 652K
Write protecting the kernel read-only data: 8192k
Freeing unused kernel image (text/rodata gap) memory: 1480K
Freeing unused kernel image (rodata/data gap) memory: 1384K
Run /init as init process


Boot took 0.54 seconds

▓ ▄▄██   ██▓  █▄ ▄        ██▓ ▓▄▄   ▄▄▒
▓█   ▀  ▓▐█▒  ██ ▀█   █  ▓▐█▒ ▒▒ ▀ ▀ ▒░
▒█ █    ▒ █▒ ▓██  ▀█ ██▒ ▒ █▒ ░░      ░
▒▓█  ▄  ░▐ ░ ▓██▒  ▐ ██▒ ░▐ ░  ░ ▄ ▄ ▒
░▒████▒ ░▐█░ ▒██░   ▓██░ ░▐█░ ▓▀▀▒ ▒▀▀▒
░░ ▒░ ░ ░▓   ░ ▒░   ▒ ▓  ░▓   ▒▒ ░ ░▓ ░
 ░ ░  ░  ▒ ░ ░ ░░   ░ ▒░  ▒ ░ ░░   ░▒ ░
   ░     ▒ ░    ░   ░ ░   ▒ ░  ░    ░
   ░  ░  ░            ░   ░    ░    ░


Welcome to EINIX


/bin/sh: can't access tty; job control turned off
~ #
~ # clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x30b59aa3db1, max_idle_ns: 440795216505 ns
clocksource: Switched to clocksource tsc

~ # echo hello!
hello!

7. Discussion

Interestingly the kernel image produced when using `make allnoconfig` is 2MB, but building with `make tinyconfig` produces a kernel image of only 949kB, but boot takes 90 ms longer:

ejo@fedora ~> ls -sh bzImage
2.0M bzImage
  ...
Boot took 0.54 seconds
ejo@fedora ~> ls -sh bzImage
952K bzImage
  ...
Boot took 0.63 seconds

8. References

This whole thing is based on chrisdone's guide

[0]: https://gist.github.com/chrisdone/02e165a0004be33734ac2334f215380e 2d1eb21fc48e

Author: eino

Created: 2026-10-09 Fri 14:13

Validate