annotate gunzip.c @ 17:5dd44ab62c24 default tip

minor change
author taiki
date Sun, 03 Nov 2013 00:49:56 -0400
parents 7ac2a177e25d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
1 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
2 * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
3 * Contributed by Alex Williamson <alex.williamson@hp.com>
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
4 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
5 * Copyright (C) 2001-2003 Hewlett-Packard Co.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
6 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
7 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
8 * Copyright (C) 2001 Silicon Graphics, Inc.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
9 * Contributed by Brent Casavant <bcasavan@sgi.com>
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
10 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
11 * This file is part of the ELILO, the EFI Linux boot loader.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
12 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
13 * ELILO is free software; you can redistribute it and/or modify
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
14 * it under the terms of the GNU General Public License as published by
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
15 * the Free Software Foundation; either version 2, or (at your option)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
16 * any later version.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
17 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
18 * ELILO is distributed in the hope that it will be useful,
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
21 * GNU General Public License for more details.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
22 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
23 * You should have received a copy of the GNU General Public License
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
24 * along with ELILO; see the file COPYING. If not, write to the Free
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
25 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
26 * 02111-1307, USA.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
27 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
28 * Please check out the elilo.txt for complete documentation on how
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
29 * to use this program.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
30 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
31
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
32 #include <efi.h>
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
33 #include <efilib.h>
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
34
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
35 #include "elilo.h"
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
36
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
37 #include "gzip.h"
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
38
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
39 #define LD_NAME L"gunzip"
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
40
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
41 #define memzero(s, n) Memset((VOID *)(s), 0, (n))
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
42 #define memcpy(a,b,n) Memcpy((VOID *)(a),(b),(n))
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
43
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
44 /* size of output buffer */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
45 #define WSIZE 0x8000 /* Window size must be at least 32k, */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
46 /* and a power of two */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
47 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
48 * gzip declarations
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
49 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
50 #define OF(args) args
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
51 #define FUNC_STATIC static
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
52
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
53 typedef unsigned char uch;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
54 typedef unsigned short ush;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
55 typedef unsigned long ulg;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
56
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
57 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
58 * static parameters to gzip helper functions
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
59 * we cannot use paramters because API was not
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
60 * designed that way
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
61 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
62 static uch *inbuf; /* input buffer (compressed data) */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
63 static uch *window; /* output buffer (uncompressed data) */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
64
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
65 static VOID *outbuf;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
66 unsigned char *outptr;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
67 static unsigned long outsize;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
68
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
69 static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
70 static unsigned outcnt = 0; /* bytes in output buffer */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
71
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
72 #define get_byte() inbuf[inptr++]
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
73
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
74 /* Diagnostic functions */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
75 #ifdef INFLATE_DEBUG
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
76 # define Assert(cond,msg) {if(!(cond)) error(msg);}
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
77 int stderr;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
78 # define Trace(x) Print(L"line %d:\n", __LINE__);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
79 # define Tracev(x) {if (verbose) Print(L"line %d:\n", __LINE__) ;}
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
80 # define Tracevv(x) {if (verbose>1) Print(L"line %d:\n", __LINE__) ;}
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
81 # define Tracec(c,x) {if (verbose && (c)) Print(L"line %d:\n", __LINE__) ;}
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
82 # define Tracecv(c,x) {if (verbose>1 && (c)) Print(L"line %d:\n", __LINE__) ;}
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
83 #else
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
84 # define Assert(cond,msg)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
85 # define Trace(x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
86 # define Tracev(x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
87 # define Tracevv(x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
88 # define Tracec(c,x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
89 # define Tracecv(c,x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
90 #endif
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
91
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
92 static void flush_window(void);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
93 static void error(char *m);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
94 static long bytes_out;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
95
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
96 static void error(char *m);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
97
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
98 #define gzip_malloc(size) (void *)alloc(size, 0)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
99 #define gzip_free(where) free(where)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
100
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
101 #include "inflate.c"
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
102
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
103 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
104 * Run a set of bytes through the crc shift register. If s is a NULL
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
105 * pointer, then initialize the crc shift register contents instead.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
106 * Return the current crc in either case.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
107 *
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
108 * Input:
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
109 * S pointer to bytes to pump through.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
110 * N number of bytes in S[].
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
111 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
112 static void
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
113 updcrc(unsigned char *s, unsigned n)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
114 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
115 register unsigned long c;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
116 /* crc is defined in inflate.c */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
117
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
118 c = crc;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
119 while (n--) {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
120 c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
121 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
122 crc = c;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
123 return;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
124 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
125
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
126 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
127 * Clear input and output buffers
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
128 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
129 static void
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
130 clear_bufs(void)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
131 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
132 outcnt = 0;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
133 inptr = 0;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
134 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
135
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
136 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
137 * Write the output window window[0..outcnt-1] holding uncompressed
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
138 * data and update crc.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
139 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
140 void
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
141 flush_window(void)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
142 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
143 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
144 * We'll end up relying on the CRC check and size check failing
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
145 * if there's actually more data than we expect.
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
146 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
147 if (!outcnt || bytes_out + outcnt > outsize)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
148 return;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
149
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
150 updcrc(window, outcnt);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
151
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
152 Memcpy(outptr, window, outcnt);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
153 outptr += outcnt;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
154 bytes_out += outcnt;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
155
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
156 outcnt = 0;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
157 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
158
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
159 static void
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
160 error(char *x)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
161 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
162 ERR_PRT((L"%s : %a", LD_NAME, x));
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
163 /* will eventually exit with error from gunzip() */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
164 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
165
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
166 static INT32
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
167 decompress(VOID)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
168 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
169 INT32 ret;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
170
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
171 clear_bufs();
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
172 makecrc();
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
173 Print(L"Uncompressing... ");
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
174 ret = gunzip();
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
175 if (ret == 0) Print(L"done\n");
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
176 return ret == 0 ? 0 : -1;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
177 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
178
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
179 int
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
180 gunzip_image(memdesc_t *image)
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
181 {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
182 UINTN pgcnt;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
183
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
184 inbuf = image->start_addr;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
185
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
186 /*
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
187 * Last 4 bytes of gzip'd image indicates the uncompressed size
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
188 */
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
189 outsize = inbuf[image->size - 1] << 24 | inbuf[image->size - 2] << 16 |
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
190 inbuf[image->size - 3] << 8 | inbuf[image->size - 4];
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
191
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
192 pgcnt = EFI_SIZE_TO_PAGES(outsize);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
193
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
194 outbuf = alloc_pages(pgcnt, EfiLoaderData, AllocateAnyPages, 0);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
195 if (outbuf == NULL) {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
196 ERR_PRT((L"%s : allocate output buffer failed\n", LD_NAME));
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
197 return -1;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
198 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
199 outptr = outbuf;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
200
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
201 window = (void *)alloc(WSIZE, 0);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
202 if (window == NULL) {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
203 ERR_PRT((L"%s : allocate output window failed\n", LD_NAME));
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
204 free(outbuf);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
205 return -1;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
206 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
207
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
208 bytes_out = 0;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
209
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
210 if (decompress() != 0) {
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
211 free(window);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
212 free(outbuf);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
213 return ELILO_LOAD_ERROR;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
214 }
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
215
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
216 free(window);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
217 free(image->start_addr);
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
218
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
219 image->start_addr = outbuf;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
220 image->size = outsize;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
221 image->pgcnt = pgcnt;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
222
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
223 return ELILO_LOAD_SUCCESS;
7ac2a177e25d add elilo source.
taiki
parents:
diff changeset
224 }