Skip to content

Instantly share code, notes, and snippets.

@zawzaww
Last active July 1, 2024 06:07
Show Gist options
  • Save zawzaww/cfedae575c7f9fc83ea3a02105dc263e to your computer and use it in GitHub Desktop.
Save zawzaww/cfedae575c7f9fc83ea3a02105dc263e to your computer and use it in GitHub Desktop.
Building a minimal Linux system from Scratch

Building a minimal Linux system from Scratch and Booting in QEMU Emulator

Prequisites

Make sure you installed the following tools on your Linux host.

Please, see the details information on Minimal requirements to install required build tools on your Linux host for compile the Busybox and Linux kernel.

  • Git
  • GCC or Clang Compiler
  • QEMU Emulator
  • Familiar with Make build system

Project Structure

linux
├── busybox
├── initrd
└── kernel
    ├── linux-mainline
    └── linux-stable

Compiling the Linux kernel

Download latest stable Linux kernel source code

$ mkdir -p linux/kernel
$ cd linux/kernel
$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux-stable
$ cd linux-stable

Compile the kernel with GCC compiler

$ make defconfig
$ make -j$(nproc --all)

(or)

Compile the kernel with Clang compiler

$ make CC=clang defconfig
$ make CC=clang -j$(nproc --all)

After compile, the kernel image is available at arch/x86/boot/ or arch/x86_64/boot

...
  OBJCOPY arch/x86/boot/vmlinux.bin
  AS      arch/x86/boot/header.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  BUILD   arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready  (#3)

Compiling the Busybox

Download the Busybox source code

$ git clone [email protected]:mirror/busybox.git

Make the Busybox configuration

$ cd busybox
$ make defconfig

EnableCONFIG_STATIC in Build Options in .config file

#
# Build Options
#
# CONFIG_PIE is not set
# CONFIG_NOMMU is not set
# CONFIG_BUILD_LIBBUSYBOX is not set
# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set
# CONFIG_FEATURE_INDIVIDUAL is not set
# CONFIG_FEATURE_SHARED_BUSYBOX is not set
CONFIG_STATIC=y
CONFIG_CROSS_COMPILER_PREFIX=""
CONFIG_SYSROOT=""
CONFIG_EXTRA_CFLAGS=""
CONFIG_EXTRA_LDFLAGS=""
CONFIG_EXTRA_LDLIBS=""
# CONFIG_USE_PORTABLE_CODE is not set
CONFIG_STACK_OPTIMIZATION_386=y
CONFIG_STATIC_LIBGCC=y

Compile the Busybox

$ make -j $(nproc --all)

Install the Busybox

$ make install

Then, generated bin at busybox/_install

total 4
drwxr-xr-x. 1 zawzaw zawzaw 966 Dec  1 13:14 bin
lrwxrwxrwx. 1 zawzaw zawzaw  11 Dec  1 13:14 linuxrc -> bin/busybox
drwxr-xr-x. 1 zawzaw zawzaw 986 Dec  1 13:14 sbin
drwxr-xr-x. 1 zawzaw zawzaw  14 Dec  1 13:11 usr

Creating Root Filesystem with initrd

Create a directory named initrd

$ mkdir initrd

Copy built Busybox bin files to initrd

$ cp -r busybox/_install/* initrd

Create file named init under initrd

#!/bin/sh
mount -t devtmpfs none /dev
mount -t proc none /proc
mount -t sysfs none /sys

echo "========================="
echo "Welcome to my Tiny Linux!"
echo "========================="

exec /bin/sh

Compress as img file with cpio tool

$ find . -print0 | cpio --null -ov --format=newc | gzip -9 > initramdisk.cpio.img

Booting in QEMU Emulator

Before boot the system in QEMU emulator, make sure you install QEMU emulator on your host machine.

Boot in QEMU emulator with No Graphic mode

$ qemu-system-x86_64 \
  -kernel kernel/linux-stable/arch/x86_64/boot/bzImage \
  -initrd initrd/initramdisk.cpio.img \
  -append "console=ttyS0" \
  -nographic

Boot in QEMU emulator with Graphic mode

$ qemu-system-x86_64 \
  -kernel kernel/linux-stable/arch/x86_64/boot/bzImage \
  -initrd initrd/initramdisk.cpio.img \
  -append "console=ttyS0"

Boot logs

Booting from ROM..                                                                                                                                                                                                 
[    0.000000] Linux version 6.7.0-rc2 (zawzaw@fedora-linux) (clang version 16.0.6 (Fedora 16.0.6-3.fc38), GNU ld version 2.39-16.fc38) #3 SMP PREEMPT_DYNAMIC Fri Dec  1 12:50:26 +0630 2023                      
[    0.000000] Command line: console=ttyS0                                                                                                                                                                         
[    0.000000] BIOS-provided physical RAM map:                                                                                                                                                                     
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable                                                                                                                                       
[    0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved                                                                                                                                     
[    0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved                                                                                                                                     
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x0000000007fdffff] usable                                                                                                                                       
[    0.000000] BIOS-e820: [mem 0x0000000007fe0000-0x0000000007ffffff] reserved                                                                                                                                     
[    0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved                                                                                                                                     
[    0.000000] BIOS-e820: [mem 0x000000fd00000000-0x000000ffffffffff] reserved                                                                                                                                     
[    0.000000] NX (Execute Disable) protection: active                                                                                                                                                             
[    0.000000] APIC: Static calls initialized                                                                                                                                                                      
[    0.000000] SMBIOS 2.8 present.                                                                                                                                                                                 
[    0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-1.fc38 04/01/2014 

Then, check booted Linux root filesystem and kernel version.

$ ls -l
total 1028
drwxr-xr-x    2 1000     1000          1900 Dec  1 06:52 bin
drwxr-xr-x    7 0        0             2260 Dec  1 07:12 dev
-rwxr-xr-x    1 1000     1000           203 Nov 25 20:31 init
-rw-r--r--    1 1000     1000       1048576 Dec  1 07:00 initramdisk.img
lrwxrwxrwx    1 1000     1000            11 Dec  1 06:52 linuxrc -> bin/busybox
drwx------    2 0        0               40 Dec  1 06:14 root
drwxr-xr-x    2 1000     1000          1480 Dec  1 06:52 sbin
drwxr-xr-x    4 1000     1000            80 Nov 25 20:31 usr
$ cat /proc/version
Linux version 6.7.0-rc2 (zawzaw@fedora-linux) (clang version 16.0.6 (Fedora 16.0.6-3.fc38), GNU ld version 2.39-16.fc38) #1 SMP PREEMPT_DYNAMIC Fri Dec  1 13:56:11 +0630 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment