๐Ÿ— Wiki

Linux

Linux

1. How to make a very minimal Linux distributable

As the person really loves Linux, I wanted to learn more about Linux kernel and tried to compile it.

2. Building the Linux kernel

  1. Visit https://kernel.org

  2. Download the xzipped kernel.

  3. make menuconfig

  4. make -j$(nproc)

  5. There should be arch/x86/boot/bzImage and ./vmlinux.

file command shows the version of the Linux kernel version that you compiled.

$ file arch/x86/boot/bzImage
arch/x86/boot/bzImage: Linux kernel x86 boot executable bzImage, version 6.5.8 (...)

2.1. BusyBox

BusyBox is a project collecting of Linux commands in a single binary. It is suitable for small linux system.

git clone git://busybox.net/busybox.git
make menuconfig

Make sure you checked 'Setting > Build static binary (no shared libs)'

make
make install

If you want to make a stable build, consider checking out a branch by git checkout origin/1_36_stable.

After executing make install command, unless you modified the configuration, there should be _install directory containing compiled busybox and structured tree of directories that you might have seen in *nix.

2.2. Preparing a root file system

Pack the _install directory with cpio. It will be a root file system of our custom Linux.

cd _install

# To make a root file system more Linux-ish
mkdir -p dev etc/init.d home/root lib mnt proc root sys tmp usr/lib var

# Pack 'em up!
find . | cpio --format=newc -o --owner=root:root > ../rootfs.cpio

# Compress
cd ..
gzip rootfs.cpio

If you successfully packed it, you can do a double check.

cpio -t < rootfs.cpio

2.3. QEmu

QEmu is a short of 'Quick Emulator', which is very suitable to emulate and run foreign programs or other operating systems.

In Ubuntu Linux 20.04, you can use apt to get a working qemu package. But it has outdated qemu, which is qemu 4.x.x. You can search for PPAs providing more recent version of qemu. Or install other package managers like Nix. In my case, I got source code from the official page and compiled it.

./configure   # Check required packages like ninja, libpixel-2, libglib2-dev, etc.
make          # You can have compiled executables in `/build`
make install

With compiled Linux kernel, which is bzImage, and packed root file system, which is rootfs.cpio.gz, you can finally run your own Linux!

#! /bin/sh

./qemu-8.1.2/build/qemu-system-x86_64 \
  -M pc \
  -smp 1 \
  -m 1G \
  -nographic \
  -kernel ./linux-6.5.8/arch/x86/boot/bzImage  \
  -initrd ./busybox/rootfs.cpio.gz \
  -append "rdinit=/linuxrc console=ttyS0"
useful explanation of some options
  • -M: machine.

  • -smp: CPU Cores.

  • -m: Memory capacity. Suffix M for Megabytes, G for Gigabytes.

  • -nographic: No graphic.

  • -append

    • rdinit

    • init

    • console: If you only can see a cursor is blinking when you run qemu command, setting it to console=ttyAMA0 might help.

    • root

2.4. Run Linux with BusyBox using QEmu

You need to confirm the two things(See Troubleshoot):

  1. You successfully compiled the statically linked BusyBox.

  2. There is a /etc/inittab file.

By default, if you just compiled the busybox, you may find there is no inittab.

Simply download the file from the official git repository of BusyBox.

It is good to understand some code lines in inittab; Each line have keywords with colon(:) delimiter. e.g., tty2::askfirst:-/bin/sh

  • ::sysinit:/etc/init.d/rcS specifies init script that will be executed when Linux kernel is loading.

  • ::askfirst:-/bin/sh will ask you to execute the shell (and you can permit it by pressing Enter key). A hyphen(-) means it is a login shell in busybox.

  • tty2::askfirst:-/bin/sh This will work on tty2.

In my case, I wrote an inittab file like this and works. It doesn’t have to write a rcS script.

# Uncomment this line if you'd like to use rcS initial script.
# ::sysinit:/etc/init.d/rcS
::respawn::-/bin/sh

# Stuff to do when restarting the init process
::restart:/sbin/init

# Stuffs to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

3. Troubleshoot

3.1. No working init found

  1. You omit /etc/inittab,

  2. or statically compiled busybox binary.

3.2. How to quit the qemu machine

To quit the qemu emulated machine, press Ctrl+a and x

5. See Also