blob: 618a1936955b5c971bf821ed750831f7fc70eb9f [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kees Cook5d3bca82013-08-16 07:59:11 -07002/*
3 * Copyright (c) 2013, The Chromium Authors
Kees Cook5d3bca82013-08-16 07:59:11 -07004 */
5
Brandon Maier61c55e82023-01-12 10:27:46 -06006#include <abuf.h>
Simon Glass6d084ce2014-12-02 13:17:35 -07007#include <bootm.h>
Kees Cook5d3bca82013-08-16 07:59:11 -07008#include <command.h>
Simon Glass1a974af2019-08-01 09:46:36 -06009#include <gzip.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060010#include <image.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070012#include <malloc.h>
Joe Hershberger65b905b2015-03-22 17:08:59 -050013#include <mapmem.h>
Simon Glass6d084ce2014-12-02 13:17:35 -070014#include <asm/io.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070015
Simon Glasscaf62672021-10-09 09:28:21 -060016#include <u-boot/lz4.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070017#include <u-boot/zlib.h>
18#include <bzlib.h>
19
20#include <lzma/LzmaTypes.h>
21#include <lzma/LzmaDec.h>
22#include <lzma/LzmaTools.h>
23
24#include <linux/lzo.h>
Brandon Maier61c55e82023-01-12 10:27:46 -060025#include <linux/zstd.h>
Simon Glass1edaed02017-11-25 11:57:33 -070026#include <test/compression.h>
27#include <test/suites.h>
28#include <test/ut.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070029
30static const char plain[] =
31 "I am a highly compressable bit of text.\n"
32 "I am a highly compressable bit of text.\n"
33 "I am a highly compressable bit of text.\n"
34 "There are many like me, but this one is mine.\n"
35 "If I were any shorter, there wouldn't be much sense in\n"
36 "compressing me in the first place. At least with lzo, anyway,\n"
37 "which appears to behave poorly in the face of short text\n"
38 "messages.\n";
39
40/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
41static const char bzip2_compressed[] =
42 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
43 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
44 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
45 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
46 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
47 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
48 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
49 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
50 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
51 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
52 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
53 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
54 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
55 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
56 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
Brandon Maier9e2d2662023-01-09 12:42:58 -060057static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070058
59/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
60static const char lzma_compressed[] =
61 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
62 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
63 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
64 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
65 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
66 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
67 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
68 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
69 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
70 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
71 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
72 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
73 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
74 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
75 "\xfd\xf5\x50\x8d\xca";
Brandon Maier9e2d2662023-01-09 12:42:58 -060076static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070077
78/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
79static const char lzo_compressed[] =
80 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
81 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
82 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
83 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
84 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
85 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
86 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
87 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
88 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
89 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
90 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
91 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
92 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
93 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
94 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
95 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
96 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
97 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
98 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
99 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
100 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600101static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -0700102
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700103/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
104static const char lz4_compressed[] =
105 "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
106 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
107 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
108 "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
109 "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
110 "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
111 "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
112 "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
113 "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
114 "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
115 "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
116 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
117 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
118 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
119 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
120 "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
121 "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
122 "\x9d\x12\x8c\x9d";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600123static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700124
Brandon Maier61c55e82023-01-12 10:27:46 -0600125/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
126static const char zstd_compressed[] =
127 "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
128 "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
129 "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
130 "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
131 "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
132 "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
133 "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
134 "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
135 "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
136 "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
137 "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
138 "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
139 "\x01\xe4\xf4\x6e\xfa";
140static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
141
Kees Cook5d3bca82013-08-16 07:59:11 -0700142#define TEST_BUFFER_SIZE 512
143
Simon Glass1edaed02017-11-25 11:57:33 -0700144typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
145 void *, unsigned long, unsigned long *);
Kees Cook5d3bca82013-08-16 07:59:11 -0700146
Simon Glass1edaed02017-11-25 11:57:33 -0700147static int compress_using_gzip(struct unit_test_state *uts,
148 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700149 void *out, unsigned long out_max,
150 unsigned long *out_size)
151{
152 int ret;
153 unsigned long inout_size = out_max;
154
155 ret = gzip(out, &inout_size, in, in_size);
156 if (out_size)
157 *out_size = inout_size;
158
159 return ret;
160}
161
Simon Glass1edaed02017-11-25 11:57:33 -0700162static int uncompress_using_gzip(struct unit_test_state *uts,
163 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700164 void *out, unsigned long out_max,
165 unsigned long *out_size)
166{
167 int ret;
168 unsigned long inout_size = in_size;
169
170 ret = gunzip(out, out_max, in, &inout_size);
171 if (out_size)
172 *out_size = inout_size;
173
174 return ret;
175}
176
Simon Glass1edaed02017-11-25 11:57:33 -0700177static int compress_using_bzip2(struct unit_test_state *uts,
178 void *in, unsigned long in_size,
Wolfgang Denkec7fbf52013-10-04 17:43:24 +0200179 void *out, unsigned long out_max,
180 unsigned long *out_size)
Kees Cook5d3bca82013-08-16 07:59:11 -0700181{
182 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700183 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600184 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700185
186 if (bzip2_compressed_size > out_max)
187 return -1;
188
189 memcpy(out, bzip2_compressed, bzip2_compressed_size);
190 if (out_size)
191 *out_size = bzip2_compressed_size;
192
193 return 0;
194}
195
Simon Glass1edaed02017-11-25 11:57:33 -0700196static int uncompress_using_bzip2(struct unit_test_state *uts,
197 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700198 void *out, unsigned long out_max,
199 unsigned long *out_size)
200{
201 int ret;
202 unsigned int inout_size = out_max;
203
204 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
205 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
206 if (out_size)
207 *out_size = inout_size;
208
209 return (ret != BZ_OK);
210}
211
Simon Glass1edaed02017-11-25 11:57:33 -0700212static int compress_using_lzma(struct unit_test_state *uts,
213 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700214 void *out, unsigned long out_max,
215 unsigned long *out_size)
216{
217 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700218 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600219 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700220
221 if (lzma_compressed_size > out_max)
222 return -1;
223
224 memcpy(out, lzma_compressed, lzma_compressed_size);
225 if (out_size)
226 *out_size = lzma_compressed_size;
227
228 return 0;
229}
230
Simon Glass1edaed02017-11-25 11:57:33 -0700231static int uncompress_using_lzma(struct unit_test_state *uts,
232 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700233 void *out, unsigned long out_max,
234 unsigned long *out_size)
235{
236 int ret;
237 SizeT inout_size = out_max;
238
239 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
240 if (out_size)
241 *out_size = inout_size;
242
243 return (ret != SZ_OK);
244}
245
Simon Glass1edaed02017-11-25 11:57:33 -0700246static int compress_using_lzo(struct unit_test_state *uts,
247 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700248 void *out, unsigned long out_max,
249 unsigned long *out_size)
250{
251 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700252 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600253 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700254
255 if (lzo_compressed_size > out_max)
256 return -1;
257
258 memcpy(out, lzo_compressed, lzo_compressed_size);
259 if (out_size)
260 *out_size = lzo_compressed_size;
261
262 return 0;
263}
264
Simon Glass1edaed02017-11-25 11:57:33 -0700265static int uncompress_using_lzo(struct unit_test_state *uts,
266 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700267 void *out, unsigned long out_max,
268 unsigned long *out_size)
269{
270 int ret;
271 size_t input_size = in_size;
272 size_t output_size = out_max;
273
274 ret = lzop_decompress(in, input_size, out, &output_size);
275 if (out_size)
276 *out_size = output_size;
277
278 return (ret != LZO_E_OK);
279}
280
Simon Glass1edaed02017-11-25 11:57:33 -0700281static int compress_using_lz4(struct unit_test_state *uts,
282 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700283 void *out, unsigned long out_max,
284 unsigned long *out_size)
285{
286 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700287 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600288 ut_asserteq_mem(plain, in, in_size);
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700289
290 if (lz4_compressed_size > out_max)
291 return -1;
292
293 memcpy(out, lz4_compressed, lz4_compressed_size);
294 if (out_size)
295 *out_size = lz4_compressed_size;
296
297 return 0;
298}
299
Simon Glass1edaed02017-11-25 11:57:33 -0700300static int uncompress_using_lz4(struct unit_test_state *uts,
301 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700302 void *out, unsigned long out_max,
303 unsigned long *out_size)
304{
305 int ret;
306 size_t input_size = in_size;
307 size_t output_size = out_max;
308
309 ret = ulz4fn(in, input_size, out, &output_size);
310 if (out_size)
311 *out_size = output_size;
312
313 return (ret != 0);
314}
315
Brandon Maier61c55e82023-01-12 10:27:46 -0600316static int compress_using_zstd(struct unit_test_state *uts,
317 void *in, unsigned long in_size,
318 void *out, unsigned long out_max,
319 unsigned long *out_size)
320{
321 /* There is no zstd compression in u-boot, so fake it. */
322 ut_asserteq(in_size, strlen(plain));
323 ut_asserteq_mem(plain, in, in_size);
324
325 if (zstd_compressed_size > out_max)
326 return -1;
327
328 memcpy(out, zstd_compressed, zstd_compressed_size);
329 if (out_size)
330 *out_size = zstd_compressed_size;
331
332 return 0;
333}
334
335static int uncompress_using_zstd(struct unit_test_state *uts,
336 void *in, unsigned long in_size,
337 void *out, unsigned long out_max,
338 unsigned long *out_size)
339{
340 struct abuf in_buf, out_buf;
341 int ret;
342
343 abuf_init_set(&in_buf, in, in_size);
344 abuf_init_set(&out_buf, out, out_max);
345
346 ret = zstd_decompress(&in_buf, &out_buf);
347 if (ret >= 0) {
348 *out_size = ret;
349 ret = 0;
350 }
351
352 return ret;
353}
354
Kees Cook5d3bca82013-08-16 07:59:11 -0700355#define errcheck(statement) if (!(statement)) { \
356 fprintf(stderr, "\tFailed: %s\n", #statement); \
357 ret = 1; \
358 goto out; \
359}
360
Simon Glass053f8012017-11-25 11:57:31 -0700361struct buf_state {
362 ulong orig_size;
363 ulong compressed_size;
364 ulong uncompressed_size;
Kees Cook5d3bca82013-08-16 07:59:11 -0700365 void *orig_buf;
Simon Glass053f8012017-11-25 11:57:31 -0700366 void *compressed_buf;
367 void *uncompressed_buf;
368 void *compare_buf;
369};
Kees Cook5d3bca82013-08-16 07:59:11 -0700370
Simon Glass1edaed02017-11-25 11:57:33 -0700371static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass053f8012017-11-25 11:57:31 -0700372 mutate_func compress, mutate_func uncompress,
373 struct buf_state *buf)
374{
375 int ret;
Kees Cook5d3bca82013-08-16 07:59:11 -0700376
377 /* Compress works as expected. */
Simon Glass053f8012017-11-25 11:57:31 -0700378 printf("\torig_size:%lu\n", buf->orig_size);
379 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600380 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass1edaed02017-11-25 11:57:33 -0700381 buf->compressed_buf, buf->compressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600382 &buf->compressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700383 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600384 ut_assert(buf->compressed_size > 0);
385 ut_assert(buf->compressed_size < buf->orig_size);
386 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
387 != 'A');
388 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700389
390 /* Uncompresses with space remaining. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600391 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700392 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600393 &buf->uncompressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700394 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600395 ut_asserteq(buf->uncompressed_size, buf->orig_size);
396 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700397
398 /* Uncompresses with exactly the right size output buffer. */
Simon Glass053f8012017-11-25 11:57:31 -0700399 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600400 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700401 buf->uncompressed_buf, buf->orig_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600402 &buf->uncompressed_size));
403 ut_asserteq(buf->uncompressed_size, buf->orig_size);
404 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
405 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700406
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600407 /* Uncompresses with trailing garbage in input buffer. */
408 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600409 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600410 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600411 &buf->uncompressed_size));
412 ut_asserteq(buf->uncompressed_size, buf->orig_size);
413 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600414
Kees Cook5d3bca82013-08-16 07:59:11 -0700415 /* Make sure compression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700416 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700417 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass053f8012017-11-25 11:57:31 -0700418 buf->compare_buf, buf->compressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700419 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600420 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
421 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700422 printf("\tcompress does not overrun\n");
423
424 /* Make sure decompression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700425 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700426 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700427 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700428 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600429 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
430 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700431 printf("\tuncompress does not overrun\n");
432
433 /* Got here, everything is fine. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600434 return 0;
Simon Glass053f8012017-11-25 11:57:31 -0700435}
436
Simon Glass1edaed02017-11-25 11:57:33 -0700437static int run_test(struct unit_test_state *uts, char *name,
438 mutate_func compress, mutate_func uncompress)
Simon Glass053f8012017-11-25 11:57:31 -0700439{
440 struct buf_state sbuf, *buf = &sbuf;
441 int ret;
442
443 printf(" testing %s ...\n", name);
444
445 buf->orig_buf = (void *)plain;
446 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
447 errcheck(buf->orig_size > 0);
448
449 buf->compressed_size = TEST_BUFFER_SIZE;
450 buf->uncompressed_size = TEST_BUFFER_SIZE;
451 buf->compressed_buf = malloc(buf->compressed_size);
452 errcheck(buf->compressed_buf);
453 buf->uncompressed_buf = malloc(buf->uncompressed_size);
454 errcheck(buf->uncompressed_buf);
455 buf->compare_buf = malloc(buf->uncompressed_size);
456 errcheck(buf->compare_buf);
457
Simon Glass1edaed02017-11-25 11:57:33 -0700458 ret = run_test_internal(uts, name, compress, uncompress, buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700459out:
460 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
461
Simon Glass053f8012017-11-25 11:57:31 -0700462 free(buf->compare_buf);
463 free(buf->uncompressed_buf);
464 free(buf->compressed_buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700465
466 return ret;
467}
468
Simon Glass1edaed02017-11-25 11:57:33 -0700469static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook5d3bca82013-08-16 07:59:11 -0700470{
Simon Glass1edaed02017-11-25 11:57:33 -0700471 return run_test(uts, "gzip", compress_using_gzip,
472 uncompress_using_gzip);
473}
474COMPRESSION_TEST(compression_test_gzip, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700475
Simon Glass1edaed02017-11-25 11:57:33 -0700476static int compression_test_bzip2(struct unit_test_state *uts)
477{
478 return run_test(uts, "bzip2", compress_using_bzip2,
479 uncompress_using_bzip2);
480}
481COMPRESSION_TEST(compression_test_bzip2, 0);
482
483static int compression_test_lzma(struct unit_test_state *uts)
484{
485 return run_test(uts, "lzma", compress_using_lzma,
486 uncompress_using_lzma);
487}
488COMPRESSION_TEST(compression_test_lzma, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700489
Simon Glass1edaed02017-11-25 11:57:33 -0700490static int compression_test_lzo(struct unit_test_state *uts)
491{
492 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
493}
494COMPRESSION_TEST(compression_test_lzo, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700495
Simon Glass1edaed02017-11-25 11:57:33 -0700496static int compression_test_lz4(struct unit_test_state *uts)
497{
498 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
Kees Cook5d3bca82013-08-16 07:59:11 -0700499}
Simon Glass1edaed02017-11-25 11:57:33 -0700500COMPRESSION_TEST(compression_test_lz4, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700501
Brandon Maier61c55e82023-01-12 10:27:46 -0600502static int compression_test_zstd(struct unit_test_state *uts)
503{
504 return run_test(uts, "zstd", compress_using_zstd,
505 uncompress_using_zstd);
506}
507COMPRESSION_TEST(compression_test_zstd, 0);
508
Simon Glass1edaed02017-11-25 11:57:33 -0700509static int compress_using_none(struct unit_test_state *uts,
510 void *in, unsigned long in_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700511 void *out, unsigned long out_max,
512 unsigned long *out_size)
513{
514 /* Here we just copy */
515 memcpy(out, in, in_size);
516 *out_size = in_size;
517
518 return 0;
519}
520
521/**
Heinrich Schuchardtd3855cf2020-03-23 18:47:47 +0100522 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6d084ce2014-12-02 13:17:35 -0700523 *
524 * @comp_type: Compression type to test
525 * @compress: Our function to compress data
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100526 * Return: 0 if OK, non-zero on failure
Simon Glass6d084ce2014-12-02 13:17:35 -0700527 */
Simon Glass1edaed02017-11-25 11:57:33 -0700528static int run_bootm_test(struct unit_test_state *uts, int comp_type,
529 mutate_func compress)
Simon Glass6d084ce2014-12-02 13:17:35 -0700530{
531 ulong compress_size = 1024;
532 void *compress_buff;
533 int unc_len;
534 int err = 0;
535 const ulong image_start = 0;
536 const ulong load_addr = 0x1000;
537 ulong load_end;
538
539 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
540 compress_buff = map_sysmem(image_start, 0);
541 unc_len = strlen(plain);
Simon Glass1edaed02017-11-25 11:57:33 -0700542 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700543 &compress_size);
Julius Werner47ef9862019-07-24 19:37:54 -0700544 err = image_decomp(comp_type, load_addr, image_start,
545 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
546 compress_buff, compress_size, unc_len,
547 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700548 ut_assertok(err);
Julius Werner47ef9862019-07-24 19:37:54 -0700549 err = image_decomp(comp_type, load_addr, image_start,
550 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
551 compress_buff, compress_size, unc_len - 1,
552 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700553 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700554
555 /* We can't detect corruption when not decompressing */
556 if (comp_type == IH_COMP_NONE)
557 return 0;
558 memset(compress_buff + compress_size / 2, '\x49',
559 compress_size / 2);
Julius Werner47ef9862019-07-24 19:37:54 -0700560 err = image_decomp(comp_type, load_addr, image_start,
561 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
562 compress_buff, compress_size, 0x10000,
563 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700564 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700565
566 return 0;
567}
568
Simon Glass1edaed02017-11-25 11:57:33 -0700569static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6d084ce2014-12-02 13:17:35 -0700570{
Simon Glass1edaed02017-11-25 11:57:33 -0700571 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
572}
573COMPRESSION_TEST(compression_test_bootm_gzip, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700574
Simon Glass1edaed02017-11-25 11:57:33 -0700575static int compression_test_bootm_bzip2(struct unit_test_state *uts)
576{
577 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
578}
579COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700580
Simon Glass1edaed02017-11-25 11:57:33 -0700581static int compression_test_bootm_lzma(struct unit_test_state *uts)
582{
583 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
584}
585COMPRESSION_TEST(compression_test_bootm_lzma, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700586
Simon Glass1edaed02017-11-25 11:57:33 -0700587static int compression_test_bootm_lzo(struct unit_test_state *uts)
588{
589 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
Simon Glass6d084ce2014-12-02 13:17:35 -0700590}
Simon Glass1edaed02017-11-25 11:57:33 -0700591COMPRESSION_TEST(compression_test_bootm_lzo, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700592
Simon Glass1edaed02017-11-25 11:57:33 -0700593static int compression_test_bootm_lz4(struct unit_test_state *uts)
594{
595 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
596}
597COMPRESSION_TEST(compression_test_bootm_lz4, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700598
Brandon Maier61c55e82023-01-12 10:27:46 -0600599static int compression_test_bootm_zstd(struct unit_test_state *uts)
600{
601 return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
602}
603COMPRESSION_TEST(compression_test_bootm_zstd, 0);
604
Simon Glass1edaed02017-11-25 11:57:33 -0700605static int compression_test_bootm_none(struct unit_test_state *uts)
606{
607 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
608}
609COMPRESSION_TEST(compression_test_bootm_none, 0);
610
Simon Glassed38aef2020-05-10 11:40:03 -0600611int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
612 char *const argv[])
Simon Glass1edaed02017-11-25 11:57:33 -0700613{
Simon Glassb50211f2021-03-07 17:35:10 -0700614 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
615 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
Simon Glass1edaed02017-11-25 11:57:33 -0700616
Philippe Reynes1f99f842019-12-17 19:07:04 +0100617 return cmd_ut_category("compression", "compression_test_",
618 tests, n_ents, argc, argv);
Simon Glass1edaed02017-11-25 11:57:33 -0700619}