blob: 8834d5e8ab3433830c073b56488c416807af43e4 [file] [log] [blame]
Kees Cook3153e912013-08-16 07:59:11 -07001/*
2 * Copyright (c) 2013, The Chromium Authors
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#define DEBUG
8
9#include <common.h>
10#include <command.h>
11#include <malloc.h>
12
13#include <u-boot/zlib.h>
14#include <bzlib.h>
15
16#include <lzma/LzmaTypes.h>
17#include <lzma/LzmaDec.h>
18#include <lzma/LzmaTools.h>
19
20#include <linux/lzo.h>
21
22static const char plain[] =
23 "I am a highly compressable bit of text.\n"
24 "I am a highly compressable bit of text.\n"
25 "I am a highly compressable bit of text.\n"
26 "There are many like me, but this one is mine.\n"
27 "If I were any shorter, there wouldn't be much sense in\n"
28 "compressing me in the first place. At least with lzo, anyway,\n"
29 "which appears to behave poorly in the face of short text\n"
30 "messages.\n";
31
32/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
33static const char bzip2_compressed[] =
34 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
35 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
36 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
37 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
38 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
39 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
40 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
41 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
42 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
43 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
44 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
45 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
46 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
47 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
48 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
49static const unsigned long bzip2_compressed_size = 240;
50
51/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
52static const char lzma_compressed[] =
53 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
54 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
55 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
56 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
57 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
58 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
59 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
60 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
61 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
62 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
63 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
64 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
65 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
66 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
67 "\xfd\xf5\x50\x8d\xca";
68static const unsigned long lzma_compressed_size = 229;
69
70/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
71static const char lzo_compressed[] =
72 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
73 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
74 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
75 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
76 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
77 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
78 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
79 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
80 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
81 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
82 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
83 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
84 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
85 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
86 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
87 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
88 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
89 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
90 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
91 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
92 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
93static const unsigned long lzo_compressed_size = 334;
94
95
96#define TEST_BUFFER_SIZE 512
97
98typedef int (*mutate_func)(void *, unsigned long, void *, unsigned long,
99 unsigned long *);
100
101static int compress_using_gzip(void *in, unsigned long in_size,
102 void *out, unsigned long out_max,
103 unsigned long *out_size)
104{
105 int ret;
106 unsigned long inout_size = out_max;
107
108 ret = gzip(out, &inout_size, in, in_size);
109 if (out_size)
110 *out_size = inout_size;
111
112 return ret;
113}
114
115static int uncompress_using_gzip(void *in, unsigned long in_size,
116 void *out, unsigned long out_max,
117 unsigned long *out_size)
118{
119 int ret;
120 unsigned long inout_size = in_size;
121
122 ret = gunzip(out, out_max, in, &inout_size);
123 if (out_size)
124 *out_size = inout_size;
125
126 return ret;
127}
128
129static int compress_using_bzip2(void *in, unsigned long in_size,
130 void *out, unsigned long out_max,
131 unsigned long *out_size)
132{
133 /* There is no bzip2 compression in u-boot, so fake it. */
134 assert(in_size == strlen(plain));
135 assert(memcmp(plain, in, in_size) == 0);
136
137 if (bzip2_compressed_size > out_max)
138 return -1;
139
140 memcpy(out, bzip2_compressed, bzip2_compressed_size);
141 if (out_size)
142 *out_size = bzip2_compressed_size;
143
144 return 0;
145}
146
147static int uncompress_using_bzip2(void *in, unsigned long in_size,
148 void *out, unsigned long out_max,
149 unsigned long *out_size)
150{
151 int ret;
152 unsigned int inout_size = out_max;
153
154 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
155 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
156 if (out_size)
157 *out_size = inout_size;
158
159 return (ret != BZ_OK);
160}
161
162static int compress_using_lzma(void *in, unsigned long in_size,
163 void *out, unsigned long out_max,
164 unsigned long *out_size)
165{
166 /* There is no lzma compression in u-boot, so fake it. */
167 assert(in_size == strlen(plain));
168 assert(memcmp(plain, in, in_size) == 0);
169
170 if (lzma_compressed_size > out_max)
171 return -1;
172
173 memcpy(out, lzma_compressed, lzma_compressed_size);
174 if (out_size)
175 *out_size = lzma_compressed_size;
176
177 return 0;
178}
179
180static int uncompress_using_lzma(void *in, unsigned long in_size,
181 void *out, unsigned long out_max,
182 unsigned long *out_size)
183{
184 int ret;
185 SizeT inout_size = out_max;
186
187 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
188 if (out_size)
189 *out_size = inout_size;
190
191 return (ret != SZ_OK);
192}
193
194static int compress_using_lzo(void *in, unsigned long in_size,
195 void *out, unsigned long out_max,
196 unsigned long *out_size)
197{
198 /* There is no lzo compression in u-boot, so fake it. */
199 assert(in_size == strlen(plain));
200 assert(memcmp(plain, in, in_size) == 0);
201
202 if (lzo_compressed_size > out_max)
203 return -1;
204
205 memcpy(out, lzo_compressed, lzo_compressed_size);
206 if (out_size)
207 *out_size = lzo_compressed_size;
208
209 return 0;
210}
211
212static int uncompress_using_lzo(void *in, unsigned long in_size,
213 void *out, unsigned long out_max,
214 unsigned long *out_size)
215{
216 int ret;
217 size_t input_size = in_size;
218 size_t output_size = out_max;
219
220 ret = lzop_decompress(in, input_size, out, &output_size);
221 if (out_size)
222 *out_size = output_size;
223
224 return (ret != LZO_E_OK);
225}
226
227#define errcheck(statement) if (!(statement)) { \
228 fprintf(stderr, "\tFailed: %s\n", #statement); \
229 ret = 1; \
230 goto out; \
231}
232
233static int run_test(char *name, mutate_func compress, mutate_func uncompress)
234{
235 ulong orig_size, compressed_size, uncompressed_size;
236 void *orig_buf;
237 void *compressed_buf = NULL;
238 void *uncompressed_buf = NULL;
239 void *compare_buf = NULL;
240 int ret;
241
242 printf(" testing %s ...\n", name);
243
244 orig_buf = (void *)plain;
245 orig_size = strlen(orig_buf); /* Trailing NULL not included. */
246 errcheck(orig_size > 0);
247
248 compressed_size = uncompressed_size = TEST_BUFFER_SIZE;
249 compressed_buf = malloc(compressed_size);
250 errcheck(compressed_buf != NULL);
251 uncompressed_buf = malloc(uncompressed_size);
252 errcheck(uncompressed_buf != NULL);
253 compare_buf = malloc(uncompressed_size);
254 errcheck(compare_buf != NULL);
255
256 /* Compress works as expected. */
257 printf("\torig_size:%lu\n", orig_size);
258 memset(compressed_buf, 'A', TEST_BUFFER_SIZE);
259 errcheck(compress(orig_buf, orig_size,
260 compressed_buf, compressed_size,
261 &compressed_size) == 0);
262 printf("\tcompressed_size:%lu\n", compressed_size);
263 errcheck(compressed_size > 0);
264 errcheck(compressed_size < orig_size);
265 errcheck(((char *)compressed_buf)[compressed_size-1] != 'A');
266 errcheck(((char *)compressed_buf)[compressed_size] == 'A');
267
268 /* Uncompresses with space remaining. */
269 errcheck(uncompress(compressed_buf, compressed_size,
270 uncompressed_buf, uncompressed_size,
271 &uncompressed_size) == 0);
272 printf("\tuncompressed_size:%lu\n", uncompressed_size);
273 errcheck(uncompressed_size == orig_size);
274 errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
275
276 /* Uncompresses with exactly the right size output buffer. */
277 memset(uncompressed_buf, 'A', TEST_BUFFER_SIZE);
278 errcheck(uncompress(compressed_buf, compressed_size,
279 uncompressed_buf, orig_size,
280 &uncompressed_size) == 0);
281 errcheck(uncompressed_size == orig_size);
282 errcheck(memcmp(orig_buf, uncompressed_buf, orig_size) == 0);
283 errcheck(((char *)uncompressed_buf)[orig_size] == 'A');
284
285 /* Make sure compression does not over-run. */
286 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
287 ret = compress(orig_buf, orig_size,
288 compare_buf, compressed_size - 1,
289 NULL);
290 errcheck(((char *)compare_buf)[compressed_size] == 'A');
291 errcheck(ret != 0);
292 printf("\tcompress does not overrun\n");
293
294 /* Make sure decompression does not over-run. */
295 memset(compare_buf, 'A', TEST_BUFFER_SIZE);
296 ret = uncompress(compressed_buf, compressed_size,
297 compare_buf, uncompressed_size - 1,
298 NULL);
299 errcheck(((char *)compare_buf)[uncompressed_size - 1] == 'A');
300 errcheck(ret != 0);
301 printf("\tuncompress does not overrun\n");
302
303 /* Got here, everything is fine. */
304 ret = 0;
305
306out:
307 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
308
309 free(compare_buf);
310 free(uncompressed_buf);
311 free(compressed_buf);
312
313 return ret;
314}
315
316
317static int do_test_compression(cmd_tbl_t *cmdtp, int flag, int argc,
318 char * const argv[])
319{
320 int err = 0;
321
322 err += run_test("gzip", compress_using_gzip, uncompress_using_gzip);
323 err += run_test("bzip2", compress_using_bzip2, uncompress_using_bzip2);
324 err += run_test("lzma", compress_using_lzma, uncompress_using_lzma);
325 err += run_test("lzo", compress_using_lzo, uncompress_using_lzo);
326
327 printf("test_compression %s\n", err == 0 ? "ok" : "FAILED");
328
329 return err;
330}
331
332U_BOOT_CMD(
333 test_compression, 5, 1, do_test_compression,
334 "Basic test of compressors: gzip bzip2 lzma lzo", ""
335);