An Embedded Linux on a Single Floppy
2025 version (v0.3.1)
FLOPPINUX was released in 2021. After four years, people found it helpful. Because of this I decided to revisit FLOPPINUX in 2025 and create an updated tutorial. It brings many updates like the latest kernel and persistent storage.
table of contents
Main project goals
Think of it as Linux from scratch but for creating a single floppy distribution.
This means a complete workshop (tutorial) that you can easily follow and modify as per your needs. This is a learning exercise. Some basic Linux knowledge is required.
The final distribution is very simple and includes only minimal tools and hardware support. As a user you will be able to boot any PC with a floppy drive to a Linux terminal, edit files, and create simple scripts. There is 264KB of space left for your newly created files.
Main characteristics:
- Booting a fully functional distribution from a single floppy
- Latest* Linux kernel
- Supporting all 32-bit x86 CPUs since Intel 486DX
- Have a working text editor (Vi) and basic file manipulation commands (move, rename, delete, etc.).
- Support for simple scripting
- Permanent storage on floppy (264KB) to physically save files
- Works on real hardware and emulation
Minimum Hardware Requirements:
- Intel 486DX 33MHz
- 20mb ram
- internal floppy disk
linux kernel
Removes i486 support in Linux kernel 6.15 (released May 2025)
6.14 (Released March 2025) is the latest version with full compatibility.
64-bit base OS
This time I will do everything Umarki Linux. It is a 64-bit operating system based on Arch Linux. The instructions should work on all POSIX systems. The only difference is that essential packages are available.
working directory
Create directory where you will keep all the files.
mkdir ~/my-linux-distro/
BASE=~/my-linux-distro/
cd $BASE
Host OS Requirements
To build things you need supporting software. This exact list may vary depending on the system you have.
Install required software/libs. On arch/omarchi 3.1:
sudo pacman -S ncurses bc flex bison syslinux cpio
Cross-compiler:
wget https://musl.cc/i486-linux-musl-cross.tgz
tar xvf i486-linux-musl-cross.tgz
rm i486-linux-musl-cross.tgz
emulation
86box is also good but slow. Bochs is the best but it is not needed here for debugging.
For simulation I will use qemu.
kernels
Get the source for the latest compatibility kernel 6.14.11: :
git clone --depth=1 --branch v6.14.11 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux
Now, since you have them linux/ The directory lets us configure and build our custom kernel. Create the smallest base configuration first:
This is Bootstrap with absolutely minimal features. Just enough to boot the system. We want a little more.
Add additional configuration settings on top of this:
Important: Do not uncheck anything in the options unless specified. Some of those options are important. You can uncheck but at your own risk.
Select options from the menu:
- general setup
- Configure standard kernel features (expert user)
- Enable support for Printk
- Initializing RAM file system and RAM disk (initramfs/initrd)
- Support compressed initial ramdisks/ramfs using XZ and
uncheck everything else
- Support compressed initial ramdisks/ramfs using XZ and
- Configure standard kernel features (expert user)
- Processor type and features
- x86 CPU resource control support
- processor family
- enable block layer
- executable file format
- Kernel support for ELF binaries
- Kernel support for scripts starting with #!
- device driver
- block devices
- general floppy disk support
- RAM Block Device Support
- Default number of RAM disks: 1
- character tools
- block devices
- file system
- DOS/FAT/exFAT/NT file system
- pseudo file system
- /proc file system support
- sysfs file system support
- native language support
- library routine
- XZ decompression and uncheck everything under
Exit configuration (yes, save settings in .config).
Compilation time!
compile kernel
make ARCH=x86 bzImage -j$(nproc)
This will take some time depending on the speed of your CPU. Finally the kernel will be created arch/x86/boot/ As
bzImage file.
take the kernel to us main directory And get back to it: :
mv arch/x86/boot/bzImage ../
cd ..
Without the tool the kernel will simply boot and you won’t be able to do anything. One of the most popular lightweight tools is BusyBox. It replaces the standard GNU utilities with smaller but still functional alternatives, perfect for embedded needs.
bring it 1.36.1 Version from busybox.net or github mirror. Download the file, extract it and change directory:
Remember to stay in the working directory.
wget https://github.com/mirror/busybox/archive/refs/tags/1_36_1.tar.gz
tar xzvf 1_36_1.tar.gz
rm 1_36_1.tar.gz
cd busybox-1_36_1/
Like the kernel you need to create initial configuration:
make ARCH=x86 allnoconfig
If you are building on Debian/Fedora you can skip this following fix
fix for Arch Linux based distribution: :
sed -i 's/main() {}/int main() {}/' scripts/kconfig/lxdialog/check-lxdialog.sh
Now the fun part. To you Choose which devices you want. Each menu entry will show how much more KB will be taken if you select it. So choose it wisely 🙂 Use my selection for the first time.
Run the configurator:
Select the following options. remember do not uncheck If nothing is mentioned here.
- settings
- support files
- Build stable binary (no shared functions)
- coreutils
- Cat
- clamshell
- df
- echo
- Ras
- mkdir
- mv
- rm
- to do together
- Examination
- console utilities
- Editor
- initial utilities
- In this
- unmarked Keep everything else (inside init: [*] only on init in this page)
- In this
- Linux System Utilities
- mdev
- Mountain
- Support multiple -o flags
- unmarked everything else
- umount
- miscellaneous utilities
- Shells
- Select nickname as (ashes)
- ash
- Optimize size instead of speed
- alias support
Now exit with save config.
cross compiler setup
Our target system should be 32-bit. To compile it on 64-bit systems we need a cross compiler. You can setup it by hand in menuconfig or just copy and paste those four lines.
Setup Path:
sed -i "s|.*CONFIG_CROSS_COMPILER_PREFIX.*|CONFIG_CROSS_COMPILER_PREFIX=\"${BASE}/i486-linux-musl-cross/bin/i486-linux-musl-\"|" .config
sed -i "s|.*CONFIG_SYSROOT.*|CONFIG_SYSROOT=\"${BASE}/i486-linux-musl-cross\"|" .config
sed -i "s|.*CONFIG_EXTRA_CFLAGS.*|CONFIG_EXTRA_CFLAGS=-I$BASE/i486-linux-musl-cross/include|" .config
sed -i "s|.*CONFIG_EXTRA_LDFLAGS.*|CONFIG_EXTRA_LDFLAGS=-L$BASE/i486-linux-musl-cross/lib|" .config
compile busybox
Build tools and create (“install”) the base file system. It will ask for option, that’s it Press Enter To default to all of them.
make ARCH=x86 -j$(nproc) && make ARCH=x86 install
This will create a file system with all the files on **_install/**. Move it to our main directory. I would like to change its name.
Finally go to that new directory.
mv _install ../filesystem
cd ../filesystem
file system
You’ve got the kernel and the basic tools but the system still needs some additional directory structure.
It created the minimum viable directory structure to meet the basic requirements of a Linux system.
Remember to be in the file system / directory.
mkdir -pv {dev,proc,etc/init.d,sys,tmp,home}
sudo mknod dev/console c 5 1
sudo mknod dev/null c 1 3
The next step is to add the minimal configuration files. The first is a welcome message that will be shown after booting.
Here’s your first real opportunity to go wild and make it your signature.
cat >> welcome << EOF
Your welome message or ASCII art.
EOF
Or download my welcome file.
wget https://krzysztofjankowski.com/floppinux/downloads/0.3.1/welcome
It looks like this:
$ cat welcome
_________________
/_/ FLOPPINUX /_/;
/ ' boot disk ' //
/ '------------' //
/ .--------. //
/ / / //
.___/_________/__// 1440KiB
'===\_________\==' 3.5"
_______FLOPPINUX_V_0.3.1 __________________________________
_______AN_EMBEDDED_SINGLE_FLOPPY_LINUX_DISTRIBUTION _______
_______BY_KRZYSZTOF_KRYSTIAN_JANKOWSKI ____________________
_______2025.12 ____________________________________________
Back to the serious topic. The inittab tells the system what to do in critical situations such as starting, exiting, and restarting. This points to the initialization script rc which is the first thing our OS will run before dropping into the shell.
Create an inittab file:
cat >> etc/inittab << EOF
::sysinit:/etc/init.d/rc
::askfirst:/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
EOF
and init rc script:
cat >> etc/init.d/rc << EOF
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mdev -s
ln -s /proc/mounts /etc/mtab
mkdir -p /mnt /home
mount -t msdos -o rw /dev/fd0 /mnt
mkdir -p /mnt/data
mount --bind /mnt/data /home
clear
cat welcome
cd /home
/bin/sh
EOF
Make the script executable and make root the owner of all files:
chmod +x etc/init.d/rc
sudo chown -R root:root .
Compress this directory into a single file. Then go back to the working directory.
find . | cpio -H newc -o | xz --check=crc32 --lzma2=dict=512KiB -e > ../rootfs.cpio.xz
cd ..
Create booting configuration.
Another place to make changes to the parameters for your version. The text after SAY will be the first to appear on the screen, usually the name of the OS.
tsc=unstable is useful on some (real) computers to get rid of randomly shown warnings about the time stamp counter.
Remember to stay in the working directory.
cat >> syslinux.cfg << EOF
DEFAULT floppinux
LABEL floppinux
SAY [ BOOTING FLOPPINUX VERSION 0.3.1 ]
KERNEL bzImage
INITRD rootfs.cpio.xz
APPEND root=/dev/ram rdinit=/etc/init.d/rc console=tty0 tsc=unstable
EOF
Make it executable:
create sample file
To make the system a little more user friendly I would like to have a sample file that the user can read and edit. You can put anything in it as per your wish. It would be a good idea to include a simple help as well.
cat >> hello.txt << EOF
Hello, FLOPPINUX user!
EOF
File system is ready. the last step is put it all on a floppy!
boot image
First we need an empty file of the exact size of the floppy disk. Then format it and make it bootable.
Create a blank floppy image:
dd if=/dev/zero of=floppinux.img bs=1k count=1440
Format it and create a bootloader:
mkdosfs -n FLOPPINUX floppinux.img
syslinux --install floppinux.img
Mount it and copy syslinux, kernel and file system onto it:
sudo mount -o loop floppinux.img /mnt
sudo mkdir /mnt/data
sudo cp hello.txt /mnt/data/
sudo cp bzImage /mnt
sudo cp rootfs.cpio.xz /mnt
sudo cp syslinux.cfg /mnt
sudo umount /mnt
Done!
test in emulator
It’s a good idea to test burn a real floppy before wasting time.
Boot new OS in Qemu:
qemu-system-i386 -fda floppinux.img -m 20M -cpu 486
If this works it means you have successfully created your distribution! Congratulations!
flopinx.img The image is ready to be burned onto the floppy and booted on real hardware!
floppy disk
Important
Change XXX to the floppy drive name in your system. In my case it is
SDB. Selecting the wrong one will erase your partition and delete all your files! think twice. Or use some GUI application for that.
sudo dd if=floppinux.img of=/dev/XXX bs=512 conv=notrunc,sync,fsync oflag=direct status=progress
After 5 minutes I got a freshly burnt floppy.
Summary
- Flopinx: 0.3.1 (December 2025)
- Linux kernel: 6.14.11
- Busybox: 1.36.1
- Image Size: 1440KiB / 1.44MiB
- Kernel size: 881KiB (bzImage)
- Devices: 137KiB (rootfs.cpio.xz)
- Free space left (df -h): 253KiB
system Tools
file and directory manipulation
cat– Display file contentscp– Copy files and directoriesmv– Move/rename files and directoriesrm– Delete files and directoriesls– list directory contentsmkdir– creates directory
System Information and Management
df -h– Display file system disk space usagesync– Force buffered data to be written to disk – Use this after any changes to the floppy file systemmount– mount file systemumount– unmount the file system
Text Processing and Output
echo– display text outputmore– Page through text output
utilities
clear– clear terminal screentest– Evaluate conditional expressions
Application
download
<a href