blob: dc76adab35213ed64ae2d534668aa7e7fd3c6920 [file] [log] [blame]
Simon Glassad35ce52022-01-09 20:14:03 -07001# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2022 Google LLC
3#
4"""Utilities to compress and decompress data"""
5
6import struct
7import tempfile
8
Simon Glass33ce3512022-01-09 20:14:06 -07009from binman import bintool
Simon Glassad35ce52022-01-09 20:14:03 -070010from patman import tools
11
Simon Glass33ce3512022-01-09 20:14:06 -070012LZ4 = bintool.Bintool.create('lz4')
13HAVE_LZ4 = LZ4.is_present()
14
Simon Glass359e4312022-01-09 20:14:08 -070015LZMA_ALONE = bintool.Bintool.create('lzma_alone')
16HAVE_LZMA_ALONE = LZMA_ALONE.is_present()
17
Simon Glass33ce3512022-01-09 20:14:06 -070018
Simon Glass0d1e95a2022-01-09 20:14:04 -070019def compress(indata, algo, with_header=True):
Simon Glassad35ce52022-01-09 20:14:03 -070020 """Compress some data using a given algorithm
21
22 Note that for lzma this uses an old version of the algorithm, not that
23 provided by xz.
24
25 This requires 'lz4' and 'lzma_alone' tools. It also requires an output
26 directory to be previously set up, by calling PrepareOutputDir().
27
Simon Glassad35ce52022-01-09 20:14:03 -070028 Args:
Simon Glass0d1e95a2022-01-09 20:14:04 -070029 indata (bytes): Input data to compress
Simon Glassa00d9712022-01-09 20:14:10 -070030 algo (str): Algorithm to use ('none', 'lz4' or 'lzma')
Simon Glassad35ce52022-01-09 20:14:03 -070031
32 Returns:
Simon Glass0d1e95a2022-01-09 20:14:04 -070033 bytes: Compressed data
Simon Glassad35ce52022-01-09 20:14:03 -070034 """
35 if algo == 'none':
36 return indata
Simon Glassad35ce52022-01-09 20:14:03 -070037 if algo == 'lz4':
Simon Glass33ce3512022-01-09 20:14:06 -070038 data = LZ4.compress(indata)
Simon Glassad35ce52022-01-09 20:14:03 -070039 # cbfstool uses a very old version of lzma
40 elif algo == 'lzma':
Simon Glass359e4312022-01-09 20:14:08 -070041 data = LZMA_ALONE.compress(indata)
Simon Glassad35ce52022-01-09 20:14:03 -070042 else:
43 raise ValueError("Unknown algorithm '%s'" % algo)
44 if with_header:
45 hdr = struct.pack('<I', len(data))
46 data = hdr + data
47 return data
48
Simon Glass0d1e95a2022-01-09 20:14:04 -070049def decompress(indata, algo, with_header=True):
Simon Glassad35ce52022-01-09 20:14:03 -070050 """Decompress some data using a given algorithm
51
52 Note that for lzma this uses an old version of the algorithm, not that
53 provided by xz.
54
55 This requires 'lz4' and 'lzma_alone' tools. It also requires an output
56 directory to be previously set up, by calling PrepareOutputDir().
57
58 Args:
Simon Glass0d1e95a2022-01-09 20:14:04 -070059 indata (bytes): Input data to decompress
Simon Glassa00d9712022-01-09 20:14:10 -070060 algo (str): Algorithm to use ('none', 'lz4' or 'lzma')
Simon Glassad35ce52022-01-09 20:14:03 -070061
62 Returns:
Simon Glass0d1e95a2022-01-09 20:14:04 -070063 (bytes) Compressed data
Simon Glassad35ce52022-01-09 20:14:03 -070064 """
65 if algo == 'none':
66 return indata
67 if with_header:
68 data_len = struct.unpack('<I', indata[:4])[0]
69 indata = indata[4:4 + data_len]
Simon Glassad35ce52022-01-09 20:14:03 -070070 if algo == 'lz4':
Simon Glass33ce3512022-01-09 20:14:06 -070071 data = LZ4.decompress(indata)
Simon Glassad35ce52022-01-09 20:14:03 -070072 elif algo == 'lzma':
Simon Glass359e4312022-01-09 20:14:08 -070073 data = LZMA_ALONE.decompress(indata)
Simon Glassad35ce52022-01-09 20:14:03 -070074 else:
75 raise ValueError("Unknown algorithm '%s'" % algo)
76 return data