Skip to content

About

Tiny educational Linux for QEMU/VirtualBox (boots in 16 MB RAM) with optional AX.25 packet radio and Dire Wolf.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

80 Commits

Folders and files

Repository files navigation

SmallHam Linux

License: GPL-2.0 Latest release

A tiny educational Linux (under 1 MB) that boots in QEMU or VirtualBox with 16 MB RAM, with optional AX.25 packet radio support.

Features

  • Tiny: the base system is 926 KB (kernel + initramfs) and boots with 16 MB RAM.
  • Amateur radio: AX.25, NET/ROM, ROSE, KISS and 6PACK in the kernel, the AX.25 tools and the Dire Wolf sound card modem. Dire Wolf and kissattach give an AX.25 network interface (ax0). A connection between two stations is not tested yet (see ROADMAP.md).
  • Persistent disk: a read-only squashfs root with an ext2 overlay for your changes.
  • Configured with menuconfig: profiles (base, persistent, ham radio) and one option for each feature.
  • Built from source without root: all programs are static (musl). The images run in QEMU and VirtualBox (ISO).

Quick start

Download and run

Download a file from the latest release and start it in QEMU (only qemu-system-x86_64 is needed):

tar xf smallham-v0.6-base-initramfs-x86_64.tar.xz
cd smallham-v0.6-base-initramfs-x86_64
./run.sh        # type 'reboot' to leave

The other files are described in Release files. For VirtualBox see Run with VirtualBox.

Build it yourself

Install the packages in Requirements, then build the base image and start it in QEMU:

git clone https://github.com/dandidev/smallham-linux.git
cd smallham-linux
make defconfig
make
make run        # type 'reboot' to leave

About

This project builds a very small Linux system, mainly for learning. You can see how a Linux system is put together from the ground up: the Linux kernel, BusyBox and a few optional programs. The system is 64-bit (x86_64); the output file names show it, e.g. smallham-ham-squashfs-vbox-x86_64.iso.

What you can learn and practice with it:

  • compiling and configuring the Linux kernel
  • initramfs and the boot process
  • a custom init system
  • core utilities with BusyBox
  • configuration with Kconfig and Makefiles
  • images that run in QEMU and VirtualBox

The amateur radio part is optional. The goal is to run it on minimal hardware, for example to simulate repeater stations or radio towers on ordinary computers.

Requirements

For building

  • An x86_64 Linux computer. The build was tested on Arch Linux.
  • Internet access: make downloads the sources (Linux kernel, BusyBox, musl, ...).
  • No root access is needed.
  • Free disk space:
Configuration Free space needed Used after the build
Base image (defconfig) about 2 GB about 1.8 GB
Ham radio setup (ham_defconfig) about 2.5 GB about 2.1 GB

Most of it is the kernel source (1.5 GB). The images themselves are only a few MB.

Packages (Arch Linux):

sudo pacman -S base-devel bc git curl cmake libelf squashfs-tools e2fsprogs util-linux qemu-system-x86
# for the VirtualBox ISO:
sudo pacman -S syslinux cdrtools qemu-img
# for 'make release':
sudo pacman -S zip

kconfig-frontends (kconfig-mconf, kconfig-conf) is not in the official repositories. Install it from the AUR, for example with an AUR helper:

yay -S kconfig-frontends

For running

You only need the built files and one of these programs:

  • QEMU: qemu-system-x86_64 (tested with QEMU 11.1)
  • VirtualBox: version 6.1 or newer, because the disk needs the VirtIO SCSI controller (tested with 7.2)

Memory (RAM) for the virtual machine:

Configuration Smallest RAM that boots Recommended RAM
Base image 16 MB 16 MB
Ham radio setup 20 MB (24 MB to run Dire Wolf) 32 MB

System size

Measured sizes of the built system:

Base image (defconfig) Ham radio setup (ham_defconfig)
Kernel (bzImage) 813 KB 1.6 MB
initramfs 113 KB (the whole system) 11 KB (only the disk mounter)
Root filesystem inside the initramfs 1.0 MB squashfs in the disk image (192 KB without the ham programs)
Total on disk 926 KB 2.6 MB (the disk image itself is 8 MB with free space)
VirtualBox ISO 1.4 MB 2.2 MB (+ 1.2 MB .vmdk disk)
RAM used after boot 1.5 MB 5.2 MB (8.8 MB with Dire Wolf running)

The ham programs in the root filesystem (xz compressed): Dire Wolf 490 KB, call 246 KB, ALSA configuration 147 KB, kissattach + kissparms + netromd 108 KB, Dire Wolf data files 52 KB.

