blob: ba98d21802cfc38c53acce284ac56ea75b851458 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kees Cook3153e912013-08-16 07:59:11 -07002/*
3 * Copyright (c) 2013, The Chromium Authors
Kees Cook3153e912013-08-16 07:59:11 -07004 */
5
Kees Cook3153e912013-08-16 07:59:11 -07006#include <common.h>
Simon Glass6ed4dc72014-12-02 13:17:35 -07007#include <bootm.h>
Kees Cook3153e912013-08-16 07:59:11 -07008#include <command.h>
Simon Glass0c670fc2019-08-01 09:46:36 -06009#include <gzip.h>
Simon Glass4d72caa2020-05-10 11:40:01 -060010#include <image.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Kees Cook3153e912013-08-16 07:59:11 -070012#include <malloc.h>
Joe Hershberger0eb25b62015-03-22 17:08:59 -050013#include <mapmem.h>
Simon Glass6ed4dc72014-12-02 13:17:35 -070014#include <asm/io.h>
Kees Cook3153e912013-08-16 07:59:11 -070015
Simon Glass2a2d8e92021-10-09 09:28:21 -060016#include <u-boot/lz4.h>
Kees Cook3153e912013-08-16 07:59:11 -070017#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>
Simon Glass0aac10f2017-11-25 11:57:33 -070025#include <test/compression.h>
26#include <test/suites.h>
27#include <test/ut.h>
Kees Cook3153e912013-08-16 07:59:11 -070028
29static 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 */
40static 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";
56static const unsigned long bzip2_compressed_size = 240;
57
58/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
59static 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";
75static const unsigned long lzma_compressed_size = 229;
76
77/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
78static 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";
100static const unsigned long lzo_compressed_size = 334;
101
Julius Werner027b7282015-10-06 20:03:53 -0700102/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
103static 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";
122static const unsigned long lz4_compressed_size = 276;
123
Kees Cook3153e912013-08-16 07:59:11 -0700124
125#define TEST_BUFFER_SIZE 512
126
Simon Glass0aac10f2017-11-25 11:57:33 -0700127typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
128 void *, unsigned long, unsigned long *);
Kees Cook3153e912013-08-16 07:59:11 -0700129
Simon Glass0aac10f2017-11-25 11:57:33 -0700130static int compress_using_gzip(struct unit_test_state *uts,
131 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700132 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
Simon Glass0aac10f2017-11-25 11:57:33 -0700145static int uncompress_using_gzip(struct unit_test_state *uts,
146 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700147 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
Simon Glass0aac10f2017-11-25 11:57:33 -0700160static int compress_using_bzip2(struct unit_test_state *uts,
161 void *in, unsigned long in_size,
Wolfgang Denk93e14592013-10-04 17:43:24 +0200162 void *out, unsigned long out_max,
163 unsigned long *out_size)
Kees Cook3153e912013-08-16 07:59:11 -0700164{
165 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700166 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600167 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700168
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
Simon Glass0aac10f2017-11-25 11:57:33 -0700179static int uncompress_using_bzip2(struct unit_test_state *uts,
180 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700181 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
Simon Glass0aac10f2017-11-25 11:57:33 -0700195static int compress_using_lzma(struct unit_test_state *uts,
196 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700197 void *out, unsigned long out_max,
198 unsigned long *out_size)
199{
200 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700201 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600202 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700203
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
Simon Glass0aac10f2017-11-25 11:57:33 -0700214static int uncompress_using_lzma(struct unit_test_state *uts,
215 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700216 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
Simon Glass0aac10f2017-11-25 11:57:33 -0700229static int compress_using_lzo(struct unit_test_state *uts,
230 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700231 void *out, unsigned long out_max,
232 unsigned long *out_size)
233{
234 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700235 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600236 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700237
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
Simon Glass0aac10f2017-11-25 11:57:33 -0700248static int uncompress_using_lzo(struct unit_test_state *uts,
249 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700250 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
Simon Glass0aac10f2017-11-25 11:57:33 -0700264static int compress_using_lz4(struct unit_test_state *uts,
265 void *in, unsigned long in_size,
Julius Werner027b7282015-10-06 20:03:53 -0700266 void *out, unsigned long out_max,
267 unsigned long *out_size)
268{
269 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700270 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600271 ut_asserteq_mem(plain, in, in_size);
Julius Werner027b7282015-10-06 20:03:53 -0700272
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
Simon Glass0aac10f2017-11-25 11:57:33 -0700283static int uncompress_using_lz4(struct unit_test_state *uts,
284 void *in, unsigned long in_size,
Julius Werner027b7282015-10-06 20:03:53 -0700285 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
Kees Cook3153e912013-08-16 07:59:11 -0700299#define errcheck(statement) if (!(statement)) { \
300 fprintf(stderr, "\tFailed: %s\n", #statement); \
301 ret = 1; \
302 goto out; \
303}
304
Simon Glass49f22c32017-11-25 11:57:31 -0700305struct buf_state {
306 ulong orig_size;
307 ulong compressed_size;
308 ulong uncompressed_size;
Kees Cook3153e912013-08-16 07:59:11 -0700309 void *orig_buf;
Simon Glass49f22c32017-11-25 11:57:31 -0700310 void *compressed_buf;
311 void *uncompressed_buf;
312 void *compare_buf;
313};
314
Simon Glass0aac10f2017-11-25 11:57:33 -0700315static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass49f22c32017-11-25 11:57:31 -0700316 mutate_func compress, mutate_func uncompress,
317 struct buf_state *buf)
318{
Kees Cook3153e912013-08-16 07:59:11 -0700319 int ret;
320
Kees Cook3153e912013-08-16 07:59:11 -0700321 /* Compress works as expected. */
Simon Glass49f22c32017-11-25 11:57:31 -0700322 printf("\torig_size:%lu\n", buf->orig_size);
323 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600324 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass0aac10f2017-11-25 11:57:33 -0700325 buf->compressed_buf, buf->compressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600326 &buf->compressed_size));
Simon Glass49f22c32017-11-25 11:57:31 -0700327 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maierbde4c492022-12-28 16:53:52 -0600328 ut_assert(buf->compressed_size > 0);
329 ut_assert(buf->compressed_size < buf->orig_size);
330 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
331 != 'A');
332 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook3153e912013-08-16 07:59:11 -0700333
334 /* Uncompresses with space remaining. */
Brandon Maierbde4c492022-12-28 16:53:52 -0600335 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700336 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600337 &buf->uncompressed_size));
Simon Glass49f22c32017-11-25 11:57:31 -0700338 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maierbde4c492022-12-28 16:53:52 -0600339 ut_asserteq(buf->uncompressed_size, buf->orig_size);
340 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook3153e912013-08-16 07:59:11 -0700341
342 /* Uncompresses with exactly the right size output buffer. */
Simon Glass49f22c32017-11-25 11:57:31 -0700343 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600344 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700345 buf->uncompressed_buf, buf->orig_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600346 &buf->uncompressed_size));
347 ut_asserteq(buf->uncompressed_size, buf->orig_size);
348 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
349 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook3153e912013-08-16 07:59:11 -0700350
Brandon Maier43b05982022-12-28 16:53:51 -0600351 /* Uncompresses with trailing garbage in input buffer. */
352 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600353 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier43b05982022-12-28 16:53:51 -0600354 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600355 &buf->uncompressed_size));
356 ut_asserteq(buf->uncompressed_size, buf->orig_size);
357 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier43b05982022-12-28 16:53:51 -0600358
Kees Cook3153e912013-08-16 07:59:11 -0700359 /* Make sure compression does not over-run. */
Simon Glass49f22c32017-11-25 11:57:31 -0700360 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass0aac10f2017-11-25 11:57:33 -0700361 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700362 buf->compare_buf, buf->compressed_size - 1,
Kees Cook3153e912013-08-16 07:59:11 -0700363 NULL);
Brandon Maierbde4c492022-12-28 16:53:52 -0600364 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
365 ut_assert(ret != 0);
Kees Cook3153e912013-08-16 07:59:11 -0700366 printf("\tcompress does not overrun\n");
367
368 /* Make sure decompression does not over-run. */
Simon Glass49f22c32017-11-25 11:57:31 -0700369 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass0aac10f2017-11-25 11:57:33 -0700370 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700371 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook3153e912013-08-16 07:59:11 -0700372 NULL);
Brandon Maierbde4c492022-12-28 16:53:52 -0600373 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
374 ut_assert(ret != 0);
Kees Cook3153e912013-08-16 07:59:11 -0700375 printf("\tuncompress does not overrun\n");
376
377 /* Got here, everything is fine. */
Brandon Maierbde4c492022-12-28 16:53:52 -0600378 return 0;
Simon Glass49f22c32017-11-25 11:57:31 -0700379}
380
Simon Glass0aac10f2017-11-25 11:57:33 -0700381static int run_test(struct unit_test_state *uts, char *name,
382 mutate_func compress, mutate_func uncompress)
Simon Glass49f22c32017-11-25 11:57:31 -0700383{
384 struct buf_state sbuf, *buf = &sbuf;
385 int ret;
386
387 printf(" testing %s ...\n", name);
388
389 buf->orig_buf = (void *)plain;
390 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
391 errcheck(buf->orig_size > 0);
392
393 buf->compressed_size = TEST_BUFFER_SIZE;
394 buf->uncompressed_size = TEST_BUFFER_SIZE;
395 buf->compressed_buf = malloc(buf->compressed_size);
396 errcheck(buf->compressed_buf);
397 buf->uncompressed_buf = malloc(buf->uncompressed_size);
398 errcheck(buf->uncompressed_buf);
399 buf->compare_buf = malloc(buf->uncompressed_size);
400 errcheck(buf->compare_buf);
401
Simon Glass0aac10f2017-11-25 11:57:33 -0700402 ret = run_test_internal(uts, name, compress, uncompress, buf);
Simon Glass49f22c32017-11-25 11:57:31 -0700403out:
Kees Cook3153e912013-08-16 07:59:11 -0700404 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
405
Simon Glass49f22c32017-11-25 11:57:31 -0700406 free(buf->compare_buf);
407 free(buf->uncompressed_buf);
408 free(buf->compressed_buf);
Kees Cook3153e912013-08-16 07:59:11 -0700409
410 return ret;
411}
412
Simon Glass0aac10f2017-11-25 11:57:33 -0700413static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook3153e912013-08-16 07:59:11 -0700414{
Simon Glass0aac10f2017-11-25 11:57:33 -0700415 return run_test(uts, "gzip", compress_using_gzip,
416 uncompress_using_gzip);
Kees Cook3153e912013-08-16 07:59:11 -0700417}
Simon Glass0aac10f2017-11-25 11:57:33 -0700418COMPRESSION_TEST(compression_test_gzip, 0);
Kees Cook3153e912013-08-16 07:59:11 -0700419
Simon Glass0aac10f2017-11-25 11:57:33 -0700420static int compression_test_bzip2(struct unit_test_state *uts)
421{
422 return run_test(uts, "bzip2", compress_using_bzip2,
423 uncompress_using_bzip2);
424}
425COMPRESSION_TEST(compression_test_bzip2, 0);
426
427static int compression_test_lzma(struct unit_test_state *uts)
428{
429 return run_test(uts, "lzma", compress_using_lzma,
430 uncompress_using_lzma);
431}
432COMPRESSION_TEST(compression_test_lzma, 0);
433
434static int compression_test_lzo(struct unit_test_state *uts)
435{
436 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
437}
438COMPRESSION_TEST(compression_test_lzo, 0);
439
440static int compression_test_lz4(struct unit_test_state *uts)
441{
442 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
443}
444COMPRESSION_TEST(compression_test_lz4, 0);
445
446static int compress_using_none(struct unit_test_state *uts,
447 void *in, unsigned long in_size,
Simon Glass6ed4dc72014-12-02 13:17:35 -0700448 void *out, unsigned long out_max,
449 unsigned long *out_size)
450{
451 /* Here we just copy */
452 memcpy(out, in, in_size);
453 *out_size = in_size;
454
455 return 0;
456}
457
458/**
Heinrich Schuchardt6cc8e542020-03-23 18:47:47 +0100459 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6ed4dc72014-12-02 13:17:35 -0700460 *
461 * @comp_type: Compression type to test
462 * @compress: Our function to compress data
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100463 * Return: 0 if OK, non-zero on failure
Simon Glass6ed4dc72014-12-02 13:17:35 -0700464 */
Simon Glass0aac10f2017-11-25 11:57:33 -0700465static int run_bootm_test(struct unit_test_state *uts, int comp_type,
466 mutate_func compress)
Simon Glass6ed4dc72014-12-02 13:17:35 -0700467{
468 ulong compress_size = 1024;
469 void *compress_buff;
470 int unc_len;
471 int err = 0;
472 const ulong image_start = 0;
473 const ulong load_addr = 0x1000;
474 ulong load_end;
475
476 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
477 compress_buff = map_sysmem(image_start, 0);
478 unc_len = strlen(plain);
Simon Glass0aac10f2017-11-25 11:57:33 -0700479 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6ed4dc72014-12-02 13:17:35 -0700480 &compress_size);
Julius Werner20908542019-07-24 19:37:54 -0700481 err = image_decomp(comp_type, load_addr, image_start,
482 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
483 compress_buff, compress_size, unc_len,
484 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700485 ut_assertok(err);
Julius Werner20908542019-07-24 19:37:54 -0700486 err = image_decomp(comp_type, load_addr, image_start,
487 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
488 compress_buff, compress_size, unc_len - 1,
489 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700490 ut_assert(err);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700491
492 /* We can't detect corruption when not decompressing */
493 if (comp_type == IH_COMP_NONE)
494 return 0;
495 memset(compress_buff + compress_size / 2, '\x49',
496 compress_size / 2);
Julius Werner20908542019-07-24 19:37:54 -0700497 err = image_decomp(comp_type, load_addr, image_start,
498 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
499 compress_buff, compress_size, 0x10000,
500 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700501 ut_assert(err);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700502
503 return 0;
504}
505
Simon Glass0aac10f2017-11-25 11:57:33 -0700506static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6ed4dc72014-12-02 13:17:35 -0700507{
Simon Glass0aac10f2017-11-25 11:57:33 -0700508 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700509}
Simon Glass0aac10f2017-11-25 11:57:33 -0700510COMPRESSION_TEST(compression_test_bootm_gzip, 0);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700511
Simon Glass0aac10f2017-11-25 11:57:33 -0700512static int compression_test_bootm_bzip2(struct unit_test_state *uts)
513{
514 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
515}
516COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700517
Simon Glass0aac10f2017-11-25 11:57:33 -0700518static int compression_test_bootm_lzma(struct unit_test_state *uts)
519{
520 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
521}
522COMPRESSION_TEST(compression_test_bootm_lzma, 0);
523
524static int compression_test_bootm_lzo(struct unit_test_state *uts)
525{
526 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
527}
528COMPRESSION_TEST(compression_test_bootm_lzo, 0);
529
530static int compression_test_bootm_lz4(struct unit_test_state *uts)
531{
532 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
533}
534COMPRESSION_TEST(compression_test_bootm_lz4, 0);
535
536static int compression_test_bootm_none(struct unit_test_state *uts)
537{
538 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
539}
540COMPRESSION_TEST(compression_test_bootm_none, 0);
541
Simon Glass09140112020-05-10 11:40:03 -0600542int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
543 char *const argv[])
Simon Glass0aac10f2017-11-25 11:57:33 -0700544{
Simon Glassa7a98752021-03-07 17:35:10 -0700545 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
546 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
Simon Glass0aac10f2017-11-25 11:57:33 -0700547
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100548 return cmd_ut_category("compression", "compression_test_",
549 tests, n_ents, argc, argv);
Simon Glass0aac10f2017-11-25 11:57:33 -0700550}