mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 19:24:40 +00:00
[Specification] Rename structs to blocks for consistency
This commit is contained in:
84
docs/spec/blocks/bitstream.adoc
Normal file
84
docs/spec/blocks/bitstream.adoc
Normal file
@@ -0,0 +1,84 @@
|
||||
=== Bitstream Data Block (`BITS`)
|
||||
|
||||
The `BITS` block contains a list of all known bitstream captures.
|
||||
|
||||
A *bitstream* is derived by interpreting flux transitions using an encoding scheme timing table.
|
||||
While bitstreams sit below sector-level data in the hierarchy, they are still a higher abstraction than raw flux transitions.
|
||||
|
||||
Storing bitstream data is valuable because multiple dumps from the same media often produce inconsistent and incomparable flux transitions.
|
||||
However, once decoded into bitstreams—regardless of whether sector-level user data can be extracted—the results remain consistent and comparable.
|
||||
|
||||
Bitstream-level representations are also preferred in low-level emulation scenarios.
|
||||
Emulators, such as floppy drive emulators, can reconstruct original media more effectively using bitstream data than flux data.
|
||||
|
||||
Bitstream data is stored in `DataBlocks` with the `bitstream` data type.
|
||||
Each image must contain exactly one deduplication table of this data type, and that table must have a single level.
|
||||
|
||||
NOTE: Bitstream deduplication tables provide a reference for associating bitstream captures and their corresponding data blocks.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The flux data block identifier, always 'BITS'
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Bitstream entries
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|head
|
||||
|Head the data corresponds to.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|track
|
||||
|Track the data corresponds to.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|subtrack
|
||||
|Substep of a track that the data corresponds to.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|tableEntry
|
||||
|Entry number in the deduplication table where the data corresponding to this bitstream entry is stored
|
||||
|===
|
||||
|
||||
To better understand the relationship between user data, bitstream data and flux data please refer to _Annex F_.
|
||||
5
docs/spec/blocks/blocks.adoc
Normal file
5
docs/spec/blocks/blocks.adoc
Normal file
@@ -0,0 +1,5 @@
|
||||
== The Blocks
|
||||
|
||||
The blocks in AaruFormat serve as the building components of the image, containing both the data and metadata extracted from the media it represents.
|
||||
|
||||
include::index.adoc[]
|
||||
74
docs/spec/blocks/cd_indexes.adoc
Normal file
74
docs/spec/blocks/cd_indexes.adoc
Normal file
@@ -0,0 +1,74 @@
|
||||
=== Compact Disc Indexes Block ('CDIX')
|
||||
|
||||
On CompactDisc and related media, tracks can contain multiple indexes.
|
||||
These are used to mark separations in the data, such as distinct segments of a musical performance.
|
||||
|
||||
The table of contents always references index 1. All other indexes—including index 0 (the pregap)—are stored in the subchannel information.
|
||||
|
||||
This block holds a list of all known indexes for quick lookup.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define CD_INDEXES_MAGIC 0x58444943
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The compact disc indexes block identifier, always `CDIX`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Index entries
|
||||
|
||||
[source,c]
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|track
|
||||
|Track this index belongs to.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|index
|
||||
|Index number.
|
||||
|
||||
|int32_t
|
||||
|4 bytes
|
||||
|lba
|
||||
|LBA where this index starts.
|
||||
|===
|
||||
110
docs/spec/blocks/checksum.adoc
Normal file
110
docs/spec/blocks/checksum.adoc
Normal file
@@ -0,0 +1,110 @@
|
||||
=== Checksum Block (`CKSM`)
|
||||
|
||||
This block stores an array of checksums corresponding to the user data embedded in the image.
|
||||
For media formats such as CompactDisc, the checksum is calculated over the complete sector—comprising the prefix, user data, and suffix—totaling 2352 bytes.
|
||||
|
||||
If the image is modified, the checksum block is considered outdated and should be either removed or excluded from the most recent index to ensure integrity.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define CHECKSUM_MAGIC 0x4D534B43
|
||||
/**
|
||||
* Checksum block, contains a checksum of all user data sectors (except for optical discs that is 2352 uint8_ts raw
|
||||
* sector if available
|
||||
* */
|
||||
typedef struct ChecksumHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.ChecksumBlock" /> */
|
||||
uint32_t identifier;
|
||||
/**Length in uint8_ts of the block */
|
||||
uint32_t length;
|
||||
/**How many checksums follow */
|
||||
uint8_t entries;
|
||||
} ChecksumHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The tracks block identifier, always `CKSM`
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|===
|
||||
|
||||
==== Checksum entries
|
||||
|
||||
[source,c]
|
||||
/**Checksum entry, followed by checksum data itself */
|
||||
typedef struct ChecksumEntry
|
||||
{
|
||||
/**Checksum algorithm */
|
||||
uint8_t type;
|
||||
/**Length in uint8_ts of checksum that follows this structure */
|
||||
uint32_t length;
|
||||
} ChecksumEntry;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|type
|
||||
|Checksum algorithm.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|Size in bytes of the checksum that immediately follows this entry.
|
||||
|===
|
||||
|
||||
==== Checksum algorithms
|
||||
|
||||
[cols="2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Value
|
||||
|Description
|
||||
|
||||
|Invalid
|
||||
|0
|
||||
|Invalid checksum entry, skip.
|
||||
|
||||
|Md5
|
||||
|1
|
||||
|MD5
|
||||
|
||||
|Sha1
|
||||
|2
|
||||
|SHA1
|
||||
|
||||
|Sha256
|
||||
|3
|
||||
|SHA-256
|
||||
|
||||
|SpamSum
|
||||
|4
|
||||
|SpamSum
|
||||
|===
|
||||
25
docs/spec/blocks/cicm.adoc
Normal file
25
docs/spec/blocks/cicm.adoc
Normal file
@@ -0,0 +1,25 @@
|
||||
=== CICM XML Metadata Block ('CICM')
|
||||
|
||||
This block header signifies the inclusion of an embedded CICM XML metadata sidecar.
|
||||
The contents of the XML are preserved in their original form and are not parsed, interpreted, or validated by the format implementation.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define CICM_MAGIC 0x4D434943
|
||||
/**Header for the CICM XML metadata block */
|
||||
typedef struct CicmMetadataBlock
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.CicmBlock" /> */
|
||||
uint32_t identifier;
|
||||
uint32_t length;
|
||||
} CicmMetadataBlock;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type|Size|Name|Description
|
||||
|uint32|4 bytes|identifier|The CICM XML metadata table identifier, always `CICM`
|
||||
|uint32|4 bytes|length|The size in bytes of the embedded CICM XML metadata that follows this header.
|
||||
|===
|
||||
83
docs/spec/blocks/data.adoc
Normal file
83
docs/spec/blocks/data.adoc
Normal file
@@ -0,0 +1,83 @@
|
||||
=== The data block (`DBLK`)
|
||||
|
||||
A data block encapsulates media-derived content and is composed of a header followed by either compressed or uncompressed data.
|
||||
|
||||
The contents of a data block may represent user data—such as media sectors—or auxiliary data elements, including media or sector-specific tags.
|
||||
|
||||
When a data block includes multiple items (e.g., sectors or sector tags), the `sectorSize` field specifies the size, in bytes, of each individual item.
|
||||
Conversely, if the block contains a single item (e.g., media tags), `sectorSize` must be set to 0.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define DATABLOCK_MAGIC 0x4B4C4244
|
||||
/**Block header, precedes block data */
|
||||
typedef struct BlockHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.DataBlock" /> */
|
||||
uint32_t identifier;
|
||||
/**Type of data contained by this block */
|
||||
uint32_t type;
|
||||
/**Compression algorithm used to compress the block */
|
||||
uint16_t compression;
|
||||
/**Size in uint8_ts of each sector contained in this block */
|
||||
uint32_t sectorSize;
|
||||
/**Compressed length for the block */
|
||||
uint32_t cmpLength;
|
||||
/**Uncompressed length for the block */
|
||||
uint32_t length;
|
||||
/**CRC64-ECMA of the compressed block */
|
||||
uint64_t cmpCrc64;
|
||||
/**CRC64-ECMA of the uncompressed block */
|
||||
uint64_t crc64;
|
||||
} BlockHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The data block identifier, always `DBLK`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|type
|
||||
|The data type contained in this block. See Annex B.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|compression
|
||||
|The compression algorithm used in the data. See Annex C.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|sectorSize
|
||||
|The size in bytes of the sectors contained in this data block if applicable.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|cmpLength
|
||||
|The size in bytes of the compressed data that follows this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The size in bytes of the data block when decompressed.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|cmpCrc64
|
||||
|The CRC64-ECMA checksum of the compressed data that follows this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the decompressed data.
|
||||
|===
|
||||
146
docs/spec/blocks/ddt.adoc
Normal file
146
docs/spec/blocks/ddt.adoc
Normal file
@@ -0,0 +1,146 @@
|
||||
=== The deduplication table (`DDT*`) *_DEPRECATED_*
|
||||
|
||||
The deduplication table is a sequential array of pointers, with each entry corresponding to a sector on the storage media.
|
||||
These pointers map sector data to logical content blocks, enabling efficient elimination of duplicate data.
|
||||
Every image must include at least one deduplication table of type `UserData`.
|
||||
|
||||
*Deprecation Notice*: This block is deprecated and *MUST NOT* be used in new image files.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define DDT_MAGIC 0X2A544444
|
||||
/**Header for a deduplication table. Table follows it */
|
||||
typedef struct DdtHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.DeDuplicationTable" /> */
|
||||
uint32_t identifier;
|
||||
/**Type of data pointed by this DDT */
|
||||
uint32_t type;
|
||||
/**Compression algorithm used to compress the DDT */
|
||||
uint16_t compression;
|
||||
/**Each entry is ((uint8_t offset in file) << shift) + (sector offset in block) */
|
||||
uint8_t shift;
|
||||
/**How many entries are in the table */
|
||||
uint64_t entries;
|
||||
/**Compressed length for the DDT */
|
||||
uint64_t cmpLength;
|
||||
/**Uncompressed length for the DDT */
|
||||
uint64_t length;
|
||||
/**CRC64-ECMA of the compressed DDT */
|
||||
uint64_t cmpCrc64;
|
||||
/**CRC64-ECMA of the uncompressed DDT */
|
||||
uint64_t crc64;
|
||||
} DdtHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The deduplication table identifier, always 'DDT*'
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|type
|
||||
|The data type pointed by this table. See Annex B.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|compression
|
||||
|The compression algorithm used in the table. See Annex C.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|shift
|
||||
|The shift used to calculate the position of a sector in a data block pointed by this table.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|entries
|
||||
|How many pointers follow this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|cmpLength
|
||||
|The size in bytes of the compressed table that follows this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The size in bytes of the table block when decompressed.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|cmpCrc64
|
||||
|The CRC64-ECMA checksum of the compressed table that follows this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the decompressed table.
|
||||
|===
|
||||
|
||||
==== Deduplication Table Entries
|
||||
|
||||
Each entry in the deduplication table references a specific data block and a particular item within that block.
|
||||
|
||||
===== Mapping Logic
|
||||
|
||||
- Entry 0 corresponds to data associated with LBA 0 of the media; subsequent entries map sequentially.
|
||||
- The pointer value for an entry is computed using the formula:
|
||||
+
|
||||
[source]
|
||||
pointer = (byte_offset_of_block << shift) + item_index_in_block
|
||||
+
|
||||
For example, a raw pointer value of `0x8003` in a table with a `shift` of 5 resolves as follows:
|
||||
- Byte offset: `0x400` → `1024`
|
||||
- Item index: `0x3` → `3`
|
||||
- Therefore, the pointer targets item 3 within the data block located at byte offset `1024` in the file.
|
||||
|
||||
==== Special Case – Corrected Sector Tables
|
||||
|
||||
Deduplication tables of type `CdSectorPrefixCorrected` and `CdSectorSuffixCorrected` split the entry value using bitmasking:
|
||||
|
||||
- Pointer component: `entry & 0x00FFFFFF`
|
||||
- Flags component: `entry & 0xFF000000`
|
||||
|
||||
===== Flags
|
||||
|
||||
[cols="2,1,6",options="header"]
|
||||
|===
|
||||
|Flag
|
||||
|Value
|
||||
|Description
|
||||
|
||||
|None
|
||||
|`0x00000000`
|
||||
|The suffix or prefix cannot be regenerated as is stored in the pointed data block.
|
||||
|
||||
|NotDumped
|
||||
|`0x10000000`
|
||||
|The sector has not been dumped. Ignore the pointer.
|
||||
|
||||
|Correct
|
||||
|`0x20000000`
|
||||
|The suffix (only for MODE 1 sectors) or prefix is correct and can be regenerated. Ignore the pointer.
|
||||
|
||||
|Mode2Form1Ok
|
||||
|`0x30000000`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 1 sector.
|
||||
|
||||
|Mode2Form2Ok
|
||||
|`0x40000000`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 2 sector with a valid CRC.
|
||||
|
||||
|Mode2Form2NoCrc
|
||||
|`0x50000000`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 2 sector with an empty CRC.
|
||||
|===
|
||||
224
docs/spec/blocks/ddt2.adoc
Normal file
224
docs/spec/blocks/ddt2.adoc
Normal file
@@ -0,0 +1,224 @@
|
||||
=== The deduplication table (`DDT2`)
|
||||
|
||||
The deduplication table is a multi-level table of pointers to LBAs contained in the image.
|
||||
It starts with the following header.
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The deduplication table identifier, always `DDT2` or `DDTS`. The first level of a table is always `DDT2` and its presence is mandatory. Subtables will have `DDTS`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|type
|
||||
|The data type pointed by this table. See Annex B.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|compression
|
||||
|The compression algorithm used in the table. See Annex C.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|levels
|
||||
|How many levels of subtables are present. 1 means this is the only level.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|tableLevel
|
||||
|What level does this table correspond to
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|previousLevel
|
||||
|Pointer to absolute byte offset in the image file where the previous table level resides
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|negative
|
||||
|The negative displacement of LBA numbers. For media that can have negative LBAs, this establishes the number to substract to the table entry number
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|start
|
||||
|The first LBA contained in this table. It must be 0 for ‘DDT2’ blocks and can be other number for subtables ‘DDTS’
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|alignment
|
||||
|Shift of alignment of all blocks in the image. This must be the same in all deduplication tables and subtables.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|shift
|
||||
|The shift used to calculate the position of a sector in a data block pointed by this table, or how many sectors are pointed by the next level.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|sizeType
|
||||
|Size type (see table below)
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|entries
|
||||
|How many pointers follow this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|cmpLength
|
||||
|The size in bytes of the compressed table that follows this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The size in bytes of the table block when decompressed.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|cmpCrc64
|
||||
|The CRC64-ECMA checksum of the compressed table that follows this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the decompressed table.
|
||||
|===
|
||||
|
||||
The size type defines the following type of entries:
|
||||
|
||||
[cols="1,1,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Value
|
||||
|Description
|
||||
|
||||
|Mini
|
||||
|0
|
||||
|Each entry uses two bytes, with the leftmost byte (mask 0xFF00) used for flags, and the rightmost byte used as a pointer to the sector or next level.
|
||||
|
||||
|Small
|
||||
|1
|
||||
|Each entry uses three bytes, with the leftmost byte used for flags and the next two bytes used as a pointer to the sector or next level.
|
||||
|
||||
|Medium
|
||||
|2
|
||||
|Each entry uses four bytes, with the leftmost byte (mask 0xFF000000) used for flags and the next three bytes used as a pointer to the sector or next level.
|
||||
|
||||
|Big
|
||||
|3
|
||||
|Each entry uses five bytes, with the leftmost byte used for flags and the next three bytes used as a pointer to the sector or next level.
|
||||
|===
|
||||
|
||||
==== Sector Pointer Resolution and Table Levels
|
||||
|
||||
When `levels` is equal to 1—indicating a single-level deduplication table—each entry in the table corresponds directly to a media sector.
|
||||
The pointer value is resolved using the following procedure:
|
||||
|
||||
- Right-shift the raw pointer value by the `shift` value.
|
||||
- Multiply the result by the `alignment` to compute the absolute byte offset of the target data block.
|
||||
- The remainder of the original pointer value modulo `(1 << shift)` yields the item index within the block.
|
||||
|
||||
Each data block stores a fixed number of bytes per sector, allowing compact and efficient sector addressing.
|
||||
|
||||
_For example_:
|
||||
Given a pointer value of `0x8003`, a `shift` of 5, and an `alignment` of 9:
|
||||
- `0x8003 >> 5 = 0x400 = 1024`
|
||||
- `1024 * 9 = 9216`
|
||||
- The sector index within the block is `0x8003 & 0x1F = 3`
|
||||
|
||||
Thus, the sector is located at byte offset `9216`, and it is the 3rd item in the block.
|
||||
|
||||
===== Multi-Level Tables
|
||||
|
||||
When `levels > 1`, the interpretation of pointer entries changes substantially.
|
||||
Although typical usage involves no more than two levels, implementations **MUST** be capable of handling an arbitrary number of levels to ensure forward compatibility.
|
||||
|
||||
At each level—except the final—the table entry functions as an address to the next-level table.
|
||||
The range of LBAs covered by each entry is calculated as:
|
||||
|
||||
[source]
|
||||
range = entry_index * (1 << shift)^(levels - 1)
|
||||
|
||||
_For example_, with a `shift` value of 9 and two levels:
|
||||
- Entry `0` spans LBAs `0–511`
|
||||
- Entry `1` spans LBAs `512–1023`
|
||||
|
||||
With three levels:
|
||||
- Entry `0` at level 0 spans LBAs `0–262143`
|
||||
- Entry `0` at level 1 within that region spans LBAs `0–511`, and so on recursively.
|
||||
|
||||
===== Resolution Example
|
||||
|
||||
To locate sector `1012` using a two-level table with `shift = 9` and `alignment = 9`:
|
||||
|
||||
1. **Level 0**:
|
||||
- Sector `1012` falls within entry `1` (covers `512–1023`)
|
||||
- Entry `1` contains the value `0x12000`
|
||||
- Multiply by `alignment` → `0x12000 * 9 = 0x225000 = 37,748,736`
|
||||
- Read the next-level table at byte offset `37,748,736`, marked with the identifier `DDTS`
|
||||
|
||||
2. **Level 1**:
|
||||
- The relevant entry is `500` (`1012 - 512 = 500`)
|
||||
- Entry `500` contains `0x35006`
|
||||
- Right-shift `0x35006 >> 9 = 0x6A = 106`
|
||||
- Multiply by `alignment`: `106 * 9 = 954`
|
||||
- Sector resides at byte offset `217,088` and is the 6th item in the block (`0x35006 & 0x1FF = 6`)
|
||||
|
||||
===== Deduplication table flags
|
||||
|
||||
[cols="2,1,6",options="header"]
|
||||
|===
|
||||
|Flag
|
||||
|Value
|
||||
|Description
|
||||
|
||||
|NotDumped
|
||||
|`0x00`
|
||||
|The sector(s) have not been dumped
|
||||
|
||||
|Dumped
|
||||
|`0x01`
|
||||
|The sector(s) have been dumped without errors
|
||||
|
||||
|Errored
|
||||
|`0x02`
|
||||
|The sector(s) returned an error on dumping
|
||||
|
||||
|Mode1Correct
|
||||
|`0x03`
|
||||
|The sector is MODE 1 and the suffix or prefix is correct and can be regenerated. Must only appear on deduplications tables with types CdSectorPrefixCorrected or CdSectorSuffixCorrected
|
||||
|
||||
|Mode2Form1Ok
|
||||
|`0x04`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 1 sector. Must only appear on deduplications tables with type CdSectorSuffixCorrected
|
||||
|
||||
|Mode2Form2Ok
|
||||
|`0x05`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 2 sector with a valid CRC. Must only appear on deduplications tables with type CdSectorSuffixCorrected
|
||||
|
||||
|Mode2Form2NoCrc
|
||||
|`0x06`
|
||||
|The suffix for MODE 2 sectors is correct, can be regenerated, and corresponds to a MODE 2 Form 2 sector with an empty CRC. Must only appear on deduplications tables with type CdSectorSuffixCorrected
|
||||
|
||||
|Twin
|
||||
|`0x07`
|
||||
|The pointer contains a “twin” sector table (see below)
|
||||
|
||||
|Unrecorded
|
||||
|`0x08`
|
||||
|The sector was unrecorded and each re-read returns random data
|
||||
|===
|
||||
|
||||
When flags are present in a table that has sublevels it applies to all the sectors that shall be present in the subtable, unless the flag specify something else.
|
||||
6
docs/spec/blocks/dpm.adoc
Normal file
6
docs/spec/blocks/dpm.adoc
Normal file
@@ -0,0 +1,6 @@
|
||||
=== Data Position Measurement Block (`DPM*`)
|
||||
|
||||
This block captures measurements of each sector’s position, providing insights into the physical structure of the disc.
|
||||
It is designed to facilitate analysis of disc geometry and sector layout.
|
||||
|
||||
The formal definition of this block’s format is reserved for a future revision of the specification.
|
||||
178
docs/spec/blocks/dumphw.adoc
Normal file
178
docs/spec/blocks/dumphw.adoc
Normal file
@@ -0,0 +1,178 @@
|
||||
=== Dump Hardware Block (`DMP*`)
|
||||
|
||||
This block defines the set of hardware components involved in capturing the media content.
|
||||
It includes an array listing each device used during the dumping process, along with the specific extents each device recorded.
|
||||
|
||||
This structure allows implementations to trace data provenance and associate dumped regions with their corresponding hardware sources, ensuring accountability and reproducibility in the dumping workflow.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/**Dump hardware block, contains a list of hardware used to dump the media on this image */
|
||||
typedef struct DumpHardwareHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.DumpHardwareBlock" /> */
|
||||
uint32_t identifier;
|
||||
/**How many entries follow this header */
|
||||
uint16_t entries;
|
||||
/**Size of the whole block, not including this header, in uint8_ts */
|
||||
uint32_t length;
|
||||
/**CRC64-ECMA of the block */
|
||||
uint64_t crc64;
|
||||
} DumpHardwareHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The dump hardware block identifier, always `DMP*`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Dump hardware entries
|
||||
|
||||
[source,c]
|
||||
/**Dump hardware entry, contains length of strings that follow, in the same order as the length, this structure */
|
||||
typedef struct DumpHardwareEntry
|
||||
{
|
||||
/**Length of UTF-8 manufacturer string */
|
||||
uint32_t manufacturerLength;
|
||||
/**Length of UTF-8 model string */
|
||||
uint32_t modelLength;
|
||||
/**Length of UTF-8 revision string */
|
||||
uint32_t revisionLength;
|
||||
/**Length of UTF-8 firmware version string */
|
||||
uint32_t firmwareLength;
|
||||
/**Length of UTF-8 serial string */
|
||||
uint32_t serialLength;
|
||||
/**Length of UTF-8 software name string */
|
||||
uint32_t softwareNameLength;
|
||||
/**Length of UTF-8 software version string */
|
||||
uint32_t softwareVersionLength;
|
||||
/**Length of UTF-8 software operating system string */
|
||||
uint32_t softwareOperatingSystemLength;
|
||||
/**How many extents are after the strings */
|
||||
uint32_t extents;
|
||||
} DumpHardwareEntry;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|manufacturerLength
|
||||
|Length of UTF-8 manufacturer string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|modelLength
|
||||
|Length of UTF-8 model string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|revisionLength
|
||||
|Length of UTF-8 revision string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|firmwareLength
|
||||
|Length of UTF-8 firmware version string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|serialLength
|
||||
|Length of UTF-8 serial number string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|softwareNameLength
|
||||
|Length of UTF-8 software name string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|softwareVersionLength
|
||||
|Length of UTF-8 software version string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|softwareOperatingSystemLength
|
||||
|Length of UTF-8 software operating system string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|extents
|
||||
|How many extents are after the strings.
|
||||
|===
|
||||
|
||||
==== Extents
|
||||
|
||||
[source,c]
|
||||
/**Dump hardware extent, contains the start and end of the extent in the media */
|
||||
typedef struct DumpHardwareExtent
|
||||
{
|
||||
/**Start of the extent in the media */
|
||||
uint64_t start;
|
||||
/**End of the extent in the media */
|
||||
uint64_t end;
|
||||
} DumpHardwareExtent;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|start
|
||||
|Starting LBA of the extent (inclusive).
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|end
|
||||
|Ending LBA of the extent (inclusive).
|
||||
|===
|
||||
|
||||
Each dump hardware entry is followed by a sequence of string fields in the following fixed order:
|
||||
|
||||
. Manufacturer
|
||||
. Model
|
||||
. Revision
|
||||
. Firmware Version
|
||||
. Serial Number
|
||||
. Software Name
|
||||
. Software Version
|
||||
. Software Operating System
|
||||
|
||||
Immediately after the final string (`Software Operating System`), the list of extents associated with that hardware entry begins.
|
||||
88
docs/spec/blocks/flux.adoc
Normal file
88
docs/spec/blocks/flux.adoc
Normal file
@@ -0,0 +1,88 @@
|
||||
=== Flux Data Block (`FLUX`)
|
||||
|
||||
This block lists all known flux captures.
|
||||
Certain hardware devices, such as Kryoflux, Pauline, and Applesauce, read magnetic media at the flux transition level.
|
||||
|
||||
Flux transition reads are digital representations of the analog properties of the media, and cannot be reliably interpreted on a sector-by-sector basis without further processing.
|
||||
Instead, the data is accessed through capture blocks whose size varies based on the medium and imaging hardware.
|
||||
For example, floppy disk captures typically represent one full track revolution; Applesauce may capture 1¼ revolutions.
|
||||
For Quick Disks, the minimum capture is often an entire side of the media.
|
||||
|
||||
Each capture block includes two flux data streams: one for user data and one for the indexing signal.
|
||||
|
||||
Flux data is represented as an array of `uint8_t` bytes.
|
||||
Each byte stores the tick count since the last flux transition.
|
||||
If no transition is detected within a byte's range, the value `0xFF` is used, and counting resumes in the next byte with ticks accumulated.
|
||||
|
||||
Flux data is stored in `DataBlocks` of the flux data type, referenced from a deduplication table of the same type.
|
||||
Only one flux-type deduplication table is allowed per image, and it must have exactly one level.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The flux data block identifier, always 'FLUX'
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Flux entries
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|head
|
||||
|Head the data corresponds to.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|track
|
||||
|Track the data corresponds to.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|subtrack
|
||||
|Substep of a track that the data corresponds to.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|resolution
|
||||
|Number of picoseconds at which the sampling was performed.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|tableEntry
|
||||
|Entry number in the deduplication table where the data corresponding to this flux entry is stored
|
||||
|===
|
||||
48
docs/spec/blocks/geom.adoc
Normal file
48
docs/spec/blocks/geom.adoc
Normal file
@@ -0,0 +1,48 @@
|
||||
=== The geometry block (`GEOM`)
|
||||
|
||||
The geometry block encapsulates metadata that defines the disk’s geometry, primarily to support transformations between CHS (Cylinder-Head-Sector) and LBA (Logical Block Addressing) addressing schemes.
|
||||
|
||||
Note that the stored geometry may not reflect the media’s actual physical layout.
|
||||
Instead, it typically represents the translation parameters active at the time the drive image was acquired.
|
||||
|
||||
[source,c]
|
||||
#define GEOM_MAGIC 0x4D4F4547
|
||||
/**Geometry block, contains physical geometry information */
|
||||
typedef struct GeometryBlockHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.GeometryBlock" /> */
|
||||
uint32_t identifier;
|
||||
uint32_t cylinders;
|
||||
uint32_t heads;
|
||||
uint32_t sectorsPerTrack;
|
||||
} GeometryBlockHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The geometry table identifier, always `GEOM`
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|cylinders
|
||||
|The number of cylinders.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|heads
|
||||
|The number of heads.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|sectorsPerTrack
|
||||
|The number of sectors per track.
|
||||
|===
|
||||
79
docs/spec/blocks/header.adoc
Normal file
79
docs/spec/blocks/header.adoc
Normal file
@@ -0,0 +1,79 @@
|
||||
== Master Header Structure
|
||||
|
||||
The AaruHeaderV2 is the fundamental header present at the beginning of every AaruFormat file.
|
||||
It defines the image's versioning, metadata, layout offset, feature compatibility, and structural alignment.
|
||||
All subsequent parsing and interpretation of the file depends on the contents of this header.
|
||||
|
||||
=== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define HEADER_APP_NAME_LEN 64
|
||||
#define GUID_SIZE 16
|
||||
/**Header, at start of file */
|
||||
typedef struct AaruHeaderV2
|
||||
{
|
||||
/**Header identifier, see AARU_MAGIC */
|
||||
uint64_t identifier;
|
||||
/**UTF-16LE name of the application that created the image */
|
||||
uint8_t application[HEADER_APP_NAME_LEN];
|
||||
/**Image format major version. A new major version means a possibly incompatible change of format */
|
||||
uint8_t imageMajorVersion;
|
||||
/**Image format minor version. A new minor version indicates a compatible change of format */
|
||||
uint8_t imageMinorVersion;
|
||||
/**Major version of the application that created the image */
|
||||
uint8_t applicationMajorVersion;
|
||||
/**Minor version of the application that created the image */
|
||||
uint8_t applicationMinorVersion;
|
||||
/**Type of media contained on image */
|
||||
uint32_t mediaType;
|
||||
/**Offset to index */
|
||||
uint64_t indexOffset;
|
||||
/**Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image creation time */
|
||||
int64_t creationTime;
|
||||
/**Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image last written time */
|
||||
int64_t lastWrittenTime;
|
||||
/**Unique identifier that allows children images to recognize and find this image */
|
||||
uint8_t guid[GUID_SIZE];
|
||||
/**Block alignment shift. All blocks in the image are aligned at 2 << blockAlignmentShift bytes */
|
||||
uint8_t blockAlignmentShift;
|
||||
/**Data shift. All data blocks in the image contain 2 << dataShift items at most */
|
||||
uint8_t dataShift;
|
||||
/**Table shift. All deduplication tables in the image use this shift to calculate the position of an item */
|
||||
uint8_t tableShift;
|
||||
/**Features used in this image that if unsupported are still compatible for reading and writing implementations */
|
||||
uint64_t featureCompatible;
|
||||
/**Features used in this image that if unsupported are still compatible for reading implementations but not for writing */
|
||||
uint64_t featureCompatibleRo;
|
||||
/**Features used in this image that if unsupported prevent reading or writing the image */
|
||||
uint64_t featureIncompatible;
|
||||
} AaruHeaderV2;
|
||||
|
||||
=== Field Descriptions
|
||||
|
||||
[cols="2,3,6",options="header"]
|
||||
|===
|
||||
| Name | Type | Description
|
||||
| identifier | uint64_t | Header identifier constant. Must match the predefined `AARU_MAGIC` value to validate the format.
|
||||
| application | uint8_t[HEADER_APP_NAME_LEN] | UTF-16LE encoded name of the application responsible for creating the image.
|
||||
|
||||
Length is defined by `HEADER_APP_NAME_LEN`.
|
||||
| imageMajorVersion | uint8_t | Major version of the AaruFormat structure.
|
||||
|
||||
A bump indicates potential breaking changes.
|
||||
| imageMinorVersion | uint8_t | Minor version of the format, for backward-compatible structural updates.
|
||||
| applicationMajorVersion | uint8_t | Major version of the creating application.
|
||||
| applicationMinorVersion | uint8_t | Minor version of the application.
|
||||
| mediaType | uint32_t | Media type identifier denoting the nature of the captured content (e.g., floppy, optical disc, tape).
|
||||
| indexOffset | uint64_t | Absolute file offset to the beginning of the index structure, used to locate blocks throughout the image.
|
||||
| creationTime | int64_t | Timestamp (Windows filetime) representing when the image was first created.
|
||||
| lastWrittenTime | int64_t | Timestamp (Windows filetime) of the last modification made to the image.
|
||||
| guid | uint8_t[GUID_SIZE] | Globally Unique Identifier (GUID) that allows linking of related image derivatives and child snapshots.
|
||||
|
||||
Length is defined by `GUID_SIZE`.
|
||||
| blockAlignmentShift | uint8_t | Determines block alignment boundaries using the formula 2 << blockAlignmentShift.
|
||||
| featureCompatible | uint64_t | Bitmask of features that, even if not implemented, still allow reading and writing the image.
|
||||
|
||||
| featureCompatibleRo | uint64_t | Bitmask of features that allow read-only processing of the image if unsupported.
|
||||
|
||||
| featureIncompatible | uint64_t | Bitmask of features that must be supported to read or write the image at all.
|
||||
|===
|
||||
87
docs/spec/blocks/index.adoc
Normal file
87
docs/spec/blocks/index.adoc
Normal file
@@ -0,0 +1,87 @@
|
||||
=== The index block (`INDX`) *_DEPRECATED_*
|
||||
|
||||
The index block stores references to all blocks present in the file.
|
||||
It is composed of a header, followed by a sequence of entries, the count of which is defined within the header.
|
||||
|
||||
Multiple index blocks may exist within a file to represent previous states or historical versions; however, only the final index block must be referenced by the main file header.
|
||||
|
||||
*Deprecation Notice*: This block is deprecated and *MUST NOT* be used in new image files.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define INDEX_MAGIC 0x58444E49
|
||||
/**Header for the index, followed by entries */
|
||||
typedef struct IndexHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.Index" /> */
|
||||
uint32_t identifier;
|
||||
/**How many entries follow this header */
|
||||
uint16_t entries;
|
||||
/**CRC64-ECMA of the index */
|
||||
uint64_t crc64;
|
||||
} IndexHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The index block identifier, always `INDX`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|CRC64-ECMA checksum of the entries following this header
|
||||
|===
|
||||
|
||||
==== Index entries
|
||||
|
||||
[source,c]
|
||||
/**Index entry */
|
||||
typedef struct IndexEntry
|
||||
{
|
||||
/**Type of item pointed by this entry */
|
||||
uint32_t blockType;
|
||||
/**Type of data contained by the block pointed by this entry */
|
||||
uint32_t dataType;
|
||||
/**Offset in file where item is stored */
|
||||
uint64_t offset;
|
||||
} IndexEntry;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|blockType
|
||||
|The type of block this entry points to.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|dataType
|
||||
|The type of data the block pointed by this entry contains.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|offset
|
||||
|The offset in bytes from the start of the file where the block pointed by this entry starts.
|
||||
|===
|
||||
85
docs/spec/blocks/index2.adoc
Normal file
85
docs/spec/blocks/index2.adoc
Normal file
@@ -0,0 +1,85 @@
|
||||
=== The index block version 2 (`IDX2`)
|
||||
|
||||
The index block stores references to all blocks present in the file.
|
||||
It is composed of a header, followed by a sequence of entries, the count of which is defined within the header.
|
||||
|
||||
Multiple index blocks may exist within a file to represent previous states or historical versions; however, only the final index block must be referenced by the main file header.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define INDEX2_MAGIC 0x32584449
|
||||
/**Header for the index, followed by entries */
|
||||
typedef struct IndexHeader2
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.Index" /> */
|
||||
uint32_t identifier;
|
||||
/**How many entries follow this header */
|
||||
uint64_t entries;
|
||||
/**CRC64-ECMA of the index */
|
||||
uint64_t crc64;
|
||||
} IndexHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The index block identifier, always `IDX2`
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|CRC64-ECMA checksum of the entries following this header
|
||||
|===
|
||||
|
||||
==== Index entries
|
||||
|
||||
[source,c]
|
||||
/**Index entry */
|
||||
typedef struct IndexEntry
|
||||
{
|
||||
/**Type of item pointed by this entry */
|
||||
uint32_t blockType;
|
||||
/**Type of data contained by the block pointed by this entry */
|
||||
uint32_t dataType;
|
||||
/**Offset in file where item is stored */
|
||||
uint64_t offset;
|
||||
} IndexEntry;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|blockType
|
||||
|The type of block this entry points to.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|dataType
|
||||
|The type of data the block pointed by this entry contains.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|offset
|
||||
|The offset in bytes from the start of the file where the block pointed by this entry starts.
|
||||
|===
|
||||
45
docs/spec/blocks/index_continuation.adoc
Normal file
45
docs/spec/blocks/index_continuation.adoc
Normal file
@@ -0,0 +1,45 @@
|
||||
=== The index block continuation (`IDXC`)
|
||||
|
||||
The index block continuation follows the same structure and semantics as the index block version 2, with the exception that it includes a pointer to the preceding index block or index block continuation.
|
||||
|
||||
At most, a single index block continuation may appear within any index block structure.
|
||||
|
||||
The purpose of this block is to enable incremental indexing prior to finalizing the image file.
|
||||
This allows new blocks to be indexed as they are written, facilitating partial recovery in the event of application failure.
|
||||
|
||||
The block is immediately followed by index entries formatted identically to those defined in index block version 2.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The index block identifier, always `IDXC`
|
||||
|
||||
|uint64
|
||||
|8 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint64
|
||||
|8 bytes
|
||||
|crc64
|
||||
|CRC64-ECMA checksum of the entries following this header
|
||||
|
||||
|uint64
|
||||
|8 bytes
|
||||
|previous
|
||||
|Pointer in image file to previous index block
|
||||
|===
|
||||
219
docs/spec/blocks/metadata.adoc
Normal file
219
docs/spec/blocks/metadata.adoc
Normal file
@@ -0,0 +1,219 @@
|
||||
=== The metadata block (`META`)
|
||||
|
||||
The metadata block contains descriptive information related to the media source, which is not part of the original media data itself.
|
||||
Typical fields may include the manufacturer name, device model, acquisition sequence identifiers, and other contextual attributes.
|
||||
|
||||
All string values within this block are encoded as little-endian UTF-16 and terminated with a null character.
|
||||
|
||||
[source,c]
|
||||
#define META_MAGIC 0x4154454D
|
||||
/**Metadata block, contains metadata */
|
||||
typedef struct MetadataBlockHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.MetadataBlock" /> */
|
||||
uint32_t identifier;
|
||||
/**Size in uint8_ts of this whole metadata block */
|
||||
uint32_t blockSize;
|
||||
/**Sequence of media set this media beint64_ts to */
|
||||
int32_t mediaSequence;
|
||||
/**Total number of media on the media set this media beint64_ts to */
|
||||
int32_t lastMediaSequence;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t creatorOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t creatorLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t commentsOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t commentsLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaTitleOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaTitleLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaManufacturerOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaManufacturerLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaModelOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaModelLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaSerialNumberOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaSerialNumberLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaBarcodeOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaBarcodeLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t mediaPartNumberOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t mediaPartNumberLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t driveManufacturerOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t driveManufacturerLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t driveModelOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t driveModelLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t driveSerialNumberOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t driveSerialNumberLength;
|
||||
/**Offset to start of creator string from start of this block */
|
||||
uint32_t driveFirmwareRevisionOffset;
|
||||
/**Length in uint8_ts of the null-terminated UTF-16LE creator string */
|
||||
uint32_t driveFirmwareRevisionLength;
|
||||
} MetadataBlockHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The metadata table identifier, always 'META'
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|blockSize
|
||||
|The size of this block including all of its data.
|
||||
|
||||
|int32_t
|
||||
|4 bytes
|
||||
|mediaSequence
|
||||
|The number of heads.
|
||||
|
||||
|int32_t
|
||||
|4 bytes
|
||||
|lastMediaSequence
|
||||
|The number of sectors per track.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|creatorOffset
|
||||
|Offset to start of creator string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|creatorLength
|
||||
|Length in bytes of the creator string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|commentsOffset
|
||||
|Offset to start of comments string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|commentsLength
|
||||
|Length in bytes of the comments string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaTitleOffset
|
||||
|Offset to start of media title string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaTitleLength
|
||||
|Length in bytes of the media title string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaManufacturerOffset
|
||||
|Offset to start of media manufacturer string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaManufacturerLength
|
||||
|Length in bytes of the media manufacturer string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaModelOffset
|
||||
|Offset to start of media model string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaModelLength
|
||||
|Length in bytes of the media model string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaSerialNumberOffset
|
||||
|Offset to start of media serial number string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaSerialNumberLength
|
||||
|Length in bytes of the media serial number string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaBarcodeOffset
|
||||
|Offset to start of media barcode string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaBarcodeLength
|
||||
|Length in bytes of the media barcode string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaPartNumberOffset
|
||||
|Offset to start of media part number string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|mediaPartNumberLength
|
||||
|Length in bytes of the media part number string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveManufacturerOffset
|
||||
|Offset to start of drive manufacturer string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveManufacturerLength
|
||||
|Length in bytes of the drive manufacturer string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveModelOffset
|
||||
|Offset to start of drive model string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveModelLength
|
||||
|Length in bytes of the drive model string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveSerialNumberOffset
|
||||
|Offset to start of drive serial number string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveSerialNumberLength
|
||||
|Length in bytes of the drive serial number string.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveFirmwareRevisionOffset
|
||||
|Offset to start of drive firmware revision string from start of this block.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|driveFirmwareRevisionLength
|
||||
|Length in bytes of the drive firmware revision string.
|
||||
|===
|
||||
58
docs/spec/blocks/parent.adoc
Normal file
58
docs/spec/blocks/parent.adoc
Normal file
@@ -0,0 +1,58 @@
|
||||
=== Parent File Block (`PRNT`)
|
||||
|
||||
The parent file block provides metadata required to locate the image file from which the current image is derived.
|
||||
Its primary purpose is to enable hierarchical composition, where non-written sectors in the current image are transparently resolved by referencing their counterparts in the parent image.
|
||||
|
||||
All sectors marked as unwritten must be read from the associated parent image, ensuring data completeness and consistency across derivative images.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The parent block identifier, always `PRNT`
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|GUID
|
||||
|16 bytes
|
||||
|parentId
|
||||
|The unique identifier of the parent.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|parentClueLength
|
||||
|The size in bytes of the clue string following this field.
|
||||
|
||||
|String
|
||||
|N bytes
|
||||
|parentClue
|
||||
|A clue, be it a path, filename, UNC, etc., to find the parent. If not valid or not found implementations shall try the directory where the image resides first and the current working directory if not found there.
|
||||
|===
|
||||
|
||||
This block contains metadata essential for locating the corresponding parent image.
|
||||
|
||||
All sectors flagged as undumped in the current image must be retrieved from the parent image to ensure completeness.
|
||||
The parent may also store supplementary blocks—such as media tags or metadata—that are not duplicated in the current image.
|
||||
However, any correctly defined data blocks or deduplication tables present in this image will override those found in the parent.
|
||||
|
||||
A clue field assists implementations in locating the parent, while a unique parent ID confirms its validity.
|
||||
If the clue fails to resolve the location, the implementation must first scan the directory containing the current image for files with a matching AaruFormat header and expected ID.
|
||||
If unsuccessful, the fallback should be the current working directory.
|
||||
|
||||
If this block is present but the parent image cannot be located, the implementation must terminate the open operation, as reconstructing the complete media content depends on the parent’s data.
|
||||
54
docs/spec/blocks/snapshot.adoc
Normal file
54
docs/spec/blocks/snapshot.adoc
Normal file
@@ -0,0 +1,54 @@
|
||||
=== Snapshot block (`SNAP`)
|
||||
|
||||
The snapshot block holds a list of historical indexes, representing earlier versions of the media captured within the image.
|
||||
This feature enables users to manually preserve a specific media state, allowing reversion to previous versions or comparison between multiple data capture attempts.
|
||||
|
||||
The active index used by the image must always be the one referenced by the image header.
|
||||
If any snapshot block references the current index, it must be ignored and treated as non-existent during image save operations.
|
||||
|
||||
Generation 0 refers to the initial image state, where only a single index—pointed to by the header—is present.
|
||||
|
||||
The latest image header should reference all available snapshots, unless individual blocks have been explicitly discarded by the user.
|
||||
Once discarded, such blocks become orphaned and are no longer reachable within the image structure.
|
||||
|
||||
During conversion from AaruFormat, only one snapshot (or the latest index) should be included, based on user selection.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The snapshot block identifier, always 'SNAP'
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|generation
|
||||
|The generation, starting from 1, of this snapshot. Every snapshot gets a generation incremented in one from the lastest recorded one.
|
||||
|
||||
|int64_t
|
||||
|8 bytes
|
||||
|creationTime
|
||||
|Creation time of this snapshot.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|index
|
||||
|Offset in bytes where the index marked by this snapshot resides.
|
||||
|===
|
||||
75
docs/spec/blocks/tape_file.adoc
Normal file
75
docs/spec/blocks/tape_file.adoc
Normal file
@@ -0,0 +1,75 @@
|
||||
=== Tape File Block ('TFLE')
|
||||
|
||||
Lists all tape files.
|
||||
Tape files are separations written to media, usually digital tapes, and are marked by filemarks.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define TAPE_FILE_MAGIC 0x454C4654
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The tape file block identifier, always `TFLE`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Tape file entries
|
||||
|
||||
[source,c]
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32
|
||||
|4 bytes
|
||||
|file
|
||||
|File number.
|
||||
|
||||
|uint8
|
||||
|1 byte
|
||||
|partition
|
||||
|Partition number this file belongs to.
|
||||
|
||||
|uint64
|
||||
|8 bytes
|
||||
|firstBlock
|
||||
|First block number, inclusive, of the file.
|
||||
|
||||
|uint64
|
||||
|8 bytes
|
||||
|lastBlock
|
||||
|Last block number, inclusive, of the file.
|
||||
|===
|
||||
72
docs/spec/blocks/tape_partition.adoc
Normal file
72
docs/spec/blocks/tape_partition.adoc
Normal file
@@ -0,0 +1,72 @@
|
||||
=== Tape Partition Block (`TPBT`)
|
||||
|
||||
This block lists all tape partitions.
|
||||
Tape partitions are separations written to media.
|
||||
They are used to distinguish two sets of related data that are distant enough to warrant separation but still belong on the same tape.
|
||||
A well-known example is the LTFS filesystem.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define TAPE_PARTITION_MAGIC 0x54504254
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The tape partition block identifier, always `TPBT`
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|entries
|
||||
|The number of entries following this header
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The length in bytes of the data following this header.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|===
|
||||
|
||||
==== Tape partition entries
|
||||
|
||||
[source,c]
|
||||
/* TODO */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|number
|
||||
|Partition number.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|firstBlock
|
||||
|First block number, inclusive, of the partition.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|lastBlock
|
||||
|Last block number, inclusive, of the partition.
|
||||
|===
|
||||
96
docs/spec/blocks/track_layout.adoc
Normal file
96
docs/spec/blocks/track_layout.adoc
Normal file
@@ -0,0 +1,96 @@
|
||||
=== Track Layout Block (`TKLY`)
|
||||
|
||||
The `TKLY` block defines the mapping between physical tracks and logical sectors, as referenced by the deduplication table.
|
||||
|
||||
Magnetic media such as floppies and hard disks may exhibit complex physical layouts that do not cleanly translate to logical block addresses.
|
||||
This block enables accurate sector location resolution by maintaining explicit layout information.
|
||||
|
||||
Each `TKLY` block corresponds to a unique combination of (sub)track and head, and is followed by a series of sector mapping entries.
|
||||
If known, sectors should be listed in physical order to preserve potential interleaving.
|
||||
Sector numbers may be duplicated.
|
||||
|
||||
NOTE: This block must not be used for optical or other logically addressable block-based media.
|
||||
|
||||
If a referenced LBA is marked as undumped and a `FLUX` block is present, it indicates the corresponding sector could not be decoded (e.g., damaged or unreadable), and should be considered undumped unless flags state otherwise.
|
||||
|
||||
If a `FLUX` block exists for a given (sub)track but no corresponding `TKLY` block is present, the entire (sub)track is considered not decoded.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The flux data block identifier, always `TKLY`
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the data following this header
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|head
|
||||
|Head the block corresponds to
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|track
|
||||
|Track the block corresponds to
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|subtrack
|
||||
|Substep of a track the data corresponds to
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|sectors
|
||||
|Number of sectors in this (sub)track, and therefore, number of entries following this header
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|flux
|
||||
|Pointer to the flux data block that contains the flux information for this (sub)track
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|bitstream
|
||||
|Pointer to the bitstream data block that contains the flux information for this (sub)track
|
||||
|===
|
||||
|
||||
==== Sector Mapping Entries
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint16_t
|
||||
|2 bytes
|
||||
|sector
|
||||
|Sector number as present in the appropriate media sector header or equivalent
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|block
|
||||
|Position in the deduplication table this sector and its flags is stored
|
||||
|===
|
||||
81
docs/spec/blocks/tracks.adoc
Normal file
81
docs/spec/blocks/tracks.adoc
Normal file
@@ -0,0 +1,81 @@
|
||||
=== The tracks block (`TRKS`)
|
||||
|
||||
The tracks block holds a structured list of track entries, typically aligned with the layout specified in the table of contents or a similar indexing schema.
|
||||
This format is common in optical media such as CDs, DVDs, and related disc-based formats.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
[source,c]
|
||||
#define TRACKS_MAGIC 0x534B5254
|
||||
/**Contains list of optical disc tracks */
|
||||
typedef struct TracksHeader
|
||||
{
|
||||
/**Identifier, <see cref="BlockType.TracksBlock" /> */
|
||||
uint32_t identifier;
|
||||
/**How many entries follow this header */
|
||||
uint16_t entries;
|
||||
/**CRC64-ECMA of the block */
|
||||
uint64_t crc64;
|
||||
} TracksHeader;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type|Size|Name|Description
|
||||
|uint32_t|4 bytes|identifier|The tracks block identifier, always `TRKS`
|
||||
|uint16_t|2 bytes|entries|The number of entries following this header
|
||||
|uint64_t|8 bytes|crc64|CRC64-ECMA checksum of the entries following this header
|
||||
|===
|
||||
|
||||
==== Track entries
|
||||
|
||||
[source,c]
|
||||
/**Optical disc track */
|
||||
typedef struct TrackEntry
|
||||
{
|
||||
/**Track sequence */
|
||||
uint8_t sequence;
|
||||
/**Track type */
|
||||
uint8_t type;
|
||||
/**Track starting LBA */
|
||||
int64_t start;
|
||||
/**Track last LBA */
|
||||
int64_t end;
|
||||
/**Track pregap in sectors */
|
||||
int64_t pregap;
|
||||
/**Track session */
|
||||
uint8_t session;
|
||||
/**Track's ISRC in ASCII */
|
||||
uint8_t isrc[13];
|
||||
/**Track flags */
|
||||
uint8_t flags;
|
||||
} TrackEntry;
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type|Size|Name|Description
|
||||
|uint8|1 byte|sequence|Track number.
|
||||
|uint8|1 byte|type|Track type (see table below).
|
||||
|int64|8 bytes|start|Track starting LBA (including pregap).
|
||||
|int64|8 bytes|end|Track ending LBA.
|
||||
|int64|8 bytes|pregap|Size of track’s pregap in sectors.
|
||||
|uint8|1 byte|session|Session the track belongs to.
|
||||
|StringA|13 bytes|isrc|Track’s ISRC in ASCIIZ.
|
||||
|uint8|1 byte|flags|Track flags as indicated in TOC if applicable.
|
||||
|===
|
||||
|
||||
==== Track Types
|
||||
|
||||
[cols="2,1,8",options="header"]
|
||||
|===
|
||||
|Type|Value|Description
|
||||
|Audio|0|All sectors in the track contain audio as defined by the Red Book.
|
||||
|Data|1|All sectors in the track contain user data that is not defined by any of the following types.
|
||||
|CdMode1|2|All sectors in the track contain user data according to MODE 1 as defined by the Yellow Book.
|
||||
|CdMode2Formless|3|All sectors in the track contain user data according to MODE 2 as defined by the Yellow and Green Books. Not all sectors belong to the same Form.
|
||||
|CdMode2Form1|4|All sectors in the track contain user data according to MODE 2 Form 1 as defined by the Yellow and Green Books. All sectors belong to the same Form.
|
||||
|CdMode2Form2|5|All sectors in the track contain user data according to MODE 2 Form 2 as defined by the Yellow and Green Books. All sectors belong to the same Form.
|
||||
|===
|
||||
85
docs/spec/blocks/twin_sector.adoc
Normal file
85
docs/spec/blocks/twin_sector.adoc
Normal file
@@ -0,0 +1,85 @@
|
||||
=== The twin sector table (`TWTB`)
|
||||
|
||||
This table enumerates hardware sectors that share an identical sector number.
|
||||
Such sectors are referred to as “twin sectors,” although the grouping may consist of more than two instances.
|
||||
The associated pointer is resolved following the same logic applied in a last-level deduplication table.
|
||||
|
||||
[source,c]
|
||||
/* Undefined */
|
||||
|
||||
==== Field Descriptions
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|identifier
|
||||
|The twin sector table identifier, always `TWTB`
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|alignment
|
||||
|Shift of alignment of all blocks in the image. This must be the same in all deduplication tables and subtables.
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|shift
|
||||
|The shift used to calculate the position of a sector in a data block pointed by this table, or how many sectors are pointed by the next level.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|entries
|
||||
|How many pointers follow this header.
|
||||
|
||||
|uint32_t
|
||||
|4 bytes
|
||||
|length
|
||||
|The size in bytes of the table block.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
|The CRC64-ECMA checksum of the decompressed table.
|
||||
|===
|
||||
|
||||
==== Twin sector entries
|
||||
|
||||
[cols="2,2,2,6",options="header"]
|
||||
|===
|
||||
|Type
|
||||
|Size
|
||||
|Name
|
||||
|Description
|
||||
|
||||
|uint32_t
|
||||
|8 bytes
|
||||
|pointer
|
||||
|Pointer to the sector.
|
||||
|===
|
||||
|
||||
==== Pointer-Based Data Block Resolution
|
||||
|
||||
To determine the corresponding data block:
|
||||
|
||||
. Right-shift the pointer value using the specified `shift` parameter.
|
||||
. Multiply the result by the `alignment` value.
|
||||
. The remainder from this operation indicates the sector's offset within the target data block.
|
||||
|
||||
Each data block contains a fixed number of bytes per sector, which remains constant across blocks.
|
||||
This invariant size allows for more efficient storage of pointer values.
|
||||
|
||||
===== Example
|
||||
|
||||
Given the following parameters:
|
||||
|
||||
* Pointer Value: `0x8003`
|
||||
* Shift Value: `5`
|
||||
* Alignment: `9`
|
||||
|
||||
The data block is located at byte offset `524288`.
|
||||
The sector referenced by the pointer is the **third entry** within this block.
|
||||
Reference in New Issue
Block a user