xref: /openbmc/u-boot/test/compression.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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