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