OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [redboot/] [v2_0/] [src/] [decompress.c] - Blame information for rev 486

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
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>
59
static z_stream stream;
60
static 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
// When free, 'size' is the size of the whole block
67
// When allocated, 'size' is the allocation size
68
// The 'magic' is kept to insure that the block being freed is reasonable
69
//
70
struct _block {
71
    int            size;
72
    long           magic;  // Must be __ZLIB_MAGIC__
73
    struct _block *next;
74
    struct _block *self;
75
};
76
static 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
83
static 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
//
92
static void
93
_zlib_init(void)
94
{
95
#ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
96
    zlib_workspace = fis_zlib_common_buffer;
97
#else
98
    // Allocate some RAM for use by the gzip/zlib routines
99
    workspace_end -= ZLIB_COMPRESSION_OVERHEAD;
100
    zlib_workspace = workspace_end;
101
#endif
102
}
103
 
104
RedBoot_init(_zlib_init, RedBoot_INIT_FIRST);
105
 
106
// #define DEBUG_ZLIB_MALLOC
107
#ifdef DEBUG_ZLIB_MALLOC
108
static void
109
show_memlist(char *when)
110
{
111
    struct _block *bp = memlist;
112
 
113
    diag_printf("memory list after %s\n", when);
114
    while (bp != (struct _block *)0) {
115
        diag_printf("   %08p %5d %08p\n", bp, bp->size, bp->next);
116
        bp = bp->next;
117
    }
118
}
119
#endif
120
 
121
// Note: these have to be global and match the prototype used by the
122
// gzip/zlib package since we are exactly replacing them.
123
 
124
void
125
*zcalloc(void *opaque, unsigned int items, unsigned int size)
126
{
127
    voidpf res;
128
    int len = (items*size);
129
    struct _block *bp = memlist;
130
    struct _block *nbp, *pbp;
131
 
132
    // Simple, first-fit algorithm
133
    pbp = (struct _block *)0;
134
    while (bp) {
135
        if (bp->size > len) {
136
            nbp = (struct _block *)((char *)bp + len + sizeof(struct _block));
137
            nbp->next = bp->next;
138
            nbp->size = bp->size - len;
139
            if (pbp) {
140
                pbp->next = nbp;
141
            } else {
142
                memlist = nbp;
143
            }
144
            res = bp;
145
            break;
146
        }
147
        pbp = bp;
148
        bp = bp->next;
149
    }
150
    if (bp) {
151
        bp->size = len;
152
        bp->magic = __ZLIB_MAGIC__;
153
        bp->self = bp;
154
        res = bp+1;
155
        memset(res, 0, len);
156
    } else {
157
        res = 0;  // No memory left
158
    }
159
#ifdef DEBUG_ZLIB_MALLOC
160
    diag_printf("%s(%d,%d) = %p\n", __FUNCTION__, items, size, res);
161
    show_memlist(__FUNCTION__);
162
#endif
163
    return res;
164
}
165
 
