FreeBSD 1.0 Qemu Installation


by Ramses Soto-Navarro ramses@sotosystems.com, 9/28/2023

FreeBSD 1.0 Qemu Installation


Overview and Brief History

Brief steps on how run FreeBSD 1.0 on on Qemu under GNU/Linux. FreeBSD 1.0 was one of the first stable versions of BSD UNIX for the Intel 386 personal computer, released June 10, 1993. The intent of this document is to demonstrate how to install FreeBSD 1.0 as a virtual guest under Qemu; and as a point of reference for computer historians, and in order to study one of the first classic BSD UNIX for the 386 architecture. The first version of BSD UNIX for the Intel 386 was ported and compiled by professor William Jolitz and his wife Lynne, back in 1989. For the first time they got Unix to run on a Intel 386 IBM PC. They called it 386BSD. Before that, and beginning in the mid 70s, BSD UNIX was mostly run on the DEC VAX, the DEC PDP, and a few other similar mainframe computers.

freebsd-1.0-qemu.jpg

After 386BSD was ported to the personal computer in 1989, a few years went by with no updates. All development was stopped because AT&T was attempting to sue Berkeley University over assumed source code copyrights violations, which was settled many years later. Meanwhile in 1991 Linus Torvalds from Finland, using the Minix scholastic operating system as a starting point, wrote a new kernel, which actually became part of the most favorite Unix like open source operating system in actuality: GNU/Linux. However BSD UNIX is an initial pioneer of all things open source.

After it’s inception 386BSD was quickly abandoned, and as a result, in late 1992, a fork was begun: NetBSD 0.8. For me this version is very difficult to install because the installation method is very buggy. However, a year later, in 1993, yet another 386BSD fork beat them to it: FreeBSD 1.0. It ran very stable from the start, and it had a good installation wizard. This is the one we are installing here.

BSD UNIX has been considered as the most important software ever written. Most modern operating systems became possible because of the source code examples of BSD UNIX; including all the current versions of UNIX, Apple Darwin, the PS4 game console, iPhone, IOS. One of its most significant contributions is the TCP/IP source code, which is the main networking protocol of every operating system in use today.

The ultimate running target in this article is a virtual machine using the latest built-in package of Qemu 5.2.0 under Debian 11 x86_64. However, I could not get it to install. I had to first install it with Bochs running under an old version of Debian 5 (i386), then convert the raw disk image over to qcow2 format. After that I can then run it in any Qemu virtualization platform. Obviously, we want to run it in Qemu using it’s built in kernel hypervisor capabilities, rather than the Bochs emulator; Qemu is much faster and simpler, and offers native tap networking, and built-in kernel virtualization capabilities.

Many sites show you how to download and run their own already preinstalled Qemu image of FreeBSD 1.0, but they do not show you the steps involved for how to actually install it yourself. Here we demonstrate that briefly.

NOTE: I got FreeBSD 1.0 to run on Bochs and Qemu, but not KVM, since it does not include the NE2000 (ISA) emulation. Modern hypervisors dropped all ISA capabilities. ISA architecture was used until the mid 90s; then everything was switched to PCI DMI architecture. So it doesn’t make sense to include it in most modern virtualization platforms. Kudos to the Qemu team for still including vintage ISA device drivers.

The Plan:

1. First install the FreeBSD 1.0 OS on Bochs under Debian 5 i386. The simplest way I could get it to install. The installation floppies crash with Qemu or Bochs under any other more modern OS, including Debian 10/11 x86_64. Afterward convert the Bochs image to qcow2, then run it with any Qemu.
2. Will need another FreeBSD already running in order to extract the distribution tarballs. I used another older FreeBSD 3.3 (i386), from the late 1990s, which is compatible (itself also running on another Qemu session).
3. For native virtual networking under Qemu, you will need a GNU/Linux network bridge configured, and the ability to auto-create a tap network interface; Debian does this with script /etc/qemu-ifup. These steps are out of scope, but I may add them later.

The audience is experienced UNIX and Linux administrators.


Bochs FreeBSD 1.0 Installation

FreeBSD 1.0 did not want to install on Qemu. I first had to install it in Bochs under Debian 5 (i386).

Host OS version: Debian 5.0.10 i386
Bochs version: 2.3.7-1

Download and copy the installation floppies and the distribution sets:

