index.html :: rss :: github :: telegram :: email

linux: build bootable image

22 Aug 2024

1. Prepare the kernel and initramfs

Inspired by these videos.

Prepare the build env

apt install qemu-system-x86 cpio flex bc bison ncurses-dev make perl libssl-dev syslinux dosfstools 

Clone and build the kernel:

git clone --depth=1 https://github.com/torvalds/linux.git 	
# or https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
make -j 

Try to run the kernel in qemu, make sure it boots

# note: no init given: will panic after the boot
qemu-system-x86_64 -nographic -serial mon:stdio -append 'console=ttyS0' -kernel bzImage

Build busybox as a userspace for the kernel

git clone --depth=1 https://git.busybox.net/busybox
make menuconfig 
# set Settings -> Build Static Binary = YES
make  -j

Make a directory for initramfs, install busybox

mkdir /root/src/distr/initramfs 
# this one will copy busybox' binaries into a CONFIG_PREFIX dir
make CONFIG_PREFIX=/root/src/distr/initramfs install

write an init script that will start the shell

# vim /root/src/distr/initramfs/init
#!/bin/sh
/bin/sh

#:wq

chmod +x /root/src/distr/initramfs/init

pack the initramfs into a kernel-friendly format, from the initramfs dir:

find . | cpio -o -H newc > ../init.cpio

run the kernel with initramfs:

qemu -nographic -serial mon:stdio -kernel bzImage -initrd init.cpio --append 'console=ttyS0' 

2. make it bootable

create the empty FAT filesystem, and install bootloader

dd if=/dev/zero of=./boot bs=1M count=50
mkfs -t fat ./boot  
syslinux ./boot

mount the boot filesystem and copy kernel

mkdir mnt
mount boot ./mnt
cp bzImage init.cpio ./mnt

create bootloader config in the filesystem root:

# cat ./mnt/syslinux.cfg
DEFAULT linux
SERIAL 0

LABEL linux
 MENU LABEL Boot Linux
 # KERNEL bzImage
 LINUX bzImage
 INITRD init.cpio
 APPEND root=/dev/sda1 ro console=ttyS0

run the system from an image

umount ./mnt
qemu-system-x86_64 -nographic -serial mon:stdio boot

3. debugging kernel