blob: 31b6e5b1eb4b8c0fd3ac8a57a7ef085887fd21ad [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 Glassecaaae82024-11-02 13:36:50 -060026#include <test/lib.h>
Simon Glass1edaed02017-11-25 11:57:33 -070027#include <test/ut.h>
Kees Cook5d3bca82013-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";
Brandon Maier9e2d2662023-01-09 12:42:58 -060056static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070057
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";
Brandon Maier9e2d2662023-01-09 12:42:58 -060075static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -070076
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";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600100static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
Kees Cook5d3bca82013-08-16 07:59:11 -0700101
Julius Wernerf41a3ca2015-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";
Brandon Maier9e2d2662023-01-09 12:42:58 -0600122static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700123
Brandon Maier61c55e82023-01-12 10:27:46 -0600124/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
125static const char zstd_compressed[] =
126 "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
127 "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
128 "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
129 "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
130 "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
131 "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
132 "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
133 "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
134 "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
135 "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
136 "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
137 "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
138 "\x01\xe4\xf4\x6e\xfa";
139static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
140
Kees Cook5d3bca82013-08-16 07:59:11 -0700141#define TEST_BUFFER_SIZE 512
142
Simon Glass1edaed02017-11-25 11:57:33 -0700143typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
144 void *, unsigned long, unsigned long *);
Kees Cook5d3bca82013-08-16 07:59:11 -0700145
Simon Glass1edaed02017-11-25 11:57:33 -0700146static int compress_using_gzip(struct unit_test_state *uts,
147 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700148 void *out, unsigned long out_max,
149 unsigned long *out_size)
150{
151 int ret;
152 unsigned long inout_size = out_max;
153
154 ret = gzip(out, &inout_size, in, in_size);
155 if (out_size)
156 *out_size = inout_size;
157
158 return ret;
159}
160
Simon Glass1edaed02017-11-25 11:57:33 -0700161static int uncompress_using_gzip(struct unit_test_state *uts,
162 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700163 void *out, unsigned long out_max,
164 unsigned long *out_size)
165{
166 int ret;
167 unsigned long inout_size = in_size;
168
169 ret = gunzip(out, out_max, in, &inout_size);
170 if (out_size)
171 *out_size = inout_size;
172
173 return ret;
174}
175
Simon Glass1edaed02017-11-25 11:57:33 -0700176static int compress_using_bzip2(struct unit_test_state *uts,
177 void *in, unsigned long in_size,
Wolfgang Denkec7fbf52013-10-04 17:43:24 +0200178 void *out, unsigned long out_max,
179 unsigned long *out_size)
Kees Cook5d3bca82013-08-16 07:59:11 -0700180{
181 /* There is no bzip2 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700182 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600183 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700184
185 if (bzip2_compressed_size > out_max)
186 return -1;
187
188 memcpy(out, bzip2_compressed, bzip2_compressed_size);
189 if (out_size)
190 *out_size = bzip2_compressed_size;
191
192 return 0;
193}
194
Simon Glass1edaed02017-11-25 11:57:33 -0700195static int uncompress_using_bzip2(struct unit_test_state *uts,
196 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700197 void *out, unsigned long out_max,
198 unsigned long *out_size)
199{
200 int ret;
201 unsigned int inout_size = out_max;
202
203 ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
204 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
205 if (out_size)
206 *out_size = inout_size;
207
208 return (ret != BZ_OK);
209}
210
Simon Glass1edaed02017-11-25 11:57:33 -0700211static int compress_using_lzma(struct unit_test_state *uts,
212 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700213 void *out, unsigned long out_max,
214 unsigned long *out_size)
215{
216 /* There is no lzma compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700217 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600218 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700219
220 if (lzma_compressed_size > out_max)
221 return -1;
222
223 memcpy(out, lzma_compressed, lzma_compressed_size);
224 if (out_size)
225 *out_size = lzma_compressed_size;
226
227 return 0;
228}
229
Simon Glass1edaed02017-11-25 11:57:33 -0700230static int uncompress_using_lzma(struct unit_test_state *uts,
231 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700232 void *out, unsigned long out_max,
233 unsigned long *out_size)
234{
235 int ret;
236 SizeT inout_size = out_max;
237
238 ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
239 if (out_size)
240 *out_size = inout_size;
241
242 return (ret != SZ_OK);
243}
244
Simon Glass1edaed02017-11-25 11:57:33 -0700245static int compress_using_lzo(struct unit_test_state *uts,
246 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700247 void *out, unsigned long out_max,
248 unsigned long *out_size)
249{
250 /* There is no lzo compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700251 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600252 ut_asserteq_mem(plain, in, in_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700253
254 if (lzo_compressed_size > out_max)
255 return -1;
256
257 memcpy(out, lzo_compressed, lzo_compressed_size);
258 if (out_size)
259 *out_size = lzo_compressed_size;
260
261 return 0;
262}
263
Simon Glass1edaed02017-11-25 11:57:33 -0700264static int uncompress_using_lzo(struct unit_test_state *uts,
265 void *in, unsigned long in_size,
Kees Cook5d3bca82013-08-16 07:59:11 -0700266 void *out, unsigned long out_max,
267 unsigned long *out_size)
268{
269 int ret;
270 size_t input_size = in_size;
271 size_t output_size = out_max;
272
273 ret = lzop_decompress(in, input_size, out, &output_size);
274 if (out_size)
275 *out_size = output_size;
276
277 return (ret != LZO_E_OK);
278}
279
Simon Glass1edaed02017-11-25 11:57:33 -0700280static int compress_using_lz4(struct unit_test_state *uts,
281 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700282 void *out, unsigned long out_max,
283 unsigned long *out_size)
284{
285 /* There is no lz4 compression in u-boot, so fake it. */
Simon Glass1edaed02017-11-25 11:57:33 -0700286 ut_asserteq(in_size, strlen(plain));
Simon Glassa3186e62020-05-10 12:52:45 -0600287 ut_asserteq_mem(plain, in, in_size);
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700288
289 if (lz4_compressed_size > out_max)
290 return -1;
291
292 memcpy(out, lz4_compressed, lz4_compressed_size);
293 if (out_size)
294 *out_size = lz4_compressed_size;
295
296 return 0;
297}
298
Simon Glass1edaed02017-11-25 11:57:33 -0700299static int uncompress_using_lz4(struct unit_test_state *uts,
300 void *in, unsigned long in_size,
Julius Wernerf41a3ca2015-10-06 20:03:53 -0700301 void *out, unsigned long out_max,
302 unsigned long *out_size)
303{
304 int ret;
305 size_t input_size = in_size;
306 size_t output_size = out_max;
307
308 ret = ulz4fn(in, input_size, out, &output_size);
309 if (out_size)
310 *out_size = output_size;
311
312 return (ret != 0);
313}
314
Brandon Maier61c55e82023-01-12 10:27:46 -0600315static int compress_using_zstd(struct unit_test_state *uts,
316 void *in, unsigned long in_size,
317 void *out, unsigned long out_max,
318 unsigned long *out_size)
319{
320 /* There is no zstd compression in u-boot, so fake it. */
321 ut_asserteq(in_size, strlen(plain));
322 ut_asserteq_mem(plain, in, in_size);
323
324 if (zstd_compressed_size > out_max)
325 return -1;
326
327 memcpy(out, zstd_compressed, zstd_compressed_size);
328 if (out_size)
329 *out_size = zstd_compressed_size;
330
331 return 0;
332}
333
334static int uncompress_using_zstd(struct unit_test_state *uts,
335 void *in, unsigned long in_size,
336 void *out, unsigned long out_max,
337 unsigned long *out_size)
338{
339 struct abuf in_buf, out_buf;
340 int ret;
341
342 abuf_init_set(&in_buf, in, in_size);
343 abuf_init_set(&out_buf, out, out_max);
344
345 ret = zstd_decompress(&in_buf, &out_buf);
346 if (ret >= 0) {
347 *out_size = ret;
348 ret = 0;
349 }
350
351 return ret;
352}
353
Kees Cook5d3bca82013-08-16 07:59:11 -0700354#define errcheck(statement) if (!(statement)) { \
355 fprintf(stderr, "\tFailed: %s\n", #statement); \
356 ret = 1; \
357 goto out; \
358}
359
Simon Glass053f8012017-11-25 11:57:31 -0700360struct buf_state {
361 ulong orig_size;
362 ulong compressed_size;
363 ulong uncompressed_size;
Kees Cook5d3bca82013-08-16 07:59:11 -0700364 void *orig_buf;
Simon Glass053f8012017-11-25 11:57:31 -0700365 void *compressed_buf;
366 void *uncompressed_buf;
367 void *compare_buf;
368};
Kees Cook5d3bca82013-08-16 07:59:11 -0700369
Simon Glass1edaed02017-11-25 11:57:33 -0700370static int run_test_internal(struct unit_test_state *uts, char *name,
Simon Glass053f8012017-11-25 11:57:31 -0700371 mutate_func compress, mutate_func uncompress,
372 struct buf_state *buf)
373{
374 int ret;
Kees Cook5d3bca82013-08-16 07:59:11 -0700375
376 /* Compress works as expected. */
Simon Glass053f8012017-11-25 11:57:31 -0700377 printf("\torig_size:%lu\n", buf->orig_size);
378 memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600379 ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass1edaed02017-11-25 11:57:33 -0700380 buf->compressed_buf, buf->compressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600381 &buf->compressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700382 printf("\tcompressed_size:%lu\n", buf->compressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600383 ut_assert(buf->compressed_size > 0);
384 ut_assert(buf->compressed_size < buf->orig_size);
385 ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
386 != 'A');
387 ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700388
389 /* Uncompresses with space remaining. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600390 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700391 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600392 &buf->uncompressed_size));
Simon Glass053f8012017-11-25 11:57:31 -0700393 printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600394 ut_asserteq(buf->uncompressed_size, buf->orig_size);
395 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Kees Cook5d3bca82013-08-16 07:59:11 -0700396
397 /* Uncompresses with exactly the right size output buffer. */
Simon Glass053f8012017-11-25 11:57:31 -0700398 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600399 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700400 buf->uncompressed_buf, buf->orig_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600401 &buf->uncompressed_size));
402 ut_asserteq(buf->uncompressed_size, buf->orig_size);
403 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
404 ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
Kees Cook5d3bca82013-08-16 07:59:11 -0700405
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600406 /* Uncompresses with trailing garbage in input buffer. */
407 memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600408 ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600409 buf->uncompressed_buf, buf->uncompressed_size,
Brandon Maier8e1bef22022-12-28 16:53:52 -0600410 &buf->uncompressed_size));
411 ut_asserteq(buf->uncompressed_size, buf->orig_size);
412 ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
Brandon Maier7e8c6f82022-12-28 16:53:51 -0600413
Kees Cook5d3bca82013-08-16 07:59:11 -0700414 /* Make sure compression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700415 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700416 ret = compress(uts, buf->orig_buf, buf->orig_size,
Simon Glass053f8012017-11-25 11:57:31 -0700417 buf->compare_buf, buf->compressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700418 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600419 ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
420 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700421 printf("\tcompress does not overrun\n");
422
423 /* Make sure decompression does not over-run. */
Simon Glass053f8012017-11-25 11:57:31 -0700424 memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
Simon Glass1edaed02017-11-25 11:57:33 -0700425 ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
Simon Glass053f8012017-11-25 11:57:31 -0700426 buf->compare_buf, buf->uncompressed_size - 1,
Kees Cook5d3bca82013-08-16 07:59:11 -0700427 NULL);
Brandon Maier8e1bef22022-12-28 16:53:52 -0600428 ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
429 ut_assert(ret != 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700430 printf("\tuncompress does not overrun\n");
431
432 /* Got here, everything is fine. */
Brandon Maier8e1bef22022-12-28 16:53:52 -0600433 return 0;
Simon Glass053f8012017-11-25 11:57:31 -0700434}
435
Simon Glass1edaed02017-11-25 11:57:33 -0700436static int run_test(struct unit_test_state *uts, char *name,
437 mutate_func compress, mutate_func uncompress)
Simon Glass053f8012017-11-25 11:57:31 -0700438{
439 struct buf_state sbuf, *buf = &sbuf;
440 int ret;
441
442 printf(" testing %s ...\n", name);
443
444 buf->orig_buf = (void *)plain;
445 buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
446 errcheck(buf->orig_size > 0);
447
448 buf->compressed_size = TEST_BUFFER_SIZE;
449 buf->uncompressed_size = TEST_BUFFER_SIZE;
450 buf->compressed_buf = malloc(buf->compressed_size);
451 errcheck(buf->compressed_buf);
452 buf->uncompressed_buf = malloc(buf->uncompressed_size);
453 errcheck(buf->uncompressed_buf);
454 buf->compare_buf = malloc(buf->uncompressed_size);
455 errcheck(buf->compare_buf);
456
Simon Glass1edaed02017-11-25 11:57:33 -0700457 ret = run_test_internal(uts, name, compress, uncompress, buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700458out:
459 printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
460
Simon Glass053f8012017-11-25 11:57:31 -0700461 free(buf->compare_buf);
462 free(buf->uncompressed_buf);
463 free(buf->compressed_buf);
Kees Cook5d3bca82013-08-16 07:59:11 -0700464
465 return ret;
466}
467
Simon Glass1edaed02017-11-25 11:57:33 -0700468static int compression_test_gzip(struct unit_test_state *uts)
Kees Cook5d3bca82013-08-16 07:59:11 -0700469{
Simon Glass1edaed02017-11-25 11:57:33 -0700470 return run_test(uts, "gzip", compress_using_gzip,
471 uncompress_using_gzip);
472}
Simon Glassecaaae82024-11-02 13:36:50 -0600473LIB_TEST(compression_test_gzip, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700474
Simon Glass1edaed02017-11-25 11:57:33 -0700475static int compression_test_bzip2(struct unit_test_state *uts)
476{
477 return run_test(uts, "bzip2", compress_using_bzip2,
478 uncompress_using_bzip2);
479}
Simon Glassecaaae82024-11-02 13:36:50 -0600480LIB_TEST(compression_test_bzip2, 0);
Simon Glass1edaed02017-11-25 11:57:33 -0700481
482static int compression_test_lzma(struct unit_test_state *uts)
483{
484 return run_test(uts, "lzma", compress_using_lzma,
485 uncompress_using_lzma);
486}
Simon Glassecaaae82024-11-02 13:36:50 -0600487LIB_TEST(compression_test_lzma, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700488
Simon Glass1edaed02017-11-25 11:57:33 -0700489static int compression_test_lzo(struct unit_test_state *uts)
490{
491 return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
492}
Simon Glassecaaae82024-11-02 13:36:50 -0600493LIB_TEST(compression_test_lzo, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700494
Simon Glass1edaed02017-11-25 11:57:33 -0700495static int compression_test_lz4(struct unit_test_state *uts)
496{
497 return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
Kees Cook5d3bca82013-08-16 07:59:11 -0700498}
Simon Glassecaaae82024-11-02 13:36:50 -0600499LIB_TEST(compression_test_lz4, 0);
Kees Cook5d3bca82013-08-16 07:59:11 -0700500
Brandon Maier61c55e82023-01-12 10:27:46 -0600501static int compression_test_zstd(struct unit_test_state *uts)
502{
503 return run_test(uts, "zstd", compress_using_zstd,
504 uncompress_using_zstd);
505}
Simon Glassecaaae82024-11-02 13:36:50 -0600506LIB_TEST(compression_test_zstd, 0);
Brandon Maier61c55e82023-01-12 10:27:46 -0600507
Simon Glass1edaed02017-11-25 11:57:33 -0700508static int compress_using_none(struct unit_test_state *uts,
509 void *in, unsigned long in_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700510 void *out, unsigned long out_max,
511 unsigned long *out_size)
512{
513 /* Here we just copy */
514 memcpy(out, in, in_size);
515 *out_size = in_size;
516
517 return 0;
518}
519
520/**
Heinrich Schuchardtd3855cf2020-03-23 18:47:47 +0100521 * run_bootm_test() - Run tests on the bootm decompression function
Simon Glass6d084ce2014-12-02 13:17:35 -0700522 *
523 * @comp_type: Compression type to test
524 * @compress: Our function to compress data
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100525 * Return: 0 if OK, non-zero on failure
Simon Glass6d084ce2014-12-02 13:17:35 -0700526 */
Simon Glass1edaed02017-11-25 11:57:33 -0700527static int run_bootm_test(struct unit_test_state *uts, int comp_type,
528 mutate_func compress)
Simon Glass6d084ce2014-12-02 13:17:35 -0700529{
530 ulong compress_size = 1024;
531 void *compress_buff;
532 int unc_len;
533 int err = 0;
534 const ulong image_start = 0;
535 const ulong load_addr = 0x1000;
536 ulong load_end;
537
538 printf("Testing: %s\n", genimg_get_comp_name(comp_type));
539 compress_buff = map_sysmem(image_start, 0);
540 unc_len = strlen(plain);
Simon Glass1edaed02017-11-25 11:57:33 -0700541 compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
Simon Glass6d084ce2014-12-02 13:17:35 -0700542 &compress_size);
Julius Werner47ef9862019-07-24 19:37:54 -0700543 err = image_decomp(comp_type, load_addr, image_start,
544 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
545 compress_buff, compress_size, unc_len,
546 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700547 ut_assertok(err);
Julius Werner47ef9862019-07-24 19:37:54 -0700548 err = image_decomp(comp_type, load_addr, image_start,
549 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
550 compress_buff, compress_size, unc_len - 1,
551 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700552 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700553
554 /* We can't detect corruption when not decompressing */
555 if (comp_type == IH_COMP_NONE)
556 return 0;
557 memset(compress_buff + compress_size / 2, '\x49',
558 compress_size / 2);
Julius Werner47ef9862019-07-24 19:37:54 -0700559 err = image_decomp(comp_type, load_addr, image_start,
560 IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
561 compress_buff, compress_size, 0x10000,
562 &load_end);
Simon Glass1edaed02017-11-25 11:57:33 -0700563 ut_assert(err);
Simon Glass6d084ce2014-12-02 13:17:35 -0700564
565 return 0;
566}
567
Simon Glass1edaed02017-11-25 11:57:33 -0700568static int compression_test_bootm_gzip(struct unit_test_state *uts)
Simon Glass6d084ce2014-12-02 13:17:35 -0700569{
Simon Glass1edaed02017-11-25 11:57:33 -0700570 return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
571}
Simon Glassecaaae82024-11-02 13:36:50 -0600572LIB_TEST(compression_test_bootm_gzip, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700573
Simon Glass1edaed02017-11-25 11:57:33 -0700574static int compression_test_bootm_bzip2(struct unit_test_state *uts)
575{
576 return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
577}
Simon Glassecaaae82024-11-02 13:36:50 -0600578LIB_TEST(compression_test_bootm_bzip2, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700579
Simon Glass1edaed02017-11-25 11:57:33 -0700580static int compression_test_bootm_lzma(struct unit_test_state *uts)
581{
582 return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
583}
Simon Glassecaaae82024-11-02 13:36:50 -0600584LIB_TEST(compression_test_bootm_lzma, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700585
Simon Glass1edaed02017-11-25 11:57:33 -0700586static int compression_test_bootm_lzo(struct unit_test_state *uts)
587{
588 return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
Simon Glass6d084ce2014-12-02 13:17:35 -0700589}
Simon Glassecaaae82024-11-02 13:36:50 -0600590LIB_TEST(compression_test_bootm_lzo, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700591
Simon Glass1edaed02017-11-25 11:57:33 -0700592static int compression_test_bootm_lz4(struct unit_test_state *uts)
593{
594 return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
595}
Simon Glassecaaae82024-11-02 13:36:50 -0600596LIB_TEST(compression_test_bootm_lz4, 0);
Simon Glass6d084ce2014-12-02 13:17:35 -0700597
Brandon Maier61c55e82023-01-12 10:27:46 -0600598static int compression_test_bootm_zstd(struct unit_test_state *uts)
599{
600 return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
601}
Simon Glassecaaae82024-11-02 13:36:50 -0600602LIB_TEST(compression_test_bootm_zstd, 0);
Brandon Maier61c55e82023-01-12 10:27:46 -0600603
Simon Glass1edaed02017-11-25 11:57:33 -0700604static int compression_test_bootm_none(struct unit_test_state *uts)
605{
606 return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
607}
Simon Glassecaaae82024-11-02 13:36:50 -0600608LIB_TEST(compression_test_bootm_none, 0);