source: SVN/cambria/redboot/packages/redboot/current/src/decompress.c @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 9.1 KB
Line 
1//==========================================================================
2//
3//      decompress.c
4//
5//      RedBoot decompress support
6//
7//==========================================================================
8//####ECOSGPLCOPYRIGHTBEGIN####
9// -------------------------------------------
10// This file is part of eCos, the Embedded Configurable Operating System.
11// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12//
13// eCos is free software; you can redistribute it and/or modify it under
14// the terms of the GNU General Public License as published by the Free
15// Software Foundation; either version 2 or (at your option) any later version.
16//
17// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20// for more details.
21//
22// You should have received a copy of the GNU General Public License along
23// with eCos; if not, write to the Free Software Foundation, Inc.,
24// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25//
26// As a special exception, if other files instantiate templates or use macros
27// or inline functions from this file, or you compile this file and link it
28// with other works to produce a work based on this file, this file does not
29// by itself cause the resulting work to be covered by the GNU General Public
30// License. However the source code for this file must still be made available
31// in accordance with section (3) of the GNU General Public License.
32//
33// This exception does not invalidate any other reasons why a work based on
34// this file might be covered by the GNU General Public License.
35//
36// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37// at http://sources.redhat.com/ecos/ecos-license/
38// -------------------------------------------
39//####ECOSGPLCOPYRIGHTEND####
40//==========================================================================
41//#####DESCRIPTIONBEGIN####
42//
43// Author(s):    jskov
44// Contributors: jskov, gthomas, tkoeller
45// Date:         2001-03-08
46// Purpose:     
47// Description: 
48//             
49// This code is part of RedBoot (tm).
50//
51//####DESCRIPTIONEND####
52//
53//==========================================================================
54
55#include <redboot.h>
56
57#ifdef CYGPKG_COMPRESS_ZLIB
58#include <cyg/compress/zlib.h>
59static z_stream stream;
60static bool stream_end;
61
62#define __ZLIB_MAGIC__ 0x5A4C4942   // 'ZLIB'
63
64//
65// Free memory [blocks] are stored as a linked list of "struct _block"
66// The 'magic' is kept to insure that the block being freed is reasonable
67//
68// One of either next or size might be removable, if a sentinal block
69// is placed at the end of the region at initialisation time.
70struct _block {
71    int            size;   // always the total length of the block, including this header
72    long           magic;  // Must be __ZLIB_MAGIC__ if allocated and 0 if free
73    struct _block *next;
74    struct _block *prev;
75};
76static struct _block *memlist;
77
78#ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
79# define ZLIB_COMPRESSION_OVERHEAD CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE
80#else
81# define ZLIB_COMPRESSION_OVERHEAD 0xC000
82#endif
83static void *zlib_workspace;
84
85//
86// This function is run as part of RedBoot's initialization.
87// It will allocate some memory from the "workspace" pool for
88// use by the gzip/zlib routines.  This allows the memory usage
89// of RedBoot to be more finely controlled than if we simply
90// used the generic 'malloc() from the heap' functionality.
91//
92static void
93_zlib_init(void)
94{
95    struct _block *bp;
96#ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
97    zlib_workspace = fis_zlib_common_buffer;
98#else
99    // Allocate some RAM for use by the gzip/zlib routines
100    workspace_end -= ZLIB_COMPRESSION_OVERHEAD;
101    zlib_workspace = workspace_end;
102#endif
103    bp = (struct _block *)zlib_workspace;
104    memlist = bp;
105    bp->next = bp->prev = 0;
106    bp->size = ZLIB_COMPRESSION_OVERHEAD; 
107    bp->magic = 0;
108#ifdef DEBUG_ZLIB_MALLOC
109    show_memlist(__FUNCTION__);
110#endif
111}
112
113RedBoot_init(_zlib_init, RedBoot_INIT_FIRST);
114
115// #define DEBUG_ZLIB_MALLOC
116#ifdef DEBUG_ZLIB_MALLOC
117static void
118show_memlist(char *when)
119{
120    struct _block *bp = memlist;
121
122    diag_printf("memory list after %s\n", when);
123    diag_printf("   --START--- --END----- --SIZE---- --PREV---- --NEXT---- TYPE-----\n");
124    while (bp != (struct _block *)0) {
125        diag_printf("   %08p-%08p 0x%08x %08p %08p %s\n", bp, (unsigned char *)bp+bp->size, 
126                    bp->size, bp->prev, bp->next, bp->magic == 0 ? "FREE" : "ALLOCATED" );
127        bp = bp->next;
128    }
129    diag_printf("\n");
130}
131#endif
132
133// Note: these have to be global and match the prototype used by the
134// gzip/zlib package since we are exactly replacing them.
135
136void 
137*zcalloc(void *opaque, unsigned int items, unsigned int size)
138{
139    voidpf res = 0;
140    int len = (items*size) + sizeof(struct _block);
141    struct _block *bp = memlist;
142    struct _block *nbp;
143
144#ifdef DEBUG_ZLIB_MALLOC
145    /* do this here because when int is called output is not setup yet */
146    static int first_alloc = 1;
147    if ( first_alloc ) {
148        show_memlist("initialization");
149        first_alloc = 0;
150    }
151#endif
152
153    // Simple, first-fit algorithm
154    while (bp) {
155        if (bp->magic == 0 && bp->size > len) {
156            nbp = (struct _block *)((char *)bp + len);
157            /* link new block into chain */
158            nbp->next = bp->next;
159            bp->next = nbp;
160            nbp->prev = bp;
161            /* split size between the two blocks */
162            nbp->size = bp->size - len;
163            bp->size = len;
164            /* mark the new block as free */
165            nbp->magic = 0;
166            /* mark allocated block as allocated */
167            bp->magic = __ZLIB_MAGIC__;
168            res = bp +1;
169            memset(res, 0, len - sizeof(struct _block));
170            break;
171        }
172        bp = bp->next;
173    }
174#ifdef DEBUG_ZLIB_MALLOC
175    diag_printf("%s(0x%x,0x%x) = %p\n", __FUNCTION__, items, size, res);
176    show_memlist(__FUNCTION__);
177#endif
178    if ( res == NULL )
179        diag_printf("zcalloc: failed to allocate 0x%x items of 0x%x bytes == 0x%x bytes\n", items, size, len);
180    return res;
181}
182
183void 
184zcfree(void *opaque, void *ptr)
185{
186    struct _block *bp;
187
188    if (!ptr) return;  // Safety
189    bp = (struct _block *)((char *)ptr - sizeof(struct _block));
190    if (bp->magic != __ZLIB_MAGIC__) {
191        diag_printf("%s(%p) - invalid block\n", __FUNCTION__, ptr);
192        return;
193    }
194
195    /* mark as free */
196    bp->magic = 0;
197
198#ifdef DEBUG_ZLIB_MALLOC
199    diag_printf("%s(%p) = 0x%x bytes\n", __FUNCTION__, ptr, bp->size);
200#endif
201
202    bp = (struct _block *)((char *)ptr - sizeof(struct _block));
203    while(bp->next && bp->next->magic == 0) {
204#ifdef DEBUG_ZLIB_MALLOC
205        diag_printf("  merging %08p and %08p (after)\n", bp, bp->next);
206#endif
207        bp->size += bp->next->size;
208        bp->next = bp->next->next;
209    }
210
211    while(bp->prev && bp->prev->magic == 0) {
212#ifdef DEBUG_ZLIB_MALLOC
213        diag_printf("  merging %08p and %08p (before)\n", bp->prev, bp);
214#endif
215        bp->prev->size += bp->size;
216        bp->prev->next = bp->next;
217        bp = bp->prev;
218    }
219
220#ifdef DEBUG_ZLIB_MALLOC
221    show_memlist(__FUNCTION__);
222#endif
223}
224
225//
226// This function is called to initialize a gzip/zlib stream.
227//
228static int
229gzip_init(_pipe_t* p)
230{
231    int err;
232
233    // Note: this code used to [re]initialize the memory pool used
234    // by zlib.  This is now done in _zlib_init(), but only once.
235    stream.zalloc = zcalloc;
236    stream.zfree = zcfree;
237    stream.next_in = NULL;
238    stream.avail_in = 0;
239    stream.next_out = NULL;
240    stream.avail_out = 0;
241    err = inflateInit(&stream);
242    stream_end = false;
243
244    return err;
245}
246
247//
248// This function is called during the decompression cycle to
249// actually cause a buffer to be filled with uncompressed data.
250//
251static int
252gzip_inflate(_pipe_t* p)
253{
254    int err, bytes_out;
255
256    if (stream_end)
257        return Z_STREAM_END;
258       
259    stream.next_in = p->in_buf;
260    stream.avail_in = p->in_avail;
261    stream.next_out = p->out_buf;
262    stream.avail_out = p->out_max;
263    err = inflate(&stream, Z_SYNC_FLUSH);
264    bytes_out = stream.next_out - p->out_buf;
265    p->out_size += bytes_out;
266    p->out_buf = stream.next_out;
267    p->msg = stream.msg;
268    p->in_avail = stream.avail_in;
269    p->in_buf = stream.next_in;
270
271    // Let upper layers process any inflated bytes at
272    // end of stream.
273    if (err == Z_STREAM_END && bytes_out) {
274        stream_end = true;
275        err = Z_OK;
276    }
277
278    return err;
279}
280
281//
282// Called when the input data is completed or an error has
283// occured.  This allows for clean up as well as passing error
284// information up.
285//
286static int
287gzip_close(_pipe_t* p, int err)
288{
289    switch (err) {
290    case Z_STREAM_END:
291        err = 0;
292        break;
293    case Z_OK:
294        if (stream_end) {
295          break;
296        }
297        // Decompression didn't complete
298        p->msg = "premature end of input";
299        // fall-through
300    default:
301        err = -1;
302        break;
303    }
304
305    inflateEnd(&stream);
306
307    return err;
308}
309
310//
311// Exported interfaces
312//
313_decompress_fun_init* _dc_init = gzip_init;
314_decompress_fun_inflate* _dc_inflate = gzip_inflate;
315_decompress_fun_close* _dc_close = gzip_close;
316#endif // CYGPKG_COMPRESS_ZLIB
Note: See TracBrowser for help on using the repository browser.