1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
23153e915SKees Cook /*
33153e915SKees Cook * Copyright (c) 2013, The Chromium Authors
43153e915SKees Cook */
53153e915SKees Cook
63153e915SKees Cook #include <common.h>
76ed4dc78SSimon Glass #include <bootm.h>
83153e915SKees Cook #include <command.h>
93153e915SKees Cook #include <malloc.h>
100eb25b61SJoe Hershberger #include <mapmem.h>
116ed4dc78SSimon Glass #include <asm/io.h>
123153e915SKees Cook
133153e915SKees Cook #include <u-boot/zlib.h>
143153e915SKees Cook #include <bzlib.h>
153153e915SKees Cook
163153e915SKees Cook #include <lzma/LzmaTypes.h>
173153e915SKees Cook #include <lzma/LzmaDec.h>
183153e915SKees Cook #include <lzma/LzmaTools.h>
193153e915SKees Cook
203153e915SKees Cook #include <linux/lzo.h>
210aac10f2SSimon Glass #include <test/compression.h>
220aac10f2SSimon Glass #include <test/suites.h>
230aac10f2SSimon Glass #include <test/ut.h>
243153e915SKees Cook
253153e915SKees Cook static const char plain[] =
263153e915SKees Cook "I am a highly compressable bit of text.\n"
273153e915SKees Cook "I am a highly compressable bit of text.\n"
283153e915SKees Cook "I am a highly compressable bit of text.\n"
293153e915SKees Cook "There are many like me, but this one is mine.\n"
303153e915SKees Cook "If I were any shorter, there wouldn't be much sense in\n"
313153e915SKees Cook "compressing me in the first place. At least with lzo, anyway,\n"
323153e915SKees Cook "which appears to behave poorly in the face of short text\n"
333153e915SKees Cook "messages.\n";
343153e915SKees Cook
353153e915SKees Cook /* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */
363153e915SKees Cook static const char bzip2_compressed[] =
373153e915SKees Cook "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00"
383153e915SKees Cook "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30"
393153e915SKees Cook "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4"
403153e915SKees Cook "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d"
413153e915SKees Cook "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52"
423153e915SKees Cook "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad"
433153e915SKees Cook "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16"
443153e915SKees Cook "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c"
453153e915SKees Cook "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0"
463153e915SKees Cook "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6"
473153e915SKees Cook "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4"
483153e915SKees Cook "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96"
493153e915SKees Cook "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
503153e915SKees Cook "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
513153e915SKees Cook "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
523153e915SKees Cook static const unsigned long bzip2_compressed_size = 240;
533153e915SKees Cook
543153e915SKees Cook /* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
553153e915SKees Cook static const char lzma_compressed[] =
563153e915SKees Cook "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88"
573153e915SKees Cook "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8"
583153e915SKees Cook "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15"
593153e915SKees Cook "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16"
603153e915SKees Cook "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57"
613153e915SKees Cook "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5"
623153e915SKees Cook "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d"
633153e915SKees Cook "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5"
643153e915SKees Cook "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b"
653153e915SKees Cook "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b"
663153e915SKees Cook "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b"
673153e915SKees Cook "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49"
683153e915SKees Cook "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
693153e915SKees Cook "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
703153e915SKees Cook "\xfd\xf5\x50\x8d\xca";
713153e915SKees Cook static const unsigned long lzma_compressed_size = 229;
723153e915SKees Cook
733153e915SKees Cook /* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
743153e915SKees Cook static const char lzo_compressed[] =
753153e915SKees Cook "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01"
763153e915SKees Cook "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00"
773153e915SKees Cook "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00"
783153e915SKees Cook "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61"
793153e915SKees Cook "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
803153e915SKees Cook "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
813153e915SKees Cook "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65"
823153e915SKees Cook "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d"
833153e915SKees Cook "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20"
843153e915SKees Cook "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84"
853153e915SKees Cook "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90"
863153e915SKees Cook "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d"
873153e915SKees Cook "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02"
883153e915SKees Cook "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73"
893153e915SKees Cook "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
903153e915SKees Cook "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77"
913153e915SKees Cook "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
923153e915SKees Cook "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
933153e915SKees Cook "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
943153e915SKees Cook "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
953153e915SKees Cook "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
963153e915SKees Cook static const unsigned long lzo_compressed_size = 334;
973153e915SKees Cook
98027b728dSJulius Werner /* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
99027b728dSJulius Werner static const char lz4_compressed[] =
100027b728dSJulius Werner "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61"
101027b728dSJulius Werner "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72"
102027b728dSJulius Werner "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74"
103027b728dSJulius Werner "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20"
104027b728dSJulius Werner "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65"
105027b728dSJulius Werner "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69"
106027b728dSJulius Werner "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00"
107027b728dSJulius Werner "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00"
108027b728dSJulius Werner "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75"
109027b728dSJulius Werner "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69"
110027b728dSJulius Werner "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73"
111027b728dSJulius Werner "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73"
112027b728dSJulius Werner "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77"
113027b728dSJulius Werner "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72"
114027b728dSJulius Werner "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72"
115027b728dSJulius Werner "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
116027b728dSJulius Werner "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
117027b728dSJulius Werner "\x9d\x12\x8c\x9d";
118027b728dSJulius Werner static const unsigned long lz4_compressed_size = 276;
119027b728dSJulius Werner
1203153e915SKees Cook
1213153e915SKees Cook #define TEST_BUFFER_SIZE 512
1223153e915SKees Cook
1230aac10f2SSimon Glass typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long,
1240aac10f2SSimon Glass void *, unsigned long, unsigned long *);
1253153e915SKees Cook
compress_using_gzip(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)1260aac10f2SSimon Glass static int compress_using_gzip(struct unit_test_state *uts,
1270aac10f2SSimon Glass void *in, unsigned long in_size,
1283153e915SKees Cook void *out, unsigned long out_max,
1293153e915SKees Cook unsigned long *out_size)
1303153e915SKees Cook {
1313153e915SKees Cook int ret;
1323153e915SKees Cook unsigned long inout_size = out_max;
1333153e915SKees Cook
1343153e915SKees Cook ret = gzip(out, &inout_size, in, in_size);
1353153e915SKees Cook if (out_size)
1363153e915SKees Cook *out_size = inout_size;
1373153e915SKees Cook
1383153e915SKees Cook return ret;
1393153e915SKees Cook }
1403153e915SKees Cook
uncompress_using_gzip(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)1410aac10f2SSimon Glass static int uncompress_using_gzip(struct unit_test_state *uts,
1420aac10f2SSimon Glass void *in, unsigned long in_size,
1433153e915SKees Cook void *out, unsigned long out_max,
1443153e915SKees Cook unsigned long *out_size)
1453153e915SKees Cook {
1463153e915SKees Cook int ret;
1473153e915SKees Cook unsigned long inout_size = in_size;
1483153e915SKees Cook
1493153e915SKees Cook ret = gunzip(out, out_max, in, &inout_size);
1503153e915SKees Cook if (out_size)
1513153e915SKees Cook *out_size = inout_size;
1523153e915SKees Cook
1533153e915SKees Cook return ret;
1543153e915SKees Cook }
1553153e915SKees Cook
compress_using_bzip2(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)1560aac10f2SSimon Glass static int compress_using_bzip2(struct unit_test_state *uts,
1570aac10f2SSimon Glass void *in, unsigned long in_size,
1583153e915SKees Cook void *out, unsigned long out_max,
1593153e915SKees Cook unsigned long *out_size)
1603153e915SKees Cook {
1613153e915SKees Cook /* There is no bzip2 compression in u-boot, so fake it. */
1620aac10f2SSimon Glass ut_asserteq(in_size, strlen(plain));
1630aac10f2SSimon Glass ut_asserteq(0, memcmp(plain, in, in_size));
1643153e915SKees Cook
1653153e915SKees Cook if (bzip2_compressed_size > out_max)
1663153e915SKees Cook return -1;
1673153e915SKees Cook
1683153e915SKees Cook memcpy(out, bzip2_compressed, bzip2_compressed_size);
1693153e915SKees Cook if (out_size)
1703153e915SKees Cook *out_size = bzip2_compressed_size;
1713153e915SKees Cook
1723153e915SKees Cook return 0;
1733153e915SKees Cook }
1743153e915SKees Cook
uncompress_using_bzip2(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)1750aac10f2SSimon Glass static int uncompress_using_bzip2(struct unit_test_state *uts,
1760aac10f2SSimon Glass void *in, unsigned long in_size,
1773153e915SKees Cook void *out, unsigned long out_max,
1783153e915SKees Cook unsigned long *out_size)
1793153e915SKees Cook {
1803153e915SKees Cook int ret;
1813153e915SKees Cook unsigned int inout_size = out_max;
1823153e915SKees Cook
1833153e915SKees Cook ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size,
1843153e915SKees Cook CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
1853153e915SKees Cook if (out_size)
1863153e915SKees Cook *out_size = inout_size;
1873153e915SKees Cook
1883153e915SKees Cook return (ret != BZ_OK);
1893153e915SKees Cook }
1903153e915SKees Cook
compress_using_lzma(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)1910aac10f2SSimon Glass static int compress_using_lzma(struct unit_test_state *uts,
1920aac10f2SSimon Glass void *in, unsigned long in_size,
1933153e915SKees Cook void *out, unsigned long out_max,
1943153e915SKees Cook unsigned long *out_size)
1953153e915SKees Cook {
1963153e915SKees Cook /* There is no lzma compression in u-boot, so fake it. */
1970aac10f2SSimon Glass ut_asserteq(in_size, strlen(plain));
1980aac10f2SSimon Glass ut_asserteq(0, memcmp(plain, in, in_size));
1993153e915SKees Cook
2003153e915SKees Cook if (lzma_compressed_size > out_max)
2013153e915SKees Cook return -1;
2023153e915SKees Cook
2033153e915SKees Cook memcpy(out, lzma_compressed, lzma_compressed_size);
2043153e915SKees Cook if (out_size)
2053153e915SKees Cook *out_size = lzma_compressed_size;
2063153e915SKees Cook
2073153e915SKees Cook return 0;
2083153e915SKees Cook }
2093153e915SKees Cook
uncompress_using_lzma(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)2100aac10f2SSimon Glass static int uncompress_using_lzma(struct unit_test_state *uts,
2110aac10f2SSimon Glass void *in, unsigned long in_size,
2123153e915SKees Cook void *out, unsigned long out_max,
2133153e915SKees Cook unsigned long *out_size)
2143153e915SKees Cook {
2153153e915SKees Cook int ret;
2163153e915SKees Cook SizeT inout_size = out_max;
2173153e915SKees Cook
2183153e915SKees Cook ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size);
2193153e915SKees Cook if (out_size)
2203153e915SKees Cook *out_size = inout_size;
2213153e915SKees Cook
2223153e915SKees Cook return (ret != SZ_OK);
2233153e915SKees Cook }
2243153e915SKees Cook
compress_using_lzo(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)2250aac10f2SSimon Glass static int compress_using_lzo(struct unit_test_state *uts,
2260aac10f2SSimon Glass void *in, unsigned long in_size,
2273153e915SKees Cook void *out, unsigned long out_max,
2283153e915SKees Cook unsigned long *out_size)
2293153e915SKees Cook {
2303153e915SKees Cook /* There is no lzo compression in u-boot, so fake it. */
2310aac10f2SSimon Glass ut_asserteq(in_size, strlen(plain));
2320aac10f2SSimon Glass ut_asserteq(0, memcmp(plain, in, in_size));
2333153e915SKees Cook
2343153e915SKees Cook if (lzo_compressed_size > out_max)
2353153e915SKees Cook return -1;
2363153e915SKees Cook
2373153e915SKees Cook memcpy(out, lzo_compressed, lzo_compressed_size);
2383153e915SKees Cook if (out_size)
2393153e915SKees Cook *out_size = lzo_compressed_size;
2403153e915SKees Cook
2413153e915SKees Cook return 0;
2423153e915SKees Cook }
2433153e915SKees Cook
uncompress_using_lzo(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)2440aac10f2SSimon Glass static int uncompress_using_lzo(struct unit_test_state *uts,
2450aac10f2SSimon Glass void *in, unsigned long in_size,
2463153e915SKees Cook void *out, unsigned long out_max,
2473153e915SKees Cook unsigned long *out_size)
2483153e915SKees Cook {
2493153e915SKees Cook int ret;
2503153e915SKees Cook size_t input_size = in_size;
2513153e915SKees Cook size_t output_size = out_max;
2523153e915SKees Cook
2533153e915SKees Cook ret = lzop_decompress(in, input_size, out, &output_size);
2543153e915SKees Cook if (out_size)
2553153e915SKees Cook *out_size = output_size;
2563153e915SKees Cook
2573153e915SKees Cook return (ret != LZO_E_OK);
2583153e915SKees Cook }
2593153e915SKees Cook
compress_using_lz4(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)2600aac10f2SSimon Glass static int compress_using_lz4(struct unit_test_state *uts,
2610aac10f2SSimon Glass void *in, unsigned long in_size,
262027b728dSJulius Werner void *out, unsigned long out_max,
263027b728dSJulius Werner unsigned long *out_size)
264027b728dSJulius Werner {
265027b728dSJulius Werner /* There is no lz4 compression in u-boot, so fake it. */
2660aac10f2SSimon Glass ut_asserteq(in_size, strlen(plain));
2670aac10f2SSimon Glass ut_asserteq(0, memcmp(plain, in, in_size));
268027b728dSJulius Werner
269027b728dSJulius Werner if (lz4_compressed_size > out_max)
270027b728dSJulius Werner return -1;
271027b728dSJulius Werner
272027b728dSJulius Werner memcpy(out, lz4_compressed, lz4_compressed_size);
273027b728dSJulius Werner if (out_size)
274027b728dSJulius Werner *out_size = lz4_compressed_size;
275027b728dSJulius Werner
276027b728dSJulius Werner return 0;
277027b728dSJulius Werner }
278027b728dSJulius Werner
uncompress_using_lz4(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)2790aac10f2SSimon Glass static int uncompress_using_lz4(struct unit_test_state *uts,
2800aac10f2SSimon Glass void *in, unsigned long in_size,
281027b728dSJulius Werner void *out, unsigned long out_max,
282027b728dSJulius Werner unsigned long *out_size)
283027b728dSJulius Werner {
284027b728dSJulius Werner int ret;
285027b728dSJulius Werner size_t input_size = in_size;
286027b728dSJulius Werner size_t output_size = out_max;
287027b728dSJulius Werner
288027b728dSJulius Werner ret = ulz4fn(in, input_size, out, &output_size);
289027b728dSJulius Werner if (out_size)
290027b728dSJulius Werner *out_size = output_size;
291027b728dSJulius Werner
292027b728dSJulius Werner return (ret != 0);
293027b728dSJulius Werner }
294027b728dSJulius Werner
2953153e915SKees Cook #define errcheck(statement) if (!(statement)) { \
2963153e915SKees Cook fprintf(stderr, "\tFailed: %s\n", #statement); \
2973153e915SKees Cook ret = 1; \
2983153e915SKees Cook goto out; \
2993153e915SKees Cook }
3003153e915SKees Cook
30149f22c38SSimon Glass struct buf_state {
30249f22c38SSimon Glass ulong orig_size;
30349f22c38SSimon Glass ulong compressed_size;
30449f22c38SSimon Glass ulong uncompressed_size;
3053153e915SKees Cook void *orig_buf;
30649f22c38SSimon Glass void *compressed_buf;
30749f22c38SSimon Glass void *uncompressed_buf;
30849f22c38SSimon Glass void *compare_buf;
30949f22c38SSimon Glass };
31049f22c38SSimon Glass
run_test_internal(struct unit_test_state * uts,char * name,mutate_func compress,mutate_func uncompress,struct buf_state * buf)3110aac10f2SSimon Glass static int run_test_internal(struct unit_test_state *uts, char *name,
31249f22c38SSimon Glass mutate_func compress, mutate_func uncompress,
31349f22c38SSimon Glass struct buf_state *buf)
31449f22c38SSimon Glass {
3153153e915SKees Cook int ret;
3163153e915SKees Cook
3173153e915SKees Cook /* Compress works as expected. */
31849f22c38SSimon Glass printf("\torig_size:%lu\n", buf->orig_size);
31949f22c38SSimon Glass memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
3200aac10f2SSimon Glass errcheck(compress(uts, buf->orig_buf, buf->orig_size,
3210aac10f2SSimon Glass buf->compressed_buf, buf->compressed_size,
3220aac10f2SSimon Glass &buf->compressed_size) == 0);
32349f22c38SSimon Glass printf("\tcompressed_size:%lu\n", buf->compressed_size);
32449f22c38SSimon Glass errcheck(buf->compressed_size > 0);
32549f22c38SSimon Glass errcheck(buf->compressed_size < buf->orig_size);
32649f22c38SSimon Glass errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
32749f22c38SSimon Glass 'A');
32849f22c38SSimon Glass errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
3293153e915SKees Cook
3303153e915SKees Cook /* Uncompresses with space remaining. */
3310aac10f2SSimon Glass errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
33249f22c38SSimon Glass buf->uncompressed_buf, buf->uncompressed_size,
33349f22c38SSimon Glass &buf->uncompressed_size) == 0);
33449f22c38SSimon Glass printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
33549f22c38SSimon Glass errcheck(buf->uncompressed_size == buf->orig_size);
33649f22c38SSimon Glass errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
33749f22c38SSimon Glass buf->orig_size) == 0);
3383153e915SKees Cook
3393153e915SKees Cook /* Uncompresses with exactly the right size output buffer. */
34049f22c38SSimon Glass memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
3410aac10f2SSimon Glass errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
34249f22c38SSimon Glass buf->uncompressed_buf, buf->orig_size,
34349f22c38SSimon Glass &buf->uncompressed_size) == 0);
34449f22c38SSimon Glass errcheck(buf->uncompressed_size == buf->orig_size);
34549f22c38SSimon Glass errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
34649f22c38SSimon Glass buf->orig_size) == 0);
34749f22c38SSimon Glass errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
3483153e915SKees Cook
3493153e915SKees Cook /* Make sure compression does not over-run. */
35049f22c38SSimon Glass memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
3510aac10f2SSimon Glass ret = compress(uts, buf->orig_buf, buf->orig_size,
35249f22c38SSimon Glass buf->compare_buf, buf->compressed_size - 1,
3533153e915SKees Cook NULL);
35449f22c38SSimon Glass errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
3553153e915SKees Cook errcheck(ret != 0);
3563153e915SKees Cook printf("\tcompress does not overrun\n");
3573153e915SKees Cook
3583153e915SKees Cook /* Make sure decompression does not over-run. */
35949f22c38SSimon Glass memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
3600aac10f2SSimon Glass ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
36149f22c38SSimon Glass buf->compare_buf, buf->uncompressed_size - 1,
3623153e915SKees Cook NULL);
36349f22c38SSimon Glass errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
3643153e915SKees Cook errcheck(ret != 0);
3653153e915SKees Cook printf("\tuncompress does not overrun\n");
3663153e915SKees Cook
3673153e915SKees Cook /* Got here, everything is fine. */
3683153e915SKees Cook ret = 0;
3693153e915SKees Cook
3703153e915SKees Cook out:
37149f22c38SSimon Glass return ret;
37249f22c38SSimon Glass }
37349f22c38SSimon Glass
run_test(struct unit_test_state * uts,char * name,mutate_func compress,mutate_func uncompress)3740aac10f2SSimon Glass static int run_test(struct unit_test_state *uts, char *name,
3750aac10f2SSimon Glass mutate_func compress, mutate_func uncompress)
37649f22c38SSimon Glass {
37749f22c38SSimon Glass struct buf_state sbuf, *buf = &sbuf;
37849f22c38SSimon Glass int ret;
37949f22c38SSimon Glass
38049f22c38SSimon Glass printf(" testing %s ...\n", name);
38149f22c38SSimon Glass
38249f22c38SSimon Glass buf->orig_buf = (void *)plain;
38349f22c38SSimon Glass buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */
38449f22c38SSimon Glass errcheck(buf->orig_size > 0);
38549f22c38SSimon Glass
38649f22c38SSimon Glass buf->compressed_size = TEST_BUFFER_SIZE;
38749f22c38SSimon Glass buf->uncompressed_size = TEST_BUFFER_SIZE;
38849f22c38SSimon Glass buf->compressed_buf = malloc(buf->compressed_size);
38949f22c38SSimon Glass errcheck(buf->compressed_buf);
39049f22c38SSimon Glass buf->uncompressed_buf = malloc(buf->uncompressed_size);
39149f22c38SSimon Glass errcheck(buf->uncompressed_buf);
39249f22c38SSimon Glass buf->compare_buf = malloc(buf->uncompressed_size);
39349f22c38SSimon Glass errcheck(buf->compare_buf);
39449f22c38SSimon Glass
3950aac10f2SSimon Glass ret = run_test_internal(uts, name, compress, uncompress, buf);
39649f22c38SSimon Glass out:
3973153e915SKees Cook printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED");
3983153e915SKees Cook
39949f22c38SSimon Glass free(buf->compare_buf);
40049f22c38SSimon Glass free(buf->uncompressed_buf);
40149f22c38SSimon Glass free(buf->compressed_buf);
4023153e915SKees Cook
4033153e915SKees Cook return ret;
4043153e915SKees Cook }
4053153e915SKees Cook
compression_test_gzip(struct unit_test_state * uts)4060aac10f2SSimon Glass static int compression_test_gzip(struct unit_test_state *uts)
4073153e915SKees Cook {
4080aac10f2SSimon Glass return run_test(uts, "gzip", compress_using_gzip,
4090aac10f2SSimon Glass uncompress_using_gzip);
4103153e915SKees Cook }
4110aac10f2SSimon Glass COMPRESSION_TEST(compression_test_gzip, 0);
4123153e915SKees Cook
compression_test_bzip2(struct unit_test_state * uts)4130aac10f2SSimon Glass static int compression_test_bzip2(struct unit_test_state *uts)
4140aac10f2SSimon Glass {
4150aac10f2SSimon Glass return run_test(uts, "bzip2", compress_using_bzip2,
4160aac10f2SSimon Glass uncompress_using_bzip2);
4170aac10f2SSimon Glass }
4180aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bzip2, 0);
4190aac10f2SSimon Glass
compression_test_lzma(struct unit_test_state * uts)4200aac10f2SSimon Glass static int compression_test_lzma(struct unit_test_state *uts)
4210aac10f2SSimon Glass {
4220aac10f2SSimon Glass return run_test(uts, "lzma", compress_using_lzma,
4230aac10f2SSimon Glass uncompress_using_lzma);
4240aac10f2SSimon Glass }
4250aac10f2SSimon Glass COMPRESSION_TEST(compression_test_lzma, 0);
4260aac10f2SSimon Glass
compression_test_lzo(struct unit_test_state * uts)4270aac10f2SSimon Glass static int compression_test_lzo(struct unit_test_state *uts)
4280aac10f2SSimon Glass {
4290aac10f2SSimon Glass return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo);
4300aac10f2SSimon Glass }
4310aac10f2SSimon Glass COMPRESSION_TEST(compression_test_lzo, 0);
4320aac10f2SSimon Glass
compression_test_lz4(struct unit_test_state * uts)4330aac10f2SSimon Glass static int compression_test_lz4(struct unit_test_state *uts)
4340aac10f2SSimon Glass {
4350aac10f2SSimon Glass return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4);
4360aac10f2SSimon Glass }
4370aac10f2SSimon Glass COMPRESSION_TEST(compression_test_lz4, 0);
4380aac10f2SSimon Glass
compress_using_none(struct unit_test_state * uts,void * in,unsigned long in_size,void * out,unsigned long out_max,unsigned long * out_size)4390aac10f2SSimon Glass static int compress_using_none(struct unit_test_state *uts,
4400aac10f2SSimon Glass void *in, unsigned long in_size,
4416ed4dc78SSimon Glass void *out, unsigned long out_max,
4426ed4dc78SSimon Glass unsigned long *out_size)
4436ed4dc78SSimon Glass {
4446ed4dc78SSimon Glass /* Here we just copy */
4456ed4dc78SSimon Glass memcpy(out, in, in_size);
4466ed4dc78SSimon Glass *out_size = in_size;
4476ed4dc78SSimon Glass
4486ed4dc78SSimon Glass return 0;
4496ed4dc78SSimon Glass }
4506ed4dc78SSimon Glass
4516ed4dc78SSimon Glass /**
4526ed4dc78SSimon Glass * run_bootm_test() - Run tests on the bootm decopmression function
4536ed4dc78SSimon Glass *
4546ed4dc78SSimon Glass * @comp_type: Compression type to test
4556ed4dc78SSimon Glass * @compress: Our function to compress data
4566ed4dc78SSimon Glass * @return 0 if OK, non-zero on failure
4576ed4dc78SSimon Glass */
run_bootm_test(struct unit_test_state * uts,int comp_type,mutate_func compress)4580aac10f2SSimon Glass static int run_bootm_test(struct unit_test_state *uts, int comp_type,
4590aac10f2SSimon Glass mutate_func compress)
4606ed4dc78SSimon Glass {
4616ed4dc78SSimon Glass ulong compress_size = 1024;
4626ed4dc78SSimon Glass void *compress_buff;
4636ed4dc78SSimon Glass int unc_len;
4646ed4dc78SSimon Glass int err = 0;
4656ed4dc78SSimon Glass const ulong image_start = 0;
4666ed4dc78SSimon Glass const ulong load_addr = 0x1000;
4676ed4dc78SSimon Glass ulong load_end;
4686ed4dc78SSimon Glass
4696ed4dc78SSimon Glass printf("Testing: %s\n", genimg_get_comp_name(comp_type));
4706ed4dc78SSimon Glass compress_buff = map_sysmem(image_start, 0);
4716ed4dc78SSimon Glass unc_len = strlen(plain);
4720aac10f2SSimon Glass compress(uts, (void *)plain, unc_len, compress_buff, compress_size,
4736ed4dc78SSimon Glass &compress_size);
4746ed4dc78SSimon Glass err = bootm_decomp_image(comp_type, load_addr, image_start,
4756ed4dc78SSimon Glass IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
4766ed4dc78SSimon Glass compress_buff, compress_size, unc_len,
4776ed4dc78SSimon Glass &load_end);
4780aac10f2SSimon Glass ut_assertok(err);
4796ed4dc78SSimon Glass err = bootm_decomp_image(comp_type, load_addr, image_start,
4806ed4dc78SSimon Glass IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
4816ed4dc78SSimon Glass compress_buff, compress_size, unc_len - 1,
4826ed4dc78SSimon Glass &load_end);
4830aac10f2SSimon Glass ut_assert(err);
4846ed4dc78SSimon Glass
4856ed4dc78SSimon Glass /* We can't detect corruption when not decompressing */
4866ed4dc78SSimon Glass if (comp_type == IH_COMP_NONE)
4876ed4dc78SSimon Glass return 0;
4886ed4dc78SSimon Glass memset(compress_buff + compress_size / 2, '\x49',
4896ed4dc78SSimon Glass compress_size / 2);
4906ed4dc78SSimon Glass err = bootm_decomp_image(comp_type, load_addr, image_start,
4916ed4dc78SSimon Glass IH_TYPE_KERNEL, map_sysmem(load_addr, 0),
4926ed4dc78SSimon Glass compress_buff, compress_size, 0x10000,
4936ed4dc78SSimon Glass &load_end);
4940aac10f2SSimon Glass ut_assert(err);
4956ed4dc78SSimon Glass
4966ed4dc78SSimon Glass return 0;
4976ed4dc78SSimon Glass }
4986ed4dc78SSimon Glass
compression_test_bootm_gzip(struct unit_test_state * uts)4990aac10f2SSimon Glass static int compression_test_bootm_gzip(struct unit_test_state *uts)
5006ed4dc78SSimon Glass {
5010aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip);
5026ed4dc78SSimon Glass }
5030aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_gzip, 0);
5046ed4dc78SSimon Glass
compression_test_bootm_bzip2(struct unit_test_state * uts)5050aac10f2SSimon Glass static int compression_test_bootm_bzip2(struct unit_test_state *uts)
5060aac10f2SSimon Glass {
5070aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2);
5080aac10f2SSimon Glass }
5090aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_bzip2, 0);
5106ed4dc78SSimon Glass
compression_test_bootm_lzma(struct unit_test_state * uts)5110aac10f2SSimon Glass static int compression_test_bootm_lzma(struct unit_test_state *uts)
5120aac10f2SSimon Glass {
5130aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma);
5140aac10f2SSimon Glass }
5150aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_lzma, 0);
5160aac10f2SSimon Glass
compression_test_bootm_lzo(struct unit_test_state * uts)5170aac10f2SSimon Glass static int compression_test_bootm_lzo(struct unit_test_state *uts)
5180aac10f2SSimon Glass {
5190aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo);
5200aac10f2SSimon Glass }
5210aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_lzo, 0);
5220aac10f2SSimon Glass
compression_test_bootm_lz4(struct unit_test_state * uts)5230aac10f2SSimon Glass static int compression_test_bootm_lz4(struct unit_test_state *uts)
5240aac10f2SSimon Glass {
5250aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4);
5260aac10f2SSimon Glass }
5270aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_lz4, 0);
5280aac10f2SSimon Glass
compression_test_bootm_none(struct unit_test_state * uts)5290aac10f2SSimon Glass static int compression_test_bootm_none(struct unit_test_state *uts)
5300aac10f2SSimon Glass {
5310aac10f2SSimon Glass return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
5320aac10f2SSimon Glass }
5330aac10f2SSimon Glass COMPRESSION_TEST(compression_test_bootm_none, 0);
5340aac10f2SSimon Glass
do_ut_compression(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])5350aac10f2SSimon Glass int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5360aac10f2SSimon Glass {
5370aac10f2SSimon Glass struct unit_test *tests = ll_entry_start(struct unit_test,
5380aac10f2SSimon Glass compression_test);
5390aac10f2SSimon Glass const int n_ents = ll_entry_count(struct unit_test, compression_test);
5400aac10f2SSimon Glass
5410aac10f2SSimon Glass return cmd_ut_category("compression", tests, n_ents, argc, argv);
5420aac10f2SSimon Glass }
543