Skip to content

snacsnoc/fluxflop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 

Repository files navigation

fluxflop - floppy-sized Linux

It's 2024 2025 and floppies are still cool. Maintain that coolness by building your own floppy-sized Linux distro like it's 1999.

This project is buildable by a gcc toolchain provided by your distribution or by building a musl toolchain. For the smallest binaries sizes, musl is recommended.

Quick Start

Two pre-built bootable floppy images are available in Releases:

  • Linux 6.12.9: Latest kernel build
qemu-system-i386 -fda fluxflop-linux-6.12.9-boot.img -boot a -m 32
  • Linux 4.20.17: Optimized for real i486DX hardware
  • Minimum requirements:
    • i486DX CPU @ 25MHz+ (SX models not supported)
    • 8MB RAM minimum (16MB recommended)
  • Boots from:
    • Real 1.44MB floppy disk
    • 86Box/PCem with i486DX configuration
    • QEMU with 5-32MB RAM setting

Building pre-reqs

gcc-i686 build:

Packages:

apt-get install build-essential gcc-i686-linux-gnu g++-i686-linux-gnu 

i486/i686-musl build:

# see README.md within musl-cross-make for all targets git clone https://github.com/richfelker/musl-cross-make cd musl-cross-make make TARGET=i486-linux-musl make install 

arm64-musl build:

make TARGET=aarch64-linux-musl make install 

Add the musl toolchain to your path: export PATH=~/musl-cross-make/output/bin:$PATH

Building on Mac OS:

Save yourself a headache and use a pre-built toolchain courtesy of homebrew-macos-cross-toolchains

brew tap messense/macos-cross-toolchains # valid targets are aarch64-unknown-linux-musl, arm-unknown-linux-musleabihf # armv7-unknown-linux-musleabihf, i686-unknown-linux-musl, x86_64-unknown-linux-musl brew install i686-unknown-linux-musl 

Install the LLVM linker:

brew install lld 

Install lkmake to included needed headers files for a successful build:

brew tap markbhasawut/markbhasawut brew -v install markbhasawut/markbhasawut/mac-linux-kdk 

For the following directions, use lkmake in place of make

Create a build dir: mkdir build/

Prepare the kernel:

cd build/ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.3.tar.xz tar -xf linux-6.9.3.tar.xz # see configs/linux for all configs available # .config - default i686 config # .config-x86-fb - i486 with framebuffer support # .config-x86-serial - i486 with serial support # .config-x86-vga - i486(DX) with VGA cp ./configs/linux/6.x.x/.config-<config-name> linux-6.9.3/.config 

The smallest kernel produced is using .config-x86-fb (XZ compression) = 592KB

Root filesystem layout:

mkdir -p root/{bin,proc,dev,sys,usr} # Create a simple init script # or compile tools/init.c and place in root/ cat > root/init <<EOF #!/bin/sh # Mount essential filesystems mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev # Start a shell exec /bin/sh -i # Infinite loop to prevent the script from exiting while true; do sleep 1 done EOF chmod a+x root/init # you will need root privileges to make these nodes mknod -m 660 ./root/dev/console c 5 1 mknod -m 666 ./root/dev/ttyS0 c 4 64 mknod -m 666 ./root/dev/tty c 5 0 

Output image directories:

mkdir -p bootable_image/{boot,isolinux} 

Build

Linux: Note: if you are including the initramfs in .config within the built image, build the rootfs first.

cd linux-6.9.3 make ARCH=x86 CROSS_COMPILE=i686-linux-gnu- -j8 #use bzImage for x86, Image.gz for arm64. adjust -gnu to -musl as needed 

Toybox:

wget https://landley.net/toybox/bin/toybox-i486 -O ./root/bin/toybox-i486 ./scripts/toybox-symlinks.sh 

Toybox provides many common Linux utilities including a shell. For the sake of simplicity, the static builds provided by Toybox is used. You can optionally compile Toybox yourself:

cd build/ wget https://landley.net/toybox/downloads/toybox-0.8.11.tar.gz tar xvf toybox-0.8.11.tar.gz cp ../configs/toybox/.config toybox-0.8.11 cd toybox-0.8.11 make CFLAGS="-march=i486 -mtune=i486" LDFLAGS="-static -s" ARCH=x86 CROSS_COMPILE=i486-linux-musl- -j8 make install cp -R install/* ./root 

