]>
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 BehĂșn, CZ.NIC, kabel@kernel.org
12 #include <linux/lzo.h>
13 #include <linux/zstd.h>
14 #include <linux/compat.h>
15 #include <u-boot/zlib.h>
16 #include <asm/unaligned.h>
18 /* Header for each segment, LE32, recording the compressed size */
20 static u32
decompress_lzo(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
22 u32 tot_len
, tot_in
, in_len
, res
;
29 tot_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
36 if (tot_len
== 0 && dlen
)
38 if (tot_len
< LZO_LEN
)
43 while (tot_len
> LZO_LEN
) {
46 in_len
= le32_to_cpu(get_unaligned((u32
*)cbuf
));
50 if (in_len
> clen
|| tot_len
< LZO_LEN
+ in_len
)
53 tot_len
-= (LZO_LEN
+ in_len
);
54 tot_in
+= (LZO_LEN
+ in_len
);
57 ret
= lzo1x_decompress_safe(cbuf
, in_len
, dbuf
, &out_len
);
69 * If the 4 bytes header does not fit to the rest of the page we
70 * have to move to next one, or we read some garbage.
72 rem_page
= PAGE_SIZE
- (tot_in
% PAGE_SIZE
);
73 if (rem_page
< LZO_LEN
) {
85 #define PRESET_DICT 0x20
87 static u32
decompress_zlib(const u8
*_cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
89 int wbits
= MAX_WBITS
, ret
= -1;
94 memset(&stream
, 0, sizeof(stream
));
100 stream
.next_out
= dbuf
;
101 stream
.avail_out
= dlen
;
102 stream
.total_out
= 0;
104 /* skip adler32 check if deflate and no dictionary */
105 if (clen
> 2 && !(cbuf
[1] & PRESET_DICT
) &&
106 ((cbuf
[0] & 0x0f) == Z_DEFLATED
) &&
107 !(((cbuf
[0] << 8) + cbuf
[1]) % 31)) {
108 wbits
= -((cbuf
[0] >> 4) + 8);
113 if (Z_OK
!= inflateInit2(&stream
, wbits
))
116 while (stream
.total_in
< clen
) {
117 stream
.next_in
= cbuf
+ stream
.total_in
;
118 stream
.avail_in
= min((u32
) (clen
- stream
.total_in
),
119 current_fs_info
->sectorsize
);
121 ret
= inflate(&stream
, Z_NO_FLUSH
);
126 res
= stream
.total_out
;
129 if (ret
!= Z_STREAM_END
)
135 #define ZSTD_BTRFS_MAX_WINDOWLOG 17
136 #define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
138 static u32
decompress_zstd(const u8
*cbuf
, u32 clen
, u8
*dbuf
, u32 dlen
)
142 abuf_init_set(&in
, (u8
*)cbuf
, clen
);
143 abuf_init_set(&out
, dbuf
, dlen
);
145 return zstd_decompress(&in
, &out
);
148 u32
btrfs_decompress(u8 type
, const char *c
, u32 clen
, char *d
, u32 dlen
)
154 cbuf
= (const u8
*) c
;
158 case BTRFS_COMPRESS_NONE
:
159 res
= dlen
< clen
? dlen
: clen
;
160 memcpy(dbuf
, cbuf
, res
);
162 case BTRFS_COMPRESS_ZLIB
:
163 return decompress_zlib(cbuf
, clen
, dbuf
, dlen
);
164 case BTRFS_COMPRESS_LZO
:
165 return decompress_lzo(cbuf
, clen
, dbuf
, dlen
);
166 case BTRFS_COMPRESS_ZSTD
:
167 return decompress_zstd(cbuf
, clen
, dbuf
, dlen
);
169 printf("%s: Unsupported compression in extent: %i\n", __func__
,