166
void
167
zcfree(void *opaque, void *ptr)
168
{
169
    struct _block *bp, *pbp, *nbp;
170
    int size;
171
 
172
    if (!ptr) return;  // Safety
173
    bp = (struct _block *)((char *)ptr - sizeof(struct _block));
174
    if ((bp->magic != __ZLIB_MAGIC__) || (bp->self != bp)) {
175
        diag_printf("%s(%p) - invalid block\n", __FUNCTION__, ptr);
176
        return;
177
    }
178
    size = bp->size;
179
#ifdef DEBUG_ZLIB_MALLOC
180
    diag_printf("%s(%p) = %d bytes\n", __FUNCTION__, ptr, size);
181
#endif
182
    // See if this block is adjacent to a free block
183
    nbp = memlist;
184
    pbp = (struct _block *)0;
185
    while (nbp) {
186
        if ((char *)bp+size+sizeof(struct _block) == (char *)nbp) {
187
            // The block being freed fits just before
188
            bp->next = nbp->next;
189
            bp->size = nbp->size + size + sizeof(struct _block);
190
#ifdef DEBUG_ZLIB_MALLOC
191
            diag_printf("Free before\n");
192
#endif
193
            if (pbp) {
194
                pbp->next = bp;
195
                // See if this new block and the previous one can
196
                // be combined.
197
                if ((char *)pbp+pbp->size == (char *)bp) {
198
#ifdef DEBUG_ZLIB_MALLOC
199
                    diag_printf("Collapse [before] - p: %p/%d/%p, n: %p/%d/%p\n",
200
                                pbp, pbp->size, pbp->next,
201
                                bp, bp->size, bp->next);
202
#endif
203
                    pbp->size += bp->size;
204
                    pbp->next = bp->next;
205
                }
206
            } else {
207
                memlist = bp;
208
            }
209
#ifdef DEBUG_ZLIB_MALLOC
210
            show_memlist(__FUNCTION__);
211
#endif
212
            return;
213
        } else
214
        if ((char *)nbp+nbp->size == (char *)bp) {
215
            // The block being freed fits just after
216
            nbp->size += size + sizeof(struct _block);
217
            // See if it will now collapse with the following block
218
#ifdef DEBUG_ZLIB_MALLOC
219
            diag_printf("Free after\n");
220
#endif
221
            if (nbp->next != (struct _block *)0) {
222
                if ((char *)nbp+nbp->size == (char *)nbp->next) {
223
#ifdef DEBUG_ZLIB_MALLOC
224
                    diag_printf("Collapse [after] - p: %p/%d/%p, n: %p/%d/%p\n",
225
                                nbp, nbp->size, nbp->next,
226
                                nbp->next, nbp->next->size, nbp->next->next);
227
#endif
228
                    nbp->size += (nbp->next)->size;
229
                    nbp->next = (nbp->next)->next;
230
                }
231
            }
232
#ifdef DEBUG_ZLIB_MALLOC
233
            show_memlist(__FUNCTION__);
234
#endif
235
            return;
236
        } else {
237
            pbp = nbp;
238
            nbp = nbp->next;
239
        }
240
    }
241
}
242
 
243
//
244
// This function is called to initialize a gzip/zlib stream.
245
// Note that it also reinitializes the memory pool every time.
246
//
247
static int
248
gzip_init(_pipe_t* p)
249
{
250
    int err;
251
    struct _block *bp;
252
 
253
    bp = (struct _block *)zlib_workspace;
254
    memlist = bp;
255
    bp->next = 0;
256
    bp->size = ZLIB_COMPRESSION_OVERHEAD;
257
    stream.zalloc = zcalloc;
258
    stream.zfree = zcfree;
259
    stream.next_in = NULL;
260
    stream.avail_in = 0;
261
    stream.next_out = NULL;
262
    stream.avail_out = 0;
263
    err = inflateInit(&stream);
264
    stream_end = false;
265
 
266
    return err;
267
}
268
 
269
//
270
// This function is called during the decompression cycle to
271
// actually cause a buffer to be filled with uncompressed data.
272
//
273
static int
274
gzip_inflate(_pipe_t* p)
275
{
276
    int err, bytes_out;
277
 
278
    if (stream_end)
279
        return Z_STREAM_END;
280
 
281
    stream.next_in = p->in_buf;
282
    stream.avail_in = p->in_avail;
283
    stream.next_out = p->out_buf;
284
    stream.avail_out = p->out_max;
285
    err = inflate(&stream, Z_SYNC_FLUSH);
286
    bytes_out = stream.next_out - p->out_buf;
287
    p->out_size += bytes_out;
288
    p->out_buf = stream.next_out;
289
    p->msg = stream.msg;
290
    p->in_avail = stream.avail_in;
291
    p->in_buf = stream.next_in;
292
 
293
    // Let upper layers process any inflated bytes at
294
    // end of stream.
295
    if (err == Z_STREAM_END && bytes_out) {
296
        stream_end = true;
297
        err = Z_OK;
298
    }
299
 
300
    return err;
301
}
302
 
303
//
304
// Called when the input data is completed or an error has
305
// occured.  This allows for clean up as well as passing error
306
// information up.
307
//
308
static int
309
gzip_close(_pipe_t* p, int err)
310
{
311
    switch (err) {
312
    case Z_STREAM_END:
313
        err = 0;
314
        break;
315
    case Z_OK:
316
        if (stream_end) {
317
          break;
318
        }
319
        // Decompression didn't complete
320
        p->msg = "premature end of input";
321
        // fall-through
322
    default:
323
        err = -1;
324
        break;
325
    }
326
 
327
    inflateEnd(&stream);
328
 
329
    return err;
330
}
331
 
332
//
333
// Exported interfaces
334
//
335
_decompress_fun_init* _dc_init = gzip_init;
336
_decompress_fun_inflate* _dc_inflate = gzip_inflate;
337
_decompress_fun_close* _dc_close = gzip_close;
338
#endif // CYGPKG_COMPRESS_ZLIB

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.