test: dfu: script enhancements
[platform/kernel/u-boot.git] / test / compression.c
1 /*
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
22 static 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 */
33 static 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";
49 static const unsigned long bzip2_compressed_size = 240;
50
51 /* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
52 static 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";
68 static const unsigned long lzma_compressed_size = 229;
69
70 /* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
71 static 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";
93 static const unsigned long lzo_compressed_size = 334;
94
95
96 #define TEST_BUFFER_SIZE        512
97
98 typedef int (*mutate_func)(void *, unsigned long, void *, unsigned long,
99                            unsigned long *);
100
101 static 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
115 static 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
129 static 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
147 static 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
162 static 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
180 static 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
194 static 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
212 static 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
233 static 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
306 out:
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
317 static 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
332 U_BOOT_CMD(
333         test_compression,       5,      1,      do_test_compression,
334         "Basic test of compressors: gzip bzip2 lzma lzo", ""
335 );