Skip to content

Anatomy of the Root (miniroot) Floppy

The Amix root floppy (amix_21_root.adf, 901,120 bytes / 880 KB) is a System V s5 "miniroot": a small s5 filesystem packed with the installer — about 30 m68k ELF binaries (cpio, fsck, mkfs, dd, amixpkg, rdb, …), the /bin/sh install scripts that drive partitioning and the tape extraction, a POSIX tar member, and the viper_kludge tape work-around plus its viper.README. ✅ (local analysis of amix_21_root.adf)

Correction (2026-07-05): this floppy's on-disk filesystem is s5, not UFS. Its superblock sits at byte 0x200 with the s5 magic 0xfd187e20 (s_type=2 = 1024-byte logical blocks, s_fsize=880 = exactly the image size). The UFS magic 0x00011954 appears in the image only inside the bundled mkfs_ufs/fsck_ufs ELF binaries, never at a superblock — which is why the string-based tools/inspect-adf.sh heuristic (it keys off lost+found) mislabels it "UFS miniroot." This is consistent with the installer's own ROOT_FSYS="s5" ("Johann ROM can only boot s5 filesystem", below): s5 is the boot-capable root fs. ✅ (forensic superblock analysis, 2026-07-05)

Unlike the boot floppy, the root floppy has no AmigaDOS bootblock — its first sectors are zeroed and the Kickstart ROM never boots it directly. It is mounted by the install kernel after you swap it in. This page dissects its on-disk structure and the install logic it carries. For the end-to-end procedure, see the install walkthrough; to understand how all three install disks are produced, see the build pipeline.

Licensing. The root floppy is Commodore material. Until 2026-09-23 this project treated it as abandonware, not licensed for redistribution; since then the Amix release restriction is lifted (see AGENTS.md §5). Do not commit it here — this is a text knowledge hub. Obtain it from amigaunix.com or the Internet Archive, then run the read-only tooling below against your own copy.

Identify your copy:

file  : amix_21_root.adf
size  : 901120 bytes  (901120 = standard 880 KB Amiga DD floppy)
sha256: 890da5e52f00cae74b817b42d1b94c3438f57b8c13b3d2b055e8b116a3feac56
✅ (tools/inspect-adf.sh on amix_21_root.adf; cross-check against sources/CHECKSUMS.txt)

No bootblock — and the body is s5, not UFS

The root floppy does not start with the AmigaDOS DOS\0 signature that a boot disk has. The boot area is zeroed, so any AmigaDOS-FS tool refuses it: ✅

$ tools/inspect-adf.sh amix_21_root.adf
detected disk type : root
  -> UFS miniroot; expect m68k ELF installer binaries + install shell scripts
[xdftool] ...
    'list' FSError: Invalid Boot Block(1):block=BootBlock:@0

That Invalid Boot Block @0 is expected and correct — it confirms there is no AmigaDOS filesystem. The body is instead an SVR4 s5 filesystem, with its superblock at byte 0x200 (magic 0xfd187e20) ✅ — see the 2026-07-05 correction at the top of this page. The UFS miniroot line the tool prints is wrong: inspect-adf.sh classifies by keying off the lost+found string, and lost+found plus the fsck/mkfs string tables are present here because the floppy carries the UFS tools as installer binaries, not because it is a UFS volume ✅ (see tools/inspect-adf.sh lines 59–63). It is a good worked example of why a string heuristic is not a filesystem identification.

Note — reading the tree. The body is s5, so a full file-tree traversal needs an s5-aware filesystem reader, not a UFS one (see the install script below). The bundled tools/unpack-root.sh does a pragmatic carve instead: it reports every ELF/script offset, carves the POSIX tar member(s), and dumps the install-script text — which is what you usually want when studying the installer. ✅

What's inside: installer ELF binaries, scripts, and a tar member

binwalk finds roughly 30 m68k ELF executables interleaved with two /bin/sh scripts and one POSIX tar member. ✅ The first object sits at offset 0x6800 (26624):

