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