Things we know about the ReplayTV file system

Conventions

The ReplayTV hard drive is generally split into two partitions; the first partition containing the ReplayTV software and program guide, the second partition containing recorded programs.  Both partitions use the same basic file system format, differing only in the partition's size, the size of the cluster (basic allocation unit) and the contents of the partition.

Because the ReplayTV is based on a MIPS processor, data found on the drive tend to be in "big-endian" format, meaning that integers larger than one byte will be stored with the most significant byte coming first, and least significant byte coming last. This is the opposite of the byte ordering used by an Intel based PC.

Example 1.
Byte ordering for hex
value 0x12345678
"Little-Endian"
(Intel)
"Big-Endian"
(MIPS)
78 56 34 12 12 34 56 78

Allowances for this should be made by any software that attempts to access these structures.

The partition layout is rather simple.  The partition is split up into "clusters" of sectors.  The minimum unit of allocation is one cluster.  Clusters are numbered starting at 0; any disk address is expressed by its cluster number.

There are four basic non-file data block structures in the file system.  With the exception of the Signature Block, all system blocks are written redundantly, with the second copy occupying the cluster immediately following the first.  In all cases, the redundant copy will exactly mirror the first copy.  It should be noted that the storage allocation tables for the file system are not stored on disk.  This implies that when the ReplayTV software mounts the partition, it must recompute the storage allocation information by mapping what space is used by the files in the partition.

Table 1.
ReplayTV File System Blocks
Name Description
Signature The first cluster in the partition.  This identifies the partition's cluster size and the number of clusters in the partition.  All useful information in this block will be found in the superblock.  Its main apparent function is to define the size of a cluster so that the SuperBlock (in cluster 1) can be found.
SuperBlock This block defines the parameters of the partition: the size of a cluster, the number of clusters in the partition, the name of the partition, and the cluster number of the root directory.
Directory This block specifies the name of a directory, and contains a list of cluster numbers that correspond to each file or directory owned by this directory.  Its format is similar to that of an inode.
inode This block specifies a file's attributes (name, creation date, size), and contains a list of all the extents that comprise the file's data.

Block header

The following structure is common to all file system blocks on the ReplayTV file structure, excepting the Signature block.  This header is found in the first 0x0018 bytes of the first sector of a cluster for a SuperBlock, Directory Block, or file inode.

Table 2.
Standard Block Header
Offset Size Description
0x0000 8 Self Pointer - The cluster number that this block (or the master copy of this block) appears in.
0x0008 4 Data Bytes - The number of valid bytes that follow the header; the number of bytes following the header represented in the CRC.
0x000C 2 CRC - a CRC-16 computed from (Data Bytes) following the block header.
0x000E 2 Filler - (unused)
0x0010 2 unknown - Contains some data; we're just not sure what it means.
0x0012 1 unknown - Contains some data; we're just not sure what it means.
0x0013 1 Header XOR - A checksum computed by XORing all bytes preceding this one.  Note that a block's CRC must be computed before the XOR.
0x0014 4 Filler - (unused)

Signature Block

The first sector of the first cluster of a partition contains minimal information.  It defines the cluster size of the partition so that the Super Block may be found.  It is the Super Block that defines the partition parameters in detail.

Table 2.
Signature Block
Offset Size Description
0x0000 0x100 Filler - (unused)
0x0100 8 Super Block - Either the version number (-1) or the cluster number of the first Super Block (=1).
0x0108 8 Cluster Count - The number of clusters in the partition.
0x0110 4 Signature - The partition signature longword, always contains 0xC2993D87.
0x0114 4 Cluster Size - The size of a cluster, in bytes.
0x0118 4 Mirrors - The number of copies of each system block that are written to disk. Normally set to 2.
0x011C 4 System Block Size - Size of a system block, in bytes.

Super Block

The Super Block defines the parameters of the partition.  This includes the cluster size, the number of clusters in the partition, and the address of the root directory.

Table 4.
Super Block
Offset Size Description
0x0000 0x018 Block Header - A standard block header as defined in Table 1.
0x0018 8 Unused - Contains zero.
0x0020 8 Cluster Count - The number of clusters in the partition.
0x0028 8 Root Dir - The cluster number of the root directory.
0x0030 8 Unknown - Usually contains a string of 0xFFs.
0x0038 4 Cluster Size - The cluster size, in bytes.
0x003C 4 Super Cluster Size - The number of clusters in a "Super Cluster."  A super cluster is the normal allocation unit for file data.
0x0040 8 Mirrors - The number of copies of each system block that are written to disk. Normally set to 2.
0x0048 0x100 Partition Name - Null terminated partition name string.
0x0148 4 System Block Size - Size of a system block, in bytes. Usually set to 0x0400.
0x014C 4 Filler - (unknown)

