Installing 386BSD on BOCHS

From Computer History Wiki
Revision as of 23:38, 26 March 2023 by Jnc (talk | contribs) (Better cat)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This is the procedure that was used to install 386 BSD onto a patched version of the Bochs IA-32 emulator. This is based on ancient FAQs and trial & error. It is assumed you use a modern Linux with a kernel that features the ip_tables packet filter and TUN/TAP as host OS. If you want to use a different platform you can still follow the tutorial as a guideline but you are on your own figuring out how to get the emulator networked. A good starting point is

Special attention has been given to the ability to run the emulator in a terminal and in the background.

Watch out for leading spaces if you copy/paste anything from the boxes below, they tend to break here-documents.


You will need the following to get a 386BSD system patched and installed:

  • A modern Linux system with iptables
  • A working copy of gunzip
  • An http/ftp client like wget
  • An acceptable C compiler like gcc to compile Bochs
  • The curses/ncurses library for Bochs to simulate a monitor in a terminal
  • An ftp server for the distribution files

On a stock Basic Fedora Core 8 box you have these in no time with

yum -y install wget
yum -y install gcc
yum -y install gcc-c++
yum -y install ncurses-devel
yum -y install vsftpd

We will get to this later in the tutorial, but for those attempting to install on a different platform or those using this tutorial as a guide, you also need:

  • The Bochs 2.4.2 sources
  • A patched
  • The 386BSD distribution and patchkits

You can download the Bochs sources from sourceforge

A patched can be found at

The 386BSD 0.1 distribution and patchkits can be found at

Preparing for installation

Get, patch, configure and compile Bochs

The Tiny 386BSD boot floppy does something odd. It writes 0x02 to port 20h of the emulated PIC. This causes Bochs to panic. The patch enables Bochs to continue in CLI mode. The available windows binary for Bochs comes up with a msgbox. The patch is included in more recent versions of Bochs.

Pasting into Bochs is a drag. Playing with BX_KBD_ELEMENTS in iodev/keyboard.h here and keyboard_paste_delay later on in the Bochs configuration can help, but YMMV.

cd /usr/local/src
gunzip -c bochs-2.4.2.tar.gz |tar -xvf -
mv -f ./bochs-2.4.2/iodev/
cd bochs-2.4.2
./configure --enable-cpu-level=3 \
            --enable-ne2000 \
            --with-term \
            --with-nogui \
            --enable-all-optimizations \
make && make install

Get and serve the 386BSD distribution and patches

During installation the 386BSD distribution files and patches can be fetched with ftp. To facilitate this set up an anon ftpd that serves up the files. It should be possible to obtain these directly from minnie during install, but there are two problems. From the looks of it Warren Toomey never intended minnie to be a 386BSD install server. There is also a catch 22 in using the famous patchkits. Stock 386BSD 0.1 comes without gzip, the patches are gzipped, so here's your chance to get around that.

echo listen=YES >> /etc/vsftpd/vsftpd.conf
cd /var/ftp
wget -r -np
wget -r -np
mv ./
rmdir ./
cd /var/ftp/BSD/386bsd-patchkits
gunzip *gz

Prepare the host for networking Bochs

To make Bochs' ne2k work without a spare NIC in your host you need to set up tunneling.

echo alias char-major-10-200 tun >>/etc/modprobe.d/modprobe.conf.dist
depmod -a

Make a tunconfig script for bochs to fire off when the ne2k comes up. In this example becomes the gw and you can pick an ip in for the guest later.

# set up the bsd dir w/ tunconfig
cd; mkdir bsd; cd bsd
printf '#!/bin/bash\n/sbin/ifconfig ${1##/*0/}\n' >tunconfig
cat >>tunconfig <<__EOF
# carnival, put your masks on and go
/sbin/iptables -D POSTROUTING -t nat -s -d ! -j MASQUERADE >& /dev/null
/sbin/iptables -t nat -s -d ! -A POSTROUTING -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
chmod +x tunconfig

Note that newer iptables has a slightly different syntax. -d ! has become ! -d.

Configure Bochs

The 386BSD installation fails on a box with a lot of mem, hence the `megs: 8' stanza in the Bochs configuration.

cat >bochsrc <<__EOF
config_interface: textconfig
display_library: term
romimage: file=/usr/local/share/bochs/BIOS-bochs-legacy
cpu: count=1, ips=80000000, reset_on_triple_fault=0
megs: 8
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
vga: extension=none
floppya: 1_44=boot.img, status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="disk.img", mode=flat, cylinders=1024, heads=16, spt=63, translation=none, model=generic
boot: disk, floppy
floppy_bootsig_check: disabled=0
log: bochsout.txt
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
vga_update_interval: 400000
keyboard_serial_delay: 250
keyboard_paste_delay: 1000000
mouse: enabled=0
private_colormap: enabled=0
keyboard_mapping: enabled=0, map=
i440fxsupport: enabled=0
ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun, script=./tunconfig
com1: enabled=0

As explained in the initial kernel suffers from a Y2K bug. This can result in timestamps with the year 1970. Unfortunately the boot floppy doesn't let you work around this because it is missing the date command. If it bothers you creating new files and directories with a timestamp predating the release date you can set the time to eg. the 16th of July 1992 using bochsrc until you have the date command.

clock: time0=711244800

Once you are running with patch 00077 installed, Y2K+ bios dates shouldn't be a problem anymore.

Create Tiny 386BSD floppy

Prepare the 386BSD boot floppy to work on our emulated box that has a fancy 1.44MB floppy drive. The original floppy was intended for 1.2MB floppys, but who wants to be caught dead using these nowadays?

(cat /var/ftp/BSD/386bsd-0.1/bootable/dist.fs;dd if=/dev/zero bs=1 count=245760)>boot.img

Create a disk image

Make a disk that has the same geometry as in the configuration file, in this case 1024 cylinders, 16 heads and 63 sectors per track. This gets you about 500 megabytes, go larger and you get yourself in heaps of trouble.

printf "hd\nflat\n504\ndisk.img\n" |bximage

If that fails you probably have a very recent version of bximage, in that case:

printf "1\nhd\nflat\n504\ndisk.img\n" |bximage

First boot, Tiny 386BSD

Start up Bochs

You should now be ready to fire up bochs in your terminal and start your journey back in time.

bochs -q -f bochsrc

After a while you should get the following output:

Plex86/Bochs VGABios 0.6c 08 Apr 2009
This VGA/VBE Bios is released under the GNU LGPL

Please visit :

NO Bochs VBE Support available!

Bochs BIOS - build: 09/28/09
$Revision: 1.235 $ $Date: 2009/09/28 16:36:02 $
Options: apmbios pcibios eltorito

ata0 master: generic ATA-6 Hard-Disk ( 504 MBytes)

Press F12 for boot menu.

Booting from Hard Disk...
Boot failed: not a bootable disk

Booting from Floppy...
386BSD Release 0.1 by William and Lynne Jolitz. [0.1.24 07/14/92 19:07]
Copyright (c) 1989,1990,1991,1992 William F. Jolitz. All rights reserved.
Based in part on work by the 386BSD User Community and the
BSD Networking Software, Release 2 by UCB EECS Department.
pc0<color> at 0x60 irq 1 on isa
wd0 <generic> at 0x1f0 irq 14 on isa
fd0 drives 0: 1.44M at 0x3f0 irq 6 drq 2 on isa
ne0 ethernet address fe:fd:00:00:00:01 at 0x300 irq 9 on isa
npx0 at 0xf0 irq 13 on isa
changing root device to fd0a

warning: no swap space present (yet)
386BSD Distribution Installation Floppy (Tiny 386BSD) Release 0.1

Please read the installation notes (type 'zmore INSTALL.NOTES')
and registration information (type 'more REGISTRATION') before use.
To install on hard disk drive, type 'install'.

erase ^?, werase ^H, kill ^U, intr ^C
|| style="background:#000000;"|  

Format drive and install the distribution utilities

At the prompt give:

(echo y; echo y)|install

This will cause the installer to format the entire drive as it sees fit and install the distribution utilities on it. When the installer is finished Tiny 386BSD and Bochs will go down gracelessly.

Second boot, Base System

=== Finish the installation.

Restart Bochs

Give another:

bochs -q -f bochsrc boot the base system. After it finds the devices it will greet you with the following:

386BSD Base System Release 0.1

Congratulations, you've got 386BSD on the hard disk!
Please read the file REGISTRATION (e.g. type 'more REGISTRATION')
to discover how to become a part of the 386BSD user group.

To finish the installation, load the remaining distribution files into /tmp
and type 'extract' . To load the files from DOS floppies, type 'mread a:*.* /tmp.

If you should wish to uninstall 386BSD, delete the partition by using the
 DOS 5 FDISK program. If installed on the entire drive, use the FDISK/MBR
 to remove the 386BSD bootstrap from the drive.

erase ^?, werase ^H, kill ^U, intr ^C
|| style="background:#000000;"|  

Write an installer

The installed 386BSD kernel keeps kprinting `startartstartart' to your screen once network is up and running. This can get on your nerves, to work around this you can write an installer in a .netrc macro.

