1 // SPDX-License-Identifier: Zlib 2 3 #include "../zlib_deflate/defutil.h" 4 #include "dfltcc_util.h" 5 #include "dfltcc_deflate.h" 6 #include <asm/setup.h> 7 #include <linux/export.h> 8 #include <linux/zutil.h> 9 10 #define GET_DFLTCC_DEFLATE_STATE(state) ((struct dfltcc_deflate_state *)GET_DFLTCC_STATE(state)) 11 12 /* 13 * Compress. 14 */ 15 int dfltcc_can_deflate( 16 z_streamp strm 17 ) 18 { 19 deflate_state *state = (deflate_state *)strm->state; 20 struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); 21 22 /* Check for kernel dfltcc command line parameter */ 23 if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED || 24 zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY) 25 return 0; 26 27 /* Unsupported compression settings */ 28 if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy, 29 dfltcc_state->level_mask)) 30 return 0; 31 32 /* Unsupported hardware */ 33 if (!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_GDHT) || 34 !is_bit_set(dfltcc_state->common.af.fns, DFLTCC_CMPR) || 35 !is_bit_set(dfltcc_state->common.af.fmts, DFLTCC_FMT0)) 36 return 0; 37 38 return 1; 39 } 40 EXPORT_SYMBOL(dfltcc_can_deflate); 41 42 void dfltcc_reset_deflate_state(z_streamp strm) { 43 deflate_state *state = (deflate_state *)strm->state; 44 struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); 45 46 dfltcc_reset_state(&dfltcc_state->common); 47 48 /* Initialize tuning parameters */ 49 if (zlib_dfltcc_support == ZLIB_DFLTCC_FULL_DEBUG) 50 dfltcc_state->level_mask = DFLTCC_LEVEL_MASK_DEBUG; 51 else 52 dfltcc_state->level_mask = DFLTCC_LEVEL_MASK; 53 dfltcc_state->block_size = DFLTCC_BLOCK_SIZE; 54 dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE; 55 dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE; 56 } 57 EXPORT_SYMBOL(dfltcc_reset_deflate_state); 58 59 static void dfltcc_gdht( 60 z_streamp strm 61 ) 62 { 63 deflate_state *state = (deflate_state *)strm->state; 64 struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; 65 size_t avail_in = strm->avail_in; 66 67 dfltcc(DFLTCC_GDHT, 68 param, NULL, NULL, 69 &strm->next_in, &avail_in, NULL); 70 } 71 72 static dfltcc_cc dfltcc_cmpr( 73 z_streamp strm 74 ) 75 { 76 deflate_state *state = (deflate_state *)strm->state; 77 struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; 78 size_t avail_in = strm->avail_in; 79 size_t avail_out = strm->avail_out; 80 dfltcc_cc cc; 81 82 cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR, 83 param, &strm->next_out, &avail_out, 84 &strm->next_in, &avail_in, state->window); 85 strm->total_in += (strm->avail_in - avail_in); 86 strm->total_out += (strm->avail_out - avail_out); 87 strm->avail_in = avail_in; 88 strm->avail_out = avail_out; 89 return cc; 90 } 91 92 static void send_eobs( 93 z_streamp strm, 94 const struct dfltcc_param_v0 *param 95 ) 96 { 97 deflate_state *state = (deflate_state *)strm->state; 98 99 zlib_tr_send_bits( 100 state, 101 bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), 102 param->eobl); 103 flush_pending(strm); 104 if (state->pending != 0) { 105 /* The remaining data is located in pending_out[0:pending]. If someone 106 * calls put_byte() - this might happen in deflate() - the byte will be 107 * placed into pending_buf[pending], which is incorrect. Move the 108 * remaining data to the beginning of pending_buf so that put_byte() is 109 * usable again. 110 */ 111 memmove(state->pending_buf, state->pending_out, state->pending); 112 state->pending_out = state->pending_buf; 113 } 114 #ifdef ZLIB_DEBUG 115 state->compressed_len += param->eobl; 116 #endif 117 } 118 119 int dfltcc_deflate( 120 z_streamp strm, 121 int flush, 122 block_state *result 123 ) 124 { 125 deflate_state *state = (deflate_state *)strm->state; 126 struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); 127 struct dfltcc_param_v0 *param = &dfltcc_state->common.param; 128 uInt masked_avail_in; 129 dfltcc_cc cc; 130 int need_empty_block; 131 int soft_bcc; 132 int no_flush; 133 134 if (!dfltcc_can_deflate(strm)) { 135 /* Clear history. */ 136 if (flush == Z_FULL_FLUSH) 137 param->hl = 0; 138 return 0; 139 } 140 141 again: 142 masked_avail_in = 0; 143 soft_bcc = 0; 144 no_flush = flush == Z_NO_FLUSH; 145 146 /* No input data. Return, except when Continuation Flag is set, which means 147 * that DFLTCC has buffered some output in the parameter block and needs to 148 * be called again in order to flush it. 149 */ 150 if (strm->avail_in == 0 && !param->cf) { 151 /* A block is still open, and the hardware does not support closing 152 * blocks without adding data. Thus, close it manually. 153 */ 154 if (!no_flush && param->bcf) { 155 send_eobs(strm, param); 156 param->bcf = 0; 157 } 158 /* Let one of deflate_* functions write a trailing empty block. */ 159 if (flush == Z_FINISH) 160 return 0; 161 /* Clear history. */ 162 if (flush == Z_FULL_FLUSH) 163 param->hl = 0; 164 /* Trigger block post-processing if necessary. */ 165 *result = no_flush ? need_more : block_done; 166 return 1; 167 } 168 169 /* There is an open non-BFINAL block, we are not going to close it just 170 * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see 171 * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new 172 * DHT in order to adapt to a possibly changed input data distribution. 173 */ 174 if (param->bcf && no_flush && 175 strm->total_in > dfltcc_state->block_threshold && 176 strm->avail_in >= dfltcc_state->dht_threshold) { 177 if (param->cf) { 178 /* We need to flush the DFLTCC buffer before writing the 179 * End-of-block Symbol. Mask the input data and proceed as usual. 180 */ 181 masked_avail_in += strm->avail_in; 182 strm->avail_in = 0; 183 no_flush = 0; 184 } else { 185 /* DFLTCC buffer is empty, so we can manually write the 186 * End-of-block Symbol right away. 187 */ 188 send_eobs(strm, param); 189 param->bcf = 0; 190 dfltcc_state->block_threshold = 191 strm->total_in + dfltcc_state->block_size; 192 } 193 } 194 195 /* No space for compressed data. If we proceed, dfltcc_cmpr() will return 196 * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still 197 * set BCF=1, which is wrong. Avoid complications and return early. 198 */ 199 if (strm->avail_out == 0) { 200 *result = need_more; 201 return 1; 202 } 203 204 /* The caller gave us too much data. Pass only one block worth of 205 * uncompressed data to DFLTCC and mask the rest, so that on the next 206 * iteration we start a new block. 207 */ 208 if (no_flush && strm->avail_in > dfltcc_state->block_size) { 209 masked_avail_in += (strm->avail_in - dfltcc_state->block_size); 210 strm->avail_in = dfltcc_state->block_size; 211 } 212 213 /* When we have an open non-BFINAL deflate block and caller indicates that 214 * the stream is ending, we need to close an open deflate block and open a 215 * BFINAL one. 216 */ 217 need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf; 218 219 /* Translate stream to parameter block */ 220 param->cvt = CVT_ADLER32; 221 if (!no_flush) 222 /* We need to close a block. Always do this in software - when there is 223 * no input data, the hardware will not hohor BCC. */ 224 soft_bcc = 1; 225 if (flush == Z_FINISH && !param->bcf) 226 /* We are about to open a BFINAL block, set Block Header Final bit 227 * until the stream ends. 228 */ 229 param->bhf = 1; 230 /* DFLTCC-CMPR will write to next_out, so make sure that buffers with 231 * higher precedence are empty. 232 */ 233 Assert(state->pending == 0, "There must be no pending bytes"); 234 Assert(state->bi_valid < 8, "There must be less than 8 pending bits"); 235 param->sbb = (unsigned int)state->bi_valid; 236 if (param->sbb > 0) 237 *strm->next_out = (Byte)state->bi_buf; 238 /* Honor history and check value */ 239 param->nt = 0; 240 param->cv = strm->adler; 241 242 /* When opening a block, choose a Huffman-Table Type */ 243 if (!param->bcf) { 244 if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) { 245 param->htt = HTT_FIXED; 246 } 247 else { 248 param->htt = HTT_DYNAMIC; 249 dfltcc_gdht(strm); 250 } 251 } 252 253 /* Deflate */ 254 do { 255 cc = dfltcc_cmpr(strm); 256 if (strm->avail_in < 4096 && masked_avail_in > 0) 257 /* We are about to call DFLTCC with a small input buffer, which is 258 * inefficient. Since there is masked data, there will be at least 259 * one more DFLTCC call, so skip the current one and make the next 260 * one handle more data. 261 */ 262 break; 263 } while (cc == DFLTCC_CC_AGAIN); 264 265 /* Translate parameter block to stream */ 266 strm->msg = oesc_msg(dfltcc_state->common.msg, param->oesc); 267 state->bi_valid = param->sbb; 268 if (state->bi_valid == 0) 269 state->bi_buf = 0; /* Avoid accessing next_out */ 270 else 271 state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1); 272 strm->adler = param->cv; 273 274 /* Unmask the input data */ 275 strm->avail_in += masked_avail_in; 276 masked_avail_in = 0; 277 278 /* If we encounter an error, it means there is a bug in DFLTCC call */ 279 Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG"); 280 281 /* Update Block-Continuation Flag. It will be used to check whether to call 282 * GDHT the next time. 283 */ 284 if (cc == DFLTCC_CC_OK) { 285 if (soft_bcc) { 286 send_eobs(strm, param); 287 param->bcf = 0; 288 dfltcc_state->block_threshold = 289 strm->total_in + dfltcc_state->block_size; 290 } else 291 param->bcf = 1; 292 if (flush == Z_FINISH) { 293 if (need_empty_block) 294 /* Make the current deflate() call also close the stream */ 295 return 0; 296 else { 297 bi_windup(state); 298 *result = finish_done; 299 } 300 } else { 301 if (flush == Z_FULL_FLUSH) 302 param->hl = 0; /* Clear history */ 303 *result = flush == Z_NO_FLUSH ? need_more : block_done; 304 } 305 } else { 306 param->bcf = 1; 307 *result = need_more; 308 } 309 if (strm->avail_in != 0 && strm->avail_out != 0) 310 goto again; /* deflate() must use all input or all output */ 311 return 1; 312 } 313 EXPORT_SYMBOL(dfltcc_deflate); 314
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.