Strip debug symbols in the root filesystem:

./scripts/stripfs.sh 

Make the initramfs:

./scripts/make-cpio.sh 

(Optional): Syslinux for ISOs:

wget https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz tar xvf syslinux-6.03.tar.gz cd syslinux-6.03 cp syslinux/bios/core/isolinux.bin bootable_image/isolinux cp syslinux/bios/com32/elflink/ldlinux/ldlinux.c32 bootable_image/isolinux # copy config cp configs/isolinux/isolinux.cfg bootable_image/isolinux 

Boot

Make a bootable ISO:

./scripts/make-iso.sh 

and boot with:

qemu-system-i386 -cdrom out.iso -m 32 -nographic 

Make a bootable floppy: If not already set, edit the Linux .config and set CONFIG_INITRAMFS_SOURCE to your rootfs cpio archive path.

cd build/ git clone https://github.com/oerg866/w98qi-tiny-floppy-bootloader cd w98qi-tiny-floppy-bootloader/ # generate a bootable floppy bash build.sh ../linux-6.9.3/arch/x86/boot/bzImage disk.img 

Boot with qemu: qemu-system-i386 -fda disk.img

Boot with kernel and initial ramdisk with qemu:

qemu-system-i386 -kernel ./linux-6.8.11/arch/x86/boot/bzImage -initrd ./rootfs.cpio.gz -append "init=/init rdinit=/init console=ttyS0,115200n8" -m 32 -nographic 

or, if you built with simple framebuffer:

qemu-system-i386 -kernel ./bzImage -initrd ./rootfs.cpio.gz -append "init=/init rdinit=/init console=tty0" -m 32 

Extra

Use a simple C program to use as init:

gcc -static -o init tools/init.c 

Use as the initramfs:

echo init | cpio -ov --format=newc > initramfs.img 

Kernel image comparison with printk support:

with:

stat -c %s arch/arm64/boot/Image 2809864 

without:

stat -c %s arch/arm64/boot/Image 2283528 

-fomit-frame-pointer:

easto@debian-build:~/testing-linux/linux-6.8.11$ ls -ls arch/x86/boot/bzImage 728 -rw-r--r-- 1 easto easto 741888 May 30 02:27 arch/x86/boot/bzImage easto@debian2:/tmp/linux-6.9.3$ stat -c %s vmlinux 1919144 make KCFLAGS="-fomit-frame-pointer" ARCH=x86 CROSS_COMPILE=i686-linux-gnu- bzImage -j8 easto@debian-build:~/testing-linux/linux-6.8.11$ ls -ls arch/x86/boot/bzImage 716 -rw-r--r-- 1 easto easto 729600 May 30 02:30 arch/x86/boot/bzImage easto@debian2:/tmp/linux-6.9.3$ stat -c %s vmlinux 1886332 

-fno-inline-small-functions:

easto@debian2:/tmp/linux-6.9.3$ stat -c %s vmlinux 1919144 make KCFLAGS="-fno-inline-small-functions" ARCH=x86 CROSS_COMPILE=i486-linux-musl- -j8 easto@debian2:/tmp/linux-6.9.3$ stat -c %s vmlinux 1919528 

find largest objects:

nm --size-sort --print-size vmlinux | tail -n 20 

or using Bloaty

bloaty -d symbols -n 100 vmlinux 

Resources

https://landley.net/toybox/

https://justine.lol/sizetricks/

https://elinux.org/images/7/72/Linux_tiny.pdf

https://git.openembedded.org/meta-micro/tree/conf

https://elinux.org/Linux_Tiny

https://ops.tips/notes/booting-linux-on-qemu/

https://android.googlesource.com/platform/external/syzkaller/+/HEAD/docs/linux/setup_linux-host_qemu-vm_arm64-kernel.md

https://github.com/ahgamut/superconfigure/?tab=readme-ov-file

https://github.com/buildroot/buildroot/tree/master/board/qemu/aarch64-virt

About

floppy-sized Linux in the modern era

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors