Making DOS bootable USB hard disks

There are a number of guides online that show one how to create DOS bootable USB floppy disks, but these all follow the same theme:

Obtain preformatted floppy image.

Write image to USB stick.

The problem with that is that you're stuck with two things:

A DOS file system that can never hold more than 1.44 MB of data (ok, 2.88 MB if you manage to find a 2.88 MB image file).

A USB stick that is useless for anything else unless you reformat it.

The other problem is that a lot of these guides are written for Windows. This one is for FreeBSD!

I've had more than one occasion where a firmware update simply couldn't fit into 1.44 MB, even after deleting everything but io.sys, msdos.sys, and command.com.

So I decided to figure out how to create a bootable DOS hard disk manually. One key difference between a hard disk and a floppy disk in this context is that the hard disk has an MBR and so can have multiple partitions - one for your bootable DOS image, another for the rest of your USB stick. The other difference is that hard disk partitions can be much larger than 1.44 MB. By setting up your USB stick like this you could even have multiple OSes installed with a boot manager to select between them, or just have a small DOS partition and another for your normal data.

So the first thing you need to do is setup your MBR and partition table. There are some limitations with DOS in that its boot partition can't start beyond a certain offset on the disk. For simplicity I'll only be showing you how to set things up with your DOS partition at the beginning of the disk, but feel free to experiment.

All commands assume your USB disk is at /dev/da0. Adjust accordingly. Before you begin you will need:

The attached bootsect.gz file.

A bootable DOS floppy image, or any source of io.sys, msdos.sys, and command.com (an MS-DOS 6.22 image from http://www.bootdisk.com/ is one option).

It's important that you follow the next few steps precisely. Veering off from these instructions may cause the file system to be created incorrectly.

Take note of the start offset of the partition you created above. In this example it is 63. Create the file system:# newfs_msdos -B /full/path/to/bootsect -o 63 /dev/da0s1
You'll notice above the partition offset goes in the "-o" parameter. Make sure you specify a full path to the bootsect file or else newfs_msdos(8) will look in /boot.

Mount your file system:# mount_msdosfs /dev/da0s1 /mnt

Setup system files root directory entries:# cd /mnt && touch IO.SYS MSDOS.SYS COMMAND.COM
The order of the files above and their uppercase names is crucial.

Copy valid system files to your file system:# cp io.sys msdos.sys command.com /mnt/
(I haven't shown you where/how to get the above system files on purpose - they could come from many sources...)

Unmount:# umount /mnt

You're done for now. You should be able to boot up with your USB stick now.

Now if you look in /tmp/dos you'll see all the DOS files that are in the image. The most important ones are io.sys, msdos.sys, and command.com mentioned in the previous post, but you might want to grab all the others too... especially since you have plenty of disk space now.

The only minor annoyance left is to fix the volume label of your DOS partition. Unfortunately you can't specify one with "-L" to newfs_msdos(8) as that will cause it to create a root directory entry before the 3 system files. This will break bootability so the volume label has to be changed after creating your boot disk in post #1.

If anyone knows of a tool to rewrite volume labels in FreeBSD, please let us know. Otherwise the only option is to use a Windows box, sorry.

Ok, so there's a half fix for those confident with a hex editor:

# dd if=/dev/da0s1 of=/tmp/bs bs=512 count=1

Open /tmp/bs in your hex editor and modify offsets 0x2B to 0x35 inclusive (11 bytes). For labels less than 11 characters, use spaces as padding (0x20).

Save your changes and then:

# dd if=/tmp/bs of=/dev/da0s1 bs=512 count=1

This is a half fix because it doesn't create a volume label entry in the root directory structure further down in the file system. Some systems only bother to read the volume label from the boot sector though. If you're really obsessed you could create that entry with a hex editor too - let us know how it went.

The bootsect file attached in post #1 is a slightly modified DOS floppy disk boot sector. I started with the floppy image referenced in post #2, but I imagine others will work too.

Following on from post #2, copy the boot sector out of the floppy image:

# dd if=/path/to/image/file of=/tmp/bootsect bs=512 count=1

Open the resulting file in a hexeditor and modify offset 0x24 - change it from 0x0 to 0x80. You can also modify the OEM string if you like. It's at 0x3 to 0xA inclusive (8 bytes) and is space padded (0x20). I set it to "FREEBSD" in the file attached in post #1.

The bootsect file is useless as is - you need to feed it to newfs_msdos(8) when you create your file system.