Directory Block

The directory block contains the name of the directory and a table of cluster numbers of all files owned by the directory.  Note that the format of the Directory Block and the File inode are quite similar.

Table 5.
Directory Block
Offset Size Description
0x0000 0x018 Block Header - A standard block header as defined in Table 1.
0x0018 8 Parent Dir - Cluster number of the parent directory.
0x0020 8 Sibling - Pointer to another inode containing information about this directory, or all 0xFFs. (Note: directory inodes might never have "siblings")
0x0028 8 File Date - File date; number of 1/1000ths of a second since 01/01/1970:00:00:00.000.
0x0030 0x023 Filler - (unused)
0x0053 1 Entry Type - Contains "D" for directory blocks.
0x0054 4 Unknown - Seems to contain 0x01.
0x0058 0x040 Filler - (unused)
0x0098 0x100 Directory Name - Null terminated directory name string.
0x0198 0x20 Filler - (unused)
0x01A8 remainder of block Entry Table - The Directory Entry Table contains one QuadWord per entry.  Each entry consists of a cluster number which is the cluster address of the file or directory represented by this entry.
The Directory Entry Table's length can be determined by the Data Bytes field in the Block Header.

"inode" Layout

Table 6.
File inode
Offset Size Description
0x0000 0x018 Block Header - A standard block header as defined in Table 1.
0x0018 8 Parent Dir - Cluster number of the parent directory.
0x0020 8 Sibling - Pointer to the inode of another file in the same directory as this file. Using this pointer the directories can contain an unlimited number files, all connected either in the entry table in the directory inode or as a linked list using this "sibling" pointer. If there is no sibling, then this value is all 0xFFs.
0x0028 8 File Date - File date; number of 1/1000ths of a second since 01/01/1970:00:00:00.000.
0x0030 0x023 Filler - (unused)
0x0053 1 Entry Type - Contains "F" for file inodes.
0x0054 4 Unknown - Seems to contain 0x01.
0x0058 0x040 Filler - (unused)
0x0098 0x100 File Name - Null terminated file name string.
0x0198 8 Size - Length of file, in bytes.
0x01A0 0x010 Unknown - Normally a string of 0xFFs.
0x01B0 0x020 Unknown - Normally zero.
0x01D0 8 Next Cluster - Normally a string of 0xFFs. When this is not 0xFFs, then this points to a cluster which has the continuation of the extent table. This is used when there are more than 31 fragments in the extent table.
0x01D8 4 Extent Count - The number of extents. This gives just the number of extents stored in this inode. If there is no continuation cluster, then this count will include the extent terminator.
0x01DC 4 Unknown - Normally 0x0022.
0x01E0 Extent Count
* 0x010
Extent Table - The table of extents describing the location(s) of the file data.  Each extent table entry consists of two QuadWords. The first (Extent Count - 1) entries have the following format:
Cluster Number The starting cluster number of the extent
Cluster Count The number of contiguous clusters in this extent
The final extent table entry, the Extent Terminator, consists of two QuadWords: The first is eight bytes of 0xFF; the second is the 1s compliment of the sum of all the cluster counts in the preceding extents. This is always the last entry in the full table, and will give a checksum for the full table even when the table is split among several clusters.

extent table continuation "inode" Layout

Table 7.
Extent table continuation inode
Offset Size Description
0x0000 0x018 Block Header - A standard block header as defined in Table 1.
0x0018 0x0028 Unknown
0x0040 8 Next Cluster - Normally a string of 0xFFs. When this is not 0xFFs, then this points to a cluster which has the continuation of the extent table. This is used when there are more fragments in the extent table than will fit in this cluster.
0x0048 4 Extent Count - The number of extents. This gives just the number of extents stored in this inode. If this is the final extent table continuation cluster, then this count will include the extent terminator.
0x004C 4 Unknown
0x0050 Extent Count
* 0x010
Extent Table - The table of extents describing the location(s) of the file data.  Each extent table entry consists of two QuadWords. The first (Extent Count - 1) entries have the following format:
Cluster Number The starting cluster number of the extent
Cluster Count The number of contiguous clusters in this extent
The final extent table entry, the Extent Terminator, consists of two QuadWords: The first is eight bytes of 0xFF; the second is the 1s compliment of the sum of all the cluster counts in the preceding extents. This is always the last entry in the full table, and gives a checksum for the full table even when the table is split among several clusters.