How to identify an unknown disk using Fdutils
Introduction
This howto document describes how to read disks with non-standard low level formats using fdutils. It applies to disk which use different sector sizes, non standard densities, a different number of cylindrers (CPM disks, Commodore disks). It does not apply to disks which merely have a different filesystem (high level ).
The most useful program for exploring disks is fdrawcmd. It allows to issue raw floppy controller commands. I recommend that you use the most recent fdutils (5.2) with the most recent patch (2805), as some earlyer versions may have bugs which make some of the following tests fail without reason.
What to do to reset the floppy driver
Occasionally, while doing these tests, the floppy driver may get into an inconsistent state. To get out of this, do:
floppycontrol --resetnow 2
fdrawcmd recalibrate 0
fdrawcmd recalibrate 0
This will reset the floppy controller, and move the drive's head to a known (consistent) position.
If you see strange results, or you see floppy operations fail which formerly worked, try these three commands.
Finding out the data transfer rate
First, you need to find out the data transfer rate (roughly the density: high, double, single).
For this, you try out fdrawcmd readid 0
rate=x
, where x is 0, 1, 2, 3 If no rate is
supplied, fdrawcmd assumes rate=0
Example:
> fdrawcmd readid 0 rate=0 need_seek track=0
0: 0
1: 0
2: 0
3: 0
4: 0
5: 1
6: 2
disk change
The first 3 output bytes are error codes. The first byte should be below 7 (i.e. the example above succeeded). The last four bytes is a sector header. Byte 3 is the cylinder (here: 0), byte 4 is the head (here: 0). Byte 5 is the sector number (here: 1) of the sector which happened to be near the R/W head when the command was issued. Byte 6 is the sector size code. Size code 0 means 128 bytes per sector, size code 1 means 256 bytes per sector, size code 2 means 512 bytes per sector, etc (i.e. size doubles with each increment).
So, you try out all 4 rates until you get one that succeeds (byte 0 <= 7). If none matches, try adding the FM keyword (to use FM coding instead of MFM).
Example:
fdrawcmd readid 0 rate=0 fm need_seek track=0
Notes:
-
If the disk you're trying to read is a 3 1/2 disk, it is possible that it is a high-density disk formatted with a double-density . This can happen if the disk was formatted/written to in a drive that only supports double density. These are very tricky to read on a drive that is high-density capable because the drive needs to go into a differnt mode for reading DD disks that for HD. Mode change is not selected by software (i.e. the floppy disk controller cannot communicate its rate setting to the drive), but rather is determined by the presence or absence of a density select hole on the floppy disk. This hole is on the opposite side from the write-protect hole. If the hole is present, the drive goes into high-density mode, else it does double density. This basically means that the drive will be in the wrong mode when confronted with a high-density disk formatted in double density . To work around this problem, just put some opaque adhesive tape over the density select hole, as shown below.
The two holes of a HD disk: Where to place the adhesive tape: -
If none of the eight combinations (4 rates with fm, 4 rates without fm) doesn't work, and neither with nor without adhesive tape over the density select hole, then the disk probably is not readable on PC hardware. Remember: the controller plays a role that is as important, if not more, than the drive. So the fact that a device uses a normal PC drive is not necessarily indicative that disks written by that device can be read on a PC.
On the other hand, if one combination matches, we have some good chance to get at the contents of that disk. Use the same fm/rate combination with all fdrawcmd's shown below.
Finding out the number of sides (heads)
Next we have to find out if the disk is double sided or single sided:
> fdrawcmd readid 4 rate=x fm need_seek track=0
The 4 means to check the other head. If you get output such as the following, then it is ok, which means that there are indeed 2 heads (0 and 1):
> fdrawcmd readid 4 rate=0 need_seek track=0
0: 4
1: 0
2: 0
3: 0
4: 1
5: 2
6: 2
disk change
If byte 0 is greater than 7, we have an error, and the disk is probably single sided. However, there are some weird formats in existence which use a different density at the second side and on the following cylinders. So, in case of failure, it might be worthwhile to try out all 8 combinations too.
Finding out how many cylinders there are, and how they are spaced
Next, let's find out whether cylinders are doublespaced or not. Especially, on older drives, the head had to be moved by two physical cylinders instead of 1 logical cylinder.
For this, seek to physical cylinder 2, and do again a readid.
> fdrawcmd readid 4 rate=0 need_seek track=2
0: 4
1: 0
2: 0
3: 2
4: 1
5: 7
6: 2
no disk change
Carefully watch byte 3 (logical cylinder). If this is 1, then we have a disk with only one logical track per two physical tracks. This is for instance the case with double density 5 1/4 disks. If on the other hand byte 3 is 2, then we have a normal disk, where one logical track corresponds exactly to one physical track.
To sum it up:
byte 3 is 2 | Plain disk (with singlespaced tracks) |
byte 3 is 1 | Disk with doublespaced tracks. |
Again, if byte 0 is greater than 7, we have an error. A different density might be used on track 2 and it might be worthwhile to try out all 8 rate/fm combinations.
Same exercise with the number of cylinders. Seek to track 81, 80, 79, 78, 77 until you can read the track. Use the rate/fm combination from track 2: no nead to try out all 8 combinations here, it is very rare that density changes again after the first track. N.B. If you have a disk with double spaced tracks, try only the even numbers:
> fdrawcmd readid 4 rate=0 need_seek track=78
...
Finding out the sector numbering scheme
For the next step, we have to determine the sector numbering scheme. Calling fdrawcmd readid several times in a row gives a good sampling of the sectors which can occur on a track. You can also use the repeat=n option to do n repetitions with one command:
> fdrawcmd readid 4 rate=0 need_seek track=78 repeat=20
...
You can also attempt reading particular sectors if you want to probe for their existence:
> fdrawcmd read phead lcyl lhead secnr secsiz nrsect gap size2 \
length=length rate=x need_seek track=pcyl
- phead
- the physical head: 0 for one side, 4 for the other.
The next 4 parameters are the sector header of the sector to be read, just as in the last 4 return bytes of the readid command
- lcyl
- the logical cylinder number (the one in the header)
- lhead
- the logical head number (the one in the header).
- secnr
- the sector number
- secsiz
- is the sizecode (see above)
- nrsect
- the total number of sectors per track (set this to zero if unknown)
- gap
- no longer used by the floppy disk controller, usually you put 0x1b, just in case
- size2
- is usually not used either: usually you supply 0xff
- pcyl
- the physical cylinder number (the cylinder where to seek to). length is the number of bytes to read. Must be an integral number of sectors.
Example:
> fdrawcmd read 0 1 0 1 2 0 0x1b 0xff length=10240 need_seek track=1 >/dev/null
remaining= 1024
0: 40
1: 4
2: 0
3: 1
4: 0
5: 13
6: 2
no disk change
This command attempts to read 10240 bytes starting at sector 1/0/2/2 (track 1, head 0, number 2, size 512) on physical track 1, and physical head 0.
The system returns an error, and says 1024 bytes remain to be read (remainging=). This means that there are 18 sectors on that track (20 - 2).
Remember: on disks with doublespaced tracks, the physical cylinder has to be the double of the logical cylinder.
It might also be interesting to probe for sector 0.
Some CPM systems have highly unusual numbering conventions, so don't be discouraged if you see them:
- Some systems number sectors continously accross sides. For example head 0 has sectors 1-10, and head 1 has 11-20.
- Some systems invert both heads: physical head 0 is logical head 1, and vice versa.
- Some systems number tracks continously accross sides. For example, side 0 contains tracks 1-77, and side 1 contains 78-154.
- Although most systems start numbering sectors at 1, some may start at 0.
- Although most systems start numbering tracks at 0, some may start at 1.
Occasionnally, not all cylinders use the same numbering scheme. Most notably, some formats use a lower density or a lower number of sectors on cylinder 0. However, it is more unusual that differences occur later. For example, 0 may be entirely different from 1, but 20 is usually the same as 30. There is usually no need to check all cylinders from 0 to 79. It should be enough to check 0, 1, 79, 80, 81, 82, 83 (the latter only because they might be absent)
Using setfdprm to read the disk
If the disk is not too unusal, you can configure your finding into the floppy driver using setfdprm, and can then use dd or cat to read the disk.
Example:
setfdprm /dev/fd0 sect=40 hd ssize=128 cyl=80
cat /dev/fd0 >image
If the is unusual enough, you unfortunately have to read the disk track by track using the above-mentioned fdrawcmd commands.
Cpmtools
Once you have access to the disk, you can read the raw data from your disk. You do not yet have access to the individual files. For this, you need a filesystem-level utility, such as mtools for disks with a Dos filesystem, or cpmtools. Most disks that use non-standard low-level formats are actually CPM disks. The low level image can be accessed using the cpmtools utility. The cpomtools package contains, among others, a cpmls and a cmpcp file, useful for listing CPM directories, and copying files.
Compilation of Cpmtools
Cmptools needs the curses library, which is has been superceded by the ncurses library. If you no longer have access to ncurses, you'll get the following error message:
gcc -g -o fsed.cpm fsed.cpm.o -lcurses
/usr/i486-linux/bin/ld: cannot open -lcurses: No such file or directory
You can still compile the tools by replacing the following line in the Makefile:
LIBCURSES= -lcurses
by:
LIBCURSES= -lncurses
Using Cpm tools
With the cpmtools, you can either work directly on the floppy disk (for thos formats where an image is available), or first extract the image, and then work on that image. The examples below show how to use cpmtools to work directly on the floppy disk. Note You need to use the setfdprm command before you can access the disk using cpmtools. The setfdprm command only needs to be issued before the first cpmtools command on that disk.
> setfdprm /dev/fd0 sect=40 hd ssize=128 cyl=80
> cpmls /dev/fd0
Copying file test from the CPM disk to the current Unix directory:
> cpmcp 0:test .