brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 437cd34 Raw
155 lines · c
1// SPDX-License-Identifier: Zlib2 3#include "../zlib_inflate/inflate.h"4#include "dfltcc_util.h"5#include "dfltcc_inflate.h"6#include <asm/setup.h>7#include <linux/export.h>8#include <linux/zutil.h>9 10/*11 * Expand.12 */13int dfltcc_can_inflate(14    z_streamp strm15)16{17    struct inflate_state *state = (struct inflate_state *)strm->state;18    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);19 20    /* Check for kernel dfltcc command line parameter */21    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||22            zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)23        return 0;24 25    /* Unsupported hardware */26    return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&27               is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);28}29EXPORT_SYMBOL(dfltcc_can_inflate);30 31void dfltcc_reset_inflate_state(z_streamp strm) {32    struct inflate_state *state = (struct inflate_state *)strm->state;33    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);34 35    dfltcc_reset_state(dfltcc_state);36}37EXPORT_SYMBOL(dfltcc_reset_inflate_state);38 39static int dfltcc_was_inflate_used(40    z_streamp strm41)42{43    struct inflate_state *state = (struct inflate_state *)strm->state;44    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;45 46    return !param->nt;47}48 49static int dfltcc_inflate_disable(50    z_streamp strm51)52{53    struct inflate_state *state = (struct inflate_state *)strm->state;54    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);55 56    if (!dfltcc_can_inflate(strm))57        return 0;58    if (dfltcc_was_inflate_used(strm))59        /* DFLTCC has already decompressed some data. Since there is not60         * enough information to resume decompression in software, the call61         * must fail.62         */63        return 1;64    /* DFLTCC was not used yet - decompress in software */65    memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));66    return 0;67}68 69static dfltcc_cc dfltcc_xpnd(70    z_streamp strm71)72{73    struct inflate_state *state = (struct inflate_state *)strm->state;74    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;75    size_t avail_in = strm->avail_in;76    size_t avail_out = strm->avail_out;77    dfltcc_cc cc;78 79    cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,80                param, &strm->next_out, &avail_out,81                &strm->next_in, &avail_in, state->window);82    strm->avail_in = avail_in;83    strm->avail_out = avail_out;84    return cc;85}86 87dfltcc_inflate_action dfltcc_inflate(88    z_streamp strm,89    int flush,90    int *ret91)92{93    struct inflate_state *state = (struct inflate_state *)strm->state;94    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);95    struct dfltcc_param_v0 *param = &dfltcc_state->param;96    dfltcc_cc cc;97 98    if (flush == Z_BLOCK || flush == Z_PACKET_FLUSH) {99        /* DFLTCC does not support stopping on block boundaries (Z_BLOCK flush option)100         * as well as the use of Z_PACKET_FLUSH option (used exclusively by PPP driver)101         */102        if (dfltcc_inflate_disable(strm)) {103            *ret = Z_STREAM_ERROR;104            return DFLTCC_INFLATE_BREAK;105        } else106            return DFLTCC_INFLATE_SOFTWARE;107    }108 109    if (state->last) {110        if (state->bits != 0) {111            strm->next_in++;112            strm->avail_in--;113            state->bits = 0;114        }115        state->mode = CHECK;116        return DFLTCC_INFLATE_CONTINUE;117    }118 119    if (strm->avail_in == 0 && !param->cf)120        return DFLTCC_INFLATE_BREAK;121 122    if (!state->window || state->wsize == 0) {123        state->mode = MEM;124        return DFLTCC_INFLATE_CONTINUE;125    }126 127    /* Translate stream to parameter block */128    param->cvt = CVT_ADLER32;129    param->sbb = state->bits;130    if (param->hl)131        param->nt = 0; /* Honor history for the first block */132    param->cv = state->check;133 134    /* Inflate */135    do {136        cc = dfltcc_xpnd(strm);137    } while (cc == DFLTCC_CC_AGAIN);138 139    /* Translate parameter block to stream */140    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);141    state->last = cc == DFLTCC_CC_OK;142    state->bits = param->sbb;143    state->check = param->cv;144    if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {145        /* Report an error if stream is corrupted */146        state->mode = BAD;147        return DFLTCC_INFLATE_CONTINUE;148    }149    state->mode = TYPEDO;150    /* Break if operands are exhausted, otherwise continue looping */151    return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?152        DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;153}154EXPORT_SYMBOL(dfltcc_inflate);155