summaryrefslogtreecommitdiff
path: root/util/mkelfImage/kunzip_src/lib/kunzip.c
blob: b8ae1c1ecc10eaa896faa6089838a94bee267316 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <string.h>
#include <stdlib.h>

/*
 * gzip support routine declartions..
 * =========================================================
 */

#ifdef DEBUG
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)
#  define DBG(x) printf x
#else
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)
#  define DBG(x)
#endif

void error(char *str)
{
	DBG(("%s\n", str));
}

static unsigned char *inbuf;	/* input buffer */
static unsigned int insize;	/* valid bytes in inbuf */
static unsigned int inptr;	/* index of next byte to be processed in inbuf */

#if !defined(DEBUG)
#define get_byte()  (inptr < insize ? inbuf[inptr++] : 0)
#else
static unsigned char get_byte(void)
{
	static int count;
	unsigned char byte = (inptr < insize ? inbuf[inptr++] : 0);
#if 0
	printf("%02x ", byte);
	if ((++count & 0x0f) == 0) {
		printf("\n");
	}
#endif
	return byte;
}

#endif

static void flush_window(void);

static long bytes_out;		/* total bytes compressed */
static unsigned outcnt;		/* bytes in output buffer */

#define WSIZE 0x8000		/* Window size must be at least 32k, and a power of two */
static unsigned char window[WSIZE];	/* Sliding window buffer */

/*
 * gzip declarations
 */

#define OF(args)  args
#define STATIC static


#define memzero(s, n)     memset ((s), 0, (n))

typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;



#include "inflate.c"


/* Variables that gunzip doesn't need to see... */
static unsigned char *output_ptr;
static unsigned long end_offset;
static struct unzip_region {
	unsigned long start;
	unsigned long end_offset;
} unzip_region;

/* Data provided by the header */
extern unsigned char zipped_data[];
extern unsigned char zipped_data_end[];
extern unsigned char entry;
/* Assembly language routines */
extern void jmp_to_program_entry(void *);

/* ===========================================================================
 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 * (Used for the decompressed data only.)
 */
static void flush_window(void)
{
	ulg c = crc;		/* temporary variable */
	unsigned n;
	unsigned long limit;
	uch *in, *out, ch;

	limit = outcnt;


	n = 0;
	in = window;
	while (n < outcnt) {
		limit = end_offset - bytes_out +n;
		if (limit > outcnt) {
			limit = outcnt;
		}
		out = output_ptr;
		DBG(("flush 0x%08lx start 0x%08lx limit 0x%08lx\n",
			(unsigned long) out, (unsigned long)n, limit));
		for (; n < limit; n++) {
			ch = *out++ = *in++;
			c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
		}
		crc = c;
		bytes_out += (out - output_ptr);
		output_ptr = out;
		if (bytes_out == end_offset) {
			if (output_ptr == (unsigned char *)(&unzip_region+1)) {
				output_ptr = (unsigned char *)(unzip_region.start);
				end_offset = unzip_region.end_offset;
			} else {
				output_ptr = (unsigned char *)&unzip_region;
				end_offset += sizeof(unzip_region);
			}
		}
	}
	outcnt = 0;
}


void gunzip_setup(void)
{
	DBG(("gunzip_setup\n"));
	outcnt = 0;
	bytes_out = 0;

	end_offset = sizeof(unzip_region);
	output_ptr = (unsigned char *)&unzip_region;

	inbuf = &zipped_data[0];
	insize = zipped_data_end - zipped_data;
	inptr = 0;

	makecrc();
	DBG(("gunzip_setup_done\n"));
}


int kunzip(int argc, char **argv)
{
	DBG(("kunzip\n"));
	gunzip_setup();
	DBG(("pre_gunzip\n"));
	if (gunzip() != 0) {
		error("gunzip failed");
		while(1) {}
		return -1;
	}
	DBG(("pre_jmp_to_program_entry: %p\n", &entry ));
	jmp_to_program_entry(&entry);
	return 0;
}