This particular BIOS actually changes two bytes in the 512-byte block read, after placing it in memory at 0x7E00 and before returning from the INT 13h call.
The current code (and binary file) I linked to, modifies the word at offset 0x12F within that buffer. Offset 0x7F2F. This happens to be the NULL and SPACE chars just after the 'SPT:' string literal.
Code:
small_params_spt db ' SPT: ',0
small_params_total db ' Total Sectors: ',0
The zero at the end of the first line and the space before the
T in
Total in the second line.
So, with this in mind, I made a few modifications, which changed the position of
small_params_spt in the code expecting two different chars to be modified.
Two different chars were modified, but not as I expected. This time the same two chars were modified with the same new value but at:
Code:
small_params_cyls db ' Cylinders: ',0
small_params_heads db ' Heads: ',0
The zero at the end of the first line and the space before the
H in
Heads in the second line.
I thought maybe it was coincidence that I modified the code enough to move the data to happen to be at this point. Not that case.
The BIOS actually found a NULL and a SPACE char and modified it.
Now, what is interesting is that the value found is:
Code:
00 20
and the new value it writes to that memory is:
Code:
FF 2F
Note that the first two bytes are actually an EMPTY FAT ENTRY. i.e.: In the buffer at 0x07E00, the first sequence of a 12-bit value of zero is changed to the second set of bytes.
The BIOS is actually marking an entry in the FAT (or what it thinks is a FAT) as used.
Here's my proof: (Well at least what I have so far. I haven't investigated further)
The second sector of the disk, of a 1.44 meg floppy, is the first FAT. The BIOS evaluated my "image" as a FAT-12 volume and has stored a cache of (at least) the second sector in memory. For some reason, it has found and marked the first free FAT entry as used (0xFFF). Then when I read the sector of the disk, it returns the cached sector it thinks is the first sector of the FAT.
This tells me that the BIOS in question is actually emulating the disk as its own version of a FAT12 volume and returns its modified FAT instead of the actual sector physically residing on the disk.
In theory, this will work just fine *IF* the volume is indeed an actual valid FAT12 volume. However, this leaves two questions:
1) Why is it finding an empty FAT entry and marking it as used (0xFFF)
2) What is it actually writing to the (cached) volume at that found cluster.
To prove my findings even more, if I move the first instance of the 12-bit value of 0x000 to not align on a 12-bit cluster entry, the BIOS finds the *next* aligned 12-bit value of 0x000. This tells me it is actually looking for a free cluster entry in a FAT12 FAT.
If I want to investigate further, I could find out which entry this actually was (which I have), and read the 512-byte sector from the disk. Would the BIOS return the actual data from the (USB) drive or would it return a cached sector (cluster, since clusters are one-sector in size)? If it returns a cached sector, what now occupies this cached sector? Definitely not what I, as a newbie would think it would be if I am at the first stages of my project and have a multi-sector boot sector which includes this found (cached) sector.
Now, before you get too far into this, yes, most of the time, I would have a completely valid FAT12 volume on the (USB) disk and this would not matter. However, I want to make two points:
1) A newbie that has yet to create a file system, solely wants to create a multi-sector boot sector (and most newbies do exactly this) to see if they can boot their new project. What happens when this BIOS modifies the first three-nibble null value it finds? (P.S. This three-nibble value has to be aligned on a 12-bit cluster entry as well). For example, what if the second sector of my multi-sector boot sector contains the following:
Code:
SomeString db 'A String to Print',0
AnotherString db ' This string starts with a space char which has a value of 0x20',0
When the newbie tells the BIOS to print the first string, the BIOS will actually print both strings with a value of 0xFF 0x2F in-between each string. Exactly what is happening in my example I link to above.
2) The BIOS is actually emulating a FAT 12 volume, not a 1.44M floppy disk.
To make a long story short, ha ha, this is actually a rare case where the user has placed a valid FAT12 BPB at the start of the disk, yet doesn't have a valid FAT12 volume on the disk. When would this happen in real life? I merely show this for two reasons, one that this little "bug" caught me, and two, this proves that the BIOS (at least the one in question here) can and does modify your boot sector/volume data when emulating the USB as a disk.
Again, this is a rare occasion; you have to have the (almost) exact sequence I have shown; you have to be booting as a legacy BIOS boot; and you have to be using a non-conforming FAT volume to get this to happen.
Though my whole point is......It did happen. :-)
Ben
P.S. Please note that I am not trying to start/continue a fight of any kind--a fight of who is right and who is wrong. I am merely trying to prove, for a newbie's sake, that if you wish to boot your code from a USB disk from a Legacy BIOS boot, *and* use a FAT12 formatted volume, you *must* have a valid FAT12 volume and BPB, or it will not work...
I removed both the BPB and the partition table entry from my example and this particular BIOS booted my code without the (erroneous) modification mentioned above.