DECIMAL   HEXADECIMAL   DESCRIPTION
26624     0x6800        ELF, 32-bit MSB executable, Motorola 68020, version 1 (SYSV)
26836     0x68D4        Unix path: /usr/lib/libc.so.1
29859     0x74A3        Unix path: /dev/rmt/4h
31802     0x7C3A        Unix path: /dev/rmt/4hn bs=256k|cpio -imdcu
31894     0x7C96        Unix path: /dev/rmt/4hn bs=256k | zcat | cpio -imdcu %s
...
94592     0x17180       POSIX tar archive
217088    0x35000       Executable script, shebang: "/bin/sh"
218112    0x35400       Executable script, shebang: "/bin/sh"
✅ (binwalk amix_21_root.adf)

The first-ELF header confirms the binary format used throughout the installer: ✅

$ dd if=amix_21_root.adf bs=1 skip=26624 count=20 2>/dev/null | xxd
00000000: 7f45 4c46 0102 0100 0000 0000 0000 0000  .ELF............
00000010: 0002 0004                                ....

Decoded: 7f 45 4c 46 = ELF magic; 01 = ELFCLASS32; 02 = ELFDATA2MSB (big-endian); 01 = version; type 0x0002 = ET_EXEC; machine 0x0004 = EM_68K. Every installer binary references /usr/lib/libc.so.1 — i.e. these are dynamically-linked SVR4 m68k executables, not static blobs. ✅

The installer binaries you can fingerprint by their embedded usage/command strings include: ✅

Binary (referenced path) Role in the install
/bin/cpio Unpacks the distribution stream from tape
fsck_s5, fsck_ufs Filesystem check, per FS type
mkfs_s5, mkfs_ufs Create an s5 or UFS filesystem
dd Reads the raw tape device (/dev/rmt/4hn)
/etc/rdb Reads/writes the Rigid Disk Block partition table
/etc/atdevs, /etc/ddsize SCSI bus scan; partition size in 512-byte blocks
amixpkg SVR4 package install wrapper (-b, -i, …)
mount / umount / swap Mount the new root, add swap
viper_kludge Tape-drive kernel patch (see below)

The two /bin/sh scripts at 0x35000/0x35400 are the install driver — the partition/filesystem logic dissected in the next section. Note that Amix's /bin/sh is pre-POSIX (no $(...), no grep -q), so the scripts use back-ticks, expr, and set -- throughout. ✅ (root.adf script text; the pre-POSIX /bin/sh limitation is corroborated by the VA2000 driver case study.)