$ DIR=/u1/bochs/freebsd/1.0
$ mkdir -p $DIR/install/a
$ cd $DIR/install
$ wget http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/ISO-IMAGES/1.0/1.0-disc1.iso
$ sudo mount -o loop 1.0-disc1.iso a
$ cp a/floppies/kcopy_ah.flp $DIR
$ cp a/floppies/filesyst.flp $DIR
$ cp a/floppies/cpio.flp $DIR
$ cd a/tarballs
$ tar zcf $DIR/tarballs.tgz bindist objdist srcdist
$ cd $DIR
$ sudo umount install/a

I like to symlink the floppies in order so that they are easy to change at the bochs prompt. Also I found that bochs is buggy and if you specify the path and file, it crashes; so this is a good quick method for installation floppy manipulation:

$ ln -s kcopy_ah.flp f1
$ ln -s filesyst.flp f2
$ ln -s cpio.flp f3

Create the bochsrc file:

$ cd $DIR

$ vi bochsrc

config_interface: wx
display_library: wx
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
keyboard_type: mf
mouse: enabled=0
private_colormap: enabled=0
floppya: 1_44=kcopy_ah.flp, status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata0-master: type=disk, path="hda.img", mode=flat, cylinders=1024, heads=16, spt=63
ata0-slave: type=cdrom, path="cd.iso", status=inserted
boot: floppy
floppy_bootsig_check: disabled=0
log: out.txt
panic: action=ask
error: action=report
info: action=report
debugger_log: -
megs: 64

Create the virtual hard disk, then run Bochs. Notice: the disk must be 504M or less or it may fail to be recognized. In the early 90’s disks larger than 500MB did not yet exist:

$ bximage -q -hd -mode=flat -size=504M hda.img

$ bochs
  • When prompted insert the f2 virtual floppy then press Enter. Click on the Bochs floppy taskbar image and proceed.
  • FreeBSD 1.0 is pretty good at detecteing the disk geometry. Take all the defaults and continue.
  • Enter “halt” at the end, then close Bochs.
  • Reboot with the same f1 install floppy as default; but this time do not change to any other floppy, just hit enter at the prompt.
  • At the next > prompt type “copy” then press Enter.
  • When asked type: copy kernel to> wd0a.
  • Close the bochs screen after system has halted.
  • Change bochsrc file entry from “boot: floppy” to “boot: disk”.
  • Start bochs again. This time it will ask for the cpio disk. Press the floppy button on the Bochs taskbar and select f3. Press Enter to continue.
  • If asked about optional dos floppy? Just press Enter for “n” or no.
  • At the end type “halt” then close bochs.
  • Boot again and verify that it comes up; it should reboot twice; then it should drop to a single-user prompt. Next, “halt” and close it one more time.

    You should now have a bare minimal FreeBSD 1.0 i386 installation on the hard disk. The Bochs emulator is no longer needed. We can continue with any Qemu virtualization session from now on. Last, we now have to extract all the other distribution sets. Including the OS binaries and source.


Extract the Distribution Sets

The current FreeBSD 1.0 is not complete. We need to extract the remaining distribution sets in order to install a full multi-user version of FreeBSD 1.0. The distribution sets come in the CD ISO in the tarballs subdirectory. These distribution sets contain the remainder of the operating system. We’ll need to copy the distributions sets tarball to the /usr/distrib/ subdirectory inside the FreeBSD 1.0 Bochs install that we already did.

Other alternatives which do not work: The network interface does not work, so no NFS share can be mounted in order to extract the distribution sets; nor mounting the CDROM, nor using a second virtual disk. None of that worked for me. We can use many virtual floppies to copy them over but that is too time consuming. The only option left is to mount and get to the /usr/distrib partition, on another stand-alone FreeBSD session, and copy the distribution sets in there.

Shutdown bochs.

Copy hda.img raw virtual disk to another Qemu directory that runs another version of FreeBSD. I like to use another pre-installed version of old FreeBSD 3.3 (i386). Other FreeBSD versions may work. Qemu did not work well for me on Debian 5 at all, so I recommend to go back to the latest Debian 10 or higher for any Qemu activity. I actually used Debian 5 only for the Bochs installation of FreeBSD 1.0.

Run the other FreeBSD 3.3 Qemu instance, make sure that hda.img is attached as the second drive. Mount the /usr/ (/dev/wd1e) on /mnt, then copy over the tarball and extract it.

# fsck -y /dev/wd1e
# mount /dev/wd1e /mnt
# cd /mnt
# mkdir distrib
# chmod 1777 distrib

