Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: Zlib
0002 
0003 #include "../zlib_inflate/inflate.h"
0004 #include "dfltcc_util.h"
0005 #include "dfltcc.h"
0006 #include <asm/setup.h>
0007 #include <linux/export.h>
0008 #include <linux/zutil.h>
0009 
0010 /*
0011  * Expand.
0012  */
0013 int dfltcc_can_inflate(
0014     z_streamp strm
0015 )
0016 {
0017     struct inflate_state *state = (struct inflate_state *)strm->state;
0018     struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
0019 
0020     /* Check for kernel dfltcc command line parameter */
0021     if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
0022             zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)
0023         return 0;
0024 
0025     /* Unsupported compression settings */
0026     if (state->wbits != HB_BITS)
0027         return 0;
0028 
0029     /* Unsupported hardware */
0030     return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
0031                is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
0032 }
0033 EXPORT_SYMBOL(dfltcc_can_inflate);
0034 
0035 static int dfltcc_was_inflate_used(
0036     z_streamp strm
0037 )
0038 {
0039     struct inflate_state *state = (struct inflate_state *)strm->state;
0040     struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
0041 
0042     return !param->nt;
0043 }
0044 
0045 static int dfltcc_inflate_disable(
0046     z_streamp strm
0047 )
0048 {
0049     struct inflate_state *state = (struct inflate_state *)strm->state;
0050     struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
0051 
0052     if (!dfltcc_can_inflate(strm))
0053         return 0;
0054     if (dfltcc_was_inflate_used(strm))
0055         /* DFLTCC has already decompressed some data. Since there is not
0056          * enough information to resume decompression in software, the call
0057          * must fail.
0058          */
0059         return 1;
0060     /* DFLTCC was not used yet - decompress in software */
0061     memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
0062     return 0;
0063 }
0064 
0065 static dfltcc_cc dfltcc_xpnd(
0066     z_streamp strm
0067 )
0068 {
0069     struct inflate_state *state = (struct inflate_state *)strm->state;
0070     struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
0071     size_t avail_in = strm->avail_in;
0072     size_t avail_out = strm->avail_out;
0073     dfltcc_cc cc;
0074 
0075     cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
0076                 param, &strm->next_out, &avail_out,
0077                 &strm->next_in, &avail_in, state->window);
0078     strm->avail_in = avail_in;
0079     strm->avail_out = avail_out;
0080     return cc;
0081 }
0082 
0083 dfltcc_inflate_action dfltcc_inflate(
0084     z_streamp strm,
0085     int flush,
0086     int *ret
0087 )
0088 {
0089     struct inflate_state *state = (struct inflate_state *)strm->state;
0090     struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
0091     struct dfltcc_param_v0 *param = &dfltcc_state->param;
0092     dfltcc_cc cc;
0093 
0094     if (flush == Z_BLOCK) {
0095         /* DFLTCC does not support stopping on block boundaries */
0096         if (dfltcc_inflate_disable(strm)) {
0097             *ret = Z_STREAM_ERROR;
0098             return DFLTCC_INFLATE_BREAK;
0099         } else
0100             return DFLTCC_INFLATE_SOFTWARE;
0101     }
0102 
0103     if (state->last) {
0104         if (state->bits != 0) {
0105             strm->next_in++;
0106             strm->avail_in--;
0107             state->bits = 0;
0108         }
0109         state->mode = CHECK;
0110         return DFLTCC_INFLATE_CONTINUE;
0111     }
0112 
0113     if (strm->avail_in == 0 && !param->cf)
0114         return DFLTCC_INFLATE_BREAK;
0115 
0116     if (!state->window || state->wsize == 0) {
0117         state->mode = MEM;
0118         return DFLTCC_INFLATE_CONTINUE;
0119     }
0120 
0121     /* Translate stream to parameter block */
0122     param->cvt = CVT_ADLER32;
0123     param->sbb = state->bits;
0124     param->hl = state->whave; /* Software and hardware history formats match */
0125     param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1);
0126     if (param->hl)
0127         param->nt = 0; /* Honor history for the first block */
0128     param->cv = state->check;
0129 
0130     /* Inflate */
0131     do {
0132         cc = dfltcc_xpnd(strm);
0133     } while (cc == DFLTCC_CC_AGAIN);
0134 
0135     /* Translate parameter block to stream */
0136     strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
0137     state->last = cc == DFLTCC_CC_OK;
0138     state->bits = param->sbb;
0139     state->whave = param->hl;
0140     state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
0141     state->check = param->cv;
0142     if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
0143         /* Report an error if stream is corrupted */
0144         state->mode = BAD;
0145         return DFLTCC_INFLATE_CONTINUE;
0146     }
0147     state->mode = TYPEDO;
0148     /* Break if operands are exhausted, otherwise continue looping */
0149     return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
0150         DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
0151 }
0152 EXPORT_SYMBOL(dfltcc_inflate);