See also: part 1, part 2 and part 3.
Updates:
- 2016/05/02 – Added link to David Ladd’s experiment.
In the first installment, I discussed a bit about how the Radio Shack Color Computer boots OS-9 using the Disk BASIC “DOS” command. I ended the article by mentioning David Ladd’s exciting experiment to place the OS-9 boot track in ROM on a CoCoSDC interface. The advantages of this would be:
- No need to write out the kernel boot track to a boot floppy (or virtual floppy).
- A whole extra track of disk space on any boot disk.
- Faster booting, since copying from ROM would be faster than loading the 18 boot sectors from a floppy drive.
Number 2 is not a huge deal on a hard drive since 4.5K isn’t much space. Neither is number 3 since reading 18 sectors from a virtual floppy on the CoCoSDC is blazing fast. I can already do a complete OS-9 boot to a shell prompt in about 3 seconds. But, faster is faster. It’s number 1 I want to focus on.
The Problem With Cobbler
The OS-9 utilities cobbler and os9gen were written to work on floppy disks. historically, that’s all anyone has ever used them on — even if the floppy was a virtual one contained on an RGB-DOS/HDB-DOS hard drive partition, or .DSK image file across Drivewire.
CoCoSDC allows you to create .DSK image files and mount them as if they are a floppy disk. The CoCoSDC decides what to do with them based on the size of the .DSK file. See the “Disk Geometry Table for DSK Images (without header)” table on the CoCoSDC blog. Basically, any .DSK file with more than 2880 sectors (as many as an 80 track quad density floppy could have) will be treated as a hard drive image.
I’m not quite sure what this implies, since if you mount such an image, Disk BASIC will still see and use the first part of it as a 35-track single sided floppy disk*. To Disk BASIC, all it knows it Tracks 0-34 each contain Sectors 1-8 and each sector is 256-bytes. If you mount such a large .DSK image and then type “DOS”, Disk BASIC will go out to Track 34, Sector 1 and start loading things in to memory at $2600, same as if it was a real floppy disk.
* Is this true? It seems to be. If it’s not, what I am about to describe shouldn’t be working.
Track 34, Sector 1 is sector number 612 (34 tracks * 18 sectors per track = 612). As long as a kernel boot track is found there, you should be able to attach a 128MB .DSK image, type “DOS” and boot in to OS-9 (assuming the boot track has the proper OS-9 booter on it for the CoCoSDC hardware, and there is a OS9Boot file properly set up, too).
This is exactly how the NitrOS9 CoCoSDC sample .dsk image works. Mount it, type “DOS”, and in seconds you are at a NitrOS9 shell prompt. The NitrOS9 makefiles create the .dsk image using the Toolshed tool “os9”. Toolshed supports formatting a .DSK image for OS-9, os9gen-ing a bootfile on to it, and dsave-ing files and directories over to it. You end up with a large bootable .DSK file that is formatted for OS-9, has a “track 34” boot track, and the OS9Boot file linked in at sector 0. Magic.
You would think you could do the same thing via OS-9, but you would be wrong. os9gen and cobbler will not work because they were never written for anything but a physical floppy drive. In a moment, I will explain why this may be an incorrect statement.
If you mounted an OS-9 boot .dsk image in DRIVE 0, and a formatted 128MB OS-9 hard drive .dsk image in DRIVE 1:
DRIVE 0,"OS9BOOT.DSK" DRIVE 1,"128MBHD.DSK"
…and then you boot in to OS-9 and try to “cobbler /sd1”, bad things happen. cobbler and os9gen will try to place the kernel boot track at track 34, sector 1. If this was a physical floppy interface, seeking to Track 34 and Sector 1 would work, but to OS-9, there is no such thing as physical tracks or sides. Every disk device is just a bunch of logical sectors, and it’s the device drivers job to translate whatever the hardware has to a series of logical sectors. The cobbler and os9gen utilities use something called “math” to figure out what logical sector corresponds to Track 34, Sector 1. It does this with a simple forumla:
logical_sector = 34 * 1 * sectors_per_track * sides (see side note)
Side Note: Sides is used because on a double sided floppy, tracks are interleaved between the two sides of the disk. On a single sided 40-track floppy, there are 720 sectors which make up the top side of the disk. On a double sided 40-track floppy, there are 1440 sectors. The first track’s worth of sectors (sectors 0-17) is written to the first track of the top side, then the next track’s worth (sectors 18-35) is written to the first track of the bottom side of the disk. The job of an OS-9 disk driver is to translate the logical sectors OS-9 uses to whatever format the hardware uses. In the case of floppy disks, it turns 1440 logical sectors of a double sided 40-track disk in to two sides of a physical floppy. On modern hard drives, the drive controller speaks sectors, so the only thing the OS-9 driver has to do is deal with the 512-sector size issue on modern drives, but that’s a topic for another series of articles.
If the hard drive is configured with a different number of sectors per track than the 18 used by a floppy disk, the math will be wrong. cobbler/os9gen will multiply the drive’s sct (sectors per track) setting by 18 (hard coded assumption) and either 1 or 2 sides (see note below) and try to write the kernel track at that location. The end result is a file being written in the wrong place on the .DSK image than where the “DOS” command expects it to be.
Side Note 2: For sides, cobbler and os9gen aren’t using the actual sides field — they are using a bit in the DD.TYP field that indicates if the device is single or double sided. For a proper OS-9 hard drive descriptor, the hard drive bit is set and the sides bit is clear, so cobbler and os9gen should see a hard drive as a huge single sided floppy disk.)
But wait! It gets worse…
While OS-9/6809 can theoretically support a 4GB hard drive, it could only do so by using a large cluster size (having multiple sectors representing one cluster). For me, I am using the largest size possible when each cluster represents one sector. Below, when I mention “cluster” or “sector”, they effectively mean the same thing for me since I am using a cluster size of one sector. Get it? Good.
On my system, in order to get the largest 1 sector cluster hard drive possible (128MB, see note below), I configure my hard drive descriptor to be 65,535 tracks (cyl=$ffff), 8 sides (sid=$8) and 1 sector per track (sct=$1). This (65535 * 8 * 1) gives me 524,280 sectors, which is as large as we can get.
As part of the file system, a series of bits is used to represent which clusters are used or are free. This is called the DAM (disk allocation map) and it serves the same purpose as the FAT table does on a PC. The largest the DAM can be is 65,535 ($FFFF) bytes and since each byte represents 8 clusters. The more clusters, the larger the DAM must be.
DAM Note: Since there are only $FFFF (65535) bytes in the DAM table, with each byte representing eight clusters, the largest amount of clusters OS-9/6809 can handle is 524280 (65535 * 8). 524280 * 256 bytes per sector is 134,215,680 which is just shy of 128MB (using 1024 bytes of a K). If only we had one more byte in the FAT, then we could fully use the 128MB. By using a larger cluster size, where each DAM bit represented 2, 4, 8, or 16 sectors, the total size of the hard drive can as much as 4GB. The 4GB limit is because OS-9 can only access up to 16,777,215 ($FFFFFF) logical sectors.
Sector Note: If you are clever, you might be thinking “oh, that’s with a 256-byte sector drive, so on an IDE drive where every sector is 512-bytes, we should be able to access 8GB!”. Very clever, but that would only be the case if OS-9 was not using deblocking drivers that split each physical 512-byte sector in to two logical 256-byte sectors. The max sector value that OS-9 can read is $FFFFFF 256-byte logical sectors. If those just happen to be half of each 512-byte sector on an IDE drive, then sure, it’s accessing an 8GB drive, but wasting half of each sector since OS-9 still only sees it as $FFFFFF 256-byte sectors. Now stop being clever so I can finish this article.
Where was I? Oh, right. Trying to use the largest hard drive I can…
If I ran cobbler or os9gen on this 128MB drive, it would multiple the number of tracks (cyl=$ffff) by 34 and then try to write the kernel boot track starting at sector 2,228,190. DOS will be looking for it at sector 612, so this clearly won’t work.
Theoretically, if I had made my hard drive use 29,126 tracks (cyl=$0x71C6), 18 sectors per track (sct=$12), and one side (sid=$1) like a simple floppy disk, I might be able to get this to work. cobbler and os9gen would do the math (track 34 * 18 sectors per track) and end up at sector 612 like it is supposed to and all would be well in the world. Except it isn’t.
First, that only gives a hard drive size of 524,268 sectors, which is 12 sectors shy of our max. I wouldn’t sleep well at night knowing I could be using 12 more sectors just by using more optimum settings. But that’s not the real issue. The real issue is that cobbler and os9gen were never written to work on hard drives. Taking a peek inside the cobbler source code, I find this:
* Request memory for the FAT buffer + 256 bytes for stack space R.G. ldd <DD.MAP addd #size+256 os9 F$Mem
First, the D register is loaded with the DD.MAP field from logical sector 0. That field holds the size of the DAM bitmap which, on a 128MB hard drive image, is $FFFF.
Next, it adds 256 to this value which, on a 16-bit register, rolls over and D ends up being 255.
Finally, it allocates memory which is will use for stuff. Instead of getting $FFFF+256 bytes, it’s really only getting 256 bytes and “bad things can happen.” This is a bug. Cobbler was not written to be used on a disk with that many clusters.
ERROR #244
Maybe that is why cobbler exits with an ERROR #244 when you try it on a hard drive configured that way. At least it does on mine.
As-written, cobbler and os9gen will fail here. They need to be updated to handle things differently, or at the very least, exit with an error if the drive is too large. And honestly, the easiest fix might be to do it like the Toolshed os9 utility does and just seek to sector 612 in the file (or 1224 in the case of a double sided disk). That’s really the only math we need for the boot track.
Up next: Finally, the original promise of this article… How to manually make a NitrOS9 hard drive bootable using only a disk editor, the copy command, and some duct tape.
Pingback: Manually making a bootable NitrOS9 hard drive image – part 3 | Sub-Etha Software
Allen, thanks for the excellent write-up on getting a bootable NitrOS9 disk image for the CoCoSDC working. I followed your directions and was able to get a 128MB image working in short order. Just recently I created a 1 GB partition that is working well (8-sectors per cluster) by increasing the number of tracks in the device descriptor and manually copying the boot track to the proper sectors and modifying the disk allocation map to protect the boot track. It was a little convoluted but since cobbler and OS9Gen won’t work and I don’t have the lwtools development system set up it was the only way.
One day I’ll write a complete B09 program to do this.