Now from the Debian 5 host PC, ftp over the tarballs onto the FreeBSD 3.3 mounted /usr/distrib/.

$ cd $DIR
$ ftp freebsd33
ftp> cd /mnt/distrib
ftp> put tarballs.tgz
ftp> bye

Extract the tarball inside the attached virtual disk in the FreeBSD 3.3 session; then unmount, fsck, then halt.

# cd /mnt/distrib
# tar zxf tarballs.tgz
# rm tarballs.tgz
# cd
# sync
# umount /mnt
# fsck -y /dev/rwd1e
# halt

From now on you can start the hda.img image of FreeBSD 1.0 inside a Qemu session with Debian 10 and up, but to complete the installation you’ll need to extract the distribution sets:

Start the FreeBSD 1.0 with the following Qemu boot file:

#!/bin/bash
NAME="FreeBSD 1.0"
CPU=486
MEM=64M
HDA=hda.img
BOOT=c

sudo qemu-system-x86_64 
-name "$NAME" 
-cpu $CPU 
-m $MEM 
-hda $HDA 
-net nic,model=ne2k_isa 
-net tap,ifname=tap0,script=/etc/qemu-ifup,downscript=no 
-boot $BOOT & > /dev/null

After the single-user login, extract the distribution sets:

$ ./boot.sh

# cd /usr/distrib/bindist
# /bin/sh EXTRACT.sh
# cd /usr/distrib/objdist
# /bin/sh EXTRACT.sh
# cd /usr/distrib/srcdist
# /bin/sh EXTRACT.sh
# cd
# rm -rf /usr/distrib
# sync
# halt

At this time you have a basic multi-user version of FreeBSD 1.0 with the source code included. Halt one more time, then boot again to verify that you can enter the multi-user prompt. It will reboot twice, after doing it’s fsck, then you can login as root, with no password.


Prepare FreeBSD 1.0 to run on Qemu

Prepare the hda.img raw disk to run on Qemu by converting it to qcow2:

$ qemu-img convert -f raw -O qcow2 hda.img hda.qcow2

Modify the Qemu boot file to run with the new virtual disk, then run the virtual machine.

$ vi boot.sh
...
HDA=hda.qcow2
...
$ ./boot.sh

It should drop you to the multi-user root prompt. Login as root, with no password. At this time you should have FreeBSD 1.0 running with Qemu.


Setup Networking

TCP/IP Networking for the NE2000 interface did not work for me natively. There was an IRQ problem with the network card driver. Before you proceed you will have to recompile the kernel in order to change the IRQ of the network driver. Below is the error that I got when trying to initialize the IP address:

# dmesg | grep ed1

ed1 at 0x300-0x31f irq 5 on isa.
ed1: address 52:54:00:12:34:56, type NE2000 (16 bit)

# ifconfig ed1 172.24.80.29 netmask 255.255.0.0
/386bsd: ed1: device timeout
/386bsd: ed1: device timeout

Let’s recompile the kernel and change it to IRQ 9. That worked for me. I comment out all the SCSI, X, COM, LPT drivers since I will not need them and also the kernel size can be reduce by omitting them. The rest of the lines you can leave alone.

# cd /usr/src/sys/i386/conf
# cp GENERICHA CUSTOM
# vi CUSTOM

  # options XSERVER
  # options UCONSOLE

  # device sd0
  # device sd1
  # device sd2
  # device sd3
  
  # device st0
  # device st1

  # device com0
  # device com1
  # device com2
  # device com3

  # device sio0
  # device sio1
  # device sio2
  # device sio3

  # device lpt0
  # device lpa0
  # device lpa1

  # device ie0
  # device is0

  # pseudo-device speaker

  device ed1 at isa? port 0x300 net irq 9 iomem 0xd8000 vector edintr

Notice the ed1 change to the irq 9 above. Don’t forget that. Compile the new kernel and make it the default:

# config CUSTOM
# cd ../../compile/CUSTOM
# make depend
# make all
# mv /386bsd /386bsd.old
# cp 386bsd /386bsd
# sync
# halt

Boot to the new kernel and manually test the networking:

# ifconfig ed1
# ifconfig ed1 172.24.80.29 netmask 255.255.0.0
# route add default 172.24.1.1
# ping -c 1 172.24.1.1

Your networking should now be working natively. Let’s test telnet from another machine.

deb11:/u1/qemu/freebsd/1.0d$ telnet f1
Trying 172.24.80.29...
Connected to f1.
Escape character is '^]'.

   FreeBSD (myname.my.domain) (ttyp0)

login: root
Last login: Thu Oct 12 19:39:50 on console
Copyright (c) 1980,1983,1986,1988,1990,1991 The Regents of the University
of California.  All rights reserved.

FreeBSD myname.my.domain 1.0.2 GENERICAH#0 i386

Welcome to FreeBSD!

Terminal type? [xterm-256color] vt220
Don't login as root, use su

myname# uname -a
FreeBSD myname.my.domain 1.0.2 GENERICAH#0 i386

myname# df
Filesystem  1K-blocks    Used   Avail Capacity  Mounted on
/dev/wd0a       14591    6423    6708    49%    /
/dev/wd0e      451335  113762  292439    28%    /usr

Configure OS

Configure hostname and static IP. There is no DHCP client included. Afterward halt and boot again and verify. NOTE: `reboot` does not work well, so simply`halt` then boot again.

# echo bsd1 > /etc/myname
# echo "ifconfig ed1 172.24.80.29 netmask 255.255.0.0" >> /etc/netstart
# echo "route add default 172.24.1.1" >> /etc/netstart

At this time we can telnet as root with no password, which is terrible. Change the root password. Also create a new admin user in order to be able to telnet and ftp as that user; do not edit /etc/passwd directly, use vipw instead; in vi copy/paste the last line to create the new user then modify. Also, do not leave any space or carriage return after the last character, or it will not work.

# passwd

# vipw

  admin:*:3000:20::0.0:Admin:/usr/staff/admin:/bin/sh

# mkdir -p /usr/staff/admin
# chown admin:wheel /usr/staff/admin
# chmod 0750 /usr/staff/admin
# passwd admin

Add admin to the wheel group so that you can su as root later on.

# vi /etc/group
  wheel:*:0:root,admin

After logon set the TERM=vt220 or vi may not work:

$ cd
$ echo TERM=vt220 >> ~/.profile

Now as admin, test telnet, ftp, and su. It should all work as the user admin.

To install bash, find it in the packages sub-directory inside the CD ISO. FTP it over, extract it, and compile it.

Verify/create an /usr/tmp/ directory with 1777 permission for dumping files, since it will have plenty of temporary space. Follow the logic.

bsd1# mkdir -p /usr/tmp
bsd1# chmod 1777 -p /usr/tmp

deb5$ sudo mount -o loop /u1/bochs/freebsd/1.0/install/1.0-disc1.iso \
           /u1/bochs/freebsd/1.0/install/a
deb5$ cd /u1/bochs/freebsd/1.0/install/a/packages
deb5$ ftp bsd1
ftp> cd /usr/tmp
ftp> put bash_src.tgz
ftp> bye

deb5$ telnet bsd1

bsd1# cd /usr/tmp
bsd1# tar zxf bash_src.tgz
bsd1# cd bash
bsd1# make
bsd1# cp bash /bin/
bsd1# /bin/bash

Change the default shell and prompt to bash:

# vipw
  admin:???:3000:20::0:0:Admin:/usr/staff/admin:/bin/bash

# vi /usr/staff/admin/.profile
  PS1='\h:\w $ '

Download FreeBSD 1.0 for Qemu

    * Download the final image of this project.
    * You can run it in Qemu.
    * Native TCP/IP networking will function with a bridge and a tap interface.
    * The root and admin password is “welcome”.
    * Static network settings: /etc/netstart.

Download: freebsd-1.0.tgz


Debian Host Settings

Sample Debian Qemu Host utilities and scripts necessary:

# apt-get install bash-completion bash-builtins \
   uml-utilities bridge-utils openssh-server bochs rsync

# ls -l /etc/qemu-ifup

# cat > /etc/network/interfaces <<EOF
auto lo
iface lo inet loopback
iface eth0 inet manual
auto br0
iface br0 inet static
	address 192.168.1.2
	network 192.168.1.0
	netmask 255.255.255.0
	broadcast 192.168.1.255
	gateway 192.168.1.1
	bridge_ports eth0
	bridge_fd 9
	bridge_hello 2
	bridge_maxage 12
	bridge_stp off
EOF

# reboot

# brctrl show

Verify the script /etc/qemu-ifup is available, in order for tap interface auto-creation.


Now you can experiment with the first stable classic legacy vintage version of Unix BSD. All source code is in /usr/src/.

Have fun!


The End.