]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - fs/btrfs/compression.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * BTRFS filesystem implementation for U-Boot
5 * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
10 #include <linux/lzo.h>
11 #include <linux/zstd.h>
12 #include <linux/compat.h>
13 #include <u-boot/zlib.h>
14 #include <asm/unaligned.h>
16 /* Header for each segment, LE32, recording the compressed size */
18 static u32
decompress_lzo(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
20 u32 tot_len
, tot_in
, in_len
, res
;
27 tot_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
34 if (tot_len
== 0 && dlen
)
36 if (tot_len
< LZO_LEN
)
41 while (tot_len
> LZO_LEN
) {
44 in_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
48 if (in_len
> clen
|| tot_len
< LZO_LEN
+ in_len
)
51 tot_len
-= (LZO_LEN
+ in_len
);
52 tot_in
+= (LZO_LEN
+ in_len
);
55 ret
= lzo1x_decompress_safe(cbuf
, in_len
, dbuf
, &out_len
);
67 * If the 4 bytes header does not fit to the rest of the page we
68 * have to move to next one, or we read some garbage.
70 rem_page
= PAGE_SIZE
- (tot_in
% PAGE_SIZE
);
71 if (rem_page
< LZO_LEN
) {
83 #define PRESET_DICT 0x20
85 static u32
decompress_zlib(const u8
*_cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
87 int wbits
= MAX_WBITS
, ret
= -1;
92 memset(&stream
, 0, sizeof(stream
));
98 stream
.next_out
= dbuf
;
99 stream
.avail_out
= dlen
;
100 stream
.total_out
= 0;
102 /* skip adler32 check if deflate and no dictionary */
103 if (clen
> 2 && !(cbuf
[1] & PRESET_DICT
) &&
104 ((cbuf
[0] & 0x0f) == Z_DEFLATED
) &&
105 !(((cbuf
[0] << 8) + cbuf
[1]) % 31)) {
106 wbits
= -((cbuf
[0] >> 4) + 8);
111 if (Z_OK
!= inflateInit2(&stream
, wbits
))
114 while (stream
.total_in
< clen
) {
115 stream
.next_in
= cbuf
+ stream
.total_in
;
116 stream
.avail_in
= min((u32
) (clen
- stream
.total_in
),
117 (u32
) btrfs_info
.sb
.sectorsize
);
119 ret
= inflate(&stream
, Z_NO_FLUSH
);
124 res
= stream
.total_out
;
127 if (ret
!= Z_STREAM_END
)
133 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
134 #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
136 static u32
decompress_zstd(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
138 ZSTD_DStream
*dstream
;
139 ZSTD_inBuffer in_buf
;
140 ZSTD_outBuffer out_buf
;
145 wsize
= ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT
);
146 workspace
= malloc(wsize
);
148 debug("%s: cannot allocate workspace of size %zu\n", __func__
,
153 dstream
= ZSTD_initDStream(ZSTD_BTRFS_MAX_INPUT
, workspace
, wsize
);
155 printf("%s: ZSTD_initDStream failed\n", __func__
);
170 ret
= ZSTD_decompressStream(dstream
, &out_buf
, &in_buf
);
171 if (ZSTD_isError(ret
)) {
172 printf("%s: ZSTD_decompressStream error %d\n", __func__
,
173 ZSTD_getErrorCode(ret
));
177 if (in_buf
.pos
>= clen
|| !ret
)
188 u32
btrfs_decompress(u8 type
, const char *c
, u32 clen
, char *d
, u32 dlen
)
194 cbuf
= (const u8
*) c
;
198 case BTRFS_COMPRESS_NONE
:
199 res
= dlen
< clen
? dlen
: clen
;
200 memcpy(dbuf
, cbuf
, res
);
202 case BTRFS_COMPRESS_ZLIB
:
203 return decompress_zlib(cbuf
, clen
, dbuf
, dlen
);
204 case BTRFS_COMPRESS_LZO
:
205 return decompress_lzo(cbuf
, clen
, dbuf
, dlen
);
206 case BTRFS_COMPRESS_ZSTD
:
207 return decompress_zstd(cbuf
, clen
, dbuf
, dlen
);
209 printf("%s: Unsupported compression in extent: %i\n", __func__
,