2020-01-31 09:16:23 +03:00
// SPDX-License-Identifier: Zlib
# include "../zlib_inflate/inflate.h"
# include "dfltcc_util.h"
# include "dfltcc.h"
2020-01-31 09:16:27 +03:00
# include <asm/setup.h>
2020-12-06 09:14:38 +03:00
# include <linux/export.h>
2020-01-31 09:16:23 +03:00
# include <linux/zutil.h>
/*
* Expand .
*/
int dfltcc_can_inflate (
z_streamp strm
)
{
struct inflate_state * state = ( struct inflate_state * ) strm - > state ;
struct dfltcc_state * dfltcc_state = GET_DFLTCC_STATE ( state ) ;
2020-01-31 09:16:27 +03:00
/* Check for kernel dfltcc command line parameter */
if ( zlib_dfltcc_support = = ZLIB_DFLTCC_DISABLED | |
zlib_dfltcc_support = = ZLIB_DFLTCC_DEFLATE_ONLY )
return 0 ;
2020-01-31 09:16:23 +03:00
/* Unsupported compression settings */
if ( state - > wbits ! = HB_BITS )
return 0 ;
/* Unsupported hardware */
return is_bit_set ( dfltcc_state - > af . fns , DFLTCC_XPND ) & &
is_bit_set ( dfltcc_state - > af . fmts , DFLTCC_FMT0 ) ;
}
2020-12-06 09:14:38 +03:00
EXPORT_SYMBOL ( dfltcc_can_inflate ) ;
2020-01-31 09:16:23 +03:00
static int dfltcc_was_inflate_used (
z_streamp strm
)
{
struct inflate_state * state = ( struct inflate_state * ) strm - > state ;
struct dfltcc_param_v0 * param = & GET_DFLTCC_STATE ( state ) - > param ;
return ! param - > nt ;
}
static int dfltcc_inflate_disable (
z_streamp strm
)
{
struct inflate_state * state = ( struct inflate_state * ) strm - > state ;
struct dfltcc_state * dfltcc_state = GET_DFLTCC_STATE ( state ) ;
if ( ! dfltcc_can_inflate ( strm ) )
return 0 ;
if ( dfltcc_was_inflate_used ( strm ) )
/* DFLTCC has already decompressed some data. Since there is not
* enough information to resume decompression in software , the call
* must fail .
*/
return 1 ;
/* DFLTCC was not used yet - decompress in software */
memset ( & dfltcc_state - > af , 0 , sizeof ( dfltcc_state - > af ) ) ;
return 0 ;
}
static dfltcc_cc dfltcc_xpnd (
z_streamp strm
)
{
struct inflate_state * state = ( struct inflate_state * ) strm - > state ;
struct dfltcc_param_v0 * param = & GET_DFLTCC_STATE ( state ) - > param ;
size_t avail_in = strm - > avail_in ;
size_t avail_out = strm - > avail_out ;
dfltcc_cc cc ;
cc = dfltcc ( DFLTCC_XPND | HBT_CIRCULAR ,
param , & strm - > next_out , & avail_out ,
& strm - > next_in , & avail_in , state - > window ) ;
strm - > avail_in = avail_in ;
strm - > avail_out = avail_out ;
return cc ;
}
dfltcc_inflate_action dfltcc_inflate (
z_streamp strm ,
int flush ,
int * ret
)
{
struct inflate_state * state = ( struct inflate_state * ) strm - > state ;
struct dfltcc_state * dfltcc_state = GET_DFLTCC_STATE ( state ) ;
struct dfltcc_param_v0 * param = & dfltcc_state - > param ;
dfltcc_cc cc ;
if ( flush = = Z_BLOCK ) {
/* DFLTCC does not support stopping on block boundaries */
if ( dfltcc_inflate_disable ( strm ) ) {
* ret = Z_STREAM_ERROR ;
return DFLTCC_INFLATE_BREAK ;
} else
return DFLTCC_INFLATE_SOFTWARE ;
}
if ( state - > last ) {
if ( state - > bits ! = 0 ) {
strm - > next_in + + ;
strm - > avail_in - - ;
state - > bits = 0 ;
}
state - > mode = CHECK ;
return DFLTCC_INFLATE_CONTINUE ;
}
if ( strm - > avail_in = = 0 & & ! param - > cf )
return DFLTCC_INFLATE_BREAK ;
if ( ! state - > window | | state - > wsize = = 0 ) {
state - > mode = MEM ;
return DFLTCC_INFLATE_CONTINUE ;
}
/* Translate stream to parameter block */
param - > cvt = CVT_ADLER32 ;
param - > sbb = state - > bits ;
param - > hl = state - > whave ; /* Software and hardware history formats match */
param - > ho = ( state - > write - state - > whave ) & ( ( 1 < < HB_BITS ) - 1 ) ;
if ( param - > hl )
param - > nt = 0 ; /* Honor history for the first block */
2020-12-30 02:15:01 +03:00
param - > cv = state - > check ;
2020-01-31 09:16:23 +03:00
/* Inflate */
do {
cc = dfltcc_xpnd ( strm ) ;
} while ( cc = = DFLTCC_CC_AGAIN ) ;
/* Translate parameter block to stream */
strm - > msg = oesc_msg ( dfltcc_state - > msg , param - > oesc ) ;
state - > last = cc = = DFLTCC_CC_OK ;
state - > bits = param - > sbb ;
state - > whave = param - > hl ;
state - > write = ( param - > ho + param - > hl ) & ( ( 1 < < HB_BITS ) - 1 ) ;
2020-12-30 02:15:01 +03:00
state - > check = param - > cv ;
2020-01-31 09:16:23 +03:00
if ( cc = = DFLTCC_CC_OP2_CORRUPT & & param - > oesc ! = 0 ) {
/* Report an error if stream is corrupted */
state - > mode = BAD ;
return DFLTCC_INFLATE_CONTINUE ;
}
state - > mode = TYPEDO ;
/* Break if operands are exhausted, otherwise continue looping */
return ( cc = = DFLTCC_CC_OP1_TOO_SHORT | | cc = = DFLTCC_CC_OP2_TOO_SHORT ) ?
DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE ;
}
2020-12-06 09:14:38 +03:00
EXPORT_SYMBOL ( dfltcc_inflate ) ;