Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LZFSE compressed data format

LZFSE compression is used in various data formats used on Mac OS, including Universal Disk Image Format (UDIF) files (.dmg) and Apple File System Compression (decmpfs), which is used in Hierarchical File System (HFS) and Apple File System (APFS).

Overview

LZFSE compressed data stream consist of:

Characteristics

CharacteristicsDescription
Byte orderlittle-endian

LZFSE block

A LZFSE block is of variable size and consits of:

OffsetSizeValueDescription
04Block signature
4...Block data

Block signatures

ValueIdentifierDescription
0x00000000LZFSE_NO_BLOCK_MAGICInvalid
0x24787662 ("bvx$")LZFSE_ENDOFSTREAM_BLOCK_MAGICEnd-of-stream block (marker)
0x2d787662 ("bvx-")LZFSE_UNCOMPRESSED_BLOCK_MAGICUncompressed (raw) block
0x31787662 ("bvx1")LZFSE_COMPRESSEDV1_BLOCK_MAGICLZFSE compressed block with uncompressed tables
0x32787662 ("bvx2")LZFSE_COMPRESSEDV2_BLOCK_MAGICLZFSE compressed block with compressed tables
0x6e787662 ("bvxn")LZFSE_COMPRESSEDLZVN_BLOCK_MAGICLZVN compressed block

End-of-stream block

An end-of-stream block is 4 bytes in size and consits of:

OffsetSizeValueDescription
Block header
04"bvx$"Block signature

Uncompressed block

An uncompressed block is of variable size and consits of:

OffsetSizeValueDescription
Block header
04"bvx-"Block signature
44Uncompressed data size
 
8...Uncompressed data

LZFSE compressed block with uncompressed tables

A LZFSE compressed block with uncompressed tables (lzfse_compressed_block_header_v1) is of variable size and consits of:

OffsetSizeValueDescription
Block header
04"bvx1"Block signature
44Uncompressed data size
84Compressed data size
124Number of literals
164Number of L, M, D values
204Number of bytes used to encode literals
244Number of bytes used to encode matches
284Unknown (Final accum_nbits for literals stream)
322First literal state
342Second literal state
362Third literal state
382Fourth literal state
404Unknown (accum_nbits for the l, m, d stream)
442L value state
462M value state
482D value state
50720Frequency table
 
770...encoded literals
......encoded L, M, D values

LZFSE compressed block with compressed tables

A LZFSE compressed block with compressed tables (lzfse_compressed_block_header_v2) is of variable size and consits of:

OffsetSizeValueDescription
Block header
04"bvx2"Block signature
44Uncompressed data size
3 x 64-bit packed fields
8.020 bitsNumber of literals
10.420 bitsNumber of bytes used to encode literals
13.020 bitsNumber of L, M, D values
15.43 bitsUnknown (Final accum_nbits for literals stream)
14.71 bitUnknown (unused)
16.010 bitsFirst literal state
17.210 bitsSecond literal state
18.410 bitsThird literal state
19.610 bitsFourth literal state
21.020 bitsNumber of bytes used to encode matches
22.43 bitsUnknown (accum_nbits for the l, m, d stream)
23.71 bitUnknown (unused)
24.032 bitsBlock header size
28.010 bitsL value state
29.210 bitsM value state
30.410 bitsD value state
31.62 bitsUnknown (unused)
If block header size > 32
32...Bit stream containing Huffman encoded frequency table
Common
......encoded literals
......encoded L, M, D values

Note that if the block header size is 32 the block does not contain frequency tables.

LZVN compressed block

A LZVN compressed block is of variable size and consits of:

OffsetSizeValueDescription
Block header
04"bvxn"Block signature
44Uncompressed data size
84Compressed data size
 
12...LZVN compressed data

LZFSE frequency table

A LZFSE frequency table consist of 360 16-bit values:

OffsetSizeValueDescription
020Literal run-lengths (L stream) frequency values
2020Match sizes (M stream) frequency values
4064Match distances (D stream) frequency values
104256Literal frequency values

Decoding the Huffman encoded frequency table

TODO: describe how to decode the Huffman encoded frequency table.

5-bits encoded value, special cases 8 and 14

lzfse_freq_nbits_table[32] = {
    2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14,
    2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14 };

lzfse_freq_value_table[32] = {
    0, 2, 1, 4, 0, 3, 1, -1, 0, 2, 1, 5, 0, 3, 1, -1,
    0, 2, 1, 6, 0, 3, 1, -1, 0, 2, 1, 7, 0, 3, 1, -1 };