Prerequisites

  1. Download busybox and linux kernel source code.

  2. Create some necessary directories.

    1
    2
    3
    mkdir initrd
    cd initrd
    mkdir {proc,sys,etc}
  3. Create init file.

    1
    2
    3
    4
    5
    #!/bin/sh
    mount -t proc proc /proc
    mount -t sysfs sysfs /sys
    mknod /dev/ttyS0 c 4 64
    setsid sh -c 'exec sh </dev/ttyS0 >/dev/ttyS0 2>&1'

Don’t forget to make init executable

Compile linux kernel

Here, I use default configuraton file, you can tweak it with gui through make menuconfig or manually configure .config file. you can get more help from make help.

1
2
3
make defconfig
make -j $(nproc)
make install

Compile busybox

1
2
3
4
make defconfig
sed -i 's/#\s*\(CONFIG_STATIC\).*/\1=y/g' .config
make -j $(nproc)
make install CONFIG_PREFIX=../initrd

Make virtual file system

1
find . | cpio -o -H newc | gzip -9 > initramfs.img

or

1
find . -print0 | cpio -0 -o -H newc | gzip -9 > initramfs.img

Boot linux with qemu

1
2
3
4
5
qemu-system-x86_64 \
-kernel kernel/bzImage \
-initrd initrd/initramfs.img \
-nographic \
-append "panic=1 console=ttyS0"

Alternatively you can pack rootfs into a disk

1
2
3
4
5
6
7
8
9
dd if=/dev/zero of=rootfs.img bs=1M count=10
mkfs.ext4 rootfs.img
mkdir rootfs
sudo mount rootfs.img rootfs
# rootfs directory
mkdir {proc,sys}
# busybox directory
make install CONFIG_PREFIX=../rootfs
sudo umount rootfs

Then boot with qemu

1
2
3
4
5
qemu-system-x86_64 \
-kernel kernel/bzImage \
-hda rootfs.img \
-append "root=/dev/sda console=ttyS0" \
-nographic

Tips and Tricks

  • method to quit qemu

    • Ctrl + A then X

    • Ctrl + A then C then type quit


References:

[1] Build a minimal Linux with only Busybox in 1 hour

[2] How to build bare minimal Linux system | Busybox, RAMfs ( initrd ) & system boot with Linux Kernel

[3] Building Bare-Minimum Linux for QEMU

[4] 从头制作一个基于 Busybox 的小型 Linux 系统