1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  "Compressed" file system			File: zipstart_readz.c
5    *
6    *  This module calls ZLIB to read a compressed file so we
7    *  can boot compressed versions of CFE.
8    *
9    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48#if CFG_ZLIB
49
50#include "cfe.h"
51#include "zipstart.h"
52#include "zlib.h"
53
54/*  *********************************************************************
55    *  ZLIBFS context
56    ********************************************************************* */
57
58/*
59 * File context - describes an open file on the file system.
60 * For raw devices, this is pretty meaningless, but we do
61 * keep track of where we are.
62 */
63
64#define ZLIBFS_BUFSIZE	1024
65typedef struct zlibfs_file_s {
66    int zlibfs_fileoffset;
67    z_stream zlibfs_stream;
68    uint8_t *zlibfs_inbuf;
69    uint8_t *zlibfs_outbuf;
70    int zlibfs_outlen;
71    uint8_t *zlibfs_outptr;
72    int zlibfs_eofseen;
73
74    /* Pointers to zip data we are reading */
75    uint8_t *zlibfs_inptr;
76    int zlibfs_inlen;
77} zlibfs_file_t;
78
79/*  *********************************************************************
80    *  Globals
81    ********************************************************************* */
82
83zlibfs_file_t rz_file;
84uint8_t rz_inbuf[ZLIBFS_BUFSIZE];
85uint8_t rz_outbuf[ZLIBFS_BUFSIZE];
86
87/*  *********************************************************************
88    *  Prototypes
89    ********************************************************************* */
90
91voidpf zcalloc(voidpf opaque,unsigned items, unsigned size);
92void zcfree(voidpf opaque,voidpf ptr);
93
94/*  *********************************************************************
95    *  ZLIB fileio dispatch table
96    ********************************************************************* */
97
98
99static uint8_t gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
100
101
102/* gzip flag byte */
103#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
104#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
105#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
106#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
107#define COMMENT      0x10 /* bit 4 set: file comment present */
108#define RESERVED     0xE0 /* bits 5..7: reserved */
109
110
111static void rz_memcpy(uint8_t *dst,uint8_t *src,int len)
112{
113    while (len > 0) {
114	*dst++ = *src++;
115	len--;
116	}
117}
118
119static void rz_memset(uint8_t *dst,int c,int cnt)
120{
121    while (cnt > 0) {
122	*dst++ = (uint8_t) c;
123	cnt--;
124	}
125}
126
127/*
128 * Utility functions needed by the ZLIB routines
129 */
130voidpf zcalloc(voidpf opaque,unsigned items, unsigned size)
131{
132    void *ptr;
133
134    ptr = zs_malloc(items*size);
135    if (ptr) rz_memset(ptr,0,items*size);
136    return ptr;
137}
138
139void zcfree(voidpf opaque,voidpf ptr)
140{
141    return zs_free(ptr);
142}
143
144
145
146static int get_byte(zlibfs_file_t *file,uint8_t *ch)
147{
148    if (file->zlibfs_inlen > 0) {
149	*ch = *(file->zlibfs_inptr++);
150	file->zlibfs_inlen--;
151	return 1;
152	}
153    else {
154	return 0;
155	}
156
157}
158
159
160static int check_header(zlibfs_file_t *file)
161{
162    int method; /* method byte */
163    int flags;  /* flags byte */
164    uInt len;
165    uint8_t c;
166    int res;
167
168    /* Check the gzip magic header */
169    for (len = 0; len < 2; len++) {
170	res = get_byte(file,&c);
171	if (c != gz_magic[len]) {
172	    return -1;
173	}
174    }
175
176    get_byte(file,&c); method = (int) c;
177    get_byte(file,&c); flags = (int) c;
178
179    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
180	return -1;
181	}
182
183    /* Discard time, xflags and OS code: */
184    for (len = 0; len < 6; len++) (void)get_byte(file,&c);
185
186    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
187	get_byte(file,&c);
188	len = (uInt) c;
189	get_byte(file,&c);
190	len += ((uInt)c)<<8;
191	/* len is garbage if EOF but the loop below will quit anyway */
192	while ((len-- != 0) && (get_byte(file,&c) == 1)) ;
193    }
194    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
195	while ((get_byte(file,&c) == 1) && (c != 0)) ;
196    }
197    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
198	while ((get_byte(file,&c) == 1) && (c != 0)) ;
199    }
200    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
201	for (len = 0; len < 2; len++) (void)get_byte(file,&c);
202    }
203
204    return 0;
205}
206
207int rz_init(uint8_t *inptr,int len)
208{
209    zlibfs_file_t *file = &rz_file;
210    int err;
211
212
213    file->zlibfs_fileoffset = 0;
214    file->zlibfs_inbuf = NULL;
215    file->zlibfs_outbuf = NULL;
216    file->zlibfs_eofseen = 0;
217
218    file->zlibfs_inptr = inptr;
219    file->zlibfs_inlen = len;
220
221    /* Open the zstream */
222
223    file->zlibfs_inbuf = rz_inbuf;
224    file->zlibfs_outbuf = rz_outbuf;
225
226    file->zlibfs_stream.next_in = NULL;
227    file->zlibfs_stream.avail_in = 0;
228    file->zlibfs_stream.next_out = file->zlibfs_outbuf;
229    file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
230    file->zlibfs_stream.zalloc = (alloc_func)0;
231    file->zlibfs_stream.zfree = (free_func)0;
232
233    file->zlibfs_outlen = 0;
234    file->zlibfs_outptr = file->zlibfs_outbuf;
235
236    err = inflateInit2(&(file->zlibfs_stream),-15);
237    if (err != Z_OK) {
238	return -1;
239	}
240
241    check_header(file);
242
243    return 0;
244}
245
246int rz_read(uint8_t *buf,int len)
247{
248    zlibfs_file_t *file = &rz_file;
249    int res = 0;
250    int err;
251    int amtcopy;
252    int ttlcopy = 0;
253
254    if (len == 0) return 0;
255
256    while (len) {
257
258	/* Figure the amount to copy.  This is the min of what we
259	   have left to do and what is available. */
260	amtcopy = len;
261	if (amtcopy > file->zlibfs_outlen) {
262	    amtcopy = file->zlibfs_outlen;
263	    }
264
265	/* Copy the data. */
266
267	if (buf) {
268	    rz_memcpy(buf,file->zlibfs_outptr,amtcopy);
269	    buf += amtcopy;
270	    }
271
272	/* Update the pointers. */
273	file->zlibfs_outptr += amtcopy;
274	file->zlibfs_outlen -= amtcopy;
275	len -= amtcopy;
276	ttlcopy += amtcopy;
277
278	/* If we've eaten all of the output, reset and call inflate
279	   again. */
280
281	if (file->zlibfs_outlen == 0) {
282	    /* If no input data to decompress, get some more if we can. */
283	    if (file->zlibfs_eofseen) break;
284	    if (file->zlibfs_stream.avail_in == 0) {
285		int amtcopy;
286		uint8_t *src,*dst;
287
288		amtcopy = file->zlibfs_inlen;
289		if (amtcopy > ZLIBFS_BUFSIZE) amtcopy = ZLIBFS_BUFSIZE;
290		res = amtcopy;
291
292		if (amtcopy > 0) {
293		    src = file->zlibfs_inptr;
294		    dst = file->zlibfs_inbuf;
295		    file->zlibfs_inptr += amtcopy;
296		    file->zlibfs_inlen -= amtcopy;
297		    file->zlibfs_stream.next_in = file->zlibfs_inbuf;
298		    file->zlibfs_stream.avail_in = amtcopy;
299		    rz_memcpy(dst,src,amtcopy);
300		    }
301		else break;
302		}
303
304	    /* inflate the input data. */
305	    file->zlibfs_stream.next_out = file->zlibfs_outbuf;
306	    file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
307	    file->zlibfs_outptr = file->zlibfs_outbuf;
308	    err = inflate(&(file->zlibfs_stream),Z_SYNC_FLUSH);
309	    if (err == Z_STREAM_END) {
310		/* We can get a partial buffer fill here. */
311	        file->zlibfs_eofseen = 1;
312		}
313	    else if (err != Z_OK) {
314		putstr("rz_read error"); putdec(0-err);
315
316		res = -1;
317		break;
318		}
319	    file->zlibfs_outlen = file->zlibfs_stream.next_out -
320		file->zlibfs_outptr;
321	    }
322
323	}
324
325    file->zlibfs_fileoffset += ttlcopy;
326
327    return (res < 0) ? res : ttlcopy;
328}
329
330
331void rz_close(void)
332{
333    zlibfs_file_t *file = &rz_file;
334
335    inflateEnd(&(file->zlibfs_stream));
336}
337
338
339#endif
340