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