1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, The Chromium Authors
4  */
5 
6 #include <abuf.h>
7 #include <bootm.h>
8 #include <command.h>
9 #include <gzip.h>
10 #include <image.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <asm/io.h>
15 
16 #include <u-boot/lz4.h>
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 <linux/zstd.h>
26 #include <test/lib.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 = sizeof(bzip2_compressed) - 1;
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 = sizeof(lzma_compressed) - 1;
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 = sizeof(lzo_compressed) - 1;
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 = sizeof(lz4_compressed) - 1;
123 
124 /* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
125 static const char zstd_compressed[] =
126 	"\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
127 	"\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
128 	"\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
129 	"\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
130 	"\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
131 	"\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
132 	"\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
133 	"\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
134 	"\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
135 	"\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
136 	"\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
137 	"\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
138 	"\x01\xe4\xf4\x6e\xfa";
139 static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
140 
141 #define TEST_BUFFER_SIZE	512
142 
143 typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
144 			   void *, unsigned long, unsigned long *);
145 
compress_using_gzip(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)146 static int compress_using_gzip(struct unit_test_state *uts,
147 			       void *in, unsigned long in_size,
148 			       void *out, unsigned long out_max,
149 			       unsigned long *out_size)
150 {
151 	int ret;
152 	unsigned long inout_size = out_max;
153 
154 	ret = gzip(out, &inout_size, in, in_size);
155 	if (out_size)
156 		*out_size = inout_size;
157 
158 	return ret;
159 }
160 
uncompress_using_gzip(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)161 static int uncompress_using_gzip(struct unit_test_state *uts,
162 				 void *in, unsigned long in_size,
163 				 void *out, unsigned long out_max,
164 				 unsigned long *out_size)
165 {
166 	int ret;
167 	unsigned long inout_size = in_size;
168 
169 	ret = gunzip(out, out_max, in, &inout_size);
170 	if (out_size)
171 		*out_size = inout_size;
172 
173 	return ret;
174 }
175 
compress_using_bzip2(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)176 static int compress_using_bzip2(struct unit_test_state *uts,
177 				void *in, unsigned long in_size,
178 				void *out, unsigned long out_max,
179 				unsigned long *out_size)
180 {
181 	/* There is no bzip2 compression in u-boot, so fake it. */
182 	ut_asserteq(in_size, strlen(plain));
183 	ut_asserteq_mem(plain, in, in_size);
184 
185 	if (bzip2_compressed_size > out_max)
186 		return -1;
187 
188 	memcpy(out, bzip2_compressed, bzip2_compressed_size);
189 	if (out_size)
190 		*out_size = bzip2_compressed_size;
191 
192 	return 0;
193 }
194 
uncompress_using_bzip2(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)195 static int uncompress_using_bzip2(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 	int ret;
201 	unsigned int inout_size = out_max;
202 
203 	ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
204 			CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
205 	if (out_size)
206 		*out_size = inout_size;
207 
208 	return (ret != BZ_OK);
209 }
210 
compress_using_lzma(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)211 static int compress_using_lzma(struct unit_test_state *uts,
212 			       void *in, unsigned long in_size,
213 			       void *out, unsigned long out_max,
214 			       unsigned long *out_size)
215 {
216 	/* There is no lzma compression in u-boot, so fake it. */
217 	ut_asserteq(in_size,  strlen(plain));
218 	ut_asserteq_mem(plain, in, in_size);
219 
220 	if (lzma_compressed_size > out_max)
221 		return -1;
222 
223 	memcpy(out, lzma_compressed, lzma_compressed_size);
224 	if (out_size)
225 		*out_size = lzma_compressed_size;
226 
227 	return 0;
228 }
229 
uncompress_using_lzma(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)230 static int uncompress_using_lzma(struct unit_test_state *uts,
231 				 void *in, unsigned long in_size,
232 				 void *out, unsigned long out_max,
233 				 unsigned long *out_size)
234 {
235 	int ret;
236 	SizeT inout_size = out_max;
237 
238 	ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
239 	if (out_size)
240 		*out_size = inout_size;
241 
242 	return (ret != SZ_OK);
243 }
244 
compress_using_lzo(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)245 static int compress_using_lzo(struct unit_test_state *uts,
246 			      void *in, unsigned long in_size,
247 			      void *out, unsigned long out_max,
248 			      unsigned long *out_size)
249 {
250 	/* There is no lzo compression in u-boot, so fake it. */
251 	ut_asserteq(in_size,  strlen(plain));
252 	ut_asserteq_mem(plain, in, in_size);
253 
254 	if (lzo_compressed_size > out_max)
255 		return -1;
256 
257 	memcpy(out, lzo_compressed, lzo_compressed_size);
258 	if (out_size)
259 		*out_size = lzo_compressed_size;
260 
261 	return 0;
262 }
263 
uncompress_using_lzo(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)264 static int uncompress_using_lzo(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 	int ret;
270 	size_t input_size = in_size;
271 	size_t output_size = out_max;
272 
273 	ret = lzop_decompress(in, input_size, out, &output_size);
274 	if (out_size)
275 		*out_size = output_size;
276 
277 	return (ret != LZO_E_OK);
278 }
279 
compress_using_lz4(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)280 static int compress_using_lz4(struct unit_test_state *uts,
281 			      void *in, unsigned long in_size,
282 			      void *out, unsigned long out_max,
283 			      unsigned long *out_size)
284 {
285 	/* There is no lz4 compression in u-boot, so fake it. */
286 	ut_asserteq(in_size,  strlen(plain));
287 	ut_asserteq_mem(plain, in, in_size);
288 
289 	if (lz4_compressed_size > out_max)
290 		return -1;
291 
292 	memcpy(out, lz4_compressed, lz4_compressed_size);
293 	if (out_size)
294 		*out_size = lz4_compressed_size;
295 
296 	return 0;
297 }
298 
uncompress_using_lz4(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)299 static int uncompress_using_lz4(struct unit_test_state *uts,
300 				void *in, unsigned long in_size,
301 				void *out, unsigned long out_max,
302 				unsigned long *out_size)
303 {
304 	int ret;
305 	size_t input_size = in_size;
306 	size_t output_size = out_max;
307 
308 	ret = ulz4fn(in, input_size, out, &output_size);
309 	if (out_size)
310 		*out_size = output_size;
311 
312 	return (ret != 0);
313 }
314 
compress_using_zstd(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)315 static int compress_using_zstd(struct unit_test_state *uts,
316 			       void *in, unsigned long in_size,
317 			       void *out, unsigned long out_max,
318 			       unsigned long *out_size)
319 {
320 	/* There is no zstd compression in u-boot, so fake it. */
321 	ut_asserteq(in_size, strlen(plain));
322 	ut_asserteq_mem(plain, in, in_size);
323 
324 	if (zstd_compressed_size > out_max)
325 		return -1;
326 
327 	memcpy(out, zstd_compressed, zstd_compressed_size);
328 	if (out_size)
329 		*out_size = zstd_compressed_size;
330 
331 	return 0;
332 }
333 
uncompress_using_zstd(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)334 static int uncompress_using_zstd(struct unit_test_state *uts,
335 				 void *in, unsigned long in_size,
336 				 void *out, unsigned long out_max,
337 				 unsigned long *out_size)
338 {
339 	struct abuf in_buf, out_buf;
340 	int ret;
341 
342 	abuf_init_set(&in_buf, in, in_size);
343 	abuf_init_set(&out_buf, out, out_max);
344 
345 	ret = zstd_decompress(&in_buf, &out_buf);
346 	if (ret >= 0) {
347 		*out_size = ret;
348 		ret = 0;
349 	}
350 
351 	return ret;
352 }
353 
354 #define errcheck(statement) if (!(statement)) { \
355 	fprintf(stderr, "\tFailed: %s\n", #statement); \
356 	ret = 1; \
357 	goto out; \
358 }
359 
360 struct buf_state {
361 	ulong orig_size;
362 	ulong compressed_size;
363 	ulong uncompressed_size;
364 	void *orig_buf;
365 	void *compressed_buf;
366 	void *uncompressed_buf;
367 	void *compare_buf;
368 };
369 
run_test_internal(struct unit_test_state * uts,char * name,mutate_func compress,mutate_func uncompress,struct buf_state * buf)370 static int run_test_internal(struct unit_test_state *uts, char *name,
371 			     mutate_func compress, mutate_func uncompress,
372 			     struct buf_state *buf)
373 {
374 	int ret;
375 
376 	/* Compress works as expected. */
377 	printf("\torig_size:%lu\n", buf->orig_size);
378 	memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
379 	ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
380 			  buf->compressed_buf, buf->compressed_size,
381 			  &buf->compressed_size));
382 	printf("\tcompressed_size:%lu\n", buf->compressed_size);
383 	ut_assert(buf->compressed_size > 0);
384 	ut_assert(buf->compressed_size < buf->orig_size);
385 	ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
386 			!= 'A');
387 	ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
388 
389 	/* Uncompresses with space remaining. */
390 	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
391 			    buf->uncompressed_buf, buf->uncompressed_size,
392 			    &buf->uncompressed_size));
393 	printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
394 	ut_asserteq(buf->uncompressed_size, buf->orig_size);
395 	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
396 
397 	/* Uncompresses with exactly the right size output buffer. */
398 	memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
399 	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
400 			    buf->uncompressed_buf, buf->orig_size,
401 			    &buf->uncompressed_size));
402 	ut_asserteq(buf->uncompressed_size, buf->orig_size);
403 	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
404 	ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
405 
406 	/* Uncompresses with trailing garbage in input buffer. */
407 	memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
408 	ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
409 			    buf->uncompressed_buf, buf->uncompressed_size,
410 			    &buf->uncompressed_size));
411 	ut_asserteq(buf->uncompressed_size, buf->orig_size);
412 	ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
413 
414 	/* Make sure compression does not over-run. */
415 	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
416 	ret = compress(uts, buf->orig_buf, buf->orig_size,
417 		       buf->compare_buf, buf->compressed_size - 1,
418 		       NULL);
419 	ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
420 	ut_assert(ret != 0);
421 	printf("\tcompress does not overrun\n");
422 
423 	/* Make sure decompression does not over-run. */
424 	memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
425 	ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
426 			 buf->compare_buf, buf->uncompressed_size - 1,
427 			 NULL);
428 	ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
429 	ut_assert(ret != 0);
430 	printf("\tuncompress does not overrun\n");
431 
432 	/* Got here, everything is fine. */
433 	return 0;
434 }
435 
run_test(struct unit_test_state * uts,char * name,mutate_func compress,mutate_func uncompress)436 static int run_test(struct unit_test_state *uts, char *name,
437 		    mutate_func compress, mutate_func uncompress)
438 {
439 	struct buf_state sbuf, *buf = &sbuf;
440 	int ret;
441 
442 	printf(" testing %s ...\n", name);
443 
444 	buf->orig_buf = (void *)plain;
445 	buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
446 	errcheck(buf->orig_size > 0);
447 
448 	buf->compressed_size = TEST_BUFFER_SIZE;
449 	buf->uncompressed_size = TEST_BUFFER_SIZE;
450 	buf->compressed_buf = malloc(buf->compressed_size);
451 	errcheck(buf->compressed_buf);
452 	buf->uncompressed_buf = malloc(buf->uncompressed_size);
453 	errcheck(buf->uncompressed_buf);
454 	buf->compare_buf = malloc(buf->uncompressed_size);
455 	errcheck(buf->compare_buf);
456 
457 	ret = run_test_internal(uts, name, compress, uncompress, buf);
458 out:
459 	printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
460 
461 	free(buf->compare_buf);
462 	free(buf->uncompressed_buf);
463 	free(buf->compressed_buf);
464 
465 	return ret;
466 }
467 
compression_test_gzip(struct unit_test_state * uts)468 static int compression_test_gzip(struct unit_test_state *uts)
469 {
470 	return run_test(uts, "gzip", compress_using_gzip,
471 			uncompress_using_gzip);
472 }
473 LIB_TEST(compression_test_gzip, 0);
474 
compression_test_bzip2(struct unit_test_state * uts)475 static int compression_test_bzip2(struct unit_test_state *uts)
476 {
477 	return run_test(uts, "bzip2", compress_using_bzip2,
478 			uncompress_using_bzip2);
479 }
480 LIB_TEST(compression_test_bzip2, 0);
481 
compression_test_lzma(struct unit_test_state * uts)482 static int compression_test_lzma(struct unit_test_state *uts)
483 {
484 	return run_test(uts, "lzma", compress_using_lzma,
485 			uncompress_using_lzma);
486 }
487 LIB_TEST(compression_test_lzma, 0);
488 
compression_test_lzo(struct unit_test_state * uts)489 static int compression_test_lzo(struct unit_test_state *uts)
490 {
491 	return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
492 }
493 LIB_TEST(compression_test_lzo, 0);
494 
compression_test_lz4(struct unit_test_state * uts)495 static int compression_test_lz4(struct unit_test_state *uts)
496 {
497 	return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
498 }
499 LIB_TEST(compression_test_lz4, 0);
500 
compression_test_zstd(struct unit_test_state * uts)501 static int compression_test_zstd(struct unit_test_state *uts)
502 {
503 	return run_test(uts, "zstd", compress_using_zstd,
504 			uncompress_using_zstd);
505 }
506 LIB_TEST(compression_test_zstd, 0);
507 
compress_using_none(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)508 static int compress_using_none(struct unit_test_state *uts,
509 			       void *in, unsigned long in_size,
510 			       void *out, unsigned long out_max,
511 			       unsigned long *out_size)
512 {
513 	/* Here we just copy */
514 	memcpy(out, in, in_size);
515 	*out_size = in_size;
516 
517 	return 0;
518 }
519 
520 /**
521  * run_bootm_test() - Run tests on the bootm decompression function
522  *
523  * @comp_type:	Compression type to test
524  * @compress:	Our function to compress data
525  * Return: 0 if OK, non-zero on failure
526  */
run_bootm_test(struct unit_test_state * uts,int comp_type,mutate_func compress)527 static int run_bootm_test(struct unit_test_state *uts, int comp_type,
528 			  mutate_func compress)
529 {
530 	ulong compress_size = 1024;
531 	void *compress_buff;
532 	int unc_len;
533 	int err = 0;
534 	const ulong image_start = 0;
535 	const ulong load_addr = 0x1000;
536 	ulong load_end;
537 
538 	printf("Testing: %s\n", genimg_get_comp_name(comp_type));
539 	compress_buff = map_sysmem(image_start, 0);
540 	unc_len = strlen(plain);
541 	compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
542 		 &compress_size);
543 	err = image_decomp(comp_type, load_addr, image_start,
544 			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
545 			   compress_buff, compress_size, unc_len,
546 			   &load_end);
547 	ut_assertok(err);
548 	err = image_decomp(comp_type, load_addr, image_start,
549 			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
550 			   compress_buff, compress_size, unc_len - 1,
551 			   &load_end);
552 	ut_assert(err);
553 
554 	/* We can't detect corruption when not decompressing */
555 	if (comp_type == IH_COMP_NONE)
556 		return 0;
557 	memset(compress_buff + compress_size / 2, '\x49',
558 	       compress_size / 2);
559 	err = image_decomp(comp_type, load_addr, image_start,
560 			   IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
561 			   compress_buff, compress_size, 0x10000,
562 			   &load_end);
563 	ut_assert(err);
564 
565 	return 0;
566 }
567 
compression_test_bootm_gzip(struct unit_test_state * uts)568 static int compression_test_bootm_gzip(struct unit_test_state *uts)
569 {
570 	return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
571 }
572 LIB_TEST(compression_test_bootm_gzip, 0);
573 
compression_test_bootm_bzip2(struct unit_test_state * uts)574 static int compression_test_bootm_bzip2(struct unit_test_state *uts)
575 {
576 	return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
577 }
578 LIB_TEST(compression_test_bootm_bzip2, 0);
579 
compression_test_bootm_lzma(struct unit_test_state * uts)580 static int compression_test_bootm_lzma(struct unit_test_state *uts)
581 {
582 	return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
583 }
584 LIB_TEST(compression_test_bootm_lzma, 0);
585 
compression_test_bootm_lzo(struct unit_test_state * uts)586 static int compression_test_bootm_lzo(struct unit_test_state *uts)
587 {
588 	return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
589 }
590 LIB_TEST(compression_test_bootm_lzo, 0);
591 
compression_test_bootm_lz4(struct unit_test_state * uts)592 static int compression_test_bootm_lz4(struct unit_test_state *uts)
593 {
594 	return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
595 }
596 LIB_TEST(compression_test_bootm_lz4, 0);
597 
compression_test_bootm_zstd(struct unit_test_state * uts)598 static int compression_test_bootm_zstd(struct unit_test_state *uts)
599 {
600 	return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
601 }
602 LIB_TEST(compression_test_bootm_zstd, 0);
603 
compression_test_bootm_none(struct unit_test_state * uts)604 static int compression_test_bootm_none(struct unit_test_state *uts)
605 {
606 	return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
607 }
608 LIB_TEST(compression_test_bootm_none, 0);
609