1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2013, The Chromium Authors
4 */
5
6#include <common.h>
7#include <abuf.h>
8#include <bootm.h>
9#include <command.h>
10#include <gzip.h>
11#include <image.h>
12#include <log.h>
13#include <malloc.h>
14#include <mapmem.h>
15#include <asm/io.h>
16
17#include <u-boot/lz4.h>
18#include <u-boot/zlib.h>
19#include <bzlib.h>
20
21#include <lzma/LzmaTypes.h>
22#include <lzma/LzmaDec.h>
23#include <lzma/LzmaTools.h>
24
25#include <linux/lzo.h>
26#include <linux/zstd.h>
27#include <test/compression.h>
28#include <test/suites.h>
29#include <test/ut.h>
30
31static const char plain[] =
32	"I am a highly compressable bit of text.\n"
33	"I am a highly compressable bit of text.\n"
34	"I am a highly compressable bit of text.\n"
35	"There are many like me, but this one is mine.\n"
36	"If I were any shorter, there wouldn't be much sense in\n"
37	"compressing me in the first place. At least with lzo, anyway,\n"
38	"which appears to behave poorly in the face of short text\n"
39	"messages.\n";
40
41/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
42static const char bzip2_compressed[] =
43	"\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
44	"\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
45	"\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
46	"\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
47	"\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
48	"\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
49	"\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
50	"\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
51	"\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
52	"\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
53	"\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
54	"\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
55	"\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
56	"\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
57	"\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
58static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
59
60/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
61static const char lzma_compressed[] =
62	"\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
63	"\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
64	"\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
65	"\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
66	"\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
67	"\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
68	"\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
69	"\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
70	"\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
71	"\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
72	"\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
73	"\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
74	"\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
75	"\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
76	"\xfd\xf5\x50\x8d\xca";
77static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
78
79/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
80static const char lzo_compressed[] =
81	"\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
82	"\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
83	"\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
84	"\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
85	"\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
86	"\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
87	"\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
88	"\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
89	"\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
90	"\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
91	"\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
92	"\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
93	"\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
94	"\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
95	"\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
96	"\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
97	"\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
98	"\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
99	"\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
100	"\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
101	"\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
102static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
103
104/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
105static const char lz4_compressed[] =
106	"\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
107	"\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
108	"\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
109	"\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
110	"\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
111	"\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
112	"\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
113	"\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
114	"\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
115	"\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
116	"\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
117	"\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
118	"\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
119	"\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
120	"\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
121	"\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
122	"\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
123	"\x9d\x12\x8c\x9d";
124static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
125
126/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
127static const char zstd_compressed[] =
128	"\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
129	"\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
130	"\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
131	"\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
132	"\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
133	"\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
134	"\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
135	"\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
136	"\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
137	"\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
138	"\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
139	"\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
140	"\x01\xe4\xf4\x6e\xfa";
141static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
142
143
144#define TEST_BUFFER_SIZE	512
145
146typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
147			   void *, unsigned long, unsigned long *);
148
149static int compress_using_gzip(struct unit_test_state *uts,
150			       void *in, unsigned long in_size,
151			       void *out, unsigned long out_max,
152			       unsigned long *out_size)
153{
154	int ret;
155	unsigned long inout_size = out_max;
156
157	ret = gzip(out, &inout_size, in, in_size);
158	if (out_size)
159		*out_size = inout_size;
160
161	return ret;
162}
163
164static int uncompress_using_gzip(struct unit_test_state *uts,
165				 void *in, unsigned long in_size,
166				 void *out, unsigned long out_max,
167				 unsigned long *out_size)
168{
169	int ret;
170	unsigned long inout_size = in_size;
171
172	ret = gunzip(out, out_max, in, &inout_size);
173	if (out_size)
174		*out_size = inout_size;
175
176	return ret;
177}
178
179static int compress_using_bzip2(struct unit_test_state *uts,
180				void *in, unsigned long in_size,
181				void *out, unsigned long out_max,
182				unsigned long *out_size)
183{
184	/* There is no bzip2 compression in u-boot, so fake it. */
185	ut_asserteq(in_size, strlen(plain));
186	ut_asserteq_mem(plain, in, in_size);
187
188	if (bzip2_compressed_size > out_max)
189		return -1;
190
191	memcpy(out, bzip2_compressed, bzip2_compressed_size);
192	if (out_size)
193		*out_size = bzip2_compressed_size;
194
195	return 0;
196}
197
198static int uncompress_using_bzip2(struct unit_test_state *uts,
199				  void *in, unsigned long in_size,
200				  void *out, unsigned long out_max,
201				  unsigned long *out_size)
202{
203	int ret;
204	unsigned int inout_size = out_max;
205
206	ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
207			CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
208	if (out_size)
209		*out_size = inout_size;
210
211	return (ret != BZ_OK);
212}
213
214static int compress_using_lzma(struct unit_test_state *uts,
215			       void *in, unsigned long in_size,
216			       void *out, unsigned long out_max,
217			       unsigned long *out_size)
218{
219	/* There is no lzma compression in u-boot, so fake it. */
220	ut_asserteq(in_size,  strlen(plain));
221	ut_asserteq_mem(plain, in, in_size);
222
223	if (lzma_compressed_size > out_max)
224		return -1;
225
226	memcpy(out, lzma_compressed, lzma_compressed_size);
227	if (out_size)
228		*out_size = lzma_compressed_size;
229
230	return 0;
231}
232
233static int uncompress_using_lzma(struct unit_test_state *uts,
234				 void *in, unsigned long in_size,
235				 void *out, unsigned long out_max,
236				 unsigned long *out_size)
237{
238	int ret;
239	SizeT inout_size = out_max;
240
241	ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
242	if (out_size)
243		*out_size = inout_size;
244
245	return (ret != SZ_OK);
246}
247
248static int compress_using_lzo(struct unit_test_state *uts,
249			      void *in, unsigned long in_size,
250			      void *out, unsigned long out_max,
251			      unsigned long *out_size)
252{
253	/* There is no lzo compression in u-boot, so fake it. */
254	ut_asserteq(in_size,  strlen(plain));
255	ut_asserteq_mem(plain, in, in_size);
256
257	if (lzo_compressed_size > out_max)
258		return -1;
259
260	memcpy(out, lzo_compressed, lzo_compressed_size);
261	if (out_size)
262		*out_size = lzo_compressed_size;
263
264	return 0;
265}
266
267static int uncompress_using_lzo(struct unit_test_state *uts,
268				void *in, unsigned long in_size,
269				void *out, unsigned long out_max,
270				unsigned long *out_size)
271{
272	int ret;
273	size_t input_size = in_size;
274	size_t output_size = out_max;
275
276	ret = lzop_decompress(in, input_size, out, &output_size);
277	if (out_size)
278		*out_size = output_size;
279
280	return (ret != LZO_E_OK);
281}
282
283static int compress_using_lz4(struct unit_test_state *uts,
284			      void *in, unsigned long in_size,
285			      void *out, unsigned long out_max,
286			      unsigned long *out_size)
287{
288	/* There is no lz4 compression in u-boot, so fake it. */
289	ut_asserteq(in_size,  strlen(plain));
290	ut_asserteq_mem(plain, in, in_size);
291
292	if (lz4_compressed_size > out_max)
293		return -1;
294
295	memcpy(out, lz4_compressed, lz4_compressed_size);
296	if (out_size)
297		*out_size = lz4_compressed_size;
298
299	return 0;
300}
301
302static int uncompress_using_lz4(struct unit_test_state *uts,
303				void *in, unsigned long in_size,
304				void *out, unsigned long out_max,
305				unsigned long *out_size)
306{
307	int ret;
308	size_t input_size = in_size;
309	size_t output_size = out_max;
310
311	ret = ulz4fn(in, input_size, out, &output_size);
312	if (out_size)
313		*out_size = output_size;
314
315	return (ret != 0);
316}
317
318static int compress_using_zstd(struct unit_test_state *uts,
319			       void *in, unsigned long in_size,
320			       void *out, unsigned long out_max,
321			       unsigned long *out_size)
322{
323	/* There is no zstd compression in u-boot, so fake it. */
324	ut_asserteq(in_size, strlen(plain));
325	ut_asserteq_mem(plain, in, in_size);
326
327	if (zstd_compressed_size > out_max)
328		return -1;
329
330	memcpy(out, zstd_compressed, zstd_compressed_size);
331	if (out_size)
332		*out_size = zstd_compressed_size;
333
334	return 0;
335}
336
337static int uncompress_using_zstd(struct unit_test_state *uts,
338				 void *in, unsigned long in_size,
339				 void *out, unsigned long out_max,
340				 unsigned long *out_size)
341{
342	struct abuf in_buf, out_buf;
343	int ret;
344
345	abuf_init_set(&in_buf, in, in_size);
346	abuf_init_set(&out_buf, out, out_max);
347
348	ret = zstd_decompress(&in_buf, &out_buf);
349	if (ret >= 0) {
350		*out_size = ret;
351		ret = 0;
352	}
353
354	return ret;
355}
356
357#define errcheck(statement) if (!(statement)) { \
358	fprintf(stderr, "\tFailed: %s\n", #statement); \
359	ret = 1; \
360	goto out; \
361}
362
363struct buf_state {
364	ulong orig_size;
365	ulong compressed_size;
366	ulong uncompressed_size;
367	void *orig_buf;
368	void *compressed_buf;
369	void *uncompressed_buf;
370	void *compare_buf;
371};
372
373static int run_test_internal(struct unit_test_state *uts, char *name,
374			     mutate_func compress, mutate_func uncompress,
375			     struct buf_state *buf)
376{
377	int ret;
378
379	/* Compress works as expected. */
380	printf("\torig_size:%lu\n", buf->orig_size);
381	memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
382	ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
383			  buf->compressed_buf, buf->compressed_size,
384			  &buf->compressed_size));
385	printf("\tcompressed_size:%lu\n", buf->compressed_size);
386	ut_assert(buf->compressed_size > 0);
387	ut_assert(buf->compressed_size < buf->orig_size);
388	ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
389			!= 'A');
390	ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
391
392	/* Uncompresses with space remaining. */
393	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
394			    buf->uncompressed_buf, buf->uncompressed_size,
395			    &buf->uncompressed_size));
396	printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
397	ut_asserteq(buf->uncompressed_size, buf->orig_size);
398	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
399
400	/* Uncompresses with exactly the right size output buffer. */
401	memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
402	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
403			    buf->uncompressed_buf, buf->orig_size,
404			    &buf->uncompressed_size));
405	ut_asserteq(buf->uncompressed_size, buf->orig_size);
406	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
407	ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
408
409	/* Uncompresses with trailing garbage in input buffer. */
410	memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
411	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
412			    buf->uncompressed_buf, buf->uncompressed_size,
413			    &buf->uncompressed_size));
414	ut_asserteq(buf->uncompressed_size, buf->orig_size);
415	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
416
417	/* Make sure compression does not over-run. */
418	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
419	ret = compress(uts, buf->orig_buf, buf->orig_size,
420		       buf->compare_buf, buf->compressed_size - 1,
421		       NULL);
422	ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
423	ut_assert(ret != 0);
424	printf("\tcompress does not overrun\n");
425
426	/* Make sure decompression does not over-run. */
427	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
428	ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
429			 buf->compare_buf, buf->uncompressed_size - 1,
430			 NULL);
431	ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
432	ut_assert(ret != 0);
433	printf("\tuncompress does not overrun\n");
434
435	/* Got here, everything is fine. */
436	return 0;
437}
438
439static int run_test(struct unit_test_state *uts, char *name,
440		    mutate_func compress, mutate_func uncompress)
441{
442	struct buf_state sbuf, *buf = &sbuf;
443	int ret;
444
445	printf(" testing %s ...\n", name);
446
447	buf->orig_buf = (void *)plain;
448	buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
449	errcheck(buf->orig_size > 0);
450
451	buf->compressed_size = TEST_BUFFER_SIZE;
452	buf->uncompressed_size = TEST_BUFFER_SIZE;
453	buf->compressed_buf = malloc(buf->compressed_size);
454	errcheck(buf->compressed_buf);
455	buf->uncompressed_buf = malloc(buf->uncompressed_size);
456	errcheck(buf->uncompressed_buf);
457	buf->compare_buf = malloc(buf->uncompressed_size);
458	errcheck(buf->compare_buf);
459
460	ret = run_test_internal(uts, name, compress, uncompress, buf);
461out:
462	printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
463
464	free(buf->compare_buf);
465	free(buf->uncompressed_buf);
466	free(buf->compressed_buf);
467
468	return ret;
469}
470
471static int compression_test_gzip(struct unit_test_state *uts)
472{
473	return run_test(uts, "gzip", compress_using_gzip,
474			uncompress_using_gzip);
475}
476COMPRESSION_TEST(compression_test_gzip, 0);
477
478static int compression_test_bzip2(struct unit_test_state *uts)
479{
480	return run_test(uts, "bzip2", compress_using_bzip2,
481			uncompress_using_bzip2);
482}
483COMPRESSION_TEST(compression_test_bzip2, 0);
484
485static int compression_test_lzma(struct unit_test_state *uts)
486{
487	return run_test(uts, "lzma", compress_using_lzma,
488			uncompress_using_lzma);
489}
490COMPRESSION_TEST(compression_test_lzma, 0);
491
492static int compression_test_lzo(struct unit_test_state *uts)
493{
494	return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
495}
496COMPRESSION_TEST(compression_test_lzo, 0);
497
498static int compression_test_lz4(struct unit_test_state *uts)
499{
500	return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
501}
502COMPRESSION_TEST(compression_test_lz4, 0);
503
504static int compression_test_zstd(struct unit_test_state *uts)
505{
506	return run_test(uts, "zstd", compress_using_zstd,
507			uncompress_using_zstd);
508}
509COMPRESSION_TEST(compression_test_zstd, 0);
510
511static int compress_using_none(struct unit_test_state *uts,
512			       void *in, unsigned long in_size,
513			       void *out, unsigned long out_max,
514			       unsigned long *out_size)
515{
516	/* Here we just copy */
517	memcpy(out, in, in_size);
518	*out_size = in_size;
519
520	return 0;
521}
522
523/**
524 * run_bootm_test() - Run tests on the bootm decompression function
525 *
526 * @comp_type:	Compression type to test
527 * @compress:	Our function to compress data
528 * Return: 0 if OK, non-zero on failure
529 */
530static int run_bootm_test(struct unit_test_state *uts, int comp_type,
531			  mutate_func compress)
532{
533	ulong compress_size = 1024;
534	void *compress_buff;
535	int unc_len;
536	int err = 0;
537	const ulong image_start = 0;
538	const ulong load_addr = 0x1000;
539	ulong load_end;
540
541	printf("Testing: %s\n", genimg_get_comp_name(comp_type));
542	compress_buff = map_sysmem(image_start, 0);
543	unc_len = strlen(plain);
544	compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
545		 &compress_size);
546	err = image_decomp(comp_type, load_addr, image_start,
547			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
548			   compress_buff, compress_size, unc_len,
549			   &load_end);
550	ut_assertok(err);
551	err = image_decomp(comp_type, load_addr, image_start,
552			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
553			   compress_buff, compress_size, unc_len - 1,
554			   &load_end);
555	ut_assert(err);
556
557	/* We can't detect corruption when not decompressing */
558	if (comp_type == IH_COMP_NONE)
559		return 0;
560	memset(compress_buff + compress_size / 2, '\x49',
561	       compress_size / 2);
562	err = image_decomp(comp_type, load_addr, image_start,
563			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
564			   compress_buff, compress_size, 0x10000,
565			   &load_end);
566	ut_assert(err);
567
568	return 0;
569}
570
571static int compression_test_bootm_gzip(struct unit_test_state *uts)
572{
573	return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
574}
575COMPRESSION_TEST(compression_test_bootm_gzip, 0);
576
577static int compression_test_bootm_bzip2(struct unit_test_state *uts)
578{
579	return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
580}
581COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
582
583static int compression_test_bootm_lzma(struct unit_test_state *uts)
584{
585	return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
586}
587COMPRESSION_TEST(compression_test_bootm_lzma, 0);
588
589static int compression_test_bootm_lzo(struct unit_test_state *uts)
590{
591	return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
592}
593COMPRESSION_TEST(compression_test_bootm_lzo, 0);
594
595static int compression_test_bootm_lz4(struct unit_test_state *uts)
596{
597	return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
598}
599COMPRESSION_TEST(compression_test_bootm_lz4, 0);
600
601static int compression_test_bootm_zstd(struct unit_test_state *uts)
602{
603	return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
604}
605COMPRESSION_TEST(compression_test_bootm_zstd, 0);
606
607static int compression_test_bootm_none(struct unit_test_state *uts)
608{
609	return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
610}
611COMPRESSION_TEST(compression_test_bootm_none, 0);
612
613int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
614		      char *const argv[])
615{
616	struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
617	const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
618
619	return cmd_ut_category("compression", "compression_test_",
620			       tests, n_ents, argc, argv);
621}
622