]>
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
11 #include <linux/lzo.h>
12 #include <linux/zstd.h>
13 #include <linux/compat.h>
14 #include <u-boot/zlib.h>
15 #include <asm/unaligned.h>
17 /* Header for each segment, LE32, recording the compressed size */
19 static u32
decompress_lzo(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
21 u32 tot_len
, tot_in
, in_len
, res
;
28 tot_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
35 if (tot_len
== 0 && dlen
)
37 if (tot_len
< LZO_LEN
)
42 while (tot_len
> LZO_LEN
) {
45 in_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
49 if (in_len
> clen
|| tot_len
< LZO_LEN
+ in_len
)
52 tot_len
-= (LZO_LEN
+ in_len
);
53 tot_in
+= (LZO_LEN
+ in_len
);
56 ret
= lzo1x_decompress_safe(cbuf
, in_len
, dbuf
, &out_len
);
68 * If the 4 bytes header does not fit to the rest of the page we
69 * have to move to next one, or we read some garbage.
71 rem_page
= PAGE_SIZE
- (tot_in
% PAGE_SIZE
);
72 if (rem_page
< LZO_LEN
) {
84 #define PRESET_DICT 0x20
86 static u32
decompress_zlib(const u8
*_cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
88 int wbits
= MAX_WBITS
, ret
= -1;
93 memset(&stream
, 0, sizeof(stream
));
99 stream
.next_out
= dbuf
;
100 stream
.avail_out
= dlen
;
101 stream
.total_out
= 0;
103 /* skip adler32 check if deflate and no dictionary */
104 if (clen
> 2 && !(cbuf
[1] & PRESET_DICT
) &&
105 ((cbuf
[0] & 0x0f) == Z_DEFLATED
) &&
106 !(((cbuf
[0] << 8) + cbuf
[1]) % 31)) {
107 wbits
= -((cbuf
[0] >> 4) + 8);
112 if (Z_OK
!= inflateInit2(&stream
, wbits
))
115 while (stream
.total_in
< clen
) {
116 stream
.next_in
= cbuf
+ stream
.total_in
;
117 stream
.avail_in
= min((u32
) (clen
- stream
.total_in
),
118 current_fs_info
->sectorsize
);
120 ret
= inflate(&stream
, Z_NO_FLUSH
);
125 res
= stream
.total_out
;
128 if (ret
!= Z_STREAM_END
)
134 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
135 #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
137 static u32
decompress_zstd(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
139 ZSTD_DStream
*dstream
;
140 ZSTD_inBuffer in_buf
;
141 ZSTD_outBuffer out_buf
;
146 wsize
= ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT
);
147 workspace
= malloc(wsize
);
149 debug("%s: cannot allocate workspace of size %zu\n", __func__
,
154 dstream
= ZSTD_initDStream(ZSTD_BTRFS_MAX_INPUT
, workspace
, wsize
);
156 printf("%s: ZSTD_initDStream failed\n", __func__
);
171 ret
= ZSTD_decompressStream(dstream
, &out_buf
, &in_buf
);
172 if (ZSTD_isError(ret
)) {
173 printf("%s: ZSTD_decompressStream error %d\n", __func__
,
174 ZSTD_getErrorCode(ret
));
178 if (in_buf
.pos
>= clen
|| !ret
)
189 u32
btrfs_decompress(u8 type
, const char *c
, u32 clen
, char *d
, u32 dlen
)
195 cbuf
= (const u8
*) c
;
199 case BTRFS_COMPRESS_NONE
:
200 res
= dlen
< clen
? dlen
: clen
;
201 memcpy(dbuf
, cbuf
, res
);
203 case BTRFS_COMPRESS_ZLIB
:
204 return decompress_zlib(cbuf
, clen
, dbuf
, dlen
);
205 case BTRFS_COMPRESS_LZO
:
206 return decompress_lzo(cbuf
, clen
, dbuf
, dlen
);
207 case BTRFS_COMPRESS_ZSTD
:
208 return decompress_zstd(cbuf
, clen
, dbuf
, dlen
);
210 printf("%s: Unsupported compression in extent: %i\n", __func__
,