The tar member at 0x17180 is a POSIX (ustar) archive; carve it with unpack-root.sh (it stops at the archive's own end-of-archive marker) for offline inspection. ✅

The install script is /etc/profile

The install driver is not an anonymous blob you have to carve out of the image — inside the miniroot's s5 filesystem it lives at the path /etc/profile ✅ (first-party, 2026-07-31: read out of the stock root floppy by path with an s5-aware filesystem reader). The placement is the launch mechanism: a Bourne login shell reads /etc/profile at startup, so the miniroot needs no separate installer hook — the install kernel mounts the floppy, spawns the shell, and sourcing the profile starts the installer. Practically, this means you no longer need the offset-carve above to study the installer: any tool that can walk the s5 filesystem inside the ADF (see the 2026-07-05 s5 correction at the top of this page) extracts the script byte-exact by its path. And it makes /etc/profile the authority for every /etc/rdb, mkfs, and partition-arithmetic question — it is the code every stock install actually runs. Its exact command lines, and the unit conventions they prove, are dissected on the filesystems & disks page.

Two identity facts to pin while the image is open ✅ (first-party, 2026-07-31):

  • /etc/rdb on this floppy is 18,416 bytes, md5 6cacf95f738abea7cfddc6bb9ebf28e7.
  • A rebuilt install miniroot (the Installer-NG media) carries a byte-identical copy of that binary — so rdb behaviour proven against the rebuilt media is the stock binary's behaviour, and vice versa. That identity is what transfers the bench-proven unit conventions on the filesystems page to the stock installer.

The install / partition logic

The install script computes a default partition layout, lets you override it, then writes the Rigid Disk Block and creates filesystems. The tunables at the top of the script are exact: ✅ (root.adf script text)

BREAKPT=120     # Larger default swap when disk is over BREAKPT mb in size
LGSWAP=30       # Suggested size of swap area, mb, for "large" disks
SMSWAP=18       # Suggested size of swap area, mb, for "small" disks
MINBOOT=2       # Minimum size of bootstrap partition in megabytes
BOOTSIZE=2      # Default bootstrap partition size
UFS_OPT="-o free=2,opt=s"    # options for mkfs_ufs

Key behaviours encoded here:

  • Boot/bootstrap partition = 2 MB. BOOTSIZE=2 and BOOTLEN=expr $BOOTSIZE '*' 2048`` ⇒ a 2 MB partition is 4096 blocks of 512 bytes. This is the small partition that holds the relocatable kernel the Superkickstart ROM boots. ✅
  • Swap scales with disk size. Disks larger than BREAKPT=120 MB get LGSWAP=30 MB of swap; smaller disks get SMSWAP=18 MB. ✅
  • The tape ID is fixed; the disk ID is prompted. The tape is always id 4 — the disk-selection loop explicitly rejects that target as tape-only: ✅
if [ "$ask" = "4" ]; then
    echo "\nSCSI device 4 must be used for the tape drive"

The install script uses a $SCSI variable for the disk, so the prompt accepts other target ids — ID 6 is a strong convention, not a kernel mandate 🟡. In practice, use id 6 for the disk: whatever target you pick is baked into the device names (c${SCSI}d0s…) written into /etc/vfstab (the SVR4 mount table) and the boot partition, so changing it after install means editing those by hand. (The tape, by contrast, is genuinely fixed at id 4 — the scripts hard-reference /dev/rmt/4h.) See the quirks page and hardware.

  • Device paths are templated on the chosen SCSI id. After partitioning, the script binds: ✅
UPART=/dev/dsk/c${SCSI}d0s${ROOTPART}    # root
SPART=/dev/dsk/c${SCSI}d0s${SWAPPART}    # swap
BPART=/dev/dsk/c${SCSI}d0s${BOOTPART}    # boot/bootstrap
EPART=/dev/dsk/c${SCSI}d0s${EXTRAPART}   # optional extra

Filesystem choice: s5 vs UFS

For each data partition the script asks: ✅

Choose a file system type for this partition:

    s5:  Traditional UNIX file system
   ufs:  Berkeley file system

What file system type is this partition? [s5]

The prompt shows [s5] as the bracketed default, and community guidance — and the brief — recommends UFS in practice; the s5 default is plausibly a 3B2-lineage hold-over. 🟡 (rationale unconfirmed). Both the per-partition and the root prompt default to s5; ANS="ufs" is set only when ufs is typed ✅ (see filesystems & disks).

There is one exception the script can enforce for the root partition: ✅

ROOT_FSYS="s5"     # Johann ROM can only boot s5 filesystem

Here the script overrides the s5/ufs choice back to s5, with the comment that the "Johann ROM" can only boot an s5 root. ✅ (root.adf script text; the "Johann" name appears verbatim in the installer comment; its relationship to the Superkickstart boot ROM is 🔴 unconfirmed in the research brief — see the boot process.)

Scope correction (2026-08-14). That force is not unconditional: it is reached only on the stock OLD_BOOT / Johann-ROM path ✅. It is therefore not the reason a given disk is s5 — a modern install path can and does produce a UFS root, and the surviving 2.1 install lineage examined by this project is UFS-rooted (superblock fingerprint -o free=2,opt=s, 8192/8) ✅. What actually makes the typical root s5 is the plain [s5] prompt default above, not this override. And nothing in the kernel insists either way — root filesystem selection is by probe, not by configuration.

RDB partition type tags

After laying out the partitions with /etc/rdb -a, the script stamps each one with an SVR4/Amix partition type tag via /etc/rdb -F (this resolves brief gap #8, the previously-undocumented RDB type IDs — values read directly from the installer): ✅

/etc/rdb -p $BOOTPART -M -B -C 2 -P 2 -F 0x554e4900 $DISK   # 'UNI\0'  bootable boot partition
/etc/rdb -p $ROOTPART -m         -F 0x554e4901 $DISK        # 'UNI\1'  UNIX root
/etc/rdb -p $SWAPPART -m         -F 0x72657376 $DISK        # 'resv'   swap

The script's own comment is explicit about why the boot partition must be 0x554e4900: ✅

# The Kickstart 2.04 booting priority algorithms require that bootable
# UNIX partitions are filesystem type 0x554e4900.  Other types may [not boot]

So: boot partition type 0x554e4900 (ASCII UNI\0), UNIX root 0x554e4901 (UNI\1), swap 0x72657376 (resv). The -B/-C 2/-P 2 flags mark the partition bootable with the boot-priority/auto-mount fields the ROM scans. ✅

Driving the package install

Once partitions and filesystems exist and the new root is mounted at /mnt, the script computes how much space is available and calls amixpkg: ✅

amixpkg -b -v -r /mnt $OPTIONS ||                       # bootstrap pass
amixpkg -i -m -d -r /mnt -y standard -s $AVAILABLE ||   # install "standard" cluster

-r /mnt is the alternate root, -y standard selects the standard package cluster, and -s $AVAILABLE caps the install to the free blocks computed from the root partition. The amixpkg wrapper is widely reported as flaky, but the miniroot install path relies on it. 🟡 (amixpkg reliability)

The tape distribution pipeline

The actual operating-system files do not live on the root floppy — they are streamed from a QIC tape at SCSI id 4 and unpacked through cpio. The script defines the tape devices and the pipelines verbatim: ✅

TAPEn=/dev/rmt/4hn      # no-rewind, high-density tape node
TAPE=/dev/rmt/4h        # auto-rewind node

The distribution is read with dd and fed to cpio. Two variants appear, depending on whether the tape image is compressed: ✅

dd if=/dev/rmt/4hn bs=256k | cpio -imdcu          # plain cpio stream
dd if=/dev/rmt/4hn bs=256k | zcat | cpio -imdcu   # compress(1)-ed stream

cpio flags here: -i extract, -m retain modification times, -d create directories, -c ASCII header, -u unconditional overwrite. A cpio -imdcuB < /dev/rmt/4hn > /dev/null invocation also appears (the B = 5120-byte block size for raw tape), used to verify/seek the tape. ✅

The device-naming convention (/dev/rmt/<id><density>[n], n = no-rewind) is part of the SVR4 tape model; the 4 is the hard-coded SCSI tape id. See the device list and the quirks page.

Tape-free installs. Because most emulator users have no real QIC drive, the practical path is to present a tape image at SCSI id 4 in the emulator, or to dd a cpio image to swap from Linux/AmigaDOS and extract with cpio. The latter is documented on comp.unix.amiga. 🟡 See emulation on WinUAE for the SCSI-id-4 tape-image setup and the install walkthrough.

viper_kludge: the non-standard-tape work-around

The root floppy ships viper_kludge (an m68k ELF) and its /viper.README, written by Frank "Crash" Edwards. Its purpose is to patch kernel memory at install time so that tape drives the Amix kernel does not natively know — specifically the Archive Viper 2150S — can be read by dd/cpio during the install. ✅ (root.adf strings; viper.README)

When you'd use it. If the install fails with a tape I/O error on a non-standard drive, you press Ctrl-D until you reach the interactive # prompt, then run viper_kludge with no arguments to read its on-screen warning, and finally viper_kludge go to apply the patch. The viper.README walks through this. ✅

viper_kludge          # prints the warning only; patches nothing
viper_kludge go       # actually patches /dev/mem

It is dangerous — heed the built-in warnings. Both the runtime banner and viper.README warn, verbatim: ✅

  • "THIS PROGRAM (viper_kludge) IS EXPERIMENTAL. BY RUNNING IT THE USER AGREES TO BEAR ALL RESPONSIBILITY FOR THE RESULTS."
  • It is incompatible with, and must not be run on systems using, the Commodore A3070, Caliper, Wangtek, and Sankyo 150 MB cartridge drives — "It PREVENTS their use". ✅
  • The patch lives only in RAM: "Shutting down and rebooting removes the kernel memory patch." So it must be re-applied per boot until a real driver is built. ✅
  • For a permanent fix, the README points at "the files in directory /usr/sys/amiga/alien/contrib" to make the kernel inherently recognise the Viper — i.e. building tape support into the kernel rather than patching live memory. ✅ (cf. the kernel-rebuild flow in kernel build & install)

Bottom line: only use viper_kludge if you have a genuinely unsupported tape drive and the standard install has already failed on a tape error. If your drive is an A3070 or any Caliper/Wangtek/Sankyo unit, do not run it.

Tooling: inspecting and unpacking the root floppy

Both scripts are read-only on the input image and operate on your own copy of the ADF.

tools/inspect-adf.sh — classify the disk and surface the installer / tape / partition strings: ✅

tools/inspect-adf.sh amix_21_root.adf
# detected disk type : root
# -> UFS miniroot; expect m68k ELF installer binaries + install shell scripts
# [root] installer / tape pipeline strings:
#     amixpkg -i -m -d -r /mnt -y standard -s $AVAILABLE ||
#     BOOTSIZE=2  # Default bootstrap partition size
#     BPART=/dev/dsk/c${SCSI}d0s${BOOTPART}
#     dd if=/dev/rmt/4hn bs=256k | zcat | cpio -imdcu %s
#     ... viper_kludge ...

tools/unpack-root.sh — scan, carve the tar member(s), and dump the install-script text into tools/_work/<image>/ (gitignored): ✅

tools/unpack-root.sh amix_21_root.adf
# == unpack-root: amix_21_root.adf -> tools/_work/amix_21_root =
# -- scanning for embedded objects (binwalk) --
# -- carving POSIX tar member(s) --
#     carved .../tar_1_at_94592.tar (from offset 94592)
# -- installer script text (high-value strings) --   (full dump in strings.txt)

Both require binwalk/strings; inspect-adf.sh additionally uses xdftool (from amitools) and xxd when present and degrades gracefully otherwise.

See also

Sources

  • amix_21_root.adf analysis via tools/inspect-adf.sh and tools/unpack-root.sh — binwalk object table (30 m68k ELF objects, first at 0x6800; tar member at 0x17180; /bin/sh scripts at 0x35000/0x35400), ELF header bytes at 0x6800 (ELFCLASS32, ELFDATA2MSB, ET_EXEC, EM_68K), and strings dump of the install script (BOOTSIZE/BREAKPT/LGSWAP/SMSWAP, BPART/UPART/SPART, s5/ufs prompts (both [s5]; empty input → ANS="s5", ANS="ufs" only on typed ufs), ROOT_FSYS="s5" # Johann ROM, RDB -F type tags 0x554e4900/0x554e4901/0x72657376, amixpkg invocations, /dev/rmt/4hn tape pipelines).
  • viper.README and the viper_kludge runtime banner extracted from amix_21_root.adf (author Frank "Crash" Edwards; incompatibility with A3070/Caliper/Wangtek/Sankyo; RAM-only patch; pointer to /usr/sys/amiga/alien/contrib).
  • Master research brief, §9 (installation flow) and §10 (root.adf anatomy); §2 (SCSI ids — tape hard-coded at 4, disk 6 by convention; RAM ceiling); §13 gap #8 (RDB partition type IDs).
  • SHA-256 cross-check: sources/CHECKSUMS.txt.
  • Disk image (not redistributed here): amigaunix.com / archive.org Amiga UNIX.
  • The Installer-NG author-path proof (not public, 2026-07-31) ✅ — the stock root floppy's install script read by path (/etc/profile) with an s5 filesystem reader, matching the carved script text above; /etc/rdb md5 6cacf95f738abea7cfddc6bb9ebf28e7 (18,416 B), byte-identical between the stock floppy and the rebuilt install miniroot.