I am trying to make a FreeDOS boot disk with OSX that's compatible with the V86 library. I need to do this in terminal (in a bash script). I'm doing all of this on OSX High Sierra.
The boot disk I'm attempting to create is an .img of a floppy diskette. I'm aware there are other ways to provide bootable disks to V86 such as a hard drive image or a cdrom .iso, but I'm trying this way and would like to at least understand what I'm doing wrong.
I suspect the problem I'm having is in attempting to properly create the diskette image's Master Boot Record (MBR).
For context, here's my understanding of the MBR/boot process works:
In the old days on DOS or on Win9x machines, I seem to remember needing to run a format command with some switches on it that would make the MBR on the disk rather than just a FAT table at the front of the disk - though I'm not sure if I'm understanding MBR correctly.
My basic, simplified understanding of the MBR as that the MBR is the first 512 bytes of the diskette, which specifies how large the disk is, as well instructions that tell the BIOS to jump to the first instruction of a boot loader that'll kickstart the operating system. For example, on a DOS diskette there is/was a COMMAND.COM fiel on it. Presumably in that case, the MBR was written to tell BIOS to start execution on the first instruction in COMMAND.COM.
Figuring out where the first instruction is seems like it could be complicated because a number of things need to happen (I think..). The first 512 bytes of the disk will be reserved for the MBR, then after that a FAT is written down which takes another X bytes of the disk, then after the FAT, there's empty space to put files down. When a file such as COMMAND.COM is written to the disk, the FAT is updated with information about where on the disk the bytes are stored. For the MBR to know where to jump to to find the first instruction of COMMAND.COM, it would need to know where COMMAND.COM is stored, which could be anywhere on the disk in the empty space after the FAT, right?
Here's my current attempt at creating the disk:
# create a 720k empty img file with all zeros in it
dd if=/dev/zero of=myfloppy.img bs=1024 count=1440
# attach our .img file without mounting it, saving the attached name such as "/dev/disk2" in the var ${DEVICE}
DEVICE=`hdiutil attach -nomount myfloppy.img`
# attempt to use diskutil to format the device as a bootable FAT12 diskette
# question: are dos boot diskettes supposed to be FAT12, FAT16, or FAT32?
diskutil eraseVolume "MS-DOS FAT12" MYFLOPPY bootable ${DEVICE}
# detach our unmounted .img file
hdiutil detach $DEVICE -force
# mount our source freedos image fetched from the V86 demo page, this mounts as /Volume/FREEDOS
# note that this sample image is also 720K
hdiutil mount freedos722.img
# mount our target .img file we just created, it'll mount as /VOLUMES/MYFLOPPY
hdiutil mount myfloppy.img
# copy minimal set of files necessary to boot the disk (probably dont need autoexec.bat ..)
# question: does the copy order of these files matter?
cp /Volumes/FREEDOS/COMMAND.COM /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/KERNEL.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/CONFIG.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/AUTOEXEC.BAT /Volumes/MYFLOPPY/
# unmount our disks
hdiutil unmount /Volumes/MYFLOPPY/
hdiutil unmount /Volumes/FREEDOS/
#TODO: might need to detach our image files even though we did mount/unmount above
That script above gets me close to bootable, the V86 startup shows "FREEDOS" rather than complaing about the disk not being bootable, but it just hangs after saying "FREEDOS", rather than continuing the boot process.
I've also tried various other ways/attempts of creating the MBR, in all of these cases I created the blank img file with the dd command, then ran these on it to create the MBR, then copied files as shown above.
# Attempt #1: After the files are copied to the target disk, try to copy the 512 byte MBR from the source image to mine, if this worked I would be surprised, it didn't.
# this shouldn't work afaik because the MBR on the source image will have instructions to jump to the first instruction in COMMAND.COM as it's layed down on the source disk, which likely isn't where it is on our target disk.
dd if=freedos722.img of=myfloppy.img bs=512 count=1 conv=notrunc
# Attempt #2: try using the diskutil partition instead of erase disk command
diskutil partitiondisk ${DEVICE} 1 MBR "MS-DOS FAT12" "MYFLOPPY" 100%
# Attempt #3: try same as above, but with FAT16 (shouldn't work, didn't, because source img was FAT12)
diskutil partitiondisk ${DEVICE} 1 MBR "MS-DOS FAT16" "MYFLOPPY" 0B
# Attempt #4: use the newfs_msdos command without any diskutil commands
newfs_msdos -F 12 -v MYFLOPPY $DEVICE
# Attempt #5: use fdisk rather than any diskutil or newfs_msdos commands
# I *think* this is making an MBR, but not sure, maybe just making a partition
#note that I have no idea what to specify here for cylinders (c) and heads (h) and just copy/pasted this from somewhere
fdisk -i -c 1024 -h 255 -s 1440 -b 512 -a dos ${DEVICE}
# Attempt #6: use fdisk to create MBR / FAT, then use fdisk to mark that partition 'active'
fdisk -i -c 1024 -h 255 -s 1440 -b 512 -a dos ${DEVICE}
fdisk -e ${DEVICE}
#fdisk -e puts us in an interactive edit mode, so we do the following
type 'a', then enter # gets us into 'set partition as active' mode
type '1', then enter # sets partition as active
type 'w', then enter # writes the MBR with the partition now marked active
I've also tried various incantations where I mix the commands above, such as running diskutil partition then running the fdisk -i command to see if there's something fdisk will do to fix the MBR for the given existing partition.
I'm aware that there are long ways to create a bootable diskette, but I want to do this in a script. These methods are listed here for completeness sake in case others are looking for possible ways to do this:
1: Use the FreeDOS installer in a virtual env such as QEMU or VirtualBox, then save an image of the created floppy diskette.
2: Use an ancient machine to create a bootable diskette from an actual DOS or Windows installation.
I thought perhaps V86 has a very narrow chance of booting a diskette if anything is wrong, which wouldn't make sense as its just emulating x86, but I tried booting from several of the creation attempts with qemu too. For anyoen who's trying to do that, you can easily install qemu with homebrew, then boot a simple VM with this:
qemu-system-x86_64 -fda myfloppy.img
And a link to a V86 issue where the developer mentions how to make QEMU images via full OS installation processes that'll work with V86:
https://github.com/copy/v86/issues/128
If you're unfamiliar with V86, it's a x86 emulator written on top of asm.js that runs a virtualized OS in a browser.
The author has various Linux, Windows, and DOS demo operating systems running on v86 on his personal host:
It took a little bit for me to figure out how to run just his FreeDOS demo image locally without the big demo that requires downloading multiple OS images, here's my source for that:
<!doctype html>
<script src="libv86.js"></script>
<script>
"use strict";
window.onload = function() {
var emulator = window.emulator = new V86Starter({
memory_size: 32 * 1024 * 1024,
vga_memory_size: 2 * 1024 * 1024,
screen_container: document.getElementById("screen_container"),
bios: { url: "seabios.bin", },
vga_bios: { url: "vgabios.bin", },
fda: { "url": "freedos722-t.img", },
autostart: true,
});
}
</script>
<div id="screen_container">
<div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
<canvas style="display: none"></canvas>
</div>
The FreeDOS .img file that works with V86 was fetched from here: