1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2012
3*4882a593Smuzhiyun * Lei Wen <leiwen@marvell.com>, Marvell Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <watchdog.h>
10*4882a593Smuzhiyun #include <command.h>
11*4882a593Smuzhiyun #include <image.h>
12*4882a593Smuzhiyun #include <malloc.h>
13*4882a593Smuzhiyun #include <memalign.h>
14*4882a593Smuzhiyun #include <u-boot/zlib.h>
15*4882a593Smuzhiyun #include "zlib/zutil.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #ifndef CONFIG_GZIP_COMPRESS_DEF_SZ
18*4882a593Smuzhiyun #define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun #define ZALLOC_ALIGNMENT 16
21*4882a593Smuzhiyun
zalloc(void * x,unsigned items,unsigned size)22*4882a593Smuzhiyun static void *zalloc(void *x, unsigned items, unsigned size)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun void *p;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun size *= items;
27*4882a593Smuzhiyun size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun p = malloc_cache_aligned(size);
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun return (p);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
zfree(void * x,void * addr,unsigned nb)34*4882a593Smuzhiyun static void zfree(void *x, void *addr, unsigned nb)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun free (addr);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun
gzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen)39*4882a593Smuzhiyun int gzip(void *dst, unsigned long *lenp,
40*4882a593Smuzhiyun unsigned char *src, unsigned long srclen)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun return zzip(dst, lenp, src, srclen, 1, NULL);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun * Compress blocks with zlib
47*4882a593Smuzhiyun */
zzip(void * dst,unsigned long * lenp,unsigned char * src,unsigned long srclen,int stoponerr,int (* func)(unsigned long,unsigned long))48*4882a593Smuzhiyun int zzip(void *dst, unsigned long *lenp, unsigned char *src,
49*4882a593Smuzhiyun unsigned long srclen, int stoponerr,
50*4882a593Smuzhiyun int (*func)(unsigned long, unsigned long))
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun z_stream s;
53*4882a593Smuzhiyun int r, flush, orig, window;
54*4882a593Smuzhiyun unsigned long comp_len, left_len;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (!srclen)
57*4882a593Smuzhiyun return 0;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #ifndef CONFIG_GZIP
60*4882a593Smuzhiyun window = MAX_WBITS;
61*4882a593Smuzhiyun #else
62*4882a593Smuzhiyun window = 2 * MAX_WBITS;
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun orig = *lenp;
65*4882a593Smuzhiyun s.zalloc = zalloc;
66*4882a593Smuzhiyun s.zfree = zfree;
67*4882a593Smuzhiyun s.opaque = Z_NULL;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window,
70*4882a593Smuzhiyun DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
71*4882a593Smuzhiyun ZLIB_VERSION, sizeof(z_stream));
72*4882a593Smuzhiyun if (r != Z_OK) {
73*4882a593Smuzhiyun printf ("Error: deflateInit2_() returned %d\n", r);
74*4882a593Smuzhiyun return -1;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun while (srclen > 0) {
78*4882a593Smuzhiyun comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
79*4882a593Smuzhiyun CONFIG_GZIP_COMPRESS_DEF_SZ : srclen;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun s.next_in = src;
82*4882a593Smuzhiyun s.avail_in = comp_len;
83*4882a593Smuzhiyun flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)?
84*4882a593Smuzhiyun Z_NO_FLUSH : Z_FINISH;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun do {
87*4882a593Smuzhiyun left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
88*4882a593Smuzhiyun CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp;
89*4882a593Smuzhiyun s.next_out = dst;
90*4882a593Smuzhiyun s.avail_out = left_len;
91*4882a593Smuzhiyun r = deflate(&s, flush);
92*4882a593Smuzhiyun if (r == Z_STREAM_ERROR && stoponerr == 1) {
93*4882a593Smuzhiyun printf("Error: deflate() returned %d\n", r);
94*4882a593Smuzhiyun r = -1;
95*4882a593Smuzhiyun goto bail;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun if (!func) {
98*4882a593Smuzhiyun dst += (left_len - s.avail_out);
99*4882a593Smuzhiyun *lenp -= (left_len - s.avail_out);
100*4882a593Smuzhiyun } else if (left_len - s.avail_out > 0) {
101*4882a593Smuzhiyun r = func((unsigned long)dst,
102*4882a593Smuzhiyun left_len - s.avail_out);
103*4882a593Smuzhiyun if (r < 0)
104*4882a593Smuzhiyun goto bail;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun } while (s.avail_out == 0 && (*lenp > 0));
107*4882a593Smuzhiyun if (s.avail_in) {
108*4882a593Smuzhiyun printf("Deflate failed to consume %u bytes", s.avail_in);
109*4882a593Smuzhiyun r = -1;
110*4882a593Smuzhiyun goto bail;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun if (*lenp == 0) {
113*4882a593Smuzhiyun printf("Deflate need more space to compress "
114*4882a593Smuzhiyun "left %lu bytes\n", srclen);
115*4882a593Smuzhiyun r = -1;
116*4882a593Smuzhiyun goto bail;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun srclen -= comp_len;
119*4882a593Smuzhiyun src += comp_len;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun r = 0;
123*4882a593Smuzhiyun bail:
124*4882a593Smuzhiyun deflateEnd(&s);
125*4882a593Smuzhiyun *lenp = orig - *lenp;
126*4882a593Smuzhiyun return r;
127*4882a593Smuzhiyun }
128