4 June 2007
In building a pair of OpenBSD firewalls, I wanted to minimize points of failure. Hard drives are one of the most failure-prone components of a server, and since a dedicated firewall doesn't need gigabytes of storage, I went with Compact Flash storage with an IDE-to-CF adapter. This vignette quickly explains how to prepare a flash card to boot OpenBSD. I plan to address the larger issue of building dedicated, redundant OpenBSD firewalls in a separate article.
The OpenBSD boot process can be a bit daunting to the newcomer. Though there's plenty of detailed documentation that explains how things work, piecing it together for an embedded application such as this can take a while unless you know what you're doing. Though I give a little recipe of sorts here, I'll add the disclaimer that every system configuration is a little different and blindly entering commands without some understanding and verification of what they do can only get you into trouble!
There are basically four things that need to happen to prepare a disk for booting a kernel:
- Write a master boot record (MBR) and partition table;
- Edit the disk label to define the partitions for OpenBSD;
- Initialize the filesystem; and
- Copy and "install" the boot loader on the card.
First, some background about the hardware. I've got an old laptop I'm using to stage the flash cards before installing them in the firewalls. The cards are 256 meg SanDisk Compact Flash cards, though these instructions should apply to just about any size or flavor of card. (I did run into trouble on my firewall machines with newer cards that support direct memory access (DMA): though they worked fine with both the PCMCIA adapter and a USB reader, some IDE-to-CF adapters don't support DMA and, unless the motherboard's BIOS can be configured to disable DMA, they will either run very slowly or won't work at all.)
For accessing the card on my staging laptop, I'm using a SanDisk Compact Flash PC Card adapter, which slides right into the laptop. USB adapters will also work, but note that disk device name may be slightly different than the example here.
Next, a few handy reference links that will explain the below commands in much more detail. If you run into problems, or you don't understand what's going on, these should help (somewhat specific to the i386 platform):
- OpenBSD FAQ: Disk Setup: Instructions for managing disks under OpenBSD.
- OpenBSD fdisk(8) Manual: MBR partition maintenance program.
- OpenBSD disklabel(8) Manual: Install, examine, or modify the label on a disk drive.
- OpenBSD installboot(8) Manual: Install a "first-stage" boot program into the boot area of a disk partition.
- OpenBSD biosboot(8) Manual Page: i386-specific "first-stage" boot program.
- OpenBSD boot(8) Manual Page: i386-specific "second-stage" boot program.
wdc2 at pcmcia1 function 0 "SanDisk, SDP, 5/3 0.6" port 0xa000/16
wd1 at wdc2 channel 0 drive 0: <SanDisk SDCFB-256>
wd1: 1-sector PIO, LBA, 245MB, 501760 sectors
wd1(wdc2:0:0): using BIOS timings
You need to take note of the device name, which will probably start with either wd or sd. For example, if you're doing this on a laptop with a single IDE hard drive using a PCMCIA adapter, the device is going to be wd1 (since wd0 is already taken by your hard drive). On the other hand, if you're using a USB adapter, the device is going to be sd0 (since you don't have any other SCSI disks). Of course, your particular mix of drives and devices is going to determine the device name: make certain that the device name you use in the below commands is indeed the flash card! I'll be using wd1 in the example.
All of the below commands must be run as root (or under sudo). Be sure to replace wd1 with your card's device name!
- Initialize the master boot record partition data:
fdisk -i wd1 If you want to see what's on the device without changing anything, just run: fdisk wd1
Frequently it's instructive to view the partitions with this command both before and after updating the MBR. On a virgin flash card, you'll probably see one DOS partition; on an updated card, you'll see one OpenBSD partition.
- Edit the disk label, deleting any existing partitions and adding a 4.2BSD partition for the whole card (or however you want to divide it up, but the rest of these instructions assume a single 'a' partition):
disklabel -E wd1 Print the existing partitions with the command 'p'; delete, for example, an existing 'a' partition with 'd a'. Don't delete partition 'c' - that's necessary and always present. Add a new 'a' partition with 'a a'; it should be of type '4.2BSD' (the default values the add command offers should be fine). The '?' or 'h' commands print some help. Quit the utility and write the new label with the 'q' command. You can print out the disk label without changing anything using:
Again, it's sometimes handy to print the label both before and after your changes to see what's going on.
- Initialize a filesystem on the 'a' partition (note that we append the partition letter to the device name):
- Create a mount point on your staging machine for the card:
mkdir /flash Note that /mnt is used by some small-footprint OpenBSD distributions (e.g., flashboot) while building, so it might not be a good choice for your mount point.
- Mount your partition. We'll use a couple of options to minimize writes to the card and just to be conservative:
mount -o sync,noatime /dev/wd1a /flash
- Copy the boot loader over to the flash card:
cp -p /usr/mdec/boot /flash
- Tell the MBR where on the disk your boot loader is:
cd /usr/mdec; ./installboot /flash/boot biosboot wd1
Slight aside: One thing that concerned me about this command is the "/flash/boot" parameter: given all of the examples I had read, I wasn't sure if prepending the mount point was going to work since the disk is mounted as "/" on the firewalls. However, what matter here are the file's block and inode on the disk, not its path. This part of the boot process happens before mount points come into play.