To introduce with the conclusion, I’ve finally got my little disk driver – for the electronics project – detecting FAT formatted volumes (non-partitioned), and determining whether they’re FAT12, FAT16 or FAT32.
This is a surprisingly difficult thing to do, it seems. There’s not any handy flag anywhere that says what format the volume is. If it’s FAT, it has a two-byte signature, which isn’t a particularly unique one (0x55 0xAA, used frequently as a marker value, and thus not nearly as unlikely as you might think), at offset 510 (i.e. the last two bytes of the boot sector). While the boot sector’s meant to start with a jump instruction, I’m not sure if it’s unique, so I can’t directly validate that either. There are plenty of other fields, but it’s hard to be deterministic about the format based on them; many can have virtually any value, since a lot of them are ignored in numerous conditions.
The whole thing’s even more complicated than just that, because there’s some big differences between FAT12/16 and FAT32 in terms of what fields are in the boot sector, and where they are. For example, there’s a FAT name, which contains something like “FAT32 ” (the extra spaces are important; it’s an opaque 8-byte field). But, for FAT12/16, it’s in a different spot. Duh. Why have a field who’s only purpose, surely, is to distinguish between formats, if in each different format it’s in a different spot?
This is why Microsoft should have as much freedom for defining standards as Rob has naming them. :P
And to make things worse, while I cannot find a single statement as to how you’re meant to distinguish between them, I’ve found many which say things like not to rely on even the presence of the FAT name, let alone that it’ll be correct.
So, I’m just winging it for the moment. We can keep this as a pretty restricted system, so we only have to support the exact volume format we want to use, but still… I’d like to think we’re pretty flexible, in so far as handling all the FATs fine… but perhaps not.
It’s interesting to note that Microsoft states that Windows will never partition removable media (e.g. floppy disks, zip disks, USB disks, etc). So in theory you couldn’t possibly get an MBR (Master Boot Record) on an SD memory card, in Microsoft-land. Of course MacOS X, conversely, does not allow you to create an unpartitioned USB disk… both OS’s handle each other’s volumes perfectly well, as far as my testing has seen, yet claim that the other is doing it wrong. Hmph.
So for the moment there’s no partitioned-volume support, because it’s extra work we don’t need at this point. It leads to the land of MBR, EMBR, GPT, and many more acronyms – all created by Microsoft, and like the FAT boot sector, all completely and absolutely rooted. It’s like they had a million monkeys at a million typewriters, and didn’t even just pick the best one – they just merged all of them.
But things are looking good, anyway, with the volume driver. FAT is at least a trivial format to use…. disgustingly slow and inefficient, but simple. Except, of course, when you start supporting things like long file names, and all the bizarre behaviours accrued by 20 years of use and abuse.
In hindsight, perhaps we should have just used ext2 or something. ;)
Or HFS. :D
But HFS is a very complicate format, because it’s very efficient and very powerful; HFS+ even more so. I wouldn’t like to try to implement it on an AVR. I think I’d definitely run out of resources. I’m still not entirely sure how FAT support is going to turn out.
What we could have done is have our own partition type, and write to it as basically a single stream. I could then perhaps have mustered up a MacOS X file system plugin to read it. But that wouldn’t make Rob very happy, stuck in Windowsland.
In fact, we wouldn’t even need a driver on MacOS X, since like all real OS’s it mounts raw volumes in /dev, so I could just read directly from the SD memory card, skipping the boot sector. Hmm. That may be how it ends up… we’ll see.