This blog has previously examined a very very strange code fragment in the BIOS module of DOS. To recap, when deciding whether a boot sector might have a valid BPB, DOS checks whether the first byte is a relative jump (opcode E9h) or a short jump (opcode EBh), both used by different DOS versions. But it also checks for a “direct jump” with 69h opcode.
The code looks like this in the MS-DOS 3.21 OAK, source file dated May 1, 1987:
cmp byte ptr cs:[DiskSector],069H ; Is it a direct jump? je Check_Signature ; don't need to find a NOP cmp byte ptr cs:[DiskSector],0E9H ; DOS 2.0 jump? je Check_Signature ; no need for NOP cmp byte ptr cs:[DiskSector],0EBH ; How about a short jump. jne BadDisk cmp byte ptr cs:[DiskSector]+2,090H ; Is next one a NOP? jne BadDisk
The code is not materially different in the MS-DOS 3.3 OAK, source file dated July 24, 1987:
cmp byte ptr cs:[DiskSector],069H ; Is it a direct jump? JE Check_bpb_MediaByte ; DON'T NEED TO FIND A NOP cmp byte ptr cs:[DiskSector],0E9H ; DOS 2.0 jump? JE Check_bpb_MediaByte ; NO NEED FOR NOP cmp byte ptr cs:[DiskSector],0EBH ; How about a short jump. JNE INVALIDBOOTSEC cmp byte ptr cs:[DiskSector]+2,090H ; Is next one a NOP? JNE INVALIDBOOTSEC
The labels are different but the logic is identical. But of course there is no such “direct jump” on x86, and the 69h opcode (undocumented on 8086, IMUL on later CPUs) makes no sense whatsoever. So what is it?
A reader previously floated the idea that the code might have been intended to support Atari ST floppies. That sort of makes sense, and sort of not. Let’s start with how it does not make sense.
The Atari ST used the Motorola 68000 CPU (ST refers to Sixteen/Thirty-two, referring to the 68k CPU’s external and internal data width) and while boot sectors started with a jump instruction (BRA.S), its opcode was 60h and not 69h.
But there are numerous ways in which Atari ST does make sense. Atari ST was one of a handful of non-PC, non-x86 platforms that used FAT-formatted floppies. The Atari ST used the same 3.5″ DD (initially) media used by PCs. It was actually possible to exchange data between Atari ST and DOS on 3.5″ floppies.
The Atari ST was introduced in 1985. When was the mysterious opcode 69h check added to DOS? As it happens, we can pin down the timeline fairly accurately. Examining IBMBIO.COM in PC DOS 3.1 and 3.2 clearly shows that the 69h check was added in DOS 3.2. The IBMBIO.COM file in PC DOS 3.1 is dated March 1985, while in PC DOS 3.2 it’s December 1985. In other words, Microsoft must have added the 69h check sometime during 1985.
From the timeline perspective, adding support for Atari ST media in 1985 makes good sense. It also just so happens that PC DOS 3.2 was the first to support 3.5″ media.
The “direct jump” comment is less obvious but makes at least some sense. The 68k BRA instruction is direct in the sense that the relative offset is part of the instruction’s opcode sequence. Unlike 68k JMP, the BRA instruction does not support any kind of indirect addressing.
The opcode mismatch could also be explained. It could be a typo since ‘9’ and ‘0’ are right next to each other on the keyboard. It could also be a misreading; especially on handwritten text, a sloppily written zero might look like a nine. In addition, 8086 programmers might well not know 68k opcodes and thus would not spot the mistake.
What’s more, the incorrect check might easily have escaped testing. To begin with, Atari ST bootable floppies do start with 60h opcode (not 69h), but non-bootable ST floppies have no such requirement anyway. Except DOS does not require a valid BPB to work with a floppy disk. If a 720K floppy were formatted on an Atari ST, its boot sector would not be recognized, but its FAT media byte would be. DOS would be able to work with it just fine, and testers would not notice that the BPB validity check failed.
Note that the above is not true for Atari ST 800K floppies. DOS will not correctly deal with those unless they have a valid BPB (i.e. boot sector). That however is something which may not have been tested.
In summary, even though it’s actually wrong, adding the 69h check to support Atari ST disks is not as implausible as it seems. It’s by no means a solid proof but it’s not crazy. And if, as circumstantial evidence shows, the check was added to support some non-x86 platform in 1985, then Atari ST is a good explanation as any.
It doesn’t even have to be handwriting. An nth-generation photocopy of
hardcopy is often quite bad enough 😡
(Me’s been playing with some BIOS code from the 5150 technical reference
listing a couple of days ago. It was a scanned copy and me had to
double-check a *lot* of digits. The OCR didn’t quite match as much as
one might have hoped, either.)
Though in this particular case, me still maintains that the ’69’ may
very well have been a place holder.
Me supposes that, like with the ‘CALL 5’ mystery, we’ll learn the truth
eventually.
True, a photocopied or faxed printout can be just as hard to read.
I’ve read that Atari ST folks had interchange problems with PCs due to slightly different formatting. PC formatted disks worked fine between machines, but Atari ST formatted ones had problems in PCs.
https://info-coach.fr/atari/software/FD-Soft.php
Things might have gotten worse when Windows 95 came out and started mucking about with VFAT entries and the boot sector (the latter screwed up many a PS/2 Reference Disk).
I know with 9x and newer I always gave disks a label when formatting, since if it was blank, Windows would use it for VFAT storage and really confuse Apple’s PC Exchange and other tools.
I wonder if the DR-DOS source would have any answers given its somewhat shared heritage with GEM/TOS.
The 800kB format could not have been tested for a DOS release in 1985 because the Atari 1040ST (the first model with a double sided drive) wasn’t available until 1986.
The source for GEMDOS that Atari TOS is derived from is out there. That was a portable alternative OS to the advanced versions of CP/M. Rather a side project if the story on Dadhacker is accurate.
MS had proposed their own DOS plus Windows port for the prospective Jackintosh which might have been the source of the extra boot code.
Note that in Windows 10’s FASTFAT.SYS driver, the code checks for 0x49 (not 0x69). Whatever that is supposed to be…
https://github.com/microsoft/Windows-driver-samples/blob/16022c593787aef040b8a37ef697316e07f1322e/filesys/fastfat/fsctrl.c#L2546
The built-in floppy disk formatter in early versions of the Atari ST’s OS (TOS 1.00 & 1.02) did actually not set the media byte correctly: neither in the FAT nor in the boot sector. This is the reason behind the stories that claim that Atari ST disks are incompatible to MS-DOS/PCs.
The issue could be easily solved by formatting the floppy disk with 3rd party software. Also, it was fixed in the built-in formatter in TOS 1.04. From TOS 1.04 onwards, the formatter sets the correct media bytes and also adds an x86 jump for good measure, even if this makes the disk unbootable on a 68000, of course.
That’s fascinating. Thanks for the pointer. It’s really too bad that there’s absolutely no hint what the 0x49 check is there for. I’ll have to do a bit of digging and see if it’s always been there.
The recently leaked XP SP1 source code already has the check for 0x49. So the change is probably at least pre-2000…
That 0x49 check was there in NT 4.0 but not in NT 3.5. So it must have been added in 1994 or 1995. Quite possibly related to NT’s expansion to the RISC platforms (Alpha, PowerPC). But so far I haven’t found out what problem it was meant to solve.
It’s pretty clear that it didn’t come from DOS though.
OS/2 (2.x) checks that the first byte is either 0xE9, or 0xEB followed by a NOP (0x90) in the third byte. No other mysterious values.
Interestingly, the floppy drivers in the Windows NT DDKs only check for 0xE9 and 0xEB, so wherever 0x49 comes from I don’t think it would be found on a floppy.
I don’t think that’s quite true. The FlConsolidateMediaTypeWithBootSector() routine would be needed if the floppy’s BPB does not match the format standard for the physical media type. If it’s a “normal” floppy (e.g. a 3.5″ HD floppy formatted as 1.44MB) then the routine wouldn’t change anything. The 0x49 check in the FASTFAT module will still be done when NT tries to mount the filesystem on the floppy.
FWIW, on PowerPC, 0x49000000 would be an absolute jump instruction, as such:
0: 49 00 00 00 b 0x1000000
And the PPC systems NT tended to run on used FAT extensively too for their special firmware (covered on this very blog); and PPC supported was added between 3.5 and 4.0. But this could be making a wrong guess. I’d be curious what branch/jump instructions in MIPS and Alpha tended to look like.
The PPC floppies I looked at actually had regular x86 style boot sectors. There are only three code bytes at the start anyway, the OEM ID starts in the fourth byte. Not enough room for a typical RISC instruction.
At least on hard disks, PowerPC (PReP) needs a special partition, the MBR as such is not booted.
AFAIK, the TOS-included formatter did not have 800k, just “single sided” for 360k, and “double sided” for 720k, at least on TOS 1.02 and 1.04 on my MegaST 4. Various third party utilities could create 800k disks, ISTR using Kobold to do it a couple of years ago? But that’s a fairly “late” file manager, new enough to handle LFNs… I seem to recall there being several (older, late 80s or so) tools that could produce an 800k disk. Hm. Maybe I’ll have to dig out my MegaST and check some things…
The official Atari ST double sided format according to the July 1985 Service Manual for the SF-314 was 16 sectors of 256 bytes each per track. That format was never used by production Atari STs AFAIK but that would have been the format MS would have supported had any support for ST disks been included in MS-DOS in 1985.
It is a bit odd that both mysterious not a jump jump routines use “i” or “I.” Given the time between now and then, I would have expected someone from either IBM or MS to write an anecdote mocking the programmer at the other who botched the format routines. It might simply be a copyright infringement trap; only by copying DOS source code would one get such an incorrect comment.
There is another set of code that writes out the BPB and mentions the initial three byte jump: SYS. I don’t see anything there that would result in the 69h but the version for IBM Japan does things a bit differently.
Yeah, production ST disks are 9×512 per track… sometimes 10×512 (800k), very rarely 11×512 (that one really only worked if you were writing an entire track in one go, possible because the WD1772 could do it; in fact formatting on WD1772 FDCs is done by writing a “blank” formatted track, complete with CRCs, IDAMs, gaps, et al), sometimes games would mix 512 and 1024 byte sectors. Also not that uncommon to make it 82 cylinders instead of 80 for a bit more space on top of that.
Curious, what’s different about the IBM Japan version?
According the SYS.ASM in the DOS 2 public source code release, the Japanese version relies on a list sector which the regular IBM version does not. I haven’t done a dive into a Japanese DOS 2 implementation nor the appropriate matching BIOS so I don’t know what the actual effect of that is.
Compare the two PUTBOOT routines.
Yes, the ASCII ‘I’ caught my eye, and IBM was the first thing I thought of. It could be that the floppies in question weren’t bootable and if left in the drive when the machine was booting, they’d just hang.