Skip to content
This repository was archived by the owner on Aug 21, 2024. It is now read-only.

Commit 3e0f562

Browse files
committed
Upload files
1 parent 04af417 commit 3e0f562

File tree

8 files changed

+3395
-0
lines changed

8 files changed

+3395
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
musl
2+
musl-build
3+
busybox
4+
rootfs
5+
rootfs.cpio
6+
linux
7+
linux-headers
8+
floppy
9+
floppy.img

Makefile

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Sources
2+
MUSL_SOURCE := git://git.musl-libc.org/musl
3+
BUSYBOX_SOURCE := git://busybox.net/busybox.git
4+
LINUX_SOURCE := git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
5+
6+
# Configuration
7+
BUSYBOX_CONFIG := busybox.config
8+
ROOTFS_OVERLAYDIR := rootfs-overlay
9+
LINUX_CONFIG := linux.config
10+
BOOTFS_LABEL := BOOT
11+
BOOTFS_SIZE := 1440
12+
BOOTFS_CREATE_GPT := 0
13+
QEMU_CMD := qemu-system-x86_64 -bios /usr/share/ovmf/x64/OVMF.fd -smp 2
14+
15+
# Temporary directories
16+
ROOTFS_DIR := rootfs
17+
BOOTFS_MOUNTDIR := floppy
18+
19+
# Recipe targets
20+
MUSL_DIR := musl
21+
MUSL_BUILD_DIR := musl-build
22+
MUSL_GCC := $(MUSL_BUILD_DIR)/bin/musl-gcc
23+
BUSYBOX_DIR := busybox
24+
BUSYBOX := $(BUSYBOX_DIR)/busybox
25+
ROOTFS_CPIO := rootfs.cpio
26+
LINUX_DIR := linux
27+
LINUX_HEADERS_DIR := linux-headers
28+
LINUX_BZIMAGE := $(LINUX_DIR)/arch/x86/boot/bzImage
29+
BOOTFS_IMAGE := floppy.img
30+
31+
.PHONY: all source update configure build clean reset
32+
all: configure $(BOOTFS_IMAGE)
33+
source: $(MUSL_DIR) $(BUSYBOX_DIR) $(LINUX_DIR)
34+
update: musl-update busybox-update linux-update
35+
configure: musl-configure busybox-configure linux-configure
36+
clean: musl-clean busybox-clean rootfs-clean linux-clean
37+
reset:
38+
rm -rf "$(MUSL_DIR)" "$(MUSL_BUILD_DIR)" "$(BUSYBOX_DIR)" "$(LINUX_DIR)" \
39+
"$(LINUX_HEADERS_DIR)" "$(ROOTFS_DIR)" "$(ROOTFS_CPIO)" \
40+
"$(BOOTFS_MOUNTDIR)" "$(BOOTFS_IMAGE)"
41+
42+
$(MUSL_DIR):
43+
git clone --depth=1 "$(MUSL_SOURCE)" "$(MUSL_DIR)"
44+
45+
$(MUSL_BUILD_DIR):
46+
mkdir -p "$(MUSL_BUILD_DIR)"/{bin,include,lib}
47+
48+
# These symlinks ensure that programs and headers required for building BusyBox
49+
# under musl are present (besides musl-gcc).
50+
# Refer: https://www.openwall.com/lists/musl/2014/08/08/13
51+
ln -s "$$(which as)" "$(MUSL_BUILD_DIR)"/bin/musl-as
52+
ln -s "$$(which ar)" "$(MUSL_BUILD_DIR)"/bin/musl-ar
53+
ln -s "$$(which nm)" "$(MUSL_BUILD_DIR)"/bin/musl-nm
54+
ln -s "$$(which strip)" "$(MUSL_BUILD_DIR)"/bin/musl-strip
55+
ln -s "$$(which objcopy)" "$(MUSL_BUILD_DIR)"/bin/musl-objcopy
56+
ln -s "$$(which objdump)" "$(MUSL_BUILD_DIR)"/bin/musl-objdum
57+
ln -s "$$(which pkg-config)" "$(MUSL_BUILD_DIR)"/bin/musl-pkg-config
58+
ln -s ../../linux-headers/include/linux "$(MUSL_BUILD_DIR)"/include/linux
59+
ln -s ../../linux-headers/include/mtd "$(MUSL_BUILD_DIR)"/include/mtd
60+
ln -s ../../linux-headers/include/asm "$(MUSL_BUILD_DIR)"/include/asm
61+
ln -s ../../linux-headers/include/asm-generic "$(MUSL_BUILD_DIR)"/include/asm-generic
62+
63+
$(MUSL_GCC): $(MUSL_DIR) $(MUSL_BUILD_DIR) $(LINUX_HEADERS_DIR) | musl-configure
64+
$(MAKE) -C "$(MUSL_DIR)" -j "$$(nproc)" all
65+
$(MAKE) -C "$(MUSL_DIR)" install
66+
67+
.PHONY: musl-update musl-configure musl-clean
68+
69+
musl-update: $(MUSL_DIR)
70+
git -C "$(MUSL_DIR)" pull
71+
72+
musl-configure: $(MUSL_DIR)
73+
cd "$(MUSL_DIR)" && ./configure --prefix=../"$(MUSL_BUILD_DIR)"
74+
75+
musl-clean:
76+
[ -d "$(MUSL_DIR)" ] && $(MAKE) -C "$(MUSL_DIR)" distclean
77+
rm -rf "$(MUSL_BUILD_DIR)"
78+
79+
$(BUSYBOX_DIR):
80+
git clone --depth=1 "$(BUSYBOX_SOURCE)" "$(BUSYBOX_DIR)"
81+
82+
$(BUSYBOX): $(BUSYBOX_DIR) $(MUSL_BUILD_DIR) | busybox-configure
83+
$(MAKE) -C "$(BUSYBOX_DIR)" -j "$$(nproc)" CC=../$(MUSL_GCC) all
84+
85+
.PHONY: busybox-update busybox-configure busybox-clean
86+
87+
busybox-update: $(BUSYBOX_DIR)
88+
git -C "$(BUSYBOX_DIR)" pull
89+
90+
busybox-configure: $(BUSYBOX_DIR) $(MUSL_GCC)
91+
cp "$(BUSYBOX_CONFIG)" "$(BUSYBOX_DIR)"/.config
92+
$(MAKE) -C "$(BUSYBOX_DIR)" CC=../$(MUSL_GCC) oldconfig
93+
94+
busybox-clean:
95+
[ -d "$(BUSYBOX_DIR)" ] && $(MAKE) -C "$(BUSYBOX_DIR)" distclean
96+
97+
# https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
98+
define _ROOTFS_BUILD_CMDS :=
99+
set -e
100+
mkdir -p "$(ROOTFS_DIR)"/{root,bin,sbin,dev,proc,etc,sys,tmp}
101+
$(MAKE) -C "$(BUSYBOX_DIR)" CC=../$(MUSL_GCC) CONFIG_PREFIX=../"$(ROOTFS_DIR)" install
102+
mknod "$(ROOTFS_DIR)"/dev/null c 1 3
103+
mknod "$(ROOTFS_DIR)"/dev/zero c 1 5
104+
mknod "$(ROOTFS_DIR)"/dev/random c 1 8
105+
mknod "$(ROOTFS_DIR)"/dev/urandom c 1 9
106+
mknod "$(ROOTFS_DIR)"/dev/tty0 c 4 0
107+
mknod "$(ROOTFS_DIR)"/dev/tty1 c 4 1
108+
mknod "$(ROOTFS_DIR)"/dev/tty2 c 4 2
109+
mknod "$(ROOTFS_DIR)"/dev/tty3 c 4 3
110+
mknod "$(ROOTFS_DIR)"/dev/tty c 5 0
111+
ln -s /proc/self/fd/0 "$(ROOTFS_DIR)"/dev/stdin
112+
ln -s /proc/self/fd/1 "$(ROOTFS_DIR)"/dev/stdout
113+
ln -s /proc/self/fd/2 "$(ROOTFS_DIR)"/dev/stderr
114+
cp -rfv "$(ROOTFS_OVERLAYDIR)"/* "$(ROOTFS_DIR)"
115+
cd "$(ROOTFS_DIR)" && find . | cpio -H newc -o > ../"$(ROOTFS_CPIO)"
116+
rm -rf "$(ROOTFS_DIR)"
117+
endef
118+
export ROOTFS_BUILD_CMDS := $(value _ROOTFS_BUILD_CMDS)
119+
$(ROOTFS_CPIO): $(BUSYBOX)
120+
# We don't need actual root privileges for this operation.
121+
echo "$${ROOTFS_BUILD_CMDS}" | fakeroot
122+
123+
.PHONY: rootfs-clean
124+
rootfs-clean:
125+
rm -rf "$(ROOTFS_DIR)" "$(ROOTFS_CPIO)"
126+
127+
$(LINUX_DIR):
128+
git clone --depth=1 "$(LINUX_SOURCE)" "$(LINUX_DIR)"
129+
130+
$(LINUX_HEADERS_DIR): $(LINUX_DIR)
131+
$(MAKE) -C "$(LINUX_DIR)" \
132+
headers_install INSTALL_HDR_PATH=../"$(LINUX_HEADERS_DIR)"
133+
134+
$(LINUX_BZIMAGE): $(LINUX_DIR) $(ROOTFS_CPIO) | linux-configure
135+
$(MAKE) -C "$(LINUX_DIR)" -j "$$(nproc)" bzImage
136+
137+
.PHONY: linux-update linux-configure linux-clean
138+
139+
linux-update: $(LINUX_DIR)
140+
git -C "$(LINUX_DIR)" pull
141+
142+
linux-configure: $(LINUX_DIR)
143+
cp "$(LINUX_CONFIG)" "$(LINUX_DIR)"/.config
144+
$(MAKE) -C "$(LINUX_DIR)" oldconfig
145+
146+
linux-clean:
147+
[ -d "$(LINUX_DIR)" ] && $(MAKE) -C "$(LINUX_DIR)" distclean
148+
rm -rf "$(LINUX_HEADERS_DIR)"
149+
150+
define _BOOTFS_BUILD_CMDS :=
151+
set -e
152+
losetup -j "$(BOOTFS_IMAGE)" | cut -d ':' -f 1 | xargs -r losetup -d
153+
if [ "$(BOOTFS_CREATE_GPT)" = 1 ]; then
154+
sgdisk -a 2 -N -t 1:EF00
155+
loopdev="$$(losetup -P -f "$(BOOTFS_IMAGE)" --show)"p1
156+
else
157+
loopdev="$$(losetup -f "$(BOOTFS_IMAGE)" --show)"
158+
fi
159+
mkfs.fat -F 12 -n "$(BOOTFS_LABEL)" "$${loopdev}"
160+
mountpoint -q "$(BOOTFS_MOUNTDIR)" && umount "$(BOOTFS_MOUNTDIR)"
161+
mount -m "$${loopdev}" "$(BOOTFS_MOUNTDIR)"
162+
mkdir -p "$(BOOTFS_MOUNTDIR)"/EFI/BOOT
163+
cp "$(LINUX_BZIMAGE)" "$(BOOTFS_MOUNTDIR)"/EFI/BOOT/BOOTX64.EFI
164+
umount "$(BOOTFS_MOUNTDIR)"
165+
rmdir "$(BOOTFS_MOUNTDIR)"
166+
losetup -d "$${loopdev%p1}"
167+
endef
168+
export BOOTFS_BUILD_CMDS := $(value _BOOTFS_BUILD_CMDS)
169+
$(BOOTFS_IMAGE): $(LINUX_BZIMAGE)
170+
dd if=/dev/zero of="$(BOOTFS_IMAGE)" \
171+
bs=1024 count="$(BOOTFS_SIZE)" conv=fsync
172+
173+
# losetup, mount and mkfs.fat likely require actual root privileges.
174+
echo "$${BOOTFS_BUILD_CMDS}" | sudo -s
175+
176+
.PHONY: runqemu-bzImage runqemu-floppy.img
177+
178+
runqemu-bzImage:
179+
$(QEMU_CMD) -kernel "$(LINUX_BZIMAGE)"
180+
181+
runqemu-$(BOOTFS_IMAGE):
182+
# QEMU's UEFI implementation doesn't seem to support booting from an internal
183+
# FDD, so we simulate an external USB-connected drive instead.
184+
$(QEMU_CMD) \
185+
-drive id=usbstick,if=none,file="$(BOOTFS_IMAGE)",format=raw \
186+
-usb \
187+
-device usb-ehci,id=ehci \
188+
-device usb-storage,bus=ehci.0,drive=usbstick,bootindex=1

README.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Floppy Disk Linux
2+
3+
![console screenshot](screenshots/console.png)
4+
5+
This repository provides a set of tools and configs to build a x86-64 Linux
6+
distribution with the very latest software (kernel and userland), fitting
7+
entirely on a 1.44 MB floppy disk and booting natively in a UEFI environment.
8+
9+
Heavily inspired by [Floppinux](https://github.com/w84death/floppinux), with the
10+
further aim of supporting some key characteristics of modern PCs (64-bit architecture, UEFI
11+
boot, SMP etc.) while also packing as much functionality as practically possible
12+
in the form of [BusyBox](https://www.busybox.net/) command-line utilities.
13+
14+
Floppy Disk Linux is intended for education and experimental purposes only. Due
15+
to the increasingly large size of the Linux kernel and related software, there
16+
is of course not very much that can be squeezed into 1.44 MB[^1].
17+
18+
## Building
19+
20+
The provided makefile automatically downloads sources, applies configurations,
21+
builds software and prepares the root filesystem as well as the final floppy
22+
disk image.
23+
24+
Makefile host system requirements:
25+
26+
- `git` for fetching and updating all sources
27+
- `fakeroot` for creating `rootfs.cpio`
28+
- `sudo`, `mount`, `umount`, `mountpoint`, `losetup`, `mkfs.fat` for creating
29+
`floppy.img`
30+
- `qemu-system-x86_64` and [OVMF](https://github.com/tianocore/tianocore.github.io/wiki/How-to-run-OVMF)
31+
for testing the images, if desired
32+
- the usual core utilities found on GNU/Linux installations
33+
- `make`, obviously
34+
35+
To fetch, configure and build everything at one go, run:
36+
37+
```sh
38+
make
39+
```
40+
41+
The result is `floppy.img`: a FAT12-formatted disk image[^2] containing the
42+
Floppy Disk Linux [EFI executable](https://www.kernel.org/doc/html/latest/admin-guide/efi-stub.html)
43+
with the root filesystem embedded as an [initramfs](https://www.kernel.org/doc/html/latest/filesystems/ramfs-rootfs-initramfs.html#what-is-initramfs).
44+
45+
The image can then be written to an actual floppy disk:
46+
47+
```sh
48+
sudo dd if=floppy.img of=/dev/fd0
49+
```
50+
51+
(Substitute `fd0` accordingly if using a different or external floppy disk drive.)
52+
53+
To quickly test the OS in a [QEMU](https://www.qemu.org/) virtual machine:
54+
55+
```sh
56+
make runqemu-bzImage
57+
```
58+
59+
Or, to test the OS booting from the floppy disk image itself:
60+
61+
```sh
62+
make runqemu-floppy.img
63+
```
64+
65+
To clean up everything:
66+
67+
```sh
68+
make reset
69+
```
70+
71+
Refer to `Makefile` itself for other possible `make` targets.
72+
73+
## Booting
74+
75+
The `floppy.img` image should allow Floppy Disk Linux to boot from external
76+
floppy disk drive connected to a modern PC via USB. Ensure that the PC's
77+
firmware is configured to boot from such media.
78+
79+
The layout of `floppy.img` is as follows:
80+
81+
```txt
82+
+--------------------------------------+-------------------------+
83+
| Linux EFI stub (bootloader) & kernel | Root filesystem archive |
84+
+--------------------------------------+-------------------------+
85+
| Linux EFI executable (\EFI\BOOT\BOOTX64.EFI) |
86+
+----------------------------------------------------------------+
87+
| FAT12 filesystem |
88+
+----------------------------------------------------------------+
89+
| Raw disk |
90+
+----------------------------------------------------------------+
91+
```
92+
93+
According to [section 13.3.1](https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#system-partition)
94+
of the UEFI Specification 2.10:
95+
96+
> For a diskette (floppy) drive, a partition is defined to be the entire media.
97+
98+
Therefore, creating a GUID Partition Table (GPT) and "EFI System Partition" on
99+
`floppy.img` should not be necessary for it to boot successfully. To create a
100+
GPT and place the filesystem on an EFI System Partition anyway, pass
101+
`BOOTFS_CREATE_GPT=1` to `make`:
102+
103+
```sh
104+
make BOOTFS_CREATE_GPT=1
105+
```
106+
107+
`floppy.img` will then take the following form instead:
108+
109+
```txt
110+
+--------------------------------------+-------------------------+
111+
| Linux EFI stub (bootloader) & kernel | Root filesystem archive |
112+
+--------------------------------------+-------------------------+
113+
| Linux EFI executable (\EFI\BOOT\BOOTX64.EFI) |
114+
+----------------------------------------------------------------+
115+
| FAT12 filesystem |
116+
+----------------------------------------------------------------+
117+
| EFI System Partition |
118+
+----------------------------------------------------------------+
119+
| GPT-formatted disk |
120+
+----------------------------------------------------------------+
121+
```
122+
123+
## Limitations
124+
125+
- No support for [block devices](https://linux-kernel-labs.github.io/refs/heads/master/labs/block_device_drivers.html)
126+
and thus accessing persistent storage media (for example, internal SSDs or
127+
external USB mass storage devices, even the disk from which the OS is booted)
128+
is not possible from the OS. This means that the only filesystem to work with
129+
resides in memory and any changes made to / will be lost on system shutdown.
130+
131+
This is because adding block device, USB and FAT filesystem functionality
132+
into the Linux kernel enlarges it by hundreds of kilobytes, beyond what would
133+
successfully fit on a 1.44 MB floppy disk.
134+
135+
If you find a reasonable way to achieve mounting filesystems on persistent
136+
media, please [open an issue](https://github.com/Expertcoderz/floppy-disk-linux/issues/new/choose)
137+
describing how to do so and it may be incorporated into Floppy Disk Linux.
138+
139+
- No support for x2APIC, which may be necessary for SMP to work on real
140+
machines. Enabling x2APIC support in the Linux kernel requires also enabling
141+
PCI and IOMMU support.
142+
143+
- No fancy graphics, only a text console on the EFI framebuffer.
144+
145+
- No networking support of any kind.
146+
147+
- Non-goals of Floppy Disk Linux which will not be supported include booting on
148+
BIOS-based (non-UEFI) systems and running on an IA-32 (32-bit) processor.
149+
150+
## TODO
151+
152+
- Implement the ability to mount persistent storage devices.
153+
154+
- Implement support for x2APIC.
155+
156+
- Experiment on the use of a minimal external bootloader instead of the Linux
157+
EFI stub, to reclaim some disk space.
158+
159+
- Add `make` targets to analyze image size.
160+
161+
[^1]: For an example of feature-rich OS on a floppy disk, see: https://menuetos.net/.
162+
163+
[^2]: Other FAT sizes such as FAT16 and FAT32 are unable to handle a 1.44 MB
164+
filesystem size and thus cannot be used to format the floppy disk.

0 commit comments

Comments
 (0)