E01 vs E01S
All sectors are uniquely numbered from the start of the disc. Sectors are 256 bytes long.
Under Level 3 the disc is partitioned, part of the disc is an ADFS area, the remaining part is set aside for network use.
For reference, the Level 3 harddisc is laid out as shown below. It appears as if the disc is laid out as two "partitions", the first is an ADFS partition (on track zero) and the file server (NFS) partition (starting on track one).
This split-partitioning persists in the FileStore, and is - I believe - a hangover of the earlier (Level 3) having the harddisc connected via ADFS.
The ADFS partition is provided purely to supply important drive parameters in a format that ADFS understands.
- Sector zero
Bytes 246 - 248: Pointer to 1st sector of NFS partition
(24 bit address)
- Sector one
Bytes 246 - 248: Pointer to copy of 1st sector of NFS partition
(24 bit address)
|Can anybody help fill out more information on this part of the disc format?|
NFS Sector 1
The initial NFS sector is laid out as follows:
All objects are referred to by SIN (System internal name). The SIN points to a map which
gives the location of the object on store.
| 0 - 3 ||"AFS0",
indicates a Fileserver disc|
| 4 - 19 ||16 characters - disc name|
|20 - 21 ||Number of cyclinders on the disc|
(16 bit, LSB first)
|22 - 24 ||Number of sectors on the disc|
(24 bit, LSB first)
|25 ||Number of physical discs in logical fileserver|
|26 - 27 ||Number of sectors per cylinder|
(16 bit, LSB first)
|28 ||Number of sectors per bit map|
|29 ||Increment to drive number to start next drive|
|31 - 33 ||SIN of root directory|
(24 bit, LSB first)
|34 - 35 ||Date of initialisation
(LSB = Day in month; MSB = Month + (16 * (Year - 1981))|
This looks suspiciously like the old style Econet date - does the FileStore include
support for the newer date format that will cope with dates after 1996?
|36 - 37 ||First free cylinder|
(16 bit, LSB first)
|38 ||If non-zero, the disc is a floppy disc|
Free space map
On initialisation, the first sector, and the copy of the first sector, will always be sector 1 in a particular cylinder.
[reading this many years later, it does not make much sense - does anybody have the formatter in source form? I only have the compressed form which isn't so easy to read!]
The first sector in every NFS cylinder contains a bit-map of that cylinder's sectors. If, for
example, a harddisc has 132 sectors per cylinder, the first sector of each cylinder has a bit
map containing 132 bits.
There are 8 bits to a byte, and therefore the bit relating to sector 'n' of a cylinder is bit
(n MOD 8) in byte
(n DIV 8). If a sector is occupied, that bit is set to zero, otherwise the bit is set to one. I have highlighted this as it may appear backwards. One means emply.
Bit zero of byte zero of a map is always set to zero - even an empty cylinder has its first sector occupied, by the bit map.
Floppy discs operate slightly differently. It would be a waste to lose a sector per track on the bitmap, so they use a packed version of the map, for which I currently have no information.
The object's length is determined by byte 8 plus the total number of sectors occupied.
|0 - 5 ||"JesMap" indicates that this is a map
|6 ||Map chain sequence number.|
A map can extend over several sectors, the last entry in a particular sector pointing
to the next part of the map.
The sequence number is a copy of the last byte of the current MAP sector.
|8 ||LSB of object length|
|10 - xx ||A list of occupied sectors,
each entry consisting of five bytes:|
0 - 2 : lowest numbered sector in contiguous group, LSB first
3 - 4 : number of contiguous sectors in group LSB first
Directories contain two linked lists. One list contains the objects in the directory, and is maintained in alphabetical order. The other contains a linked list of free entries in the directory.
The entries in the linked lists are measured relative to the start of the directory, so 50B would refer to an entry beginning at byte 0B in sector 05 of the directory. The last entry in either linked list is 00.
The last byte of the directory is a copy of the sequence number. This is used to check for
|0 - 1 ||Pointer to first entry in object linked
list (LSB first)|
|2 ||Cycle number of directory|
|3 - 12 ||10 characters of directory name|
|13 - 14 ||Pointer to first entry in free entries
linked list (LSB first)|
|15 - 16 ||Number of entries in the directory. This
is specified as a 16 bit number (LSB first), though in reality a directory cannot be more
than 255 entries long.|
|17 - xx ||Contents of directory, 26 bytes
|0 - 1 ||Pointer to next entry in linked list|
|2 - 11 ||10 characters of object name|
|12 - 15 ||Load address (4 bytes)|
|16 - 19 ||Exec address (4 bytes)|
| ||On RISC OS machines, the load and exec addresses are
usually replaced by the filetype (3 bytes) and datestamp (5 bytes).|
|20 ||Attribute byte
|b7 ||undefined (on some systems this may be interpreted as 'hidden')|
|b6 ||undefined (on some systems this may be interpreted as 'protected directory')|
|b5 ||If 1, is writeable by others|
|b4 ||If 1, is readable by others|
|b3 ||If 1, is locked|
|b2 ||undefined (on some systems this may be interpreted as 'execute')|
|b1 ||If 1, is writeable by owner|
|b0 ||If 1, is readable by owner|
|21 - 22 ||Date of most recent update to entry (as per
date of initialisation)|
|23 - 25 ||SIN of object, LSB first|
Converting SINs to an actual disc address
It appears that in order to convert a SIN to an actual disc address, we need only shift it eight places to the left, i.e.:
disc_address% = object_sin% << 8
This will be because a sector is either used or not used. As each sector is 256 bytes long, a SIN can only point to an address that is
Reading FileStore discs on a RISC OS machine
I tried to write a FileStore "AFS0" disc filing system (similar in concept to DOSFS), but it does not work correctly. It scans for disc information on the Service_IdentifyDisc call, reads the NFS sector to retrieve the disc size, shape, etc. Upon claiming the service call it causes the filer to report an address exception and maybe crash.
I present you the bare-bones source code if you wish to have a look and see what I have monumentally screwed up. Download fsfs.zip (14K). Written in C/assembler.
The module has been officially registered, so you should use the SWI chunk
0x561C0. The filing system number for FSFS should be
175, and the disc filetype for FSFS images should be
0xA94, called "
Alternatively, if you are only looking to pull some files off of a FileStore disc, my 'BudgieSoft' Econet Management Suite contains a program called !FSfloppy which is a three part process to create a directory containing a mirror of the files on the FileStore disc.
The three parts to the process are:
Not the most ideal solution, but one that works provided your disc is not corrupt! Full source code is available, so you can tweak or look at how I did it for writing something better!
- FetchDisc - to verify the disc format and then read the entire disc as a big file. Logically, this will require ~640Kb of disc space for the disc image.
- BuildMap - will scan through the disc image (created by Fetchdisc) looking for files and directories. It does not follow recursively, it scans from end to end adding directories on one pass and examining them on the following pass. When no more directories are to be added, the process is complete.
This isn't the most logical way to attack this problem, however it was the easiest to create and implement.
- Resolver - will take the index file created by BuildMap and the image created by FetchDisc and pull out the files, creating directories if necessary. It can follow non-contiguous blocks (following the information provided by BuildMap).
The passwords file is stored as "
$.Passwords". It must be an integral number of sectors long (i.e. byte 8 of its JesMap must be zero). Other than that, it does not have to reside in any special part of the disc.