1 // SPDX-License-Identifier: Zlib
3 #include "../zlib_inflate/inflate.h"
4 #include "dfltcc_util.h"
7 #include <linux/export.h>
8 #include <linux/zutil.h>
13 int dfltcc_can_inflate(
17 struct inflate_state
*state
= (struct inflate_state
*)strm
->state
;
18 struct dfltcc_state
*dfltcc_state
= GET_DFLTCC_STATE(state
);
20 /* Check for kernel dfltcc command line parameter */
21 if (zlib_dfltcc_support
== ZLIB_DFLTCC_DISABLED
||
22 zlib_dfltcc_support
== ZLIB_DFLTCC_DEFLATE_ONLY
)
25 /* Unsupported compression settings */
26 if (state
->wbits
!= HB_BITS
)
29 /* Unsupported hardware */
30 return is_bit_set(dfltcc_state
->af
.fns
, DFLTCC_XPND
) &&
31 is_bit_set(dfltcc_state
->af
.fmts
, DFLTCC_FMT0
);
33 EXPORT_SYMBOL(dfltcc_can_inflate
);
35 static int dfltcc_was_inflate_used(
39 struct inflate_state
*state
= (struct inflate_state
*)strm
->state
;
40 struct dfltcc_param_v0
*param
= &GET_DFLTCC_STATE(state
)->param
;
45 static int dfltcc_inflate_disable(
49 struct inflate_state
*state
= (struct inflate_state
*)strm
->state
;
50 struct dfltcc_state
*dfltcc_state
= GET_DFLTCC_STATE(state
);
52 if (!dfltcc_can_inflate(strm
))
54 if (dfltcc_was_inflate_used(strm
))
55 /* DFLTCC has already decompressed some data. Since there is not
56 * enough information to resume decompression in software, the call
60 /* DFLTCC was not used yet - decompress in software */
61 memset(&dfltcc_state
->af
, 0, sizeof(dfltcc_state
->af
));
65 static dfltcc_cc
dfltcc_xpnd(
69 struct inflate_state
*state
= (struct inflate_state
*)strm
->state
;
70 struct dfltcc_param_v0
*param
= &GET_DFLTCC_STATE(state
)->param
;
71 size_t avail_in
= strm
->avail_in
;
72 size_t avail_out
= strm
->avail_out
;
75 cc
= dfltcc(DFLTCC_XPND
| HBT_CIRCULAR
,
76 param
, &strm
->next_out
, &avail_out
,
77 &strm
->next_in
, &avail_in
, state
->window
);
78 strm
->avail_in
= avail_in
;
79 strm
->avail_out
= avail_out
;
83 dfltcc_inflate_action
dfltcc_inflate(
89 struct inflate_state
*state
= (struct inflate_state
*)strm
->state
;
90 struct dfltcc_state
*dfltcc_state
= GET_DFLTCC_STATE(state
);
91 struct dfltcc_param_v0
*param
= &dfltcc_state
->param
;
94 if (flush
== Z_BLOCK
) {
95 /* DFLTCC does not support stopping on block boundaries */
96 if (dfltcc_inflate_disable(strm
)) {
97 *ret
= Z_STREAM_ERROR
;
98 return DFLTCC_INFLATE_BREAK
;
100 return DFLTCC_INFLATE_SOFTWARE
;
104 if (state
->bits
!= 0) {
110 return DFLTCC_INFLATE_CONTINUE
;
113 if (strm
->avail_in
== 0 && !param
->cf
)
114 return DFLTCC_INFLATE_BREAK
;
116 if (!state
->window
|| state
->wsize
== 0) {
118 return DFLTCC_INFLATE_CONTINUE
;
121 /* Translate stream to parameter block */
122 param
->cvt
= CVT_ADLER32
;
123 param
->sbb
= state
->bits
;
124 param
->hl
= state
->whave
; /* Software and hardware history formats match */
125 param
->ho
= (state
->write
- state
->whave
) & ((1 << HB_BITS
) - 1);
127 param
->nt
= 0; /* Honor history for the first block */
128 param
->cv
= state
->check
;
132 cc
= dfltcc_xpnd(strm
);
133 } while (cc
== DFLTCC_CC_AGAIN
);
135 /* Translate parameter block to stream */
136 strm
->msg
= oesc_msg(dfltcc_state
->msg
, param
->oesc
);
137 state
->last
= cc
== DFLTCC_CC_OK
;
138 state
->bits
= param
->sbb
;
139 state
->whave
= param
->hl
;
140 state
->write
= (param
->ho
+ param
->hl
) & ((1 << HB_BITS
) - 1);
141 state
->check
= param
->cv
;
142 if (cc
== DFLTCC_CC_OP2_CORRUPT
&& param
->oesc
!= 0) {
143 /* Report an error if stream is corrupted */
145 return DFLTCC_INFLATE_CONTINUE
;
147 state
->mode
= TYPEDO
;
148 /* Break if operands are exhausted, otherwise continue looping */
149 return (cc
== DFLTCC_CC_OP1_TOO_SHORT
|| cc
== DFLTCC_CC_OP2_TOO_SHORT
) ?
150 DFLTCC_INFLATE_BREAK
: DFLTCC_INFLATE_CONTINUE
;
152 EXPORT_SYMBOL(dfltcc_inflate
);