Configuration (menuconfig)

The base image has only the kernel and a BusyBox shell. You add every other feature with make menuconfig:

make defconfig            # base image (used when there is no .config)
make base_squashfs_defconfig  # base system on a persistent disk (Persistent system profile)
make ham_defconfig        # ham radio setup: disk, network, USB sound, AX.25, Dire Wolf
make base_vbox_defconfig  # base image for VirtualBox (ISO)
make ham_vbox_defconfig   # ham radio setup for VirtualBox (ISO + disk)
make menuconfig           # add or remove features
make savedefconfig        # save the current selection to ./defconfig

To keep a selection, copy ./defconfig to configs/<name>_defconfig. Then make <name>_defconfig loads it.

In make menuconfig press ? to read the help of an option.

How the options are used:

What Where How
Kernel configs/kernel/*.config starts with everything off (allnoconfig), then adds the files of the selected options; all drivers are built in (no modules)
BusyBox configs/busybox/*.config the same way as the kernel
Root filesystem rootfs/<name>/ the selected directories are copied over each other (base always)
Programs packages/*.mk built with musl and copied to the root filesystem

scripts/check-config.sh stops the build if an option did not get into the final config. This happens with a misspelled option name or a missing dependency.

Profile

A profile turns on a group of options with one choice. You can still turn off any option of the group or add others. Your changes are kept when you change the profile later.

  • None – no group (the base image)
  • Persistent system – persistent disk, network, common tools, vi, system log (no ham radio)
  • Ham radio station – the same as make ham_defconfig

System

  • Image name: part of the output file names. By default it comes from the profile (base or ham), the root filesystem (initramfs or squashfs) and the platform (-vbox for VirtualBox), e.g. base-initramfs, base-squashfs, ham-squashfs-vbox
  • Target platform: QEMU (disk: virtio-blk, /dev/vda) or VirtualBox (ISO) (disk: VirtIO SCSI, /dev/sda)
  • Root filesystem:
    • initramfs only: the whole system is in RAM, changes are lost on reboot
    • Persistent disk: a read-only squashfs plus a writable ext2 partition, joined with overlayfs (fs_init); changes are kept
  • Console: VGA screen and PS/2 keyboard, or serial port (ttyS0, QEMU runs with -nographic)
  • ACPI: poweroff switches off the virtual machine (without it use reboot)

Kernel drivers

  • NET – network (virtio-net, IPv4, DHCP with ifup and udhcpc)
  • USB – USB host controllers (xHCI, EHCI), for USB devices passed to the VM
  • USB_STORAGE – USB drives, with FAT filesystem
  • SOUND – USB sound cards (ALSA)
  • HAM – AX.25, NET/ROM, ROSE, MKISS (KISS), 6PACK, BPQ, Baycom, YAM, pseudo terminals

Userspace

  • BB_TOOLS – grep, sed, find, head, tail, less, top, ...
  • BB_EDITOR – vi
  • BB_SYSLOG – syslogd, logread

Extras

  • AX.25 tools (kissattach, kissparms, netromd), AX.25 apps (call, listen, ax25ipd), Dire Wolf, aplay
  • Default config files, if you want them: /usr/etc/ax25/axports, /etc/direwolf.conf

Adding a kernel feature

A feature has three parts: a Kconfig option, a config file and a few lines in the Makefile. Example: USB serial adapters (CP210x).

  1. Kconfig:
config USB_SERIAL
    bool "USB serial adapters (CP210x)"
    depends on USB
  1. configs/kernel/usb-serial.config:
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CP210X=y
  1. Makefile, next to the other options:
ifeq ($(CONFIG_USB_SERIAL),y)
KERNEL_FRAGMENTS += usb-serial
endif

BusyBox commands (BUSYBOX_FRAGMENTS) and root filesystem files (ROOTFS_OVERLAYS) are added the same way.

Adding a package

A package is a packages/<name>.mk file. The main Makefile includes it. The file tells what to build and what to copy with three lists (FEATURE is a Kconfig option without CONFIG_):

PKG_FEATURES += FEATURE|<make target>              # build it
PKG_BINS     += FEATURE|<built program>            # copy it to /usr/bin
PKG_DIRS     += FEATURE|<built dir>:<rootfs dir>    # copy a data directory

Build the programs as static binaries with $(MUSL_CC). See packages/ax25-tools.mk.

Build

make

The output files are in build/out/. Their names are smallham-<image name>-x86_64-..., so the files of different configurations (and later of other architectures) do not overwrite each other. make dbg-vars shows the name for your configuration.

File (example: ham_defconfig) What it is
smallham-ham-squashfs-x86_64-bzImage the kernel
smallham-ham-squashfs-x86_64-initramfs.cpio.xz the initramfs (the whole system, or only fs_init with the persistent disk)
smallham-ham-squashfs-x86_64-disk.img the disk image, only with Persistent disk
smallham-ham-squashfs-x86_64-rootfs.squashfs the read-only root filesystem (also inside the disk image), only with Persistent disk

Partitions of the disk image:

Partition Content Used as
1 (vda1) squashfs (xz), read-only root lower layer of the overlay
2 (vda2) ext2, writable upper layer of the overlay (your changes)

Note: make builds the disk image again, and this deletes your changes on the writable partition. You can change the sizes, e.g. make DISK_SIZE_MB=16 SQUASHFS_SIZE_MB=8.

Make targets:

Target What it does
make builds the kernel, the initramfs and the disk image
make run starts the system in QEMU
make iso makes the VirtualBox ISO (and .vmdk)
make run-script writes the make run QEMU command as a script next to the output files
make release builds all release variants into build/release/<version>/ (see Release files)
make menuconfig, defconfig, <name>_defconfig, oldconfig, savedefconfig configuration
make IMAGE_NAME=<name> build with another image name (other output file names)
make dbg-vars shows the selected config files, packages and the kernel command line
make clean-distro deletes the root filesystem and the output files, except the disk image
make clean deletes everything, also the downloaded sources (~2 GB to download again)

Release files

make release builds every variant one after the other and puts the files into build/release/<version>/. The version comes from the git tag (git describe), so run it in a clean checkout of a release tag. Your .config is restored at the end.

File Configuration What it is
smallham-<version>-base-initramfs-x86_64.tar.xz defconfig QEMU: kernel + initramfs (the whole system in RAM), run.sh
smallham-<version>-base-squashfs-x86_64.tar.xz base_squashfs_defconfig QEMU: base system on a persistent disk, run.sh
smallham-<version>-ham-squashfs-x86_64.tar.xz ham_defconfig QEMU: ham radio setup on a persistent disk, run.sh
smallham-<version>-base-initramfs-vbox-x86_64.iso base_vbox_defconfig VirtualBox: boots from the ISO alone
smallham-<version>-ham-squashfs-vbox-x86_64.zip ham_vbox_defconfig VirtualBox: ISO + .vmdk disk
smallham-<version>-sources.tar source code of SmallHam and of the programs in the images, except the kernel (list: SOURCES.md inside)
linux-<kernel version>.tar.xz source code of the kernel (unmodified, the same file as on kernel.org)
SHA256SUMS checksums: sha256sum -c SHA256SUMS

The .tar.xz and .zip files also contain the license texts of the programs (licenses/) and a short README.txt.

Run

Run with Qemu (make run)

make run builds the kernel and the initramfs if the configuration changed, then starts QEMU. It does not build the disk image again if it exists, so your changes are kept. Run make if you changed what goes into the root filesystem.

make run                      # default RAM: 30 MB
make run QEMU_MEM=20          # change RAM size (MB)
make run QEMU_EXTRA="-device qemu-xhci -device usb-host,vendorid=0x08bb,productid=0x2902"

QEMU_EXTRA is given to QEMU as it is. The example passes a USB device of your computer to the VM. Use the ids from lsusb on your computer; QEMU must have access to /dev/bus/usb. With NET the VM uses QEMU's user network (udhcpc gets 10.0.2.15).

To leave the system type reboot. QEMU runs with -no-reboot, so it stops instead of starting again. With the ACPI option poweroff works too. With the serial console leave QEMU with Ctrl-A X.

Run with Qemu (without make)

You can copy the files from build/out/ to any computer with QEMU and start them there. make dbg-vars shows the kernel command line (-append) of your configuration.

  • Base image (defconfig): copy the bzImage and the initramfs
qemu-system-x86_64 -m 16 -no-reboot \
  -kernel smallham-base-initramfs-x86_64-bzImage \
  -initrd smallham-base-initramfs-x86_64-initramfs.cpio.xz \
  -append "notsc"
  • Ham radio setup (ham_defconfig, persistent disk): copy also the disk image
qemu-system-x86_64 -m 32 -no-reboot \
  -kernel smallham-ham-squashfs-x86_64-bzImage \
  -initrd smallham-ham-squashfs-x86_64-initramfs.cpio.xz \
  -drive file=smallham-ham-squashfs-x86_64-disk.img,format=raw,if=virtio \
  -append "notsc squashfs_dev=/dev/vda1 rw_dev=/dev/vda2" \
  -netdev user,id=net0 -device virtio-net-pci,netdev=net0
  • Serial console: add console=ttyS0 to -append and -nographic to QEMU
  • ISO (ham_vbox_defconfig): the kernel command line is inside the ISO. -boot d is needed, because the disk has no boot loader.
qemu-system-x86_64 -m 32 -no-reboot -boot d -cdrom smallham-ham-squashfs-vbox-x86_64.iso \
  -device virtio-scsi-pci,id=scsi0 \
  -drive file=smallham-ham-squashfs-vbox-x86_64-disk.img,format=raw,if=none,id=disk0 \
  -device scsi-hd,drive=disk0,bus=scsi0.0 \
  -netdev user,id=net0 -device virtio-net-pci,netdev=net0

(For the base image only -cdrom smallham-base-initramfs-vbox-x86_64.iso is needed.)

Run with VirtualBox

Load a VirtualBox configuration (or select Target platform: VirtualBox (ISO) in make menuconfig), then make the ISO:

make ham_vbox_defconfig     # or: make base_vbox_defconfig
make iso

Output in build/out/:

File (example: ham_vbox_defconfig) What it is
smallham-ham-squashfs-vbox-x86_64.iso bootable CD image with the kernel and the initramfs
smallham-ham-squashfs-vbox-x86_64-disk.vmdk the persistent disk in VirtualBox format (only with Persistent disk)

Copy these files to any computer with VirtualBox and set up a VM:

  • Type: Linux, 64-bit. Memory: 16 MB for the base image, 32 MB for the ham radio setup
  • Optical drive (IDE): the .iso file, boot from it
  • Persistent disk: add a VirtIO SCSI storage controller and attach the .vmdk file to it
  • Network: adapter type Paravirtualized Network (virtio-net)

The same from the command line:

VBoxManage createvm --name smallham --ostype Linux_64 --register
VBoxManage modifyvm smallham --memory 32 --boot1 dvd --boot2 disk --nic1 nat --nictype1 virtio --graphicscontroller vboxvga --audio-enabled off
VBoxManage storagectl smallham --name IDE --add ide
VBoxManage storagectl smallham --name VSCSI --add virtio-scsi
VBoxManage storageattach smallham --storagectl IDE --port 1 --device 0 --type dvddrive --medium smallham-ham-squashfs-vbox-x86_64.iso
VBoxManage storageattach smallham --storagectl VSCSI --port 0 --device 0 --type hdd --medium smallham-ham-squashfs-vbox-x86_64-disk.vmdk
VBoxManage startvm smallham

Bridged network (host setup)

With a bridge the VM can be reached from your computer and your local network. Run these commands on your computer as root.

  • Create the virbr0 bridge
ip link add name virbr0 type bridge
ip addr add 192.168.122.1/24 dev virbr0
ip link set virbr0 up
ethtool -K virbr0 tx off rx off
#ip addr show virbr0
  • Allow QEMU to use the bridge
echo "allow virbr0" >> /etc/qemu/bridge.conf
  • DHCP with dnsmasq (port=5353 turns off its DNS part; the VM gets public DNS servers)
# vim /etc/dnsmasq.conf
port=5353
interface=virbr0
bind-interfaces
listen-address=192.168.122.1
dhcp-range=192.168.122.100,192.168.122.150,12h
dhcp-option=3,192.168.122.1
dhcp-option=6,8.8.8.8,8.8.4.4
  • Iptables (${interface} is your computer's network interface to the internet, e.g. eth0)
iptables -A INPUT -i virbr0 -j ACCEPT
iptables -A OUTPUT -o virbr0 -j ACCEPT

iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i virbr0 -o ${interface} -j ACCEPT
iptables -t nat -A POSTROUTING -o ${interface} -j MASQUERADE
  • Turn on forwarding
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
  • Start QEMU with the bridge (persistent disk)
qemu-system-x86_64 -m 32 -no-reboot \
  -kernel build/out/smallham-ham-squashfs-x86_64-bzImage \
  -initrd build/out/smallham-ham-squashfs-x86_64-initramfs.cpio.xz \
  -drive file=build/out/smallham-ham-squashfs-x86_64-disk.img,format=raw,if=virtio \
  -append "notsc squashfs_dev=/dev/vda1 rw_dev=/dev/vda2" \
  -device qemu-xhci -device usb-host,vendorid=0x08bb,productid=0x2902 \
  -netdev bridge,id=net0,br=virbr0 \
  -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56

Using the system

There are no users: everything runs as root. This is why Dire Wolf shows a warning at start. The commands below need the options in brackets (make menuconfig).

Network (NET)

The network starts at boot from /etc/network/interfaces (eth0 with DHCP). To set it by hand:

ip link set eth0 up
udhcpc -i eth0
# or a fixed address:
ip addr add 10.0.2.15/24 dev eth0
ip route add default via 10.0.2.2

Sound card (SOUND)

ls -la /sys/class/sound/
cat /proc/asound/cards
lsusb

For a test without a real sound card, QEMU can emulate a USB speaker (output only):

make run QEMU_EXTRA="-audiodev none,id=snd0 -device qemu-xhci -device usb-audio,audiodev=snd0"

AX.25 over KISS with Dire Wolf (HAM, DIREWOLF, AX25_TOOLS_KISS)

Dire Wolf is the sound card modem. With -p it gives a virtual KISS TNC on a pseudo terminal (link: /tmp/kisstnc). kissattach connects it to an AX.25 network interface (ax0).

  • AX.25 port (or turn on AX25_DEFAULT_CONFIG). Use your own callsign instead of N0CALL.
mkdir -p /usr/etc/ax25
echo "radio N0CALL-1 9600 255 2 KISS" > /usr/etc/ax25/axports
  • Dire Wolf configuration (or turn on DIREWOLF_DEFAULT_CONFIG)
echo "ADEVICE plughw:0,0" > /etc/direwolf.conf

Dire Wolf needs a sound input. The QEMU USB speaker (see Sound card) has only an output, so with it take the input from UDP (no packets arrive, but Dire Wolf starts and the KISS TNC works):

echo "ADEVICE udp:7355 plughw:0,0" > /etc/direwolf.conf
  • Start
direwolf -t 0 -p -c /etc/direwolf.conf > /tmp/direwolf.log 2>&1 &
kissattach /tmp/kisstnc radio 10.1.1.1
kissparms -c 1 -p radio     # CRC off: Dire Wolf expects plain KISS
ip addr show ax0

-t 0 turns off the colors. Without kissparms -c 1 Dire Wolf says "Invalid transmit channel" for the frames of the Linux KISS driver.

Look into the disk image

Without root, on your computer. The read-only root is also a separate file:

cd build/out
unsquashfs -ls smallham-ham-squashfs-x86_64-rootfs.squashfs   # read-only root

Your changes are on the second partition of the disk image (the numbers are for the default partition sizes, see sfdisk -l <disk image>):

dd if=smallham-ham-squashfs-x86_64-disk.img of=/tmp/rw.ext2 bs=512 skip=14336
debugfs -R "ls -l /rw_root" /tmp/rw.ext2         # your changes

With root:

sudo losetup -fP build/out/smallham-ham-squashfs-x86_64-disk.img
#losetup -a
#lsblk
sudo mkdir -p /mnt/ro /mnt/rw
sudo mount -o ro /dev/loop0p1 /mnt/ro   # squashfs (read-only root)
sudo mount /dev/loop0p2 /mnt/rw         # ext2 (your changes: rw_root/)

Project layout

Path Content
Kconfig, configs/*_defconfig feature selection
configs/kernel/, configs/busybox/ config files of the features
rootfs/ root filesystem files (base, network, ...)
fs_init/ small init program for the persistent disk (mounts squashfs + overlay)
packages/ extra programs (musl, AX.25, Dire Wolf, ALSA, ...)
patches/ patches for the programs
scripts/ helper scripts for the config files
build/out/ output files: kernel, initramfs, disk image, ISO
sources/, toolchain/, build/ downloaded sources, libraries, build output (not in git)

Roadmap

Planned work and things that are not tested yet: ROADMAP.md. The changes of each version: CHANGELOG.md.

License

The files of this project (Makefile, Kconfig, configs/, packages/, scripts/, rootfs/, fs_init/) are licensed under the GNU General Public License version 2 (GPL-2.0-only), the same as the Linux kernel and BusyBox. See LICENSE.

The programs that make downloads and builds (Linux kernel, BusyBox, musl, Dire Wolf, AX.25 tools, ALSA, ncurses, ...) have their own licenses. The files in patches/ change these programs and have the license of the program they change.

About

Tiny educational Linux for QEMU/VirtualBox (boots in 16 MB RAM) with optional AX.25 packet radio and Dire Wolf.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages