BSD Disk Images

I'm repeatedly installing OpenBSD on a test machine, but I don't want to
waste a keyboard or a monitor on it. While I have the equipment, desk space is
precious. That leads me to a serial console. Booting an OpenBSD system with a
serial console is pretty easy: enter set tty com0 at either the
boot prompt or in /etc/boot.conf. The first won't work in this
case. If I had a keyboard and monitor attached, I wouldn't
need the serial console. The second seems difficult, given
that the OpenBSD boot disks are disk images downloaded from the Internet. But
editing those images isn't that difficult. In this article, we'll show how to
set up and use /etc/boot.conf on an OpenBSD installation boot
floppy. This same approach works on both FreeBSD and NetBSD as well.

OpenBSD's /etc/boot.conf has a variety of other features, such
as letting you adjust the memory configuration to skip the famous Compaq 16MB
memory hole, or letting you choose an alternate boot disk. You can see all the
details in boot(8), but we're going to focus on diverting the
console to the serial port. Since I'm going to be running this install
repeatedly, I'd like to have a custom boot floppy image that I can use to burn
as many floppies as I like. Floppies tend to go bad after all, and I don't
want my single customized boot floppy to die after only 60 or so installs.
The simplest way to do this is to mount the disk image, edit it, and write that
image to a floppy disk.

Mounting a disk image file has two steps. First, you need to tie the disk
image to a device node. Then, you can mount that device node as you would any
other device. This is true for floppy disk images, CD-ROM images, or any other
sort of disk image you might have. OpenBSD provides vnconfig(8)
to map an image to a device node. NetBSD and FreeBSD also have
vnconfig(8) programs, although their syntax differs. You can edit
the disk image on any operating system so long as the operating system can
mount the filesystem used on the image.

If you look at the manual page for vnconfig, it talks about
vnode disks. What the heck is a vnode disk? Originally, the Fast File
System had index nodes, or inodes, that marked how files were laid out on
disk. The kernel read inodes to get information on files. Each group of
inodes was tied to a disk device, so the kernel knew to ask vnode number X on
device node Y.

Foreign filesystems (such as CD-ROMs and FAT floppy disks) don't have
inodes, but instead have their own file indexing and layout systems. This was
fine, until it became necessary to mount these filesystems on a UNIX box.
Virtual nodes, or vnodes, were introduced as an abstraction layer between
certain kernel functions and the filesystems that they wanted to access. The
vnodes handle any translations between the kernel and inodes, File Allocation
Tables, and so on. So, a vnode disk is pretty much anything that vnodes can
talk to, a disk image.

The file has vnodes, but the kernel needs a device to read those vnodes
through. That's where vnconfig(8) comes in; it ties vnodes to a
device node.

OpenBSD provides two different sorts of device nodes for different sorts of
disk access. Disks that contain filesystems should be accessed through the
buffer cache, and hence should use a safe vnode device, such as
/dev/svnd0. Disk images that do not contain filesystems, such as
those used for swap space, should use unbuffered access vnode devices,
/dev/vnd0. The GENERIC kernel provides 4 vnode devices.

Once we have a device node for our filesystem, mounting it will be trivial.

First, download the OpenBSD install disk image you need. Copy this image
to a separate file, so you don't have to re-download the image if you make a
mistake. You could just re-download it, but remember: bandwidth costs money,
if not for you then for the people hosting the mirrors.

vnconfig(8) has a simple syntax: the command, the type of node
to use, and the disk image to mount. Since this is a complete disk image, to
use the appropriate node for a complete image, a whole disk is a "c"
partition. We want to access this device through the buffer cache, so
we'll use a safe vnode. Since this is our first safe vnode device, we can use
/dev/svnd0c. Our test disk image is
/tmp/floppy32custom.fs.

# vnconfig /dev/svnd0c /tmp/floppy32custom.fs

This disk image is now tied to that device node. You can mount it just as
you would any other device node.

Most people have probably never actually looked at a disk image before.
The boot file is the i386 system bootstrap loader, while
/bsd is the compressed kernel and installation utilities.

A df shows that this disk is 99 percent full, but that's OK; there's
enough room to cram on a single file and a directory. Create an
/etc/ directory, and make an /etc/boot.conf file
containing the single line:

set tty com0

Save your work, and unmount the disk image. The svnd0c device
will remain attached to this image until you unconfigure it. It's important to
unconfigure your vnode devices, because you cannot re-use that device until it
is unconfigured.

vnconfig -u /dev/svnd0c

Then copy your custom boot image onto floppy disk, and boot your
installation machine. It will go almost immediately to serial console, without
any user intervention.

You can use this same technique to make any other simple boot.conf
alterations on an OpenBSD system, or to mount disk images of other sorts. This
technique works for CD-ROM images, FAT disk images, ZIP disk images, or anything
else.