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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [decompress.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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