1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 /* $FreeBSD$ */ 4 /** 5 ***************************************************************************** 6 * @file dc_header_footer.c 7 * 8 * @ingroup Dc_DataCompression 9 * 10 * @description 11 * Implementation of the Data Compression header and footer operations. 12 * 13 *****************************************************************************/ 14 15 /* 16 ******************************************************************************* 17 * Include public/global header files 18 ******************************************************************************* 19 */ 20 #include "cpa.h" 21 #include "cpa_dc.h" 22 #include "icp_adf_init.h" 23 24 /* 25 ******************************************************************************* 26 * Include private header files 27 ******************************************************************************* 28 */ 29 #include "dc_header_footer.h" 30 #include "dc_session.h" 31 #include "dc_datapath.h" 32 33 CpaStatus 34 cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle, 35 CpaFlatBuffer *pDestBuff, 36 Cpa32U *count) 37 { 38 dc_session_desc_t *pSessionDesc = NULL; 39 40 LAC_CHECK_NULL_PARAM(pSessionHandle); 41 LAC_CHECK_NULL_PARAM(pDestBuff); 42 LAC_CHECK_NULL_PARAM(pDestBuff->pData); 43 LAC_CHECK_NULL_PARAM(count); 44 45 pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); 46 47 if (NULL == pSessionDesc) { 48 QAT_UTILS_LOG("Session handle not as expected\n"); 49 return CPA_STATUS_INVALID_PARAM; 50 } 51 52 if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { 53 QAT_UTILS_LOG("Invalid session direction\n"); 54 return CPA_STATUS_INVALID_PARAM; 55 } 56 57 if (CPA_DC_DEFLATE == pSessionDesc->compType) { 58 /* Adding a Gzip header */ 59 if (CPA_DC_CRC32 == pSessionDesc->checksumType) { 60 Cpa8U *pDest = pDestBuff->pData; 61 62 if (pDestBuff->dataLenInBytes < DC_GZIP_HEADER_SIZE) { 63 QAT_UTILS_LOG( 64 "The dataLenInBytes of the dest buffer is too small.\n"); 65 return CPA_STATUS_INVALID_PARAM; 66 } 67 68 pDest[0] = DC_GZIP_ID1; /* ID1 */ 69 pDest[1] = DC_GZIP_ID2; /* ID2 */ 70 pDest[2] = 71 0x08; /* CM = 8 denotes "deflate" compression */ 72 pDest[3] = 0x00; /* FLG = 0 denotes "No extra fields" */ 73 pDest[4] = 0x00; 74 pDest[5] = 0x00; 75 pDest[6] = 0x00; 76 pDest[7] = 0x00; /* MTIME = 0x00 means time stamp not 77 available */ 78 79 /* XFL = 4 - compressor used fastest compression, */ 80 /* XFL = 2 - compressor used maximum compression. */ 81 pDest[8] = 0; 82 if (CPA_DC_L1 == pSessionDesc->compLevel) 83 pDest[8] = DC_GZIP_FAST_COMP; 84 else if (CPA_DC_L4 >= pSessionDesc->compLevel) 85 pDest[8] = DC_GZIP_MAX_COMP; 86 87 pDest[9] = 88 DC_GZIP_FILESYSTYPE; /* OS = 0 means FAT filesystem 89 (MS-DOS, OS/2, NT/Win32), 3 - Unix */ 90 91 /* Set to the number of bytes added to the buffer */ 92 *count = DC_GZIP_HEADER_SIZE; 93 } 94 95 /* Adding a Zlib header */ 96 else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { 97 Cpa8U *pDest = pDestBuff->pData; 98 Cpa16U header = 0, level = 0; 99 100 if (pDestBuff->dataLenInBytes < DC_ZLIB_HEADER_SIZE) { 101 QAT_UTILS_LOG( 102 "The dataLenInBytes of the dest buffer is too small.\n"); 103 return CPA_STATUS_INVALID_PARAM; 104 } 105 106 /* CMF = CM | CMINFO. 107 CM = 8 denotes "deflate" compression, 108 CMINFO = 7 indicates a 32K window size */ 109 /* Depending on the device, at compression levels above 110 L1, the 111 window size can be 8 or 16K bytes. 112 The file will decompress ok if a greater window size 113 is specified 114 in the header. */ 115 header = 116 (DC_ZLIB_CM_DEFLATE + 117 (DC_32K_WINDOW_SIZE << DC_ZLIB_WINDOWSIZE_OFFSET)) 118 << LAC_NUM_BITS_IN_BYTE; 119 120 switch (pSessionDesc->compLevel) { 121 case CPA_DC_L1: 122 level = DC_ZLIB_LEVEL_0; 123 break; 124 case CPA_DC_L2: 125 level = DC_ZLIB_LEVEL_1; 126 break; 127 case CPA_DC_L3: 128 level = DC_ZLIB_LEVEL_2; 129 break; 130 default: 131 level = DC_ZLIB_LEVEL_3; 132 } 133 134 /* Bits 6 - 7: FLEVEL, compression level */ 135 header |= level << DC_ZLIB_FLEVEL_OFFSET; 136 137 /* The header has to be a multiple of 31 */ 138 header += DC_ZLIB_HEADER_OFFSET - 139 (header % DC_ZLIB_HEADER_OFFSET); 140 141 pDest[0] = (Cpa8U)(header >> LAC_NUM_BITS_IN_BYTE); 142 pDest[1] = (Cpa8U)header; 143 144 /* Set to the number of bytes added to the buffer */ 145 *count = DC_ZLIB_HEADER_SIZE; 146 } 147 148 /* If deflate but no checksum required */ 149 else { 150 *count = 0; 151 } 152 } else { 153 /* There is no header for other compressed data */ 154 *count = 0; 155 } 156 return CPA_STATUS_SUCCESS; 157 } 158 159 CpaStatus 160 cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle, 161 CpaFlatBuffer *pDestBuff, 162 CpaDcRqResults *pRes) 163 { 164 dc_session_desc_t *pSessionDesc = NULL; 165 166 LAC_CHECK_NULL_PARAM(pSessionHandle); 167 LAC_CHECK_NULL_PARAM(pDestBuff); 168 LAC_CHECK_NULL_PARAM(pDestBuff->pData); 169 LAC_CHECK_NULL_PARAM(pRes); 170 171 pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); 172 173 if (NULL == pSessionDesc) { 174 QAT_UTILS_LOG("Session handle not as expected\n"); 175 return CPA_STATUS_INVALID_PARAM; 176 } 177 178 if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { 179 QAT_UTILS_LOG("Invalid session direction\n"); 180 return CPA_STATUS_INVALID_PARAM; 181 } 182 183 if (CPA_DC_DEFLATE == pSessionDesc->compType) { 184 if (CPA_DC_CRC32 == pSessionDesc->checksumType) { 185 Cpa8U *pDest = pDestBuff->pData; 186 Cpa32U crc32 = pRes->checksum; 187 Cpa64U totalLenBeforeCompress = 188 pSessionDesc->cumulativeConsumedBytes; 189 190 if (pDestBuff->dataLenInBytes < DC_GZIP_FOOTER_SIZE) { 191 QAT_UTILS_LOG( 192 "The dataLenInBytes of the dest buffer is too small.\n"); 193 return CPA_STATUS_INVALID_PARAM; 194 } 195 196 /* Crc32 of the uncompressed data */ 197 pDest[0] = (Cpa8U)crc32; 198 pDest[1] = (Cpa8U)(crc32 >> LAC_NUM_BITS_IN_BYTE); 199 pDest[2] = (Cpa8U)(crc32 >> 2 * LAC_NUM_BITS_IN_BYTE); 200 pDest[3] = (Cpa8U)(crc32 >> 3 * LAC_NUM_BITS_IN_BYTE); 201 202 /* Length of the uncompressed data */ 203 pDest[4] = (Cpa8U)totalLenBeforeCompress; 204 pDest[5] = (Cpa8U)(totalLenBeforeCompress >> 205 LAC_NUM_BITS_IN_BYTE); 206 pDest[6] = (Cpa8U)(totalLenBeforeCompress >> 207 2 * LAC_NUM_BITS_IN_BYTE); 208 pDest[7] = (Cpa8U)(totalLenBeforeCompress >> 209 3 * LAC_NUM_BITS_IN_BYTE); 210 211 /* Increment produced by the number of bytes added to 212 * the buffer */ 213 pRes->produced += DC_GZIP_FOOTER_SIZE; 214 } else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { 215 Cpa8U *pDest = pDestBuff->pData; 216 Cpa32U adler32 = pRes->checksum; 217 218 if (pDestBuff->dataLenInBytes < DC_ZLIB_FOOTER_SIZE) { 219 QAT_UTILS_LOG( 220 "The dataLenInBytes of the dest buffer is too small.\n"); 221 return CPA_STATUS_INVALID_PARAM; 222 } 223 224 /* Adler32 of the uncompressed data */ 225 pDest[0] = (Cpa8U)(adler32 >> 3 * LAC_NUM_BITS_IN_BYTE); 226 pDest[1] = (Cpa8U)(adler32 >> 2 * LAC_NUM_BITS_IN_BYTE); 227 pDest[2] = (Cpa8U)(adler32 >> LAC_NUM_BITS_IN_BYTE); 228 pDest[3] = (Cpa8U)adler32; 229 230 /* Increment produced by the number of bytes added to 231 * the buffer */ 232 pRes->produced += DC_ZLIB_FOOTER_SIZE; 233 } 234 } 235 236 return CPA_STATUS_SUCCESS; 237 } 238