Last active
April 24, 2023 12:04
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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