1f856f099SNavdeep Parhar /*
2f856f099SNavdeep Parhar FastLZ - lightning-fast lossless compression library
3f856f099SNavdeep Parhar
4f856f099SNavdeep Parhar Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
5f856f099SNavdeep Parhar Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
6f856f099SNavdeep Parhar Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
7f856f099SNavdeep Parhar
8f856f099SNavdeep Parhar Permission is hereby granted, free of charge, to any person obtaining a copy
9f856f099SNavdeep Parhar of this software and associated documentation files (the "Software"), to deal
10f856f099SNavdeep Parhar in the Software without restriction, including without limitation the rights
11f856f099SNavdeep Parhar to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12f856f099SNavdeep Parhar copies of the Software, and to permit persons to whom the Software is
13f856f099SNavdeep Parhar furnished to do so, subject to the following conditions:
14f856f099SNavdeep Parhar
15f856f099SNavdeep Parhar The above copyright notice and this permission notice shall be included in
16f856f099SNavdeep Parhar all copies or substantial portions of the Software.
17f856f099SNavdeep Parhar
18f856f099SNavdeep Parhar THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19f856f099SNavdeep Parhar IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20f856f099SNavdeep Parhar FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21f856f099SNavdeep Parhar AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22f856f099SNavdeep Parhar LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23f856f099SNavdeep Parhar OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24f856f099SNavdeep Parhar THE SOFTWARE.
25f856f099SNavdeep Parhar */
26f856f099SNavdeep Parhar #include <sys/cdefs.h>
27f856f099SNavdeep Parhar #include "osdep.h"
28f856f099SNavdeep Parhar #include "cudbg.h"
29f856f099SNavdeep Parhar #include "cudbg_lib_common.h"
30f856f099SNavdeep Parhar #include "fastlz.h"
31f856f099SNavdeep Parhar
32f856f099SNavdeep Parhar static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10};
33f856f099SNavdeep Parhar
34f856f099SNavdeep Parhar #define CUDBG_BLOCK_SIZE (63*1024)
35f856f099SNavdeep Parhar #define CUDBG_CHUNK_BUF_LEN 16
36f856f099SNavdeep Parhar #define CUDBG_MIN_COMPR_LEN 32 /*min data length for applying compression*/
37f856f099SNavdeep Parhar
38f856f099SNavdeep Parhar /* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */
39f856f099SNavdeep Parhar
40f856f099SNavdeep Parhar #define ADLER32_BASE 65521
41f856f099SNavdeep Parhar
update_adler32(unsigned long checksum,const void * buf,int len)42f856f099SNavdeep Parhar static inline unsigned long update_adler32(unsigned long checksum,
43f856f099SNavdeep Parhar const void *buf, int len)
44f856f099SNavdeep Parhar {
45f856f099SNavdeep Parhar const unsigned char *ptr = (const unsigned char *)buf;
46f856f099SNavdeep Parhar unsigned long s1 = checksum & 0xffff;
47f856f099SNavdeep Parhar unsigned long s2 = (checksum >> 16) & 0xffff;
48f856f099SNavdeep Parhar
49f856f099SNavdeep Parhar while (len > 0) {
50f856f099SNavdeep Parhar unsigned k = len < 5552 ? len : 5552;
51f856f099SNavdeep Parhar len -= k;
52f856f099SNavdeep Parhar
53f856f099SNavdeep Parhar while (k >= 8) {
54f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
55f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
56f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
57f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
58f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
59f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
60f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
61f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
62f856f099SNavdeep Parhar k -= 8;
63f856f099SNavdeep Parhar }
64f856f099SNavdeep Parhar
65f856f099SNavdeep Parhar while (k-- > 0) {
66f856f099SNavdeep Parhar s1 += *ptr++; s2 += s1;
67f856f099SNavdeep Parhar }
68f856f099SNavdeep Parhar s1 = s1 % ADLER32_BASE;
69f856f099SNavdeep Parhar s2 = s2 % ADLER32_BASE;
70f856f099SNavdeep Parhar }
71f856f099SNavdeep Parhar return (s2 << 16) + s1;
72f856f099SNavdeep Parhar }
73f856f099SNavdeep Parhar
write_magic(struct cudbg_buffer * _out_buff)74f856f099SNavdeep Parhar int write_magic(struct cudbg_buffer *_out_buff)
75f856f099SNavdeep Parhar {
76f856f099SNavdeep Parhar int rc;
77f856f099SNavdeep Parhar
78f856f099SNavdeep Parhar rc = write_to_buf(_out_buff->data, _out_buff->size, &_out_buff->offset,
79f856f099SNavdeep Parhar sixpack_magic, 8);
80f856f099SNavdeep Parhar
81f856f099SNavdeep Parhar return rc;
82f856f099SNavdeep Parhar }
83f856f099SNavdeep Parhar
write_to_buf(void * out_buf,u32 out_buf_size,u32 * offset,void * in_buf,u32 in_buf_size)84f856f099SNavdeep Parhar int write_to_buf(void *out_buf, u32 out_buf_size, u32 *offset, void *in_buf,
85f856f099SNavdeep Parhar u32 in_buf_size)
86f856f099SNavdeep Parhar {
87f856f099SNavdeep Parhar int rc = 0;
88f856f099SNavdeep Parhar
89f856f099SNavdeep Parhar if (*offset >= out_buf_size) {
90f856f099SNavdeep Parhar rc = CUDBG_STATUS_OUTBUFF_OVERFLOW;
91f856f099SNavdeep Parhar goto err;
92f856f099SNavdeep Parhar }
93f856f099SNavdeep Parhar
94f856f099SNavdeep Parhar memcpy((char *)out_buf + *offset, in_buf, in_buf_size);
95f856f099SNavdeep Parhar *offset = *offset + in_buf_size;
96f856f099SNavdeep Parhar
97f856f099SNavdeep Parhar err:
98f856f099SNavdeep Parhar return rc;
99f856f099SNavdeep Parhar }
100f856f099SNavdeep Parhar
read_from_buf(void * in_buf,u32 in_buf_size,u32 * offset,void * out_buf,u32 out_buf_size)101f856f099SNavdeep Parhar int read_from_buf(void *in_buf, u32 in_buf_size, u32 *offset, void *out_buf,
102f856f099SNavdeep Parhar u32 out_buf_size)
103f856f099SNavdeep Parhar {
104f856f099SNavdeep Parhar if (in_buf_size - *offset < out_buf_size)
105f856f099SNavdeep Parhar return 0;
106f856f099SNavdeep Parhar
107f856f099SNavdeep Parhar memcpy((char *)out_buf, (char *)in_buf + *offset, out_buf_size);
108f856f099SNavdeep Parhar *offset = *offset + out_buf_size;
109f856f099SNavdeep Parhar return out_buf_size;
110f856f099SNavdeep Parhar }
111f856f099SNavdeep Parhar
write_chunk_header(struct cudbg_buffer * _outbuf,int id,int options,unsigned long size,unsigned long checksum,unsigned long extra)112f856f099SNavdeep Parhar int write_chunk_header(struct cudbg_buffer *_outbuf, int id, int options,
113f856f099SNavdeep Parhar unsigned long size, unsigned long checksum,
114f856f099SNavdeep Parhar unsigned long extra)
115f856f099SNavdeep Parhar {
116f856f099SNavdeep Parhar unsigned char buffer[CUDBG_CHUNK_BUF_LEN];
117f856f099SNavdeep Parhar int rc = 0;
118f856f099SNavdeep Parhar
119f856f099SNavdeep Parhar buffer[0] = id & 255;
120f856f099SNavdeep Parhar buffer[1] = (unsigned char)(id >> 8);
121f856f099SNavdeep Parhar buffer[2] = options & 255;
122f856f099SNavdeep Parhar buffer[3] = (unsigned char)(options >> 8);
123f856f099SNavdeep Parhar buffer[4] = size & 255;
124f856f099SNavdeep Parhar buffer[5] = (size >> 8) & 255;
125f856f099SNavdeep Parhar buffer[6] = (size >> 16) & 255;
126f856f099SNavdeep Parhar buffer[7] = (size >> 24) & 255;
127f856f099SNavdeep Parhar buffer[8] = checksum & 255;
128f856f099SNavdeep Parhar buffer[9] = (checksum >> 8) & 255;
129f856f099SNavdeep Parhar buffer[10] = (checksum >> 16) & 255;
130f856f099SNavdeep Parhar buffer[11] = (checksum >> 24) & 255;
131f856f099SNavdeep Parhar buffer[12] = extra & 255;
132f856f099SNavdeep Parhar buffer[13] = (extra >> 8) & 255;
133f856f099SNavdeep Parhar buffer[14] = (extra >> 16) & 255;
134f856f099SNavdeep Parhar buffer[15] = (extra >> 24) & 255;
135f856f099SNavdeep Parhar
136f856f099SNavdeep Parhar rc = write_to_buf(_outbuf->data, _outbuf->size, &_outbuf->offset,
137f856f099SNavdeep Parhar buffer, 16);
138f856f099SNavdeep Parhar
139f856f099SNavdeep Parhar return rc;
140f856f099SNavdeep Parhar }
141f856f099SNavdeep Parhar
write_compression_hdr(struct cudbg_buffer * pin_buff,struct cudbg_buffer * pout_buff)142f856f099SNavdeep Parhar int write_compression_hdr(struct cudbg_buffer *pin_buff,
143f856f099SNavdeep Parhar struct cudbg_buffer *pout_buff)
144f856f099SNavdeep Parhar {
145f856f099SNavdeep Parhar struct cudbg_buffer tmp_buffer;
146f856f099SNavdeep Parhar unsigned long fsize = pin_buff->size;
147f856f099SNavdeep Parhar unsigned char *buffer;
148f856f099SNavdeep Parhar unsigned long checksum;
149f856f099SNavdeep Parhar int rc;
150f856f099SNavdeep Parhar char *shown_name = "abc";
151f856f099SNavdeep Parhar
152f856f099SNavdeep Parhar /* Always release inner scratch buffer, before releasing outer. */
153f856f099SNavdeep Parhar rc = get_scratch_buff(pout_buff, 10, &tmp_buffer);
154f856f099SNavdeep Parhar
155f856f099SNavdeep Parhar if (rc)
156f856f099SNavdeep Parhar goto err;
157f856f099SNavdeep Parhar
158f856f099SNavdeep Parhar buffer = (unsigned char *)tmp_buffer.data;
159f856f099SNavdeep Parhar
160f856f099SNavdeep Parhar rc = write_magic(pout_buff);
161f856f099SNavdeep Parhar
162f856f099SNavdeep Parhar if (rc)
163f856f099SNavdeep Parhar goto err1;
164f856f099SNavdeep Parhar
165f856f099SNavdeep Parhar /* chunk for File Entry */
166f856f099SNavdeep Parhar buffer[0] = fsize & 255;
167f856f099SNavdeep Parhar buffer[1] = (fsize >> 8) & 255;
168f856f099SNavdeep Parhar buffer[2] = (fsize >> 16) & 255;
169f856f099SNavdeep Parhar buffer[3] = (fsize >> 24) & 255;
170f856f099SNavdeep Parhar buffer[4] = 0;
171f856f099SNavdeep Parhar buffer[5] = 0;
172f856f099SNavdeep Parhar buffer[6] = 0;
173f856f099SNavdeep Parhar buffer[7] = 0;
174f856f099SNavdeep Parhar buffer[8] = (strlen(shown_name)+1) & 255;
175f856f099SNavdeep Parhar buffer[9] = (unsigned char)((strlen(shown_name)+1) >> 8);
176f856f099SNavdeep Parhar checksum = 1L;
177f856f099SNavdeep Parhar checksum = update_adler32(checksum, buffer, 10);
178f856f099SNavdeep Parhar checksum = update_adler32(checksum, shown_name,
179f856f099SNavdeep Parhar (int)strlen(shown_name)+1);
180f856f099SNavdeep Parhar
181f856f099SNavdeep Parhar rc = write_chunk_header(pout_buff, 1, 0,
182f856f099SNavdeep Parhar 10+(unsigned long)strlen(shown_name)+1,
183f856f099SNavdeep Parhar checksum, 0);
184f856f099SNavdeep Parhar
185f856f099SNavdeep Parhar if (rc)
186f856f099SNavdeep Parhar goto err1;
187f856f099SNavdeep Parhar
188f856f099SNavdeep Parhar rc = write_to_buf(pout_buff->data, pout_buff->size,
189f856f099SNavdeep Parhar &(pout_buff->offset), buffer, 10);
190f856f099SNavdeep Parhar
191f856f099SNavdeep Parhar if (rc)
192f856f099SNavdeep Parhar goto err1;
193f856f099SNavdeep Parhar
194f856f099SNavdeep Parhar rc = write_to_buf(pout_buff->data, pout_buff->size,
195f856f099SNavdeep Parhar &(pout_buff->offset), shown_name,
196f856f099SNavdeep Parhar (u32)strlen(shown_name)+1);
197f856f099SNavdeep Parhar
198f856f099SNavdeep Parhar if (rc)
199f856f099SNavdeep Parhar goto err1;
200f856f099SNavdeep Parhar
201f856f099SNavdeep Parhar err1:
202f856f099SNavdeep Parhar release_scratch_buff(&tmp_buffer, pout_buff);
203f856f099SNavdeep Parhar err:
204f856f099SNavdeep Parhar return rc;
205f856f099SNavdeep Parhar }
206f856f099SNavdeep Parhar
compress_buff(struct cudbg_buffer * pin_buff,struct cudbg_buffer * pout_buff)207f856f099SNavdeep Parhar int compress_buff(struct cudbg_buffer *pin_buff, struct cudbg_buffer *pout_buff)
208f856f099SNavdeep Parhar {
209f856f099SNavdeep Parhar struct cudbg_buffer tmp_buffer;
210f856f099SNavdeep Parhar struct cudbg_hdr *cudbg_hdr;
211f856f099SNavdeep Parhar unsigned long checksum;
212f856f099SNavdeep Parhar unsigned char *result;
213f856f099SNavdeep Parhar unsigned int bytes_read;
214f856f099SNavdeep Parhar int chunk_size, level = 2, rc = 0;
215f856f099SNavdeep Parhar int compress_method = 1;
216f856f099SNavdeep Parhar
217f856f099SNavdeep Parhar bytes_read = pin_buff->size;
218f856f099SNavdeep Parhar rc = get_scratch_buff(pout_buff, CUDBG_BLOCK_SIZE, &tmp_buffer);
219f856f099SNavdeep Parhar
220f856f099SNavdeep Parhar if (rc)
221f856f099SNavdeep Parhar goto err;
222f856f099SNavdeep Parhar
223f856f099SNavdeep Parhar result = (unsigned char *)tmp_buffer.data;
224f856f099SNavdeep Parhar
225f856f099SNavdeep Parhar if (bytes_read < 32)
226f856f099SNavdeep Parhar compress_method = 0;
227f856f099SNavdeep Parhar
228f856f099SNavdeep Parhar cudbg_hdr = (struct cudbg_hdr *) pout_buff->data;
229f856f099SNavdeep Parhar
230f856f099SNavdeep Parhar switch (compress_method) {
231f856f099SNavdeep Parhar case 1:
232f856f099SNavdeep Parhar chunk_size = fastlz_compress_level(level, pin_buff->data,
233f856f099SNavdeep Parhar bytes_read, result);
234f856f099SNavdeep Parhar
235f856f099SNavdeep Parhar checksum = update_adler32(1L, result, chunk_size);
236f856f099SNavdeep Parhar
237f856f099SNavdeep Parhar if ((chunk_size > 62000) && (cudbg_hdr->reserved[7] < (u32)
238f856f099SNavdeep Parhar chunk_size)) /* 64512 */
239f856f099SNavdeep Parhar cudbg_hdr->reserved[7] = (u32) chunk_size;
240f856f099SNavdeep Parhar
241f856f099SNavdeep Parhar rc = write_chunk_header(pout_buff, 17, 1, chunk_size, checksum,
242f856f099SNavdeep Parhar bytes_read);
243f856f099SNavdeep Parhar
244f856f099SNavdeep Parhar if (rc)
245f856f099SNavdeep Parhar goto err_put_buff;
246f856f099SNavdeep Parhar
247f856f099SNavdeep Parhar rc = write_to_buf(pout_buff->data, pout_buff->size,
248f856f099SNavdeep Parhar &pout_buff->offset, result, chunk_size);
249f856f099SNavdeep Parhar
250f856f099SNavdeep Parhar if (rc)
251f856f099SNavdeep Parhar goto err_put_buff;
252f856f099SNavdeep Parhar
253f856f099SNavdeep Parhar break;
254f856f099SNavdeep Parhar
255f856f099SNavdeep Parhar /* uncompressed, also fallback method */
256f856f099SNavdeep Parhar case 0:
257f856f099SNavdeep Parhar default:
258f856f099SNavdeep Parhar checksum = update_adler32(1L, pin_buff->data, bytes_read);
259f856f099SNavdeep Parhar
260f856f099SNavdeep Parhar rc = write_chunk_header(pout_buff, 17, 0, bytes_read, checksum,
261f856f099SNavdeep Parhar bytes_read);
262f856f099SNavdeep Parhar
263f856f099SNavdeep Parhar if (rc)
264f856f099SNavdeep Parhar goto err_put_buff;
265f856f099SNavdeep Parhar
266f856f099SNavdeep Parhar rc = write_to_buf(pout_buff->data, pout_buff->size,
267f856f099SNavdeep Parhar &pout_buff->offset, pin_buff->data,
268f856f099SNavdeep Parhar bytes_read);
269f856f099SNavdeep Parhar if (rc)
270f856f099SNavdeep Parhar goto err_put_buff;
271f856f099SNavdeep Parhar
272f856f099SNavdeep Parhar break;
273f856f099SNavdeep Parhar }
274f856f099SNavdeep Parhar
275f856f099SNavdeep Parhar err_put_buff:
276f856f099SNavdeep Parhar release_scratch_buff(&tmp_buffer, pout_buff);
277f856f099SNavdeep Parhar err:
278f856f099SNavdeep Parhar return rc;
279f856f099SNavdeep Parhar }
280f856f099SNavdeep Parhar
281f856f099SNavdeep Parhar /* return non-zero if magic sequence is detected */
282f856f099SNavdeep Parhar /* warning: reset the read pointer to the beginning of the file */
detect_magic(struct cudbg_buffer * _c_buff)283f856f099SNavdeep Parhar int detect_magic(struct cudbg_buffer *_c_buff)
284f856f099SNavdeep Parhar {
285f856f099SNavdeep Parhar unsigned char buffer[8];
286f856f099SNavdeep Parhar size_t bytes_read;
287f856f099SNavdeep Parhar int c;
288f856f099SNavdeep Parhar
289f856f099SNavdeep Parhar bytes_read = read_from_buf(_c_buff->data, _c_buff->size,
290f856f099SNavdeep Parhar &_c_buff->offset, buffer, 8);
291f856f099SNavdeep Parhar
292f856f099SNavdeep Parhar if (bytes_read < 8)
293f856f099SNavdeep Parhar return 0;
294f856f099SNavdeep Parhar
295f856f099SNavdeep Parhar for (c = 0; c < 8; c++)
296f856f099SNavdeep Parhar if (buffer[c] != sixpack_magic[c])
297f856f099SNavdeep Parhar return 0;
298f856f099SNavdeep Parhar
299f856f099SNavdeep Parhar return -1;
300f856f099SNavdeep Parhar }
301f856f099SNavdeep Parhar
readU16(const unsigned char * ptr)302f856f099SNavdeep Parhar static inline unsigned long readU16(const unsigned char *ptr)
303f856f099SNavdeep Parhar {
304f856f099SNavdeep Parhar return ptr[0]+(ptr[1]<<8);
305f856f099SNavdeep Parhar }
306f856f099SNavdeep Parhar
readU32(const unsigned char * ptr)307f856f099SNavdeep Parhar static inline unsigned long readU32(const unsigned char *ptr)
308f856f099SNavdeep Parhar {
309f856f099SNavdeep Parhar return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
310f856f099SNavdeep Parhar }
311f856f099SNavdeep Parhar
read_chunk_header(struct cudbg_buffer * pc_buff,int * pid,int * poptions,unsigned long * psize,unsigned long * pchecksum,unsigned long * pextra)312f856f099SNavdeep Parhar int read_chunk_header(struct cudbg_buffer *pc_buff, int *pid, int *poptions,
313f856f099SNavdeep Parhar unsigned long *psize, unsigned long *pchecksum,
314f856f099SNavdeep Parhar unsigned long *pextra)
315f856f099SNavdeep Parhar {
316f856f099SNavdeep Parhar unsigned char buffer[CUDBG_CHUNK_BUF_LEN];
317f856f099SNavdeep Parhar int byte_r = read_from_buf(pc_buff->data, pc_buff->size,
318f856f099SNavdeep Parhar &pc_buff->offset, buffer, 16);
319f856f099SNavdeep Parhar if (byte_r == 0)
320f856f099SNavdeep Parhar return 0;
321f856f099SNavdeep Parhar
322f856f099SNavdeep Parhar *pid = readU16(buffer) & 0xffff;
323f856f099SNavdeep Parhar *poptions = readU16(buffer+2) & 0xffff;
324f856f099SNavdeep Parhar *psize = readU32(buffer+4) & 0xffffffff;
325f856f099SNavdeep Parhar *pchecksum = readU32(buffer+8) & 0xffffffff;
326f856f099SNavdeep Parhar *pextra = readU32(buffer+12) & 0xffffffff;
327f856f099SNavdeep Parhar return 0;
328f856f099SNavdeep Parhar }
329f856f099SNavdeep Parhar
validate_buffer(struct cudbg_buffer * compressed_buffer)330f856f099SNavdeep Parhar int validate_buffer(struct cudbg_buffer *compressed_buffer)
331f856f099SNavdeep Parhar {
332f856f099SNavdeep Parhar if (!detect_magic(compressed_buffer))
333f856f099SNavdeep Parhar return CUDBG_STATUS_INVALID_BUFF;
334f856f099SNavdeep Parhar
335f856f099SNavdeep Parhar return 0;
336f856f099SNavdeep Parhar }
337f856f099SNavdeep Parhar
decompress_buffer(struct cudbg_buffer * pc_buff,struct cudbg_buffer * pd_buff)338f856f099SNavdeep Parhar int decompress_buffer(struct cudbg_buffer *pc_buff,
339f856f099SNavdeep Parhar struct cudbg_buffer *pd_buff)
340f856f099SNavdeep Parhar {
341f856f099SNavdeep Parhar struct cudbg_buffer tmp_compressed_buffer;
342f856f099SNavdeep Parhar struct cudbg_buffer tmp_decompressed_buffer;
343f856f099SNavdeep Parhar unsigned char *compressed_buffer;
344f856f099SNavdeep Parhar unsigned char *decompressed_buffer;
345f856f099SNavdeep Parhar unsigned char buffer[CUDBG_MIN_COMPR_LEN];
346f856f099SNavdeep Parhar unsigned long chunk_size;
347f856f099SNavdeep Parhar unsigned long chunk_checksum;
348f856f099SNavdeep Parhar unsigned long chunk_extra;
349f856f099SNavdeep Parhar unsigned long checksum;
350f856f099SNavdeep Parhar unsigned long r;
351f856f099SNavdeep Parhar unsigned long remaining;
352f856f099SNavdeep Parhar unsigned long bytes_read;
353f856f099SNavdeep Parhar u32 decompressed_size = 0;
354f856f099SNavdeep Parhar int chunk_id, chunk_options, rc;
355f856f099SNavdeep Parhar
356f856f099SNavdeep Parhar if (pd_buff->size < 2 * CUDBG_BLOCK_SIZE)
357f856f099SNavdeep Parhar return CUDBG_STATUS_SMALL_BUFF;
358f856f099SNavdeep Parhar
359f856f099SNavdeep Parhar rc = get_scratch_buff(pd_buff, CUDBG_BLOCK_SIZE,
360f856f099SNavdeep Parhar &tmp_compressed_buffer);
361f856f099SNavdeep Parhar
362f856f099SNavdeep Parhar if (rc)
363f856f099SNavdeep Parhar goto err_cbuff;
364f856f099SNavdeep Parhar
365f856f099SNavdeep Parhar rc = get_scratch_buff(pd_buff, CUDBG_BLOCK_SIZE,
366f856f099SNavdeep Parhar &tmp_decompressed_buffer);
367f856f099SNavdeep Parhar if (rc)
368f856f099SNavdeep Parhar goto err_dcbuff;
369f856f099SNavdeep Parhar
370f856f099SNavdeep Parhar compressed_buffer = (unsigned char *)tmp_compressed_buffer.data;
371f856f099SNavdeep Parhar decompressed_buffer = (unsigned char *)tmp_decompressed_buffer.data;
372f856f099SNavdeep Parhar
373f856f099SNavdeep Parhar /* main loop */
374f856f099SNavdeep Parhar
375f856f099SNavdeep Parhar for (;;) {
376f856f099SNavdeep Parhar if (pc_buff->offset > pc_buff->size)
377f856f099SNavdeep Parhar break;
378f856f099SNavdeep Parhar
379f856f099SNavdeep Parhar rc = read_chunk_header(pc_buff, &chunk_id, &chunk_options,
380f856f099SNavdeep Parhar &chunk_size, &chunk_checksum,
381f856f099SNavdeep Parhar &chunk_extra);
382f856f099SNavdeep Parhar if (rc != 0)
383f856f099SNavdeep Parhar break;
384f856f099SNavdeep Parhar
385f856f099SNavdeep Parhar /* skip 8+16 */
386f856f099SNavdeep Parhar if ((chunk_id == 1) && (chunk_size > 10) &&
387f856f099SNavdeep Parhar (chunk_size < CUDBG_BLOCK_SIZE)) {
388f856f099SNavdeep Parhar
389f856f099SNavdeep Parhar bytes_read = read_from_buf(pc_buff->data, pc_buff->size,
390f856f099SNavdeep Parhar &pc_buff->offset, buffer,
391f856f099SNavdeep Parhar chunk_size);
392f856f099SNavdeep Parhar
393f856f099SNavdeep Parhar if (bytes_read == 0)
394f856f099SNavdeep Parhar return 0;
395f856f099SNavdeep Parhar
396f856f099SNavdeep Parhar checksum = update_adler32(1L, buffer, chunk_size);
397f856f099SNavdeep Parhar if (checksum != chunk_checksum)
398f856f099SNavdeep Parhar return CUDBG_STATUS_CHKSUM_MISSMATCH;
399f856f099SNavdeep Parhar
400f856f099SNavdeep Parhar decompressed_size = (u32)readU32(buffer);
401f856f099SNavdeep Parhar
402f856f099SNavdeep Parhar if (pd_buff->size < decompressed_size) {
403f856f099SNavdeep Parhar
404f856f099SNavdeep Parhar pd_buff->size = 2 * CUDBG_BLOCK_SIZE +
405f856f099SNavdeep Parhar decompressed_size;
406f856f099SNavdeep Parhar pc_buff->offset -= chunk_size + 16;
407f856f099SNavdeep Parhar return CUDBG_STATUS_SMALL_BUFF;
408f856f099SNavdeep Parhar }
409f856f099SNavdeep Parhar }
410f856f099SNavdeep Parhar
411f856f099SNavdeep Parhar if (chunk_size > CUDBG_BLOCK_SIZE) {
412f856f099SNavdeep Parhar /* Release old allocated memory */
413f856f099SNavdeep Parhar release_scratch_buff(&tmp_decompressed_buffer, pd_buff);
414f856f099SNavdeep Parhar release_scratch_buff(&tmp_compressed_buffer, pd_buff);
415f856f099SNavdeep Parhar
416f856f099SNavdeep Parhar /* allocate new memory with chunk_size size */
417f856f099SNavdeep Parhar rc = get_scratch_buff(pd_buff, chunk_size,
418f856f099SNavdeep Parhar &tmp_compressed_buffer);
419f856f099SNavdeep Parhar if (rc)
420f856f099SNavdeep Parhar goto err_cbuff;
421f856f099SNavdeep Parhar
422f856f099SNavdeep Parhar rc = get_scratch_buff(pd_buff, chunk_size,
423f856f099SNavdeep Parhar &tmp_decompressed_buffer);
424f856f099SNavdeep Parhar if (rc)
425f856f099SNavdeep Parhar goto err_dcbuff;
426f856f099SNavdeep Parhar
427f856f099SNavdeep Parhar compressed_buffer = (unsigned char *)tmp_compressed_buffer.data;
428f856f099SNavdeep Parhar decompressed_buffer = (unsigned char *)tmp_decompressed_buffer.data;
429f856f099SNavdeep Parhar }
430f856f099SNavdeep Parhar
431f856f099SNavdeep Parhar if ((chunk_id == 17) && decompressed_size) {
432f856f099SNavdeep Parhar /* uncompressed */
433f856f099SNavdeep Parhar switch (chunk_options) {
434f856f099SNavdeep Parhar /* stored, simply copy to output */
435f856f099SNavdeep Parhar case 0:
436f856f099SNavdeep Parhar remaining = chunk_size;
437f856f099SNavdeep Parhar checksum = 1L;
438f856f099SNavdeep Parhar for (;;) {
439*5bdf58e1SGordon Bergling /* Write a function for this */
440f856f099SNavdeep Parhar r = (CUDBG_BLOCK_SIZE < remaining) ?
441f856f099SNavdeep Parhar CUDBG_BLOCK_SIZE : remaining;
442f856f099SNavdeep Parhar bytes_read =
443f856f099SNavdeep Parhar read_from_buf(pc_buff->data,
444f856f099SNavdeep Parhar pc_buff->size,
445f856f099SNavdeep Parhar &pc_buff->offset, buffer,
446f856f099SNavdeep Parhar r);
447f856f099SNavdeep Parhar
448f856f099SNavdeep Parhar if (bytes_read == 0)
449f856f099SNavdeep Parhar return 0;
450f856f099SNavdeep Parhar
451f856f099SNavdeep Parhar write_to_buf(pd_buff->data,
452f856f099SNavdeep Parhar pd_buff->size,
453f856f099SNavdeep Parhar &pd_buff->offset, buffer,
454f856f099SNavdeep Parhar bytes_read);
455f856f099SNavdeep Parhar checksum = update_adler32(checksum,
456f856f099SNavdeep Parhar buffer,
457f856f099SNavdeep Parhar bytes_read);
458f856f099SNavdeep Parhar remaining -= bytes_read;
459f856f099SNavdeep Parhar
460f856f099SNavdeep Parhar /* verify everything is written
461f856f099SNavdeep Parhar * correctly */
462f856f099SNavdeep Parhar if (checksum != chunk_checksum)
463f856f099SNavdeep Parhar return
464f856f099SNavdeep Parhar CUDBG_STATUS_CHKSUM_MISSMATCH;
465f856f099SNavdeep Parhar }
466f856f099SNavdeep Parhar
467f856f099SNavdeep Parhar break;
468f856f099SNavdeep Parhar
469f856f099SNavdeep Parhar /* compressed using FastLZ */
470f856f099SNavdeep Parhar case 1:
471f856f099SNavdeep Parhar bytes_read = read_from_buf(pc_buff->data,
472f856f099SNavdeep Parhar pc_buff->size,
473f856f099SNavdeep Parhar &pc_buff->offset,
474f856f099SNavdeep Parhar compressed_buffer,
475f856f099SNavdeep Parhar chunk_size);
476f856f099SNavdeep Parhar
477f856f099SNavdeep Parhar if (bytes_read == 0)
478f856f099SNavdeep Parhar return 0;
479f856f099SNavdeep Parhar
480f856f099SNavdeep Parhar checksum = update_adler32(1L, compressed_buffer,
481f856f099SNavdeep Parhar chunk_size);
482f856f099SNavdeep Parhar
483f856f099SNavdeep Parhar /* verify that the chunk data is correct */
484f856f099SNavdeep Parhar if (checksum != chunk_checksum) {
485f856f099SNavdeep Parhar return CUDBG_STATUS_CHKSUM_MISSMATCH;
486f856f099SNavdeep Parhar } else {
487f856f099SNavdeep Parhar /* decompress and verify */
488f856f099SNavdeep Parhar remaining =
489f856f099SNavdeep Parhar fastlz_decompress(compressed_buffer,
490f856f099SNavdeep Parhar chunk_size,
491f856f099SNavdeep Parhar decompressed_buffer,
492f856f099SNavdeep Parhar chunk_extra);
493f856f099SNavdeep Parhar
494f856f099SNavdeep Parhar if (remaining != chunk_extra) {
495f856f099SNavdeep Parhar rc =
496f856f099SNavdeep Parhar CUDBG_STATUS_DECOMPRESS_FAIL;
497f856f099SNavdeep Parhar goto err;
498f856f099SNavdeep Parhar } else {
499f856f099SNavdeep Parhar write_to_buf(pd_buff->data,
500f856f099SNavdeep Parhar pd_buff->size,
501f856f099SNavdeep Parhar &pd_buff->offset,
502f856f099SNavdeep Parhar decompressed_buffer,
503f856f099SNavdeep Parhar chunk_extra);
504f856f099SNavdeep Parhar }
505f856f099SNavdeep Parhar }
506f856f099SNavdeep Parhar break;
507f856f099SNavdeep Parhar
508f856f099SNavdeep Parhar default:
509f856f099SNavdeep Parhar break;
510f856f099SNavdeep Parhar }
511f856f099SNavdeep Parhar
512f856f099SNavdeep Parhar }
513f856f099SNavdeep Parhar
514f856f099SNavdeep Parhar }
515f856f099SNavdeep Parhar
516f856f099SNavdeep Parhar err:
517f856f099SNavdeep Parhar release_scratch_buff(&tmp_decompressed_buffer, pd_buff);
518f856f099SNavdeep Parhar err_dcbuff:
519f856f099SNavdeep Parhar release_scratch_buff(&tmp_compressed_buffer, pd_buff);
520f856f099SNavdeep Parhar
521f856f099SNavdeep Parhar err_cbuff:
522f856f099SNavdeep Parhar return rc;
523f856f099SNavdeep Parhar }
524f856f099SNavdeep Parhar
525