blob: 3df90819a1fb7611c32448e9f563ed7fa5cd46b4 [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
Kees Cook5d3bca82013-08-16 07:59:11 -07006#include <common.h>
Brandon Maier61c55e82023-01-12 10:27:46 -06007#include <abuf.h>
Simon Glass6d084ce2014-12-02 13:17:35 -07008#include <bootm.h>
Kees Cook5d3bca82013-08-16 07:59:11 -07009#include <command.h>
Simon Glass1a974af2019-08-01 09:46:36 -060010#include <gzip.h>
Simon Glass2dc9c342020-05-10 11:40:01 -060011#include <image.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070013#include <malloc.h>
Joe Hershberger65b905b2015-03-22 17:08:59 -050014#include <mapmem.h>
Simon Glass6d084ce2014-12-02 13:17:35 -070015#include <asm/io.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070016
Simon Glasscaf62672021-10-09 09:28:21 -060017#include <u-boot/lz4.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070018#include <u-boot/zlib.h>
19#include <bzlib.h>
20
21#include <lzma/LzmaTypes.h>
22#include <lzma/LzmaDec.h>
23#include <lzma/LzmaTools.h>
24
25#include <linux/lzo.h>
Brandon Maier61c55e82023-01-12 10:27:46 -060026#include <linux/zstd.h>
Simon Glass1edaed02017-11-25 11:57:33 -070027#include <test/compression.h>
28#include <test/suites.h>
29#include <test/ut.h>
Kees Cook5d3bca82013-08-16 07:59:11 -070030
31static const char plain[] =
32 "I am a highly compressable bit of text.\n"
33 "I am a highly compressable bit of text.\n"
34 "I am a highly compressable bit of text.\n"
35 "There are many like me, but this one is mine.\n"
36 "If I were any shorter, there wouldn't be much sense in\n"
37 "compressing me in the first place. At least with lzo, anyway,\n"
38 "which appears to behave poorly in the face of short text\n"
39 "messages.\n";
40
41/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
42static const char bzip2_compressed[] =
43 "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
44 "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
45 "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
46 "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
47 "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
48 "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
49 "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
50 "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
51 "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
52 "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
53 "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
54 "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
55 "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
56 "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
57 "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
Brandon Maier9e2d2662023-01-09 12:42:58 -060058static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070059
60/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
61static const char lzma_compressed[] =
62 "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
63 "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
64 "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
65 "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
66 "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
67 "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
68 "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
69 "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
70 "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
71 "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
72 "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
73 "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
74 "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
75 "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
76 "\xfd\xf5\x50\x8d\xca";
Brandon Maier9e2d2662023-01-09 12:42:58 -060077static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070078
79/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
80static const char lzo_compressed[] =
81 "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
82 "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
83 "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
84 "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
85 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
86 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
87 "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
88 "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
89 "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
90 "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
91 "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
92 "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
93 "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
94 "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
95 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
96 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
97 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
98 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
99 "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
100 "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
101 "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600102static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -0700103
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700104/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
105static const char lz4_compressed[] =
106 "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
107 "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
108 "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
109 "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
110 "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
111 "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
112 "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
113 "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
114 "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
115 "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
116 "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
117 "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
118 "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
119 "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
120 "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
121 "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
122 "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
123 "\x9d\x12\x8c\x9d";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600124static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700125
Brandon Maier61c55e82023-01-12 10:27:46 -0600126/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
127static const char zstd_compressed[] =
128 "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
129 "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
130 "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
131 "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
132 "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
133 "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
134 "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
135 "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
136 "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
137 "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
138 "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
139 "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
140 "\x01\xe4\xf4\x6e\xfa";
141static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
142
Kees Cook5d3bca82013-08-16 07:59:11 -0700143
144#define TEST_BUFFER_SIZE 512
145
Simon Glass1edaed02017-11-25 11:57:33 -0700146typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
147 void *, unsigned long, unsigned long *);
Kees Cook5d3bca82013-08-16 07:59:11 -0700148
Simon Glass1edaed02017-11-25 11:57:33 -0700149static int compress_using_gzip(struct unit_test_state *uts,
150 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700151 void *out, unsigned long out_max,
152 unsigned long *out_size)
153{
154 int ret;
155 unsigned long inout_size = out_max;
156
157 ret = gzip(out, &inout_size, in, in_size);
158 if (out_size)
159 *out_size = inout_size;
160
161 return ret;
162}
163
Simon Glass1edaed02017-11-25 11:57:33 -0700164static int uncompress_using_gzip(struct unit_test_state *uts,
165 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700166 void *out, unsigned long out_max,
167 unsigned long *out_size)
168{
169 int ret;
170 unsigned long inout_size = in_size;
171
172 ret = gunzip(out, out_max, in, &inout_size);
173 if (out_size)
174 *out_size = inout_size;
175
176 return ret;
177}
178
Simon Glass1edaed02017-11-25 11:57:33 -0700179static int compress_using_bzip2(struct unit_test_state *uts,
180 void *in, unsigned long in_size,
Wolfgang Denkec7fbf52013-10-04 17:43:24 +0200181 void *out, unsigned long out_max,
182 unsigned long *out_size)
Kees Cook5d3bca82013-08-16 07:59:11 -0700183{
184 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700185 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600186 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700187
188 if (bzip2_compressed_size > out_max)
189 return -1;
190
191 memcpy(out, bzip2_compressed, bzip2_compressed_size);
192 if (out_size)
193 *out_size = bzip2_compressed_size;
194
195 return 0;
196}
197
Simon Glass1edaed02017-11-25 11:57:33 -0700198static int uncompress_using_bzip2(struct unit_test_state *uts,
199 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700200 void *out, unsigned long out_max,
201 unsigned long *out_size)
202{
203 int ret;
204 unsigned int inout_size = out_max;
205
206 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
207 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
208 if (out_size)
209 *out_size = inout_size;
210
211 return (ret != BZ_OK);
212}
213
Simon Glass1edaed02017-11-25 11:57:33 -0700214static int compress_using_lzma(struct unit_test_state *uts,
215 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700216 void *out, unsigned long out_max,
217 unsigned long *out_size)
218{
219 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700220 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600221 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700222
223 if (lzma_compressed_size > out_max)
224 return -1;
225
226 memcpy(out, lzma_compressed, lzma_compressed_size);
227 if (out_size)
228 *out_size = lzma_compressed_size;
229
230 return 0;
231}
232
Simon Glass1edaed02017-11-25 11:57:33 -0700233static int uncompress_using_lzma(struct unit_test_state *uts,
234 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700235 void *out, unsigned long out_max,
236 unsigned long *out_size)
237{
238 int ret;
239 SizeT inout_size = out_max;
240
241 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
242 if (out_size)
243 *out_size = inout_size;
244
245 return (ret != SZ_OK);
246}
247
Simon Glass1edaed02017-11-25 11:57:33 -0700248static int compress_using_lzo(struct unit_test_state *uts,
249 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700250 void *out, unsigned long out_max,
251 unsigned long *out_size)
252{
253 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700254 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600255 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700256
257 if (lzo_compressed_size > out_max)
258 return -1;
259
260 memcpy(out, lzo_compressed, lzo_compressed_size);
261 if (out_size)
262 *out_size = lzo_compressed_size;
263
264 return 0;
265}
266
Simon Glass1edaed02017-11-25 11:57:33 -0700267static int uncompress_using_lzo(struct unit_test_state *uts,
268 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700269 void *out, unsigned long out_max,
270 unsigned long *out_size)
271{
272 int ret;
273 size_t input_size = in_size;
274 size_t output_size = out_max;
275
276 ret = lzop_decompress(in, input_size, out, &output_size);
277 if (out_size)
278 *out_size = output_size;
279
280 return (ret != LZO_E_OK);
281}
282
Simon Glass1edaed02017-11-25 11:57:33 -0700283static int compress_using_lz4(struct unit_test_state *uts,
284 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700285 void *out, unsigned long out_max,
286 unsigned long *out_size)
287{
288 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700289 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600290 ut_asserteq_mem(plain, in, in_size);
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700291
292 if (lz4_compressed_size > out_max)
293 return -1;
294
295 memcpy(out, lz4_compressed, lz4_compressed_size);
296 if (out_size)
297 *out_size = lz4_compressed_size;
298
299 return 0;
300}
301
Simon Glass1edaed02017-11-25 11:57:33 -0700302static int uncompress_using_lz4(struct unit_test_state *uts,
303 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700304 void *out, unsigned long out_max,
305 unsigned long *out_size)
306{
307 int ret;
308 size_t input_size = in_size;
309 size_t output_size = out_max;
310
311 ret = ulz4fn(in, input_size, out, &output_size);
312 if (out_size)
313 *out_size = output_size;
314
315 return (ret != 0);
316}
317
Brandon Maier61c55e82023-01-12 10:27:46 -0600318static int compress_using_zstd(struct unit_test_state *uts,
319 void *in, unsigned long in_size,
320 void *out, unsigned long out_max,
321 unsigned long *out_size)
322{
323 /* There is no zstd compression in u-boot, so fake it. */
324 ut_asserteq(in_size, strlen(plain));
325 ut_asserteq_mem(plain, in, in_size);
326
327 if (zstd_compressed_size > out_max)
328 return -1;
329
330 memcpy(out, zstd_compressed, zstd_compressed_size);
331 if (out_size)
332 *out_size = zstd_compressed_size;
333
334 return 0;
335}
336
337static int uncompress_using_zstd(struct unit_test_state *uts,
338 void *in, unsigned long in_size,
339 void *out, unsigned long out_max,
340 unsigned long *out_size)
341{
342 struct abuf in_buf, out_buf;
343 int ret;
344
345 abuf_init_set(&in_buf, in, in_size);
346 abuf_init_set(&out_buf, out, out_max);
347
348 ret = zstd_decompress(&in_buf, &out_buf);
349 if (ret >= 0) {
350 *out_size = ret;
351 ret = 0;
352 }
353
354 return ret;
355}
356
Kees Cook5d3bca82013-08-16 07:59:11 -0700357#define errcheck(statement) if (!(statement)) { \
358 fprintf(stderr, "\tFailed: %s\n", #statement); \
359 ret = 1; \
360 goto out; \
361}
362
Simon Glass053f8012017-11-25 11:57:31 -0700363struct buf_state {
364 ulong orig_size;
365 ulong compressed_size;
366 ulong uncompressed_size;
Kees Cook5d3bca82013-08-16 07:59:11 -0700367 void *orig_buf;
Simon Glass053f8012017-11-25 11:57:31 -0700368 void *compressed_buf;
369 void *uncompressed_buf;
370 void *compare_buf;
371};
Kees Cook5d3bca82013-08-16 07:59:11 -0700372
Simon Glass1edaed02017-11-25 11:57:33 -0700373static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass053f8012017-11-25 11:57:31 -0700374 mutate_func compress, mutate_func uncompress,
375 struct buf_state *buf)
376{
377 int ret;
Kees Cook5d3bca82013-08-16 07:59:11 -0700378
379 /* Compress works as expected. */
Simon Glass053f8012017-11-25 11:57:31 -0700380 printf("\torig_size:%lu\n", buf->orig_size);
381 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600382 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass1edaed02017-11-25 11:57:33 -0700383 buf->compressed_buf, buf->compressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600384 &buf->compressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700385 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600386 ut_assert(buf->compressed_size > 0);
387 ut_assert(buf->compressed_size < buf->orig_size);
388 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
389 != 'A');
390 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700391
392 /* Uncompresses with space remaining. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600393 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700394 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600395 &buf->uncompressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700396 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600397 ut_asserteq(buf->uncompressed_size, buf->orig_size);
398 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700399
400 /* Uncompresses with exactly the right size output buffer. */
Simon Glass053f8012017-11-25 11:57:31 -0700401 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600402 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700403 buf->uncompressed_buf, buf->orig_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600404 &buf->uncompressed_size));
405 ut_asserteq(buf->uncompressed_size, buf->orig_size);
406 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
407 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700408
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600409 /* Uncompresses with trailing garbage in input buffer. */
410 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600411 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600412 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600413 &buf->uncompressed_size));
414 ut_asserteq(buf->uncompressed_size, buf->orig_size);
415 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600416
Kees Cook5d3bca82013-08-16 07:59:11 -0700417 /* Make sure compression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700418 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700419 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass053f8012017-11-25 11:57:31 -0700420 buf->compare_buf, buf->compressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700421 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600422 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
423 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700424 printf("\tcompress does not overrun\n");
425
426 /* Make sure decompression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700427 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700428 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700429 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700430 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600431 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
432 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700433 printf("\tuncompress does not overrun\n");
434
435 /* Got here, everything is fine. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600436 return 0;
Simon Glass053f8012017-11-25 11:57:31 -0700437}
438
Simon Glass1edaed02017-11-25 11:57:33 -0700439static int run_test(struct unit_test_state *uts, char *name,
440 mutate_func compress, mutate_func uncompress)
Simon Glass053f8012017-11-25 11:57:31 -0700441{
442 struct buf_state sbuf, *buf = &sbuf;
443 int ret;
444
445 printf(" testing %s ...\n", name);
446
447 buf->orig_buf = (void *)plain;
448 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
449 errcheck(buf->orig_size > 0);
450
451 buf->compressed_size = TEST_BUFFER_SIZE;
452 buf->uncompressed_size = TEST_BUFFER_SIZE;
453 buf->compressed_buf = malloc(buf->compressed_size);
454 errcheck(buf->compressed_buf);
455 buf->uncompressed_buf = malloc(buf->uncompressed_size);
456 errcheck(buf->uncompressed_buf);
457 buf->compare_buf = malloc(buf->uncompressed_size);
458 errcheck(buf->compare_buf);
459
Simon Glass1edaed02017-11-25 11:57:33 -0700460 ret = run_test_internal(uts, name, compress, uncompress, buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700461out:
462 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
463
Simon Glass053f8012017-11-25 11:57:31 -0700464 free(buf->compare_buf);
465 free(buf->uncompressed_buf);
466 free(buf->compressed_buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700467
468 return ret;
469}
470
Simon Glass1edaed02017-11-25 11:57:33 -0700471static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook5d3bca82013-08-16 07:59:11 -0700472{
Simon Glass1edaed02017-11-25 11:57:33 -0700473 return run_test(uts, "gzip", compress_using_gzip,
474 uncompress_using_gzip);
475}
476COMPRESSION_TEST(compression_test_gzip, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700477
Simon Glass1edaed02017-11-25 11:57:33 -0700478static int compression_test_bzip2(struct unit_test_state *uts)
479{
480 return run_test(uts, "bzip2", compress_using_bzip2,
481 uncompress_using_bzip2);
482}
483COMPRESSION_TEST(compression_test_bzip2, 0);
484
485static int compression_test_lzma(struct unit_test_state *uts)
486{
487 return run_test(uts, "lzma", compress_using_lzma,
488 uncompress_using_lzma);
489}
490COMPRESSION_TEST(compression_test_lzma, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700491
Simon Glass1edaed02017-11-25 11:57:33 -0700492static int compression_test_lzo(struct unit_test_state *uts)
493{
494 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
495}
496COMPRESSION_TEST(compression_test_lzo, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700497
Simon Glass1edaed02017-11-25 11:57:33 -0700498static int compression_test_lz4(struct unit_test_state *uts)
499{
500 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
Kees Cook5d3bca82013-08-16 07:59:11 -0700501}
Simon Glass1edaed02017-11-25 11:57:33 -0700502COMPRESSION_TEST(compression_test_lz4, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700503
Brandon Maier61c55e82023-01-12 10:27:46 -0600504static int compression_test_zstd(struct unit_test_state *uts)
505{
506 return run_test(uts, "zstd", compress_using_zstd,
507 uncompress_using_zstd);
508}
509COMPRESSION_TEST(compression_test_zstd, 0);
510
Simon Glass1edaed02017-11-25 11:57:33 -0700511static int compress_using_none(struct unit_test_state *uts,
512 void *in, unsigned long in_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700513 void *out, unsigned long out_max,
514 unsigned long *out_size)
515{
516 /* Here we just copy */
517 memcpy(out, in, in_size);
518 *out_size = in_size;
519
520 return 0;
521}
522
523/**
Heinrich Schuchardtd3855cf2020-03-23 18:47:47 +0100524 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6d084ce2014-12-02 13:17:35 -0700525 *
526 * @comp_type: Compression type to test
527 * @compress: Our function to compress data
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100528 * Return: 0 if OK, non-zero on failure
Simon Glass6d084ce2014-12-02 13:17:35 -0700529 */
Simon Glass1edaed02017-11-25 11:57:33 -0700530static int run_bootm_test(struct unit_test_state *uts, int comp_type,
531 mutate_func compress)
Simon Glass6d084ce2014-12-02 13:17:35 -0700532{
533 ulong compress_size = 1024;
534 void *compress_buff;
535 int unc_len;
536 int err = 0;
537 const ulong image_start = 0;
538 const ulong load_addr = 0x1000;
539 ulong load_end;
540
541 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
542 compress_buff = map_sysmem(image_start, 0);
543 unc_len = strlen(plain);
Simon Glass1edaed02017-11-25 11:57:33 -0700544 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700545 &compress_size);
Julius Werner47ef9862019-07-24 19:37:54 -0700546 err = image_decomp(comp_type, load_addr, image_start,
547 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
548 compress_buff, compress_size, unc_len,
549 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700550 ut_assertok(err);
Julius Werner47ef9862019-07-24 19:37:54 -0700551 err = image_decomp(comp_type, load_addr, image_start,
552 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
553 compress_buff, compress_size, unc_len - 1,
554 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700555 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700556
557 /* We can't detect corruption when not decompressing */
558 if (comp_type == IH_COMP_NONE)
559 return 0;
560 memset(compress_buff + compress_size / 2, '\x49',
561 compress_size / 2);
Julius Werner47ef9862019-07-24 19:37:54 -0700562 err = image_decomp(comp_type, load_addr, image_start,
563 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
564 compress_buff, compress_size, 0x10000,
565 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700566 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700567
568 return 0;
569}
570
Simon Glass1edaed02017-11-25 11:57:33 -0700571static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6d084ce2014-12-02 13:17:35 -0700572{
Simon Glass1edaed02017-11-25 11:57:33 -0700573 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
574}
575COMPRESSION_TEST(compression_test_bootm_gzip, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700576
Simon Glass1edaed02017-11-25 11:57:33 -0700577static int compression_test_bootm_bzip2(struct unit_test_state *uts)
578{
579 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
580}
581COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700582
Simon Glass1edaed02017-11-25 11:57:33 -0700583static int compression_test_bootm_lzma(struct unit_test_state *uts)
584{
585 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
586}
587COMPRESSION_TEST(compression_test_bootm_lzma, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700588
Simon Glass1edaed02017-11-25 11:57:33 -0700589static int compression_test_bootm_lzo(struct unit_test_state *uts)
590{
591 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
Simon Glass6d084ce2014-12-02 13:17:35 -0700592}
Simon Glass1edaed02017-11-25 11:57:33 -0700593COMPRESSION_TEST(compression_test_bootm_lzo, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700594
Simon Glass1edaed02017-11-25 11:57:33 -0700595static int compression_test_bootm_lz4(struct unit_test_state *uts)
596{
597 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
598}
599COMPRESSION_TEST(compression_test_bootm_lz4, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700600
Brandon Maier61c55e82023-01-12 10:27:46 -0600601static int compression_test_bootm_zstd(struct unit_test_state *uts)
602{
603 return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
604}
605COMPRESSION_TEST(compression_test_bootm_zstd, 0);
606
Simon Glass1edaed02017-11-25 11:57:33 -0700607static int compression_test_bootm_none(struct unit_test_state *uts)
608{
609 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
610}
611COMPRESSION_TEST(compression_test_bootm_none, 0);
612
Simon Glassed38aef2020-05-10 11:40:03 -0600613int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
614 char *const argv[])
Simon Glass1edaed02017-11-25 11:57:33 -0700615{
Simon Glassb50211f2021-03-07 17:35:10 -0700616 struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test);
617 const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test);
Simon Glass1edaed02017-11-25 11:57:33 -0700618
Philippe Reynes1f99f842019-12-17 19:07:04 +0100619 return cmd_ut_category("compression", "compression_test_",
620 tests, n_ents, argc, argv);
Simon Glass1edaed02017-11-25 11:57:33 -0700621}