1 // SPDX-License-Identifier: GPL-2.0+
2 #include "decompress.h"
4 #if IS_ENABLED(CONFIG_ZLIB)
5 #include <u-boot/zlib.h>
7 /* report a zlib or i/o error */
8 static int zerr(int ret)
23 static int z_erofs_decompress_deflate(struct z_erofs_decompress_req *rq)
25 u8 *dest = (u8 *)rq->out;
26 u8 *src = (u8 *)rq->in;
28 unsigned int inputmargin = 0;
32 while (!src[inputmargin & (erofs_blksiz() - 1)])
33 if (!(++inputmargin & (erofs_blksiz() - 1)))
36 if (inputmargin >= rq->inputsize)
39 if (rq->decodedskip) {
40 buff = malloc(rq->decodedlength);
46 /* allocate inflate state */
51 strm.next_in = Z_NULL;
52 ret = inflateInit2(&strm, -15);
58 strm.next_in = src + inputmargin;
59 strm.avail_in = rq->inputsize - inputmargin;
61 strm.avail_out = rq->decodedlength;
63 ret = inflate(&strm, rq->partial_decoding ? Z_SYNC_FLUSH : Z_FINISH);
64 if (ret != Z_STREAM_END || strm.total_out != rq->decodedlength) {
65 if (ret != Z_OK || !rq->partial_decoding) {
72 memcpy(rq->out, dest + rq->decodedskip,
73 rq->decodedlength - rq->decodedskip);
83 #if IS_ENABLED(CONFIG_LZ4)
84 #include <u-boot/lz4.h>
85 static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq)
91 bool support_0padding = false;
92 unsigned int inputmargin = 0;
94 if (erofs_sb_has_lz4_0padding()) {
95 support_0padding = true;
97 while (!src[inputmargin & (erofs_blksiz() - 1)])
98 if (!(++inputmargin & (erofs_blksiz() - 1)))
101 if (inputmargin >= rq->inputsize)
105 if (rq->decodedskip) {
106 buff = malloc(rq->decodedlength);
112 if (rq->partial_decoding || !support_0padding)
113 ret = LZ4_decompress_safe_partial(src + inputmargin, dest,
114 rq->inputsize - inputmargin,
115 rq->decodedlength, rq->decodedlength);
117 ret = LZ4_decompress_safe(src + inputmargin, dest,
118 rq->inputsize - inputmargin,
121 if (ret != (int)rq->decodedlength) {
122 erofs_err("failed to %s decompress %d in[%u, %u] out[%u]",
123 rq->partial_decoding ? "partial" : "full",
124 ret, rq->inputsize, inputmargin, rq->decodedlength);
130 memcpy(rq->out, dest + rq->decodedskip,
131 rq->decodedlength - rq->decodedskip);
141 int z_erofs_decompress(struct z_erofs_decompress_req *rq)
143 if (rq->alg == Z_EROFS_COMPRESSION_INTERLACED) {
144 unsigned int count, rightpart, skip;
146 /* XXX: should support inputsize >= erofs_blksiz() later */
147 if (rq->inputsize > erofs_blksiz())
148 return -EFSCORRUPTED;
150 if (rq->decodedlength > erofs_blksiz())
151 return -EFSCORRUPTED;
153 if (rq->decodedlength < rq->decodedskip)
154 return -EFSCORRUPTED;
156 count = rq->decodedlength - rq->decodedskip;
157 skip = erofs_blkoff(rq->interlaced_offset + rq->decodedskip);
158 rightpart = min(erofs_blksiz() - skip, count);
159 memcpy(rq->out, rq->in + skip, rightpart);
160 memcpy(rq->out + rightpart, rq->in, count - rightpart);
162 } else if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
163 if (rq->decodedlength > rq->inputsize)
164 return -EFSCORRUPTED;
166 DBG_BUGON(rq->decodedlength < rq->decodedskip);
167 memcpy(rq->out, rq->in + rq->decodedskip,
168 rq->decodedlength - rq->decodedskip);
172 #if IS_ENABLED(CONFIG_LZ4)
173 if (rq->alg == Z_EROFS_COMPRESSION_LZ4)
174 return z_erofs_decompress_lz4(rq);
176 #if IS_ENABLED(CONFIG_ZLIB)
177 if (rq->alg == Z_EROFS_COMPRESSION_DEFLATE)
178 return z_erofs_decompress_deflate(rq);