]>
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 <u-boot/zlib.h>
13 #include <asm/unaligned.h>
15 static u32
decompress_lzo(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
17 u32 tot_len
, in_len
, res
;
24 tot_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
29 if (tot_len
== 0 && dlen
)
37 in_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
41 if (in_len
> clen
|| tot_len
< 4 + in_len
)
44 tot_len
-= 4 + in_len
;
47 ret
= lzo1x_decompress_safe(cbuf
, in_len
, dbuf
, &out_len
);
63 #define PRESET_DICT 0x20
65 static u32
decompress_zlib(const u8
*_cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
67 int wbits
= MAX_WBITS
, ret
= -1;
72 memset(&stream
, 0, sizeof(stream
));
78 stream
.next_out
= dbuf
;
79 stream
.avail_out
= dlen
;
82 /* skip adler32 check if deflate and no dictionary */
83 if (clen
> 2 && !(cbuf
[1] & PRESET_DICT
) &&
84 ((cbuf
[0] & 0x0f) == Z_DEFLATED
) &&
85 !(((cbuf
[0] << 8) + cbuf
[1]) % 31)) {
86 wbits
= -((cbuf
[0] >> 4) + 8);
91 if (Z_OK
!= inflateInit2(&stream
, wbits
))
94 while (stream
.total_in
< clen
) {
95 stream
.next_in
= cbuf
+ stream
.total_in
;
96 stream
.avail_in
= min((u32
) (clen
- stream
.total_in
),
97 (u32
) btrfs_info
.sb
.sectorsize
);
99 ret
= inflate(&stream
, Z_NO_FLUSH
);
104 res
= stream
.total_out
;
107 if (ret
!= Z_STREAM_END
)
113 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
114 #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
116 static u32
decompress_zstd(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
118 ZSTD_DStream
*dstream
;
119 ZSTD_inBuffer in_buf
;
120 ZSTD_outBuffer out_buf
;
125 wsize
= ZSTD_DStreamWorkspaceBound(ZSTD_BTRFS_MAX_INPUT
);
126 workspace
= malloc(wsize
);
128 debug("%s: cannot allocate workspace of size %zu\n", __func__
,
133 dstream
= ZSTD_initDStream(ZSTD_BTRFS_MAX_INPUT
, workspace
, wsize
);
135 printf("%s: ZSTD_initDStream failed\n", __func__
);
150 ret
= ZSTD_decompressStream(dstream
, &out_buf
, &in_buf
);
151 if (ZSTD_isError(ret
)) {
152 printf("%s: ZSTD_decompressStream error %d\n", __func__
,
153 ZSTD_getErrorCode(ret
));
157 if (in_buf
.pos
>= clen
|| !ret
)
168 u32
btrfs_decompress(u8 type
, const char *c
, u32 clen
, char *d
, u32 dlen
)
174 cbuf
= (const u8
*) c
;
178 case BTRFS_COMPRESS_NONE
:
179 res
= dlen
< clen
? dlen
: clen
;
180 memcpy(dbuf
, cbuf
, res
);
182 case BTRFS_COMPRESS_ZLIB
:
183 return decompress_zlib(cbuf
, clen
, dbuf
, dlen
);
184 case BTRFS_COMPRESS_LZO
:
185 return decompress_lzo(cbuf
, clen
, dbuf
, dlen
);
186 case BTRFS_COMPRESS_ZSTD
:
187 return decompress_zstd(cbuf
, clen
, dbuf
, dlen
);
189 printf("%s: Unsupported compression in extent: %i\n", __func__
,