blob: 618a1936955b5c971bf821ed750831f7fc70eb9f [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
Brandon Maier65d373a2023-01-12 10:27:46 -06006#include <abuf.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>
Brandon Maier65d373a2023-01-12 10:27:46 -060025#include <linux/zstd.h>
Simon Glass0aac10f2017-11-25 11:57:33 -070026#include <test/compression.h>
27#include <test/suites.h>
28#include <test/ut.h>
Kees Cook3153e912013-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 Maier093e8c82023-01-09 12:42:58 -060057static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
Kees Cook3153e912013-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 Maier093e8c82023-01-09 12:42:58 -060076static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
Kees Cook3153e912013-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 Maier093e8c82023-01-09 12:42:58 -0600101static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
Kees Cook3153e912013-08-16 07:59:11 -0700102
Julius Werner027b7282015-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 Maier093e8c82023-01-09 12:42:58 -0600123static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
Julius Werner027b7282015-10-06 20:03:53 -0700124
Brandon Maier65d373a2023-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 Cook3153e912013-08-16 07:59:11 -0700142#define TEST_BUFFER_SIZE 512
143
Simon Glass0aac10f2017-11-25 11:57:33 -0700144typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
145 void *, unsigned long, unsigned long *);
Kees Cook3153e912013-08-16 07:59:11 -0700146
Simon Glass0aac10f2017-11-25 11:57:33 -0700147static int compress_using_gzip(struct unit_test_state *uts,
148 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700149 void *out, unsigned long out_max,
150 unsigned long *out_size)
151{
152 int ret;
153 unsigned long inout_size = out_max;
154
155 ret = gzip(out, &inout_size, in, in_size);
156 if (out_size)
157 *out_size = inout_size;
158
159 return ret;
160}
161
Simon Glass0aac10f2017-11-25 11:57:33 -0700162static int uncompress_using_gzip(struct unit_test_state *uts,
163 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700164 void *out, unsigned long out_max,
165 unsigned long *out_size)
166{
167 int ret;
168 unsigned long inout_size = in_size;
169
170 ret = gunzip(out, out_max, in, &inout_size);
171 if (out_size)
172 *out_size = inout_size;
173
174 return ret;
175}
176
Simon Glass0aac10f2017-11-25 11:57:33 -0700177static int compress_using_bzip2(struct unit_test_state *uts,
178 void *in, unsigned long in_size,
Wolfgang Denk93e14592013-10-04 17:43:24 +0200179 void *out, unsigned long out_max,
180 unsigned long *out_size)
Kees Cook3153e912013-08-16 07:59:11 -0700181{
182 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700183 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600184 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700185
186 if (bzip2_compressed_size > out_max)
187 return -1;
188
189 memcpy(out, bzip2_compressed, bzip2_compressed_size);
190 if (out_size)
191 *out_size = bzip2_compressed_size;
192
193 return 0;
194}
195
Simon Glass0aac10f2017-11-25 11:57:33 -0700196static int uncompress_using_bzip2(struct unit_test_state *uts,
197 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700198 void *out, unsigned long out_max,
199 unsigned long *out_size)
200{
201 int ret;
202 unsigned int inout_size = out_max;
203
204 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
205 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
206 if (out_size)
207 *out_size = inout_size;
208
209 return (ret != BZ_OK);
210}
211
Simon Glass0aac10f2017-11-25 11:57:33 -0700212static int compress_using_lzma(struct unit_test_state *uts,
213 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700214 void *out, unsigned long out_max,
215 unsigned long *out_size)
216{
217 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700218 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600219 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700220
221 if (lzma_compressed_size > out_max)
222 return -1;
223
224 memcpy(out, lzma_compressed, lzma_compressed_size);
225 if (out_size)
226 *out_size = lzma_compressed_size;
227
228 return 0;
229}
230
Simon Glass0aac10f2017-11-25 11:57:33 -0700231static int uncompress_using_lzma(struct unit_test_state *uts,
232 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700233 void *out, unsigned long out_max,
234 unsigned long *out_size)
235{
236 int ret;
237 SizeT inout_size = out_max;
238
239 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
240 if (out_size)
241 *out_size = inout_size;
242
243 return (ret != SZ_OK);
244}
245
Simon Glass0aac10f2017-11-25 11:57:33 -0700246static int compress_using_lzo(struct unit_test_state *uts,
247 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700248 void *out, unsigned long out_max,
249 unsigned long *out_size)
250{
251 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700252 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600253 ut_asserteq_mem(plain, in, in_size);
Kees Cook3153e912013-08-16 07:59:11 -0700254
255 if (lzo_compressed_size > out_max)
256 return -1;
257
258 memcpy(out, lzo_compressed, lzo_compressed_size);
259 if (out_size)
260 *out_size = lzo_compressed_size;
261
262 return 0;
263}
264
Simon Glass0aac10f2017-11-25 11:57:33 -0700265static int uncompress_using_lzo(struct unit_test_state *uts,
266 void *in, unsigned long in_size,
Kees Cook3153e912013-08-16 07:59:11 -0700267 void *out, unsigned long out_max,
268 unsigned long *out_size)
269{
270 int ret;
271 size_t input_size = in_size;
272 size_t output_size = out_max;
273
274 ret = lzop_decompress(in, input_size, out, &output_size);
275 if (out_size)
276 *out_size = output_size;
277
278 return (ret != LZO_E_OK);
279}
280
Simon Glass0aac10f2017-11-25 11:57:33 -0700281static int compress_using_lz4(struct unit_test_state *uts,
282 void *in, unsigned long in_size,
Julius Werner027b7282015-10-06 20:03:53 -0700283 void *out, unsigned long out_max,
284 unsigned long *out_size)
285{
286 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass0aac10f2017-11-25 11:57:33 -0700287 ut_asserteq(in_size, strlen(plain));
Simon Glassf91f3662020-05-10 12:52:45 -0600288 ut_asserteq_mem(plain, in, in_size);
Julius Werner027b7282015-10-06 20:03:53 -0700289
290 if (lz4_compressed_size > out_max)
291 return -1;
292
293 memcpy(out, lz4_compressed, lz4_compressed_size);
294 if (out_size)
295 *out_size = lz4_compressed_size;
296
297 return 0;
298}
299
Simon Glass0aac10f2017-11-25 11:57:33 -0700300static int uncompress_using_lz4(struct unit_test_state *uts,
301 void *in, unsigned long in_size,
Julius Werner027b7282015-10-06 20:03:53 -0700302 void *out, unsigned long out_max,
303 unsigned long *out_size)
304{
305 int ret;
306 size_t input_size = in_size;
307 size_t output_size = out_max;
308
309 ret = ulz4fn(in, input_size, out, &output_size);
310 if (out_size)
311 *out_size = output_size;
312
313 return (ret != 0);
314}
315
Brandon Maier65d373a2023-01-12 10:27:46 -0600316static int compress_using_zstd(struct unit_test_state *uts,
317 void *in, unsigned long in_size,
318 void *out, unsigned long out_max,
319 unsigned long *out_size)
320{
321 /* There is no zstd compression in u-boot, so fake it. */
322 ut_asserteq(in_size, strlen(plain));
323 ut_asserteq_mem(plain, in, in_size);
324
325 if (zstd_compressed_size > out_max)
326 return -1;
327
328 memcpy(out, zstd_compressed, zstd_compressed_size);
329 if (out_size)
330 *out_size = zstd_compressed_size;
331
332 return 0;
333}
334
335static int uncompress_using_zstd(struct unit_test_state *uts,
336 void *in, unsigned long in_size,
337 void *out, unsigned long out_max,
338 unsigned long *out_size)
339{
340 struct abuf in_buf, out_buf;
341 int ret;
342
343 abuf_init_set(&in_buf, in, in_size);
344 abuf_init_set(&out_buf, out, out_max);
345
346 ret = zstd_decompress(&in_buf, &out_buf);
347 if (ret >= 0) {
348 *out_size = ret;
349 ret = 0;
350 }
351
352 return ret;
353}
354
Kees Cook3153e912013-08-16 07:59:11 -0700355#define errcheck(statement) if (!(statement)) { \
356 fprintf(stderr, "\tFailed: %s\n", #statement); \
357 ret = 1; \
358 goto out; \
359}
360
Simon Glass49f22c32017-11-25 11:57:31 -0700361struct buf_state {
362 ulong orig_size;
363 ulong compressed_size;
364 ulong uncompressed_size;
Kees Cook3153e912013-08-16 07:59:11 -0700365 void *orig_buf;
Simon Glass49f22c32017-11-25 11:57:31 -0700366 void *compressed_buf;
367 void *uncompressed_buf;
368 void *compare_buf;
369};
370
Simon Glass0aac10f2017-11-25 11:57:33 -0700371static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass49f22c32017-11-25 11:57:31 -0700372 mutate_func compress, mutate_func uncompress,
373 struct buf_state *buf)
374{
Kees Cook3153e912013-08-16 07:59:11 -0700375 int ret;
376
Kees Cook3153e912013-08-16 07:59:11 -0700377 /* Compress works as expected. */
Simon Glass49f22c32017-11-25 11:57:31 -0700378 printf("\torig_size:%lu\n", buf->orig_size);
379 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600380 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass0aac10f2017-11-25 11:57:33 -0700381 buf->compressed_buf, buf->compressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600382 &buf->compressed_size));
Simon Glass49f22c32017-11-25 11:57:31 -0700383 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maierbde4c492022-12-28 16:53:52 -0600384 ut_assert(buf->compressed_size > 0);
385 ut_assert(buf->compressed_size < buf->orig_size);
386 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
387 != 'A');
388 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook3153e912013-08-16 07:59:11 -0700389
390 /* Uncompresses with space remaining. */
Brandon Maierbde4c492022-12-28 16:53:52 -0600391 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700392 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600393 &buf->uncompressed_size));
Simon Glass49f22c32017-11-25 11:57:31 -0700394 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maierbde4c492022-12-28 16:53:52 -0600395 ut_asserteq(buf->uncompressed_size, buf->orig_size);
396 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook3153e912013-08-16 07:59:11 -0700397
398 /* Uncompresses with exactly the right size output buffer. */
Simon Glass49f22c32017-11-25 11:57:31 -0700399 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600400 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700401 buf->uncompressed_buf, buf->orig_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600402 &buf->uncompressed_size));
403 ut_asserteq(buf->uncompressed_size, buf->orig_size);
404 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
405 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook3153e912013-08-16 07:59:11 -0700406
Brandon Maier43b05982022-12-28 16:53:51 -0600407 /* Uncompresses with trailing garbage in input buffer. */
408 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maierbde4c492022-12-28 16:53:52 -0600409 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier43b05982022-12-28 16:53:51 -0600410 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maierbde4c492022-12-28 16:53:52 -0600411 &buf->uncompressed_size));
412 ut_asserteq(buf->uncompressed_size, buf->orig_size);
413 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier43b05982022-12-28 16:53:51 -0600414
Kees Cook3153e912013-08-16 07:59:11 -0700415 /* Make sure compression does not over-run. */
Simon Glass49f22c32017-11-25 11:57:31 -0700416 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass0aac10f2017-11-25 11:57:33 -0700417 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700418 buf->compare_buf, buf->compressed_size - 1,
Kees Cook3153e912013-08-16 07:59:11 -0700419 NULL);
Brandon Maierbde4c492022-12-28 16:53:52 -0600420 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
421 ut_assert(ret != 0);
Kees Cook3153e912013-08-16 07:59:11 -0700422 printf("\tcompress does not overrun\n");
423
424 /* Make sure decompression does not over-run. */
Simon Glass49f22c32017-11-25 11:57:31 -0700425 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass0aac10f2017-11-25 11:57:33 -0700426 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass49f22c32017-11-25 11:57:31 -0700427 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook3153e912013-08-16 07:59:11 -0700428 NULL);
Brandon Maierbde4c492022-12-28 16:53:52 -0600429 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
430 ut_assert(ret != 0);
Kees Cook3153e912013-08-16 07:59:11 -0700431 printf("\tuncompress does not overrun\n");
432
433 /* Got here, everything is fine. */
Brandon Maierbde4c492022-12-28 16:53:52 -0600434 return 0;
Simon Glass49f22c32017-11-25 11:57:31 -0700435}
436
Simon Glass0aac10f2017-11-25 11:57:33 -0700437static int run_test(struct unit_test_state *uts, char *name,
438 mutate_func compress, mutate_func uncompress)
Simon Glass49f22c32017-11-25 11:57:31 -0700439{
440 struct buf_state sbuf, *buf = &sbuf;
441 int ret;
442
443 printf(" testing %s ...\n", name);
444
445 buf->orig_buf = (void *)plain;
446 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
447 errcheck(buf->orig_size > 0);
448
449 buf->compressed_size = TEST_BUFFER_SIZE;
450 buf->uncompressed_size = TEST_BUFFER_SIZE;
451 buf->compressed_buf = malloc(buf->compressed_size);
452 errcheck(buf->compressed_buf);
453 buf->uncompressed_buf = malloc(buf->uncompressed_size);
454 errcheck(buf->uncompressed_buf);
455 buf->compare_buf = malloc(buf->uncompressed_size);
456 errcheck(buf->compare_buf);
457
Simon Glass0aac10f2017-11-25 11:57:33 -0700458 ret = run_test_internal(uts, name, compress, uncompress, buf);
Simon Glass49f22c32017-11-25 11:57:31 -0700459out:
Kees Cook3153e912013-08-16 07:59:11 -0700460 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
461
Simon Glass49f22c32017-11-25 11:57:31 -0700462 free(buf->compare_buf);
463 free(buf->uncompressed_buf);
464 free(buf->compressed_buf);
Kees Cook3153e912013-08-16 07:59:11 -0700465
466 return ret;
467}
468
Simon Glass0aac10f2017-11-25 11:57:33 -0700469static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook3153e912013-08-16 07:59:11 -0700470{
Simon Glass0aac10f2017-11-25 11:57:33 -0700471 return run_test(uts, "gzip", compress_using_gzip,
472 uncompress_using_gzip);
Kees Cook3153e912013-08-16 07:59:11 -0700473}
Simon Glass0aac10f2017-11-25 11:57:33 -0700474COMPRESSION_TEST(compression_test_gzip, 0);
Kees Cook3153e912013-08-16 07:59:11 -0700475
Simon Glass0aac10f2017-11-25 11:57:33 -0700476static int compression_test_bzip2(struct unit_test_state *uts)
477{
478 return run_test(uts, "bzip2", compress_using_bzip2,
479 uncompress_using_bzip2);
480}
481COMPRESSION_TEST(compression_test_bzip2, 0);
482
483static int compression_test_lzma(struct unit_test_state *uts)
484{
485 return run_test(uts, "lzma", compress_using_lzma,
486 uncompress_using_lzma);
487}
488COMPRESSION_TEST(compression_test_lzma, 0);
489
490static int compression_test_lzo(struct unit_test_state *uts)
491{
492 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
493}
494COMPRESSION_TEST(compression_test_lzo, 0);
495
496static int compression_test_lz4(struct unit_test_state *uts)
497{
498 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
499}
500COMPRESSION_TEST(compression_test_lz4, 0);
501
Brandon Maier65d373a2023-01-12 10:27:46 -0600502static int compression_test_zstd(struct unit_test_state *uts)
503{
504 return run_test(uts, "zstd", compress_using_zstd,
505 uncompress_using_zstd);
506}
507COMPRESSION_TEST(compression_test_zstd, 0);
508
Simon Glass0aac10f2017-11-25 11:57:33 -0700509static int compress_using_none(struct unit_test_state *uts,
510 void *in, unsigned long in_size,
Simon Glass6ed4dc72014-12-02 13:17:35 -0700511 void *out, unsigned long out_max,
512 unsigned long *out_size)
513{
514 /* Here we just copy */
515 memcpy(out, in, in_size);
516 *out_size = in_size;
517
518 return 0;
519}
520
521/**
Heinrich Schuchardt6cc8e542020-03-23 18:47:47 +0100522 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6ed4dc72014-12-02 13:17:35 -0700523 *
524 * @comp_type: Compression type to test
525 * @compress: Our function to compress data
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100526 * Return: 0 if OK, non-zero on failure
Simon Glass6ed4dc72014-12-02 13:17:35 -0700527 */
Simon Glass0aac10f2017-11-25 11:57:33 -0700528static int run_bootm_test(struct unit_test_state *uts, int comp_type,
529 mutate_func compress)
Simon Glass6ed4dc72014-12-02 13:17:35 -0700530{
531 ulong compress_size = 1024;
532 void *compress_buff;
533 int unc_len;
534 int err = 0;
535 const ulong image_start = 0;
536 const ulong load_addr = 0x1000;
537 ulong load_end;
538
539 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
540 compress_buff = map_sysmem(image_start, 0);
541 unc_len = strlen(plain);
Simon Glass0aac10f2017-11-25 11:57:33 -0700542 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6ed4dc72014-12-02 13:17:35 -0700543 &compress_size);
Julius Werner20908542019-07-24 19:37:54 -0700544 err = image_decomp(comp_type, load_addr, image_start,
545 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
546 compress_buff, compress_size, unc_len,
547 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700548 ut_assertok(err);
Julius Werner20908542019-07-24 19:37:54 -0700549 err = image_decomp(comp_type, load_addr, image_start,
550 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
551 compress_buff, compress_size, unc_len - 1,
552 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700553 ut_assert(err);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700554
555 /* We can't detect corruption when not decompressing */
556 if (comp_type == IH_COMP_NONE)
557 return 0;
558 memset(compress_buff + compress_size / 2, '\x49',
559 compress_size / 2);
Julius Werner20908542019-07-24 19:37:54 -0700560 err = image_decomp(comp_type, load_addr, image_start,
561 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
562 compress_buff, compress_size, 0x10000,
563 &load_end);
Simon Glass0aac10f2017-11-25 11:57:33 -0700564 ut_assert(err);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700565
566 return 0;
567}
568
Simon Glass0aac10f2017-11-25 11:57:33 -0700569static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6ed4dc72014-12-02 13:17:35 -0700570{
Simon Glass0aac10f2017-11-25 11:57:33 -0700571 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700572}
Simon Glass0aac10f2017-11-25 11:57:33 -0700573COMPRESSION_TEST(compression_test_bootm_gzip, 0);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700574
Simon Glass0aac10f2017-11-25 11:57:33 -0700575static int compression_test_bootm_bzip2(struct unit_test_state *uts)
576{
577 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
578}
579COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6ed4dc72014-12-02 13:17:35 -0700580
Simon Glass0aac10f2017-11-25 11:57:33 -0700581static int compression_test_bootm_lzma(struct unit_test_state *uts)
582{
583 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
584}
585COMPRESSION_TEST(compression_test_bootm_lzma, 0);
586
587static int compression_test_bootm_lzo(struct unit_test_state *uts)
588{
589 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
590}
591COMPRESSION_TEST(compression_test_bootm_lzo, 0);
592
593static int compression_test_bootm_lz4(struct unit_test_state *uts)
594{
595 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
596}
597COMPRESSION_TEST(compression_test_bootm_lz4, 0);
598
Brandon Maier65d373a2023-01-12 10:27:46 -0600599static int compression_test_bootm_zstd(struct unit_test_state *uts)
600{
601 return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
602}
603COMPRESSION_TEST(compression_test_bootm_zstd, 0);
604
Simon Glass0aac10f2017-11-25 11:57:33 -0700605static int compression_test_bootm_none(struct unit_test_state *uts)
606{
607 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
608}
609COMPRESSION_TEST(compression_test_bootm_none, 0);
610
Simon Glass09140112020-05-10 11:40:03 -0600611int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
612 char *const argv[])
Simon Glass0aac10f2017-11-25 11:57:33 -0700613{
Simon Glassa7a98752021-03-07 17:35:10 -0700614 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
615 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
Simon Glass0aac10f2017-11-25 11:57:33 -0700616
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100617 return cmd_ut_category("compression", "compression_test_",
618 tests, n_ents, argc, argv);
Simon Glass0aac10f2017-11-25 11:57:33 -0700619}