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