Change the ips below, to where your ftpd lives, to your gw and to the ip you want to give the guest. Change odin into the name you want to give the guest.

echo "machine" >.netrc
echo "login ftp" >>.netrc
echo "password" >>.netrc
echo "macdef init" >>.netrc
echo "#" >>.netrc
echo "pasv" >>.netrc
echo "prompt" >>.netrc
echo "bin" >>.netrc
echo "lcd /tmp" >>.netrc
echo "cd BSD/386bsd-0.1/bindist/" >>.netrc
echo "mget *" >>.netrc
echo "cd ../etcdist/" >>.netrc
echo "mget *" >>.netrc
echo "cd ../srcdist/" >>.netrc
echo "mget *" >>.netrc
echo "cd ../../386bsd-patchkits" >>.netrc
echo "mget *tar" >>.netrc
echo "!echo odin |extract bin01" >>.netrc
echo "!csh -c \"limit openfiles 512; extract src01 ; extract etc01 ; tar -cf /dist.tar /tmp/ ; cp pk023.tar /pk023.tar ; cp pk023024.tar /pk023024.tar ; sync ; sync ; sync ; /sbin/shutdown -r now\"" >>.netrc
echo "quit" >>.netrc
echo "#newl" >>.netrc
echo "" >>.netrc
chmod 400 .netrc

Configure the network

Watch out for the startarts.

ifconfig ne0 netmask up
route add default

Start the installation

Extract will complain with:

/tmp/install.src01: Can't open /tmp/install.src01
extract: Cannot execute installation script of distribution, failed

according to an ancient FAQ this is a joke from Jolitz. I don't get it.

Extract (or cat) also opens more files than the base sh can handle in case you were wondering about the use of csh.


When the macro is finished Bochs will go down gracelessly.

Third boot, fsck

When you restart Bochs again with:

bochs -q -f bochsrc

386BSD will boot, fsck the disk and shut down again. Don't panic.

Fourth boot, multiuser mode

Restart Bochs

After another

bochs -q -f bochsrc

you boot into multisuser mode.

