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
cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle,CpaFlatBuffer * pDestBuff,Cpa32U * count)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
cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle,CpaFlatBuffer * pDestBuff,CpaDcRqResults * pRes)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