178ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
278ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
378ee8d1cSJulian Grajkowski /**
478ee8d1cSJulian Grajkowski  *****************************************************************************
578ee8d1cSJulian Grajkowski  * @file dc_header_footer.c
678ee8d1cSJulian Grajkowski  *
778ee8d1cSJulian Grajkowski  * @ingroup Dc_DataCompression
878ee8d1cSJulian Grajkowski  *
978ee8d1cSJulian Grajkowski  * @description
1078ee8d1cSJulian Grajkowski  *      Implementation of the Data Compression header and footer operations.
1178ee8d1cSJulian Grajkowski  *
1278ee8d1cSJulian Grajkowski  *****************************************************************************/
1378ee8d1cSJulian Grajkowski 
1478ee8d1cSJulian Grajkowski /*
1578ee8d1cSJulian Grajkowski  *******************************************************************************
1678ee8d1cSJulian Grajkowski  * Include public/global header files
1778ee8d1cSJulian Grajkowski  *******************************************************************************
1878ee8d1cSJulian Grajkowski  */
1978ee8d1cSJulian Grajkowski #include "cpa.h"
2078ee8d1cSJulian Grajkowski #include "cpa_dc.h"
2178ee8d1cSJulian Grajkowski #include "icp_adf_init.h"
2278ee8d1cSJulian Grajkowski 
2378ee8d1cSJulian Grajkowski /*
2478ee8d1cSJulian Grajkowski  *******************************************************************************
2578ee8d1cSJulian Grajkowski  * Include private header files
2678ee8d1cSJulian Grajkowski  *******************************************************************************
2778ee8d1cSJulian Grajkowski  */
2878ee8d1cSJulian Grajkowski #include "dc_header_footer.h"
2978ee8d1cSJulian Grajkowski #include "dc_session.h"
3078ee8d1cSJulian Grajkowski #include "dc_datapath.h"
3178ee8d1cSJulian Grajkowski 
3278ee8d1cSJulian Grajkowski CpaStatus
cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle,CpaFlatBuffer * pDestBuff,Cpa32U * count)3378ee8d1cSJulian Grajkowski cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle,
3478ee8d1cSJulian Grajkowski 		    CpaFlatBuffer *pDestBuff,
3578ee8d1cSJulian Grajkowski 		    Cpa32U *count)
3678ee8d1cSJulian Grajkowski {
3778ee8d1cSJulian Grajkowski 	dc_session_desc_t *pSessionDesc = NULL;
3878ee8d1cSJulian Grajkowski 
3978ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pSessionHandle);
4078ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pDestBuff);
4178ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pDestBuff->pData);
4278ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(count);
4378ee8d1cSJulian Grajkowski 
4478ee8d1cSJulian Grajkowski 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
4578ee8d1cSJulian Grajkowski 
4678ee8d1cSJulian Grajkowski 	if (NULL == pSessionDesc) {
4778ee8d1cSJulian Grajkowski 		QAT_UTILS_LOG("Session handle not as expected\n");
4878ee8d1cSJulian Grajkowski 		return CPA_STATUS_INVALID_PARAM;
4978ee8d1cSJulian Grajkowski 	}
5078ee8d1cSJulian Grajkowski 
5178ee8d1cSJulian Grajkowski 	if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
5278ee8d1cSJulian Grajkowski 		QAT_UTILS_LOG("Invalid session direction\n");
5378ee8d1cSJulian Grajkowski 		return CPA_STATUS_INVALID_PARAM;
5478ee8d1cSJulian Grajkowski 	}
5578ee8d1cSJulian Grajkowski 
5678ee8d1cSJulian Grajkowski 	if (CPA_DC_DEFLATE == pSessionDesc->compType) {
5778ee8d1cSJulian Grajkowski 		/* Adding a Gzip header */
5878ee8d1cSJulian Grajkowski 		if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
5978ee8d1cSJulian Grajkowski 			Cpa8U *pDest = pDestBuff->pData;
6078ee8d1cSJulian Grajkowski 
6178ee8d1cSJulian Grajkowski 			if (pDestBuff->dataLenInBytes < DC_GZIP_HEADER_SIZE) {
6278ee8d1cSJulian Grajkowski 				QAT_UTILS_LOG(
6378ee8d1cSJulian Grajkowski 				    "The dataLenInBytes of the dest buffer is too small.\n");
6478ee8d1cSJulian Grajkowski 				return CPA_STATUS_INVALID_PARAM;
6578ee8d1cSJulian Grajkowski 			}
6678ee8d1cSJulian Grajkowski 
6778ee8d1cSJulian Grajkowski 			pDest[0] = DC_GZIP_ID1; /* ID1 */
6878ee8d1cSJulian Grajkowski 			pDest[1] = DC_GZIP_ID2; /* ID2 */
6978ee8d1cSJulian Grajkowski 			pDest[2] =
7078ee8d1cSJulian Grajkowski 			    0x08; /* CM = 8 denotes "deflate" compression */
7178ee8d1cSJulian Grajkowski 			pDest[3] = 0x00; /* FLG = 0 denotes "No extra fields" */
7278ee8d1cSJulian Grajkowski 			pDest[4] = 0x00;
7378ee8d1cSJulian Grajkowski 			pDest[5] = 0x00;
7478ee8d1cSJulian Grajkowski 			pDest[6] = 0x00;
7578ee8d1cSJulian Grajkowski 			pDest[7] = 0x00; /* MTIME = 0x00 means time stamp not
7678ee8d1cSJulian Grajkowski 					    available */
7778ee8d1cSJulian Grajkowski 
7878ee8d1cSJulian Grajkowski 			/* XFL = 4 - compressor used fastest compression, */
7978ee8d1cSJulian Grajkowski 			/* XFL = 2 - compressor used maximum compression. */
8078ee8d1cSJulian Grajkowski 			pDest[8] = 0;
8178ee8d1cSJulian Grajkowski 			if (CPA_DC_L1 == pSessionDesc->compLevel)
8278ee8d1cSJulian Grajkowski 				pDest[8] = DC_GZIP_FAST_COMP;
8378ee8d1cSJulian Grajkowski 			else if (CPA_DC_L4 >= pSessionDesc->compLevel)
8478ee8d1cSJulian Grajkowski 				pDest[8] = DC_GZIP_MAX_COMP;
8578ee8d1cSJulian Grajkowski 
8678ee8d1cSJulian Grajkowski 			pDest[9] =
8778ee8d1cSJulian Grajkowski 			    DC_GZIP_FILESYSTYPE; /* OS = 0 means FAT filesystem
8878ee8d1cSJulian Grajkowski 				  (MS-DOS, OS/2, NT/Win32), 3 - Unix */
8978ee8d1cSJulian Grajkowski 
9078ee8d1cSJulian Grajkowski 			/* Set to the number of bytes added to the buffer */
9178ee8d1cSJulian Grajkowski 			*count = DC_GZIP_HEADER_SIZE;
9278ee8d1cSJulian Grajkowski 		}
9378ee8d1cSJulian Grajkowski 
9478ee8d1cSJulian Grajkowski 		/* Adding a Zlib header */
9578ee8d1cSJulian Grajkowski 		else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
9678ee8d1cSJulian Grajkowski 			Cpa8U *pDest = pDestBuff->pData;
9778ee8d1cSJulian Grajkowski 			Cpa16U header = 0, level = 0;
9878ee8d1cSJulian Grajkowski 
9978ee8d1cSJulian Grajkowski 			if (pDestBuff->dataLenInBytes < DC_ZLIB_HEADER_SIZE) {
10078ee8d1cSJulian Grajkowski 				QAT_UTILS_LOG(
10178ee8d1cSJulian Grajkowski 				    "The dataLenInBytes of the dest buffer is too small.\n");
10278ee8d1cSJulian Grajkowski 				return CPA_STATUS_INVALID_PARAM;
10378ee8d1cSJulian Grajkowski 			}
10478ee8d1cSJulian Grajkowski 
10578ee8d1cSJulian Grajkowski 			/*  CMF = CM | CMINFO.
10678ee8d1cSJulian Grajkowski 			    CM = 8 denotes "deflate" compression,
10778ee8d1cSJulian Grajkowski 			    CMINFO = 7 indicates a 32K window size */
10878ee8d1cSJulian Grajkowski 			/* Depending on the device, at compression levels above
10978ee8d1cSJulian Grajkowski 			   L1, the
11078ee8d1cSJulian Grajkowski 			   window size can be 8 or 16K bytes.
11178ee8d1cSJulian Grajkowski 			   The file will decompress ok if a greater window size
11278ee8d1cSJulian Grajkowski 			   is specified
11378ee8d1cSJulian Grajkowski 			   in the header. */
11478ee8d1cSJulian Grajkowski 			header =
11578ee8d1cSJulian Grajkowski 			    (DC_ZLIB_CM_DEFLATE +
11678ee8d1cSJulian Grajkowski 			     (DC_32K_WINDOW_SIZE << DC_ZLIB_WINDOWSIZE_OFFSET))
11778ee8d1cSJulian Grajkowski 			    << LAC_NUM_BITS_IN_BYTE;
11878ee8d1cSJulian Grajkowski 
11978ee8d1cSJulian Grajkowski 			switch (pSessionDesc->compLevel) {
12078ee8d1cSJulian Grajkowski 			case CPA_DC_L1:
12178ee8d1cSJulian Grajkowski 				level = DC_ZLIB_LEVEL_0;
12278ee8d1cSJulian Grajkowski 				break;
12378ee8d1cSJulian Grajkowski 			case CPA_DC_L2:
12478ee8d1cSJulian Grajkowski 				level = DC_ZLIB_LEVEL_1;
12578ee8d1cSJulian Grajkowski 				break;
12678ee8d1cSJulian Grajkowski 			case CPA_DC_L3:
12778ee8d1cSJulian Grajkowski 				level = DC_ZLIB_LEVEL_2;
12878ee8d1cSJulian Grajkowski 				break;
12978ee8d1cSJulian Grajkowski 			default:
13078ee8d1cSJulian Grajkowski 				level = DC_ZLIB_LEVEL_3;
13178ee8d1cSJulian Grajkowski 			}
13278ee8d1cSJulian Grajkowski 
13378ee8d1cSJulian Grajkowski 			/* Bits 6 - 7: FLEVEL, compression level */
13478ee8d1cSJulian Grajkowski 			header |= level << DC_ZLIB_FLEVEL_OFFSET;
13578ee8d1cSJulian Grajkowski 
13678ee8d1cSJulian Grajkowski 			/* The header has to be a multiple of 31 */
13778ee8d1cSJulian Grajkowski 			header += DC_ZLIB_HEADER_OFFSET -
13878ee8d1cSJulian Grajkowski 			    (header % DC_ZLIB_HEADER_OFFSET);
13978ee8d1cSJulian Grajkowski 
14078ee8d1cSJulian Grajkowski 			pDest[0] = (Cpa8U)(header >> LAC_NUM_BITS_IN_BYTE);
14178ee8d1cSJulian Grajkowski 			pDest[1] = (Cpa8U)header;
14278ee8d1cSJulian Grajkowski 
14378ee8d1cSJulian Grajkowski 			/* Set to the number of bytes added to the buffer */
14478ee8d1cSJulian Grajkowski 			*count = DC_ZLIB_HEADER_SIZE;
14578ee8d1cSJulian Grajkowski 		}
14678ee8d1cSJulian Grajkowski 
14778ee8d1cSJulian Grajkowski 		/* If deflate but no checksum required */
14878ee8d1cSJulian Grajkowski 		else {
14978ee8d1cSJulian Grajkowski 			*count = 0;
15078ee8d1cSJulian Grajkowski 		}
15178ee8d1cSJulian Grajkowski 	} else {
15278ee8d1cSJulian Grajkowski 		/* There is no header for other compressed data */
15378ee8d1cSJulian Grajkowski 		*count = 0;
15478ee8d1cSJulian Grajkowski 	}
15578ee8d1cSJulian Grajkowski 	return CPA_STATUS_SUCCESS;
15678ee8d1cSJulian Grajkowski }
15778ee8d1cSJulian Grajkowski 
15878ee8d1cSJulian Grajkowski CpaStatus
cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle,CpaFlatBuffer * pDestBuff,CpaDcRqResults * pRes)15978ee8d1cSJulian Grajkowski cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle,
16078ee8d1cSJulian Grajkowski 		    CpaFlatBuffer *pDestBuff,
16178ee8d1cSJulian Grajkowski 		    CpaDcRqResults *pRes)
16278ee8d1cSJulian Grajkowski {
16378ee8d1cSJulian Grajkowski 	dc_session_desc_t *pSessionDesc = NULL;
16478ee8d1cSJulian Grajkowski 
16578ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pSessionHandle);
16678ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pDestBuff);
16778ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pDestBuff->pData);
16878ee8d1cSJulian Grajkowski 	LAC_CHECK_NULL_PARAM(pRes);
16978ee8d1cSJulian Grajkowski 
17078ee8d1cSJulian Grajkowski 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
17178ee8d1cSJulian Grajkowski 
17278ee8d1cSJulian Grajkowski 	if (NULL == pSessionDesc) {
17378ee8d1cSJulian Grajkowski 		QAT_UTILS_LOG("Session handle not as expected\n");
17478ee8d1cSJulian Grajkowski 		return CPA_STATUS_INVALID_PARAM;
17578ee8d1cSJulian Grajkowski 	}
17678ee8d1cSJulian Grajkowski 
17778ee8d1cSJulian Grajkowski 	if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
17878ee8d1cSJulian Grajkowski 		QAT_UTILS_LOG("Invalid session direction\n");
17978ee8d1cSJulian Grajkowski 		return CPA_STATUS_INVALID_PARAM;
18078ee8d1cSJulian Grajkowski 	}
18178ee8d1cSJulian Grajkowski 
18278ee8d1cSJulian Grajkowski 	if (CPA_DC_DEFLATE == pSessionDesc->compType) {
18378ee8d1cSJulian Grajkowski 		if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
18478ee8d1cSJulian Grajkowski 			Cpa8U *pDest = pDestBuff->pData;
18578ee8d1cSJulian Grajkowski 			Cpa32U crc32 = pRes->checksum;
18678ee8d1cSJulian Grajkowski 			Cpa64U totalLenBeforeCompress =
18778ee8d1cSJulian Grajkowski 			    pSessionDesc->cumulativeConsumedBytes;
18878ee8d1cSJulian Grajkowski 
18978ee8d1cSJulian Grajkowski 			if (pDestBuff->dataLenInBytes < DC_GZIP_FOOTER_SIZE) {
19078ee8d1cSJulian Grajkowski 				QAT_UTILS_LOG(
19178ee8d1cSJulian Grajkowski 				    "The dataLenInBytes of the dest buffer is too small.\n");
19278ee8d1cSJulian Grajkowski 				return CPA_STATUS_INVALID_PARAM;
19378ee8d1cSJulian Grajkowski 			}
19478ee8d1cSJulian Grajkowski 
19578ee8d1cSJulian Grajkowski 			/* Crc32 of the uncompressed data */
19678ee8d1cSJulian Grajkowski 			pDest[0] = (Cpa8U)crc32;
19778ee8d1cSJulian Grajkowski 			pDest[1] = (Cpa8U)(crc32 >> LAC_NUM_BITS_IN_BYTE);
19878ee8d1cSJulian Grajkowski 			pDest[2] = (Cpa8U)(crc32 >> 2 * LAC_NUM_BITS_IN_BYTE);
19978ee8d1cSJulian Grajkowski 			pDest[3] = (Cpa8U)(crc32 >> 3 * LAC_NUM_BITS_IN_BYTE);
20078ee8d1cSJulian Grajkowski 
20178ee8d1cSJulian Grajkowski 			/* Length of the uncompressed data */
20278ee8d1cSJulian Grajkowski 			pDest[4] = (Cpa8U)totalLenBeforeCompress;
20378ee8d1cSJulian Grajkowski 			pDest[5] = (Cpa8U)(totalLenBeforeCompress >>
20478ee8d1cSJulian Grajkowski 					   LAC_NUM_BITS_IN_BYTE);
20578ee8d1cSJulian Grajkowski 			pDest[6] = (Cpa8U)(totalLenBeforeCompress >>
20678ee8d1cSJulian Grajkowski 					   2 * LAC_NUM_BITS_IN_BYTE);
20778ee8d1cSJulian Grajkowski 			pDest[7] = (Cpa8U)(totalLenBeforeCompress >>
20878ee8d1cSJulian Grajkowski 					   3 * LAC_NUM_BITS_IN_BYTE);
20978ee8d1cSJulian Grajkowski 
21078ee8d1cSJulian Grajkowski 			/* Increment produced by the number of bytes added to
21178ee8d1cSJulian Grajkowski 			 * the buffer */
21278ee8d1cSJulian Grajkowski 			pRes->produced += DC_GZIP_FOOTER_SIZE;
21378ee8d1cSJulian Grajkowski 		} else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
21478ee8d1cSJulian Grajkowski 			Cpa8U *pDest = pDestBuff->pData;
21578ee8d1cSJulian Grajkowski 			Cpa32U adler32 = pRes->checksum;
21678ee8d1cSJulian Grajkowski 
21778ee8d1cSJulian Grajkowski 			if (pDestBuff->dataLenInBytes < DC_ZLIB_FOOTER_SIZE) {
21878ee8d1cSJulian Grajkowski 				QAT_UTILS_LOG(
21978ee8d1cSJulian Grajkowski 				    "The dataLenInBytes of the dest buffer is too small.\n");
22078ee8d1cSJulian Grajkowski 				return CPA_STATUS_INVALID_PARAM;
22178ee8d1cSJulian Grajkowski 			}
22278ee8d1cSJulian Grajkowski 
22378ee8d1cSJulian Grajkowski 			/* Adler32 of the uncompressed data */
22478ee8d1cSJulian Grajkowski 			pDest[0] = (Cpa8U)(adler32 >> 3 * LAC_NUM_BITS_IN_BYTE);
22578ee8d1cSJulian Grajkowski 			pDest[1] = (Cpa8U)(adler32 >> 2 * LAC_NUM_BITS_IN_BYTE);
22678ee8d1cSJulian Grajkowski 			pDest[2] = (Cpa8U)(adler32 >> LAC_NUM_BITS_IN_BYTE);
22778ee8d1cSJulian Grajkowski 			pDest[3] = (Cpa8U)adler32;
22878ee8d1cSJulian Grajkowski 
22978ee8d1cSJulian Grajkowski 			/* Increment produced by the number of bytes added to
23078ee8d1cSJulian Grajkowski 			 * the buffer */
23178ee8d1cSJulian Grajkowski 			pRes->produced += DC_ZLIB_FOOTER_SIZE;
23278ee8d1cSJulian Grajkowski 		}
23378ee8d1cSJulian Grajkowski 	}
23478ee8d1cSJulian Grajkowski 
23578ee8d1cSJulian Grajkowski 	return CPA_STATUS_SUCCESS;
23678ee8d1cSJulian Grajkowski }
237