386BSD Release 0.1 by William and Lynne Jolitz. [0.1.24 07/14/92 19:07]
Copyright (c) 1989,1990,1991,1992 William F. Jolitz. All rights reserved.
Based in part on work by the 386BSD User Community and the
BSD Networking Software, Release 2 by UCB EECS Department.
pc0<color> at 0x60 irq 1 on isa
wd0 <generic> at 0x1f0 irq 14 on isa
fd0 drives 0: 1.44M at 0x3f0 irq 6 drq 2 on isa
ne0 ethernet address fe:fd:00:00:00:01 at 0x300 irq 9 on isa
npx0 at 0xf0 irq 13 on isa
Automatic reboot in progress...
/dev/rwd0a: 13409 files, 240517 used, 253130 free (674 frags, 31557 blocks, 0.1%
starting network                                                                
starting system logger.                                                        
checking for core dump...                                                      
preserving editor files                                                        
clearing /tmp                                                                  
standard daemons: update crond.                                                
starting network daemons: routed printer sendmail inetd.                        
starting local daemons:.                                                        
Wed Apr  8 13:16:44 PST 1970                                                    
   386BSD (odin) (console)

|| style="background:#000000;"|  

386BSD 0.1 is installed now. You are at the point where Bill and Lynne Jolitz said "Cut the Tape" on 14th of July 1992. Now that you have 386BSD installed you can take the opportunity to travel forward in time to the birth of modern BSD. In 1992 and 1993 people released patch kits for 386BSD. 386BSD 0.2 never came and in early 1993 David Greenman proposed a new operating system based on the patchkits with a new name: "FreeBSD."

A few months later Chris Demetriou wrote “So you say you want an interim release of 386bsd?” and officially announced the first version of NetBSD. The CHANGES file reads “Changes from 386bsd 0.1 + patchkit 0.2.2” and “some alpha patchkit 0.2.3 stuff (piecemeal, and in some cases improved)”.

For more on this part of history read:

There is a BSD history book in the making by Jeremy C. Reed. It is very detailed and has a full annotated chapter on the patch kits. It is not yet in print, but rumor has the chapter can be obtained together with a warezed copy of NetBSD 0.8 in a manilla folder from a coughing, chain smoking guy in a raincoat if you know the right parking garage. For now see:

There were quite some patches. Rodney Grimes announced patchkit 0.2.3 in April 1993 and the last one 0.2.4 was announced in June 1993. The guided tour will bring 386BSD all up to the point where maintaining the patch kits became rather cumbersome. The shortest and most available route is installing the last two official unofficial patch kits and skipping 0.2.2.

Apply the first patchkit

Login as root, no password, and install the first of the two patchkits.

exec sh
cd /
tar -xvf pk023.tar
mv patch dist
cd dist/bin
(echo y; echo; echo; echo IALL; echo y ; echo ; echo q)|./patches

Recompile the kernel

As instructed by afterinstall, recompile the kernel. For Bochs the GENERICISA will do for now. There is something to be said for adjusting the kernel configuration, but this is left as an exercise better done later on.

rm -r /sys/compile/*
cd /sys/i386/conf
cd /sys/compile/GENERICISA
make depend
mv /386bsd /386bsd.old
cp 386bsd /386bsd
sync; sync; sync
shutdown -rf now

Fifth boot, GENERICISA

Upgrade the virtual machine and restart

Now that you have a proper kernel you can upgrade your machine to use some more than the 8 megs we gave it before.

sed -e's/megs: 8/megs: 64/' bochsrc >bochsrc64
bochs -q -f bochsrc64


The system is in a bit of an odd state, the sources are patched but most of the binaries are still the same. So put your new memory to good use, log in as root and execute a buildworld. Note that this can take a while.

exec sh
cd /patch/bin
sync; sync; sync
shutdown -rf now

and fire up Bochs again

bochs -q -f bochsrc64

Sixth boot, patched and recompiled system

Apply the second patchkit

Login as root, don't use su.

exec sh
cd /
tar -xvf pk023024.tar
cd dist/bin
(echo y ; echo ; echo ; echo IALL ; echo y ; echo ; echo q )|./patches


rm -r /sys/compile/*
cd /sys/i386/conf
cd /sys/compile/GENERICISA
make depend
mv /386bsd /386bsd.old
cp 386bsd /386bsd
sync; sync; sync
shutdown -rf now

and fire up Bochs again

bochs -q -f bochsrc64

Seventh boot, almost there


Login as root and perform another buildworld. Like before, this takes a while.

exec sh
cd /patch/bin
sync; sync; sync

The system is now up to date with the last patch kits released for 386BSD 0.1. This is a good point to save a copy of your image. Except for the hostname it is now in a pristine unconfigured state. What follows are some things you can do with the system and this is a point to rely on in case of a screw up or trying different routes.

Reboot at least once without the f(astboot) option for a long overdue fsck. Put zeros to a file and remove it when the disk is full if you care about image compression.

Disk images created by roughly automating the above steps with github and travis-ci is available via this trilogy

Running 386BSD

Kernel configuration, rolling your own

In bringing up the system the GENERICISA kernel served well and is more than fine if you want to just explore the system. If you want to do some more crazy things, like trying to get modern software compiled or even something more mundane as moving swap space around you will end up rolling your own kernel. This serves as an example on how to do just that. More specific configurations later when they are on topic. For now make it fit the current hardware and software configuration. More in depth information about config(8) at

As usual do

rm -r /sys/compile/*
cd /sys/i386/conf

Now copy the GENERICISA configuration, give it a fitting name, eg. BOCHS, and dive into it with your favorite editor.

grep -v "^#" GENERICISA > BOCHS

machine         "i386"
cpu             "i386"
## Private ident, shows up in eg. motd.
#ident           GENERICISA
ident           BOCHS
## Zone info, leap seconds and all are ancient.
## Living in a 90s Berkeley time zone will do for now.
timezone        8 dst
## We can handle a lot more in our emulator, let's double up.
#maxusers        10
maxusers        20
options         INET                    #InterNETworking

## No CD configured yet.
#options         ISOFS                   #ISO File System
## No NFS configured yet.
#options         NFS                     #Network File System
options         "COMPAT_43"             #Compatible with BSD 4.3
## No 4.2BSD boxen around at the moment.
#options         "TCP_COMPAT_42"         #TCP/IP compatible with 4.2
## No X installed yet.
#options         XSERVER                 #Xserver
#options         UCONSOLE                #X Console support

## No SCSI configured in bochs yet.
#config          "386bsd"        root on wd0 swap on wd0 and sd0
config          "386bsd"        root on wd0 swap on wd0

controller      isa0

controller      fd0     at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
disk            fd0     at fd0 drive 0
## One floppy is enough, second one is a bit broken anyway.
#disk            fd1     at fd0 drive 1

controller      wd0     at isa? port "IO_WD1" bio irq 14 vector wdintr
disk            wd0     at wd0 drive 0
## About 180 megabyte left, keep the slot for upgrade.
disk            wd1     at wd0 drive 1

## Lot of things not in Bochs, not turned on or rather useless.
#controller      ahb0    at isa? bio irq 11 vector ahbintr
#controller      aha0    at isa? port "IO_AHA0" bio irq 11 drq 5 vector ahaintr
#controller      scbus0

#device          sd0
#device          sd1
#device          sd2
#device          sd3

#device          st0
#device          st1
#device          st2
#device          st3

#device          cd0
#device          cd1

## Not set up for headless operation yet, screen and keyboard yes, com no.
device          pc0     at isa? port "IO_KBD" tty irq 1 vector pcrint
device          npx0    at isa? port "IO_NPX" irq 13 vector npxintr

#device          com0    at isa? port "IO_COM1" tty irq 4 vector comintr
#device          com1    at isa? port "IO_COM2" tty irq 3 vector comintr
#device          com2    at isa? port "IO_COM3" tty irq 5 vector comintr
#device          com3    at isa? port "IO_COM4" tty irq 9 vector comintr

#device          lpt0    at isa? port "IO_LPT3" tty irq 7 vector lptintr
#device          lpa0    at isa? port "IO_LPT1" tty
#device          lpa1    at isa? port "IO_LPT2" tty

## Network cards, Bochs only knows ne2k and we only have one configured.
#device we0 at isa? port 0x280 net irq 9 iomem 0xd0000 iosiz 8192 vector weintr
device ne0 at isa? port 0x300 net irq 9 vector neintr
#device ec0 at isa? port 0x250 net irq 9 iomem 0xd8000 iosiz 8192 vector ecintr
#device is0 at isa? port 0x280 net irq 10 drq 7 vector isintr

#device          wt0     at isa? port 0x300 bio irq 5 drq 1 vector wtintr

pseudo-device   loop
pseudo-device   ether
pseudo-device   log
## No Slip and PPP for now.
#pseudo-device   sl      2
##You run out of these fast when running screen.
#pseudo-device   pty     4
pseudo-device   pty     16
## Just in case 386BSD wants to say something.
pseudo-device   speaker

pseudo-device   swappager
pseudo-device   vnodepager
pseudo-device   devpager

Now bump the version and give it a shot. MAKEDEV is probably not needed.

config BOCHS
cd /sys/compile/BOCHS
make newvers
make depend
mv /386bsd /386bsd.old
cp 386bsd /386bsd
sync; sync; sync
shutdown -rf now

You should see the bumped minor version number, new ident and compile time..

[0.1.1 (BOCHS)  04/29/10 05:54]

.. and some moaning about the missing second drive..

wd0 0:<generic> 1:<wdgetctlr failed, assuming OK> at 0x1f0 irq 14 on isa

If you look in / you notice your kernel got a lot smaller and dropped from around 500k to around 350k.


  • Guest network config
  • Disklabeling and adding swap space
  • Tweaks to get big things to compile (limits, DFLDSIZ & MAXDSIZ / bash as sh )
  • Upgrade to NetBSD 0.8 ;)
  • Upgrade to 0.x