blob: aa1d38bb7bc53b6124e6955c5e725f49b216a3e1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kees Cook5d3bca82013-08-16 07:59:11 -07002/*
3 * Copyright (c) 2013, The Chromium Authors
Kees Cook5d3bca82013-08-16 07:59:11 -07004 */
5
Brandon Maier61c55e82023-01-12 10:27:46 -06006#include <abuf.h>
Simon Glass6d084ce2014-12-02 13:17:35 -07007#include <bootm.h>
Kees Cook5d3bca82013-08-16 07:59:11 -07008#include <command.h>
Simon Glass1a974af2019-08-01 09:46:36 -06009#include <gzip.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060010#include <image.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070012#include <malloc.h>
Joe Hershberger65b905b2015-03-22 17:08:59 -050013#include <mapmem.h>
Simon Glass6d084ce2014-12-02 13:17:35 -070014#include <asm/io.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070015
Simon Glasscaf62672021-10-09 09:28:21 -060016#include <u-boot/lz4.h>
Kees Cook5d3bca82013-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>
Brandon Maier61c55e82023-01-12 10:27:46 -060025#include <linux/zstd.h>
Simon Glass1edaed02017-11-25 11:57:33 -070026#include <test/compression.h>
27#include <test/suites.h>
28#include <test/ut.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070029
30static const char plain[] =
31 "I am a highly compressable bit of text.\n"
32 "I am a highly compressable bit of text.\n"
33 "I am a highly compressable bit of text.\n"
34 "There are many like me, but this one is mine.\n"
35 "If I were any shorter, there wouldn't be much sense in\n"
36 "compressing me in the first place. At least with lzo, anyway,\n"
37 "which appears to behave poorly in the face of short text\n"
38 "messages.\n";
39
40/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
41static const char bzip2_compressed[] =
42 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
43 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
44 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
45 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
46 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
47 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
48 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
49 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
50 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
51 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
52 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
53 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
54 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
55 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
56 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
Brandon Maier9e2d2662023-01-09 12:42:58 -060057static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070058
59/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
60static const char lzma_compressed[] =
61 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
62 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
63 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
64 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
65 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
66 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
67 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
68 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
69 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
70 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
71 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
72 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
73 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
74 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
75 "\xfd\xf5\x50\x8d\xca";
Brandon Maier9e2d2662023-01-09 12:42:58 -060076static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070077
78/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
79static const char lzo_compressed[] =
80 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
81 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
82 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
83 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
84 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
85 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
86 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
87 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
88 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
89 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
90 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
91 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
92 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
93 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
94 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
95 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
96 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
97 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
98 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
99 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
100 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600101static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -0700102
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700103/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
104static const char lz4_compressed[] =
105 "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
106 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
107 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
108 "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
109 "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
110 "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
111 "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
112 "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
113 "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
114 "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
115 "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
116 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
117 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
118 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
119 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
120 "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
121 "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
122 "\x9d\x12\x8c\x9d";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600123static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700124
Brandon Maier61c55e82023-01-12 10:27:46 -0600125/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
126static const char zstd_compressed[] =
127 "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
128 "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
129 "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
130 "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
131 "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
132 "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
133 "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
134 "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
135 "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
136 "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
137 "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
138 "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
139 "\x01\xe4\xf4\x6e\xfa";
140static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
141
Kees Cook5d3bca82013-08-16 07:59:11 -0700142
143#define TEST_BUFFER_SIZE 512
144
Simon Glass1edaed02017-11-25 11:57:33 -0700145typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
146 void *, unsigned long, unsigned long *);
Kees Cook5d3bca82013-08-16 07:59:11 -0700147
Simon Glass1edaed02017-11-25 11:57:33 -0700148static int compress_using_gzip(struct unit_test_state *uts,
149 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700150 void *out, unsigned long out_max,
151 unsigned long *out_size)
152{
153 int ret;
154 unsigned long inout_size = out_max;
155
156 ret = gzip(out, &inout_size, in, in_size);
157 if (out_size)
158 *out_size = inout_size;
159
160 return ret;
161}
162
Simon Glass1edaed02017-11-25 11:57:33 -0700163static int uncompress_using_gzip(struct unit_test_state *uts,
164 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700165 void *out, unsigned long out_max,
166 unsigned long *out_size)
167{
168 int ret;
169 unsigned long inout_size = in_size;
170
171 ret = gunzip(out, out_max, in, &inout_size);
172 if (out_size)
173 *out_size = inout_size;
174
175 return ret;
176}
177
Simon Glass1edaed02017-11-25 11:57:33 -0700178static int compress_using_bzip2(struct unit_test_state *uts,
179 void *in, unsigned long in_size,
Wolfgang Denkec7fbf52013-10-04 17:43:24 +0200180 void *out, unsigned long out_max,
181 unsigned long *out_size)
Kees Cook5d3bca82013-08-16 07:59:11 -0700182{
183 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700184 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600185 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700186
187 if (bzip2_compressed_size > out_max)
188 return -1;
189
190 memcpy(out, bzip2_compressed, bzip2_compressed_size);
191 if (out_size)
192 *out_size = bzip2_compressed_size;
193
194 return 0;
195}
196
Simon Glass1edaed02017-11-25 11:57:33 -0700197static int uncompress_using_bzip2(struct unit_test_state *uts,
198 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700199 void *out, unsigned long out_max,
200 unsigned long *out_size)
201{
202 int ret;
203 unsigned int inout_size = out_max;
204
205 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
206 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
207 if (out_size)
208 *out_size = inout_size;
209
210 return (ret != BZ_OK);
211}
212
Simon Glass1edaed02017-11-25 11:57:33 -0700213static int compress_using_lzma(struct unit_test_state *uts,
214 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700215 void *out, unsigned long out_max,
216 unsigned long *out_size)
217{
218 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700219 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600220 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700221
222 if (lzma_compressed_size > out_max)
223 return -1;
224
225 memcpy(out, lzma_compressed, lzma_compressed_size);
226 if (out_size)
227 *out_size = lzma_compressed_size;
228
229 return 0;
230}
231
Simon Glass1edaed02017-11-25 11:57:33 -0700232static int uncompress_using_lzma(struct unit_test_state *uts,
233 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700234 void *out, unsigned long out_max,
235 unsigned long *out_size)
236{
237 int ret;
238 SizeT inout_size = out_max;
239
240 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
241 if (out_size)
242 *out_size = inout_size;
243
244 return (ret != SZ_OK);
245}
246
Simon Glass1edaed02017-11-25 11:57:33 -0700247static int compress_using_lzo(struct unit_test_state *uts,
248 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700249 void *out, unsigned long out_max,
250 unsigned long *out_size)
251{
252 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700253 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600254 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700255
256 if (lzo_compressed_size > out_max)
257 return -1;
258
259 memcpy(out, lzo_compressed, lzo_compressed_size);
260 if (out_size)
261 *out_size = lzo_compressed_size;
262
263 return 0;
264}
265
Simon Glass1edaed02017-11-25 11:57:33 -0700266static int uncompress_using_lzo(struct unit_test_state *uts,
267 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700268 void *out, unsigned long out_max,
269 unsigned long *out_size)
270{
271 int ret;
272 size_t input_size = in_size;
273 size_t output_size = out_max;
274
275 ret = lzop_decompress(in, input_size, out, &output_size);
276 if (out_size)
277 *out_size = output_size;
278
279 return (ret != LZO_E_OK);
280}
281
Simon Glass1edaed02017-11-25 11:57:33 -0700282static int compress_using_lz4(struct unit_test_state *uts,
283 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700284 void *out, unsigned long out_max,
285 unsigned long *out_size)
286{
287 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700288 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600289 ut_asserteq_mem(plain, in, in_size);
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700290
291 if (lz4_compressed_size > out_max)
292 return -1;
293
294 memcpy(out, lz4_compressed, lz4_compressed_size);
295 if (out_size)
296 *out_size = lz4_compressed_size;
297
298 return 0;
299}
300
Simon Glass1edaed02017-11-25 11:57:33 -0700301static int uncompress_using_lz4(struct unit_test_state *uts,
302 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700303 void *out, unsigned long out_max,
304 unsigned long *out_size)
305{
306 int ret;
307 size_t input_size = in_size;
308 size_t output_size = out_max;
309
310 ret = ulz4fn(in, input_size, out, &output_size);
311 if (out_size)
312 *out_size = output_size;
313
314 return (ret != 0);
315}
316
Brandon Maier61c55e82023-01-12 10:27:46 -0600317static int compress_using_zstd(struct unit_test_state *uts,
318 void *in, unsigned long in_size,
319 void *out, unsigned long out_max,
320 unsigned long *out_size)
321{
322 /* There is no zstd compression in u-boot, so fake it. */
323 ut_asserteq(in_size, strlen(plain));
324 ut_asserteq_mem(plain, in, in_size);
325
326 if (zstd_compressed_size > out_max)
327 return -1;
328
329 memcpy(out, zstd_compressed, zstd_compressed_size);
330 if (out_size)
331 *out_size = zstd_compressed_size;
332
333 return 0;
334}
335
336static int uncompress_using_zstd(struct unit_test_state *uts,
337 void *in, unsigned long in_size,
338 void *out, unsigned long out_max,
339 unsigned long *out_size)
340{
341 struct abuf in_buf, out_buf;
342 int ret;
343
344 abuf_init_set(&in_buf, in, in_size);
345 abuf_init_set(&out_buf, out, out_max);
346
347 ret = zstd_decompress(&in_buf, &out_buf);
348 if (ret >= 0) {
349 *out_size = ret;
350 ret = 0;
351 }
352
353 return ret;
354}
355
Kees Cook5d3bca82013-08-16 07:59:11 -0700356#define errcheck(statement) if (!(statement)) { \
357 fprintf(stderr, "\tFailed: %s\n", #statement); \
358 ret = 1; \
359 goto out; \
360}
361
Simon Glass053f8012017-11-25 11:57:31 -0700362struct buf_state {
363 ulong orig_size;
364 ulong compressed_size;
365 ulong uncompressed_size;
Kees Cook5d3bca82013-08-16 07:59:11 -0700366 void *orig_buf;
Simon Glass053f8012017-11-25 11:57:31 -0700367 void *compressed_buf;
368 void *uncompressed_buf;
369 void *compare_buf;
370};
Kees Cook5d3bca82013-08-16 07:59:11 -0700371
Simon Glass1edaed02017-11-25 11:57:33 -0700372static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass053f8012017-11-25 11:57:31 -0700373 mutate_func compress, mutate_func uncompress,
374 struct buf_state *buf)
375{
376 int ret;
Kees Cook5d3bca82013-08-16 07:59:11 -0700377
378 /* Compress works as expected. */
Simon Glass053f8012017-11-25 11:57:31 -0700379 printf("\torig_size:%lu\n", buf->orig_size);
380 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600381 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass1edaed02017-11-25 11:57:33 -0700382 buf->compressed_buf, buf->compressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600383 &buf->compressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700384 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600385 ut_assert(buf->compressed_size > 0);
386 ut_assert(buf->compressed_size < buf->orig_size);
387 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
388 != 'A');
389 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700390
391 /* Uncompresses with space remaining. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600392 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700393 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600394 &buf->uncompressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700395 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600396 ut_asserteq(buf->uncompressed_size, buf->orig_size);
397 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700398
399 /* Uncompresses with exactly the right size output buffer. */
Simon Glass053f8012017-11-25 11:57:31 -0700400 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600401 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700402 buf->uncompressed_buf, buf->orig_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600403 &buf->uncompressed_size));
404 ut_asserteq(buf->uncompressed_size, buf->orig_size);
405 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
406 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700407
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600408 /* Uncompresses with trailing garbage in input buffer. */
409 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600410 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600411 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600412 &buf->uncompressed_size));
413 ut_asserteq(buf->uncompressed_size, buf->orig_size);
414 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600415
Kees Cook5d3bca82013-08-16 07:59:11 -0700416 /* Make sure compression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700417 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700418 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass053f8012017-11-25 11:57:31 -0700419 buf->compare_buf, buf->compressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700420 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600421 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
422 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700423 printf("\tcompress does not overrun\n");
424
425 /* Make sure decompression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700426 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700427 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700428 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700429 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600430 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
431 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700432 printf("\tuncompress does not overrun\n");
433
434 /* Got here, everything is fine. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600435 return 0;
Simon Glass053f8012017-11-25 11:57:31 -0700436}
437
Simon Glass1edaed02017-11-25 11:57:33 -0700438static int run_test(struct unit_test_state *uts, char *name,
439 mutate_func compress, mutate_func uncompress)
Simon Glass053f8012017-11-25 11:57:31 -0700440{
441 struct buf_state sbuf, *buf = &sbuf;
442 int ret;
443
444 printf(" testing %s ...\n", name);
445
446 buf->orig_buf = (void *)plain;
447 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
448 errcheck(buf->orig_size > 0);
449
450 buf->compressed_size = TEST_BUFFER_SIZE;
451 buf->uncompressed_size = TEST_BUFFER_SIZE;
452 buf->compressed_buf = malloc(buf->compressed_size);
453 errcheck(buf->compressed_buf);
454 buf->uncompressed_buf = malloc(buf->uncompressed_size);
455 errcheck(buf->uncompressed_buf);
456 buf->compare_buf = malloc(buf->uncompressed_size);
457 errcheck(buf->compare_buf);
458
Simon Glass1edaed02017-11-25 11:57:33 -0700459 ret = run_test_internal(uts, name, compress, uncompress, buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700460out:
461 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
462
Simon Glass053f8012017-11-25 11:57:31 -0700463 free(buf->compare_buf);
464 free(buf->uncompressed_buf);
465 free(buf->compressed_buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700466
467 return ret;
468}
469
Simon Glass1edaed02017-11-25 11:57:33 -0700470static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook5d3bca82013-08-16 07:59:11 -0700471{
Simon Glass1edaed02017-11-25 11:57:33 -0700472 return run_test(uts, "gzip", compress_using_gzip,
473 uncompress_using_gzip);
474}
475COMPRESSION_TEST(compression_test_gzip, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700476
Simon Glass1edaed02017-11-25 11:57:33 -0700477static int compression_test_bzip2(struct unit_test_state *uts)
478{
479 return run_test(uts, "bzip2", compress_using_bzip2,
480 uncompress_using_bzip2);
481}
482COMPRESSION_TEST(compression_test_bzip2, 0);
483
484static int compression_test_lzma(struct unit_test_state *uts)
485{
486 return run_test(uts, "lzma", compress_using_lzma,
487 uncompress_using_lzma);
488}
489COMPRESSION_TEST(compression_test_lzma, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700490
Simon Glass1edaed02017-11-25 11:57:33 -0700491static int compression_test_lzo(struct unit_test_state *uts)
492{
493 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
494}
495COMPRESSION_TEST(compression_test_lzo, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700496
Simon Glass1edaed02017-11-25 11:57:33 -0700497static int compression_test_lz4(struct unit_test_state *uts)
498{
499 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
Kees Cook5d3bca82013-08-16 07:59:11 -0700500}
Simon Glass1edaed02017-11-25 11:57:33 -0700501COMPRESSION_TEST(compression_test_lz4, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700502
Brandon Maier61c55e82023-01-12 10:27:46 -0600503static int compression_test_zstd(struct unit_test_state *uts)
504{
505 return run_test(uts, "zstd", compress_using_zstd,
506 uncompress_using_zstd);
507}
508COMPRESSION_TEST(compression_test_zstd, 0);
509
Simon Glass1edaed02017-11-25 11:57:33 -0700510static int compress_using_none(struct unit_test_state *uts,
511 void *in, unsigned long in_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700512 void *out, unsigned long out_max,
513 unsigned long *out_size)
514{
515 /* Here we just copy */
516 memcpy(out, in, in_size);
517 *out_size = in_size;
518
519 return 0;
520}
521
522/**
Heinrich Schuchardtd3855cf2020-03-23 18:47:47 +0100523 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6d084ce2014-12-02 13:17:35 -0700524 *
525 * @comp_type: Compression type to test
526 * @compress: Our function to compress data
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100527 * Return: 0 if OK, non-zero on failure
Simon Glass6d084ce2014-12-02 13:17:35 -0700528 */
Simon Glass1edaed02017-11-25 11:57:33 -0700529static int run_bootm_test(struct unit_test_state *uts, int comp_type,
530 mutate_func compress)
Simon Glass6d084ce2014-12-02 13:17:35 -0700531{
532 ulong compress_size = 1024;
533 void *compress_buff;
534 int unc_len;
535 int err = 0;
536 const ulong image_start = 0;
537 const ulong load_addr = 0x1000;
538 ulong load_end;
539
540 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
541 compress_buff = map_sysmem(image_start, 0);
542 unc_len = strlen(plain);
Simon Glass1edaed02017-11-25 11:57:33 -0700543 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700544 &compress_size);
Julius Werner47ef9862019-07-24 19:37:54 -0700545 err = image_decomp(comp_type, load_addr, image_start,
546 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
547 compress_buff, compress_size, unc_len,
548 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700549 ut_assertok(err);
Julius Werner47ef9862019-07-24 19:37:54 -0700550 err = image_decomp(comp_type, load_addr, image_start,
551 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
552 compress_buff, compress_size, unc_len - 1,
553 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700554 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700555
556 /* We can't detect corruption when not decompressing */
557 if (comp_type == IH_COMP_NONE)
558 return 0;
559 memset(compress_buff + compress_size / 2, '\x49',
560 compress_size / 2);
Julius Werner47ef9862019-07-24 19:37:54 -0700561 err = image_decomp(comp_type, load_addr, image_start,
562 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
563 compress_buff, compress_size, 0x10000,
564 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700565 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700566
567 return 0;
568}
569
Simon Glass1edaed02017-11-25 11:57:33 -0700570static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6d084ce2014-12-02 13:17:35 -0700571{
Simon Glass1edaed02017-11-25 11:57:33 -0700572 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
573}
574COMPRESSION_TEST(compression_test_bootm_gzip, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700575
Simon Glass1edaed02017-11-25 11:57:33 -0700576static int compression_test_bootm_bzip2(struct unit_test_state *uts)
577{
578 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
579}
580COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700581
Simon Glass1edaed02017-11-25 11:57:33 -0700582static int compression_test_bootm_lzma(struct unit_test_state *uts)
583{
584 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
585}
586COMPRESSION_TEST(compression_test_bootm_lzma, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700587
Simon Glass1edaed02017-11-25 11:57:33 -0700588static int compression_test_bootm_lzo(struct unit_test_state *uts)
589{
590 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
Simon Glass6d084ce2014-12-02 13:17:35 -0700591}
Simon Glass1edaed02017-11-25 11:57:33 -0700592COMPRESSION_TEST(compression_test_bootm_lzo, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700593
Simon Glass1edaed02017-11-25 11:57:33 -0700594static int compression_test_bootm_lz4(struct unit_test_state *uts)
595{
596 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
597}
598COMPRESSION_TEST(compression_test_bootm_lz4, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700599
Brandon Maier61c55e82023-01-12 10:27:46 -0600600static int compression_test_bootm_zstd(struct unit_test_state *uts)
601{
602 return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
603}
604COMPRESSION_TEST(compression_test_bootm_zstd, 0);
605
Simon Glass1edaed02017-11-25 11:57:33 -0700606static int compression_test_bootm_none(struct unit_test_state *uts)
607{
608 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
609}
610COMPRESSION_TEST(compression_test_bootm_none, 0);
611
Simon Glassed38aef2020-05-10 11:40:03 -0600612int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
613 char *const argv[])
Simon Glass1edaed02017-11-25 11:57:33 -0700614{
Simon Glassb50211f2021-03-07 17:35:10 -0700615 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
616 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
Simon Glass1edaed02017-11-25 11:57:33 -0700617
Philippe Reynes1f99f842019-12-17 19:07:04 +0100618 return cmd_ut_category("compression", "compression_test_",
619 tests, n_ents, argc, argv);
Simon Glass1edaed02017-11-25 11:57:33 -0700620}