I'd grabbed this Conner CFS210A hard disk from my junk box — according to Hard Drive History, one of the pioneering Chinese-made hard disks — but having installed FreeDOS on it I couldn't get it to boot...
... wait a minute — what machine did that disk come out of? Shouldn't I have imaged it first before overwriting it?
Luckily I knew that I'd only overwritten the start of the disk, with a new partition table and a tiny partition for FreeDOS. I was pretty sure this wasn't from one of my machines, but now I was curious... and with FAT filesystems, I knew that you could corrupt much of the start of the filesystem and still be able to reconstruct it. So here's a worked example.
The filesystem should start with the boot block and other reserved sectors, then two copies of the FAT, then the root directory, then the data clusters. A FAT directory looks pretty distinctive: 32-byte entries starting with a filename. Hexdumping the image showed that there was an MS-DOS 5 root directory at 0x37a00 (sector 445) — MS-DOS 5 means it's almost certainly a FAT16B filesystem.
We can reconstruct the boot block by generating a new filesystem using
mkdosfs
and copying the surviving data over.
Let's assume that the sector size is 512 bytes (as usual). To get the layout right, we need to know how many sectors are in a cluster. We can work these out by looking for two of the files in the root directory:
00037b00 43 4f 4e 46 49 47 20 20 53 59 53 20 00 00 00 00 |CONFIG SYS ....|
00037b10 00 00 00 00 00 00 53 a2 96 24 5e 03 90 00 00 00 |......S..$^.....|
...
00037b40 41 55 54 4f 45 58 45 43 42 41 54 20 00 00 00 00 |AUTOEXECBAT ....|
00037b50 00 00 00 00 00 00 44 73 97 24 bc 04 d6 00 00 00 |......Ds.$......|
So config.sys
is 0x90 bytes long, with the first cluster being 0x35e
(you then find the subsequent clusters by looking them up in the FAT).
This file usually starts with DEVICE=
, which I found in the hexdump at
0x397a00: sector 7357.
Similarly, autoexec.bat
is 0xd6 bytes long, with the first cluster
being 0x4bc.
This usually starts @ECHO OFF
, and there's a plausible-looking file
that starts at 0x4f5a00: sector 10157 (although it has an extra
SMARTDRV
invocation at the top).
We found those two files are 10157 - 7357 = 2800 sectors apart, and the directory says they're 0x4bc - 0x35e = 350 clusters apart, so a cluster is 2800 / 350 = 8 sectors = 4096 bytes (which is plausible).
From the position of config.sys
in the image, cluster 0's data should
be at 0x397a00 - (4096 * 0x35e) = 0x39a00.
However, cluster numbers 0 and 1 have special meanings, and the first
cluster that's actually stored on disk is cluster 2, immediately after
the root directory.
Cluster 2 starts at 0x39a00 + (2 * 4096) = 0x3ba00 (sector 477).
As each directory entry is 32 bytes long, the root directory is
therefore (0x3ba00 - 0x37a00) / 32 = 512 entries long.
Before the root directory should be the two FATs, which on a healthy filesystem are identical. FATs also look distinctive: each cluster's entry is the number of the next cluster or 0xffff for end of file, so any file that's more than one cluster long will produce a series of increasing numbers ending in 0xffff. This also means that entries at the start of the FAT will tend to have low numbers.
By inspection, there's FAT data at 0x6c00, but it's not the start of the FAT since the numbers start at 0xF01:
00006c00 01 0f 02 0f 03 0f 04 0f 05 0f 06 0f 07 0f 08 0f
The last allocated cluster is 0x36B4, so the filesystem has 0x36b4 * 4096 = ~57 MB of data on it.
Scanning forwards until the numbers go down again finds the start of the second FAT at 0x1e400, which is intact:
0001e400 f8 ff ff ff ff ff 04 00 05 00 06 00 07 00 08 00
The second FAT's data from 0x20200 onward is the same as the first FAT's from 0x6c00, so the start of the first FAT should have been at 0x6c00 - (0x20200 - 0x1e400) = 0x4e00.
The length of the FAT is therefore 0x1e400 - 0x4e00 = 0x19600 bytes. This is consistent with the root directory starting at 0x1e400 + 0x19600 = 0x37a00. The biggest possible cluster number in the FAT is 0x19600 / 2 = 0xcb00, which means the maximum amount of data that could be allocated in the FAT is 0xcb00 * 4096 = ~212MB, which is just about right for a 210MB drive.
The layout of the filesystem as a whole must look like:
- sector 37 (0x4a00) or 38 (0x4c00): 1 or 2 reserved sectors (corrupt)
- sector 39 (0x4e00): FAT 1 (partially corrupt), 0xcb00 entries
- sector 242 (0x1e400): FAT 2, 0xcb00 entries
- sector 445 (0x37a00): root directory, 512 entries
- sector 477 (0x3ba00): cluster 2+ data, (0xcb00 - 2) = 0xcafe clusters
So the next block after the end of the filesystem is at sector 477 + (0xcafe * 8) = sector 416205; the filesystem as a whole is 416205 - 37 = 416168 sectors long.
We can now make a new filesystem image with the parameters we know:
$ dd if=/dev/zero of=rebuilt bs=512 count=416168
$ mkdosfs -F 16 -r 512 -R 2 -s 8 -S 512 rebuilt
mkdosfs 3.0.9 (31 Jan 2010)
rebuilt has 64 heads and 32 sectors per track,
logical sector size is 512,
using 0xf8 media descriptor, with 416168 sectors;
file system has 2 16-bit FATs and 8 sectors per cluster.
FAT size is 208 sectors, and provides 51964 clusters.
There are 8 reserved sectors.
Root directory contains 512 slots and uses 32 sectors.
Volume ID is 8cf86786, no volume label.
And try copying something into it to see where things are:
$ mcopy -i rebuilt SomeFile ::
Looking at a hexdump shows:
- sector 8 (0x1000): FAT 1
- sector 216 (0x1b000): FAT 2
- sector 424 (0x35000): root directory
- sector 456 (0x39000): cluster 2+ data
The FAT is slightly longer than we want, but that's not a problem. We can now copy the intact FAT from the original filesystem into both FAT 1 and FAT 2 in the new one, and then copy the rest of the data starting with the root directory:
$ dd if=cfs210a.img of=rebuilt skip=242 seek=8 count=203 bs=512
$ dd if=cfs210a.img of=rebuilt skip=242 seek=216 count=203 bs=512
$ dd if=cfs210a.img of=rebuilt skip=445 seek=424 bs=512
And now we can look at the contents using mtools:
$ mdir -i rebuilt
Volume in drive : is MS-DOS_5
Volume Serial Number is 4530-D4E3
Directory for ::/
dos <DIR> 1994-08-10 12:20
windows <DIR> 1994-08-10 16:47
win32app <DIR> 1996-09-03 11:01
command com 54645 1994-05-31 6:22
wina20 386 9349 1994-05-31 6:22
config sys 144 1998-04-22 20:18
mouse drv 10672 1992-04-06 16:01
autoexec bat 214 1998-04-23 14:26
8 files 75 024 bytes
155 676 672 bytes free
$ mtype -i rebuilt ::autoexec.bat
C:\DOS\SMARTDRV.EXE /X
@ECHO OFF
...
So: as I thought, this definitely wasn't one of mine — it probably came from a UKC departmental machine, judging by the software installed and the phone numbers in one of the files. Bit of an anticlimax, but if I ever need to do this again, I now know how...