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