Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jlxip
Last active April 24, 2023 12:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlxip/97717185b073ae1a5921ab82338f0393 to your computer and use it in GitHub Desktop.
Save jlxip/97717185b073ae1a5921ab82338f0393 to your computer and use it in GitHub Desktop.
µlfs: the simplest Linux From Scratch. Part of a series of posts: https://jlxip.net/blog
#!/bin/bash -eu
# µlfs
IMGSZ=128M
KERNEL_VARIANT=linux-virt
KERNEL_FILE=vmlinuz-virt
# ----- IMG FILE -----
# Generate img file
IMG=hdd.img
dd if=/dev/zero of=$IMG bs=$IMGSZ count=1
# Partition it
echo "n
a
w
" | fdisk $IMG
# Set up loop device
LOOP="$(sudo losetup --partscan --show --find $IMG)"
# Format partition and get UUID
PART="$LOOP"p1
sudo mkfs.ext4 $PART
UUID="$(sudo blkid -s UUID $PART | cut -d'"' -f2)"
# Mount partition
mkdir -p mnt/
sudo mount $PART mnt/
# Basic filesystem
sudo mkdir -p mnt/{proc,sys,run,dev,etc,root}
# ----- KERNEL -----
# Steal a kernel from Alpine Linux
ALPINE="https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/"
if [ ! -d linux ]; then
PKG="$(curl $ALPINE | grep -e "\"$KERNEL_VARIANT-[0-9]" | cut -d'"' -f2)"
mkdir linux
cd linux
wget "$ALPINE/$PKG"
tar xvfz $PKG
cd ..
fi
sudo cp -ar linux/{boot,lib,usr} mnt/
KERNEL="$(ls linux/lib/modules)"
# ----- INIT -----
# Get hummingbird
if [ ! -d hummingbird ]; then
git clone https://github.com/Sweets/hummingbird --depth 1
cd hummingbird
make CC="gcc -static" hummingbird
cd ..
fi
# Install hummingbird
cd hummingbird
DESTDIR="`pwd`/../mnt" make install
cd ..
# ----- SHELL AND COREUTILS -----
# Get and install busybox
if [ ! -d busybox ]; then
# This mirror is way faster than the official one
git clone https://github.com/mirror/busybox --depth 1
cd busybox
make defconfig
CONFIG_STATIC=y make -j`nproc`
CONFIG_STATIC=y make install # Installs to _install/
cd ..
fi
sudo cp -ar busybox/_install/* mnt/
# ----- INITRAMFS -----
mkdir -p initramfs/{bin,dev,etc,lib,lib64,mnt/root,proc,root,sbin,sys}
sudo cp -ar busybox/_install/* initramfs/
cp -ar linux/lib initramfs/
echo "#!/bin/busybox sh
echo Oh, hello
mount -t proc none /proc
mount -t sysfs none /sys
find /sys -name modalias | xargs sort -u | xargs -n 1 /bin/busybox modprobe
mount -t devtmpfs none /dev
mount -t ext4 UUID=$UUID /mnt/root
umount /dev
umount /sys
umount /proc
exec switch_root /mnt/root /usr/bin/hummingbird
" | sudo tee initramfs/init
sudo chmod +x initramfs/init
cd initramfs
find . -print0 | cpio --null --create --verbose --format=newc | gzip --best > ../mnt/boot/initramfs.cpio.gz
cd ..
# ----- PASSWD -----
echo "root:x:0:0:root:/root:/bin/sh" | sudo tee mnt/etc/passwd
echo "root:::0:::::" | sudo tee mnt/etc/shadow
sudo chmod 0644 mnt/etc/passwd
sudo chmod 0640 mnt/etc/shadow
# ----- BOOTLOADER -----
# Copy syslinux files
sudo mkdir -p mnt/boot/syslinux/
sudo cp -a /usr/lib/syslinux/bios/*.c32 mnt/boot/syslinux/
# Install
sudo extlinux --install mnt/boot/syslinux
# Config
echo "
DEFAULT µlfs
TIMEOUT 0
PROMPT 0
LABEL µlfs
LINUX ../$KERNEL_FILE
APPEND root=UUID=$UUID loglevel=3 rw
INITRD ../initramfs.cpio.gz
" | sudo tee mnt/boot/syslinux/syslinux.cfg
# Unmount
sudo umount -R mnt/
sudo losetup -d $LOOP
# Write MBR
dd bs=440 conv=notrunc count=1 if=/usr/lib/syslinux/bios/mbr.bin of=hdd.img
# That's it! Good luck. Try it out with:
# qemu-system-x86_64 -hda hdd.img
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment