1 #include <xen/errno.h>
2 #include <xen/gunzip.h>
3 #include <xen/init.h>
4 #include <xen/lib.h>
5 #include <xen/mm.h>
6
7 #define WSIZE 0x80000000U
8
9 struct gunzip_state {
10 unsigned char *window;
11
12 /* window position */
13 unsigned int wp;
14
15 unsigned char *inbuf;
16 unsigned int insize;
17 /* Index of next byte to be processed in inbuf: */
18 unsigned int inptr;
19
20 unsigned long bytes_out;
21
22 unsigned long bb; /* bit buffer */
23 unsigned int bk; /* bits in bit buffer */
24
25 uint32_t crc_32_tab[256];
26 uint32_t crc;
27 };
28
29 #define malloc(a) xmalloc_bytes(a)
30 #define free(a) xfree(a)
31 #define memzero(s, n) memset((s), 0, (n))
32
33 typedef unsigned char uch;
34 typedef unsigned short ush;
35 typedef unsigned long ulg;
36
37 /* Diagnostic functions */
38 #ifdef DEBUG
39 # define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0)
40 # define Trace(x) do { fprintf x; } while (0)
41 # define Tracev(x) do { if (verbose) fprintf x ; } while (0)
42 # define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0)
43 # define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0)
44 # define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0)
45 #else
46 # define Assert(cond, msg)
47 # define Trace(x)
48 # define Tracev(x)
49 # define Tracevv(x)
50 # define Tracec(c, x)
51 # define Tracecv(c, x)
52 #endif
53
54 static void flush_window(struct gunzip_state *s);
55
error(const char * x)56 static __init void error(const char *x)
57 {
58 panic("%s\n", x);
59 }
60
get_byte(struct gunzip_state * s)61 static __init int get_byte(struct gunzip_state *s)
62 {
63 if ( s->inptr >= s->insize )
64 {
65 error("ran out of input data");
66 return -1;
67 }
68
69 return s->inbuf[s->inptr++];
70 }
71
72 #include "inflate.c"
73
flush_window(struct gunzip_state * s)74 static __init void flush_window(struct gunzip_state *s)
75 {
76 /*
77 * The window is equal to the output buffer therefore only need to
78 * compute the crc.
79 */
80 uint32_t c = ~s->crc;
81 unsigned int n;
82 unsigned char *in, ch;
83
84 in = s->window;
85 for ( n = 0; n < s->wp; n++ )
86 {
87 ch = *in++;
88 c = s->crc_32_tab[(c ^ ch) & 0xff] ^ (c >> 8);
89 }
90 s->crc = ~c;
91
92 s->bytes_out += s->wp;
93 s->wp = 0;
94 }
95
gzip_check(char * image,unsigned long image_len)96 __init int gzip_check(char *image, unsigned long image_len)
97 {
98 unsigned char magic0, magic1;
99
100 if ( image_len < 2 )
101 return 0;
102
103 magic0 = (unsigned char)image[0];
104 magic1 = (unsigned char)image[1];
105
106 return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e));
107 }
108
perform_gunzip(char * output,char * image,unsigned long image_len)109 __init int perform_gunzip(char *output, char *image, unsigned long image_len)
110 {
111 struct gunzip_state *s;
112 int rc;
113
114 if ( !gzip_check(image, image_len) )
115 return 1;
116
117 s = malloc(sizeof(struct gunzip_state));
118 if ( !s )
119 return -ENOMEM;
120
121 s->window = (unsigned char *)output;
122 s->inbuf = (unsigned char *)image;
123 s->insize = image_len;
124 s->inptr = 0;
125 s->bytes_out = 0;
126
127 makecrc(s);
128
129 if ( gunzip(s) < 0 )
130 {
131 rc = -EINVAL;
132 }
133 else
134 {
135 rc = 0;
136 }
137
138 free(s);
139
140 return rc;
141 }
142
143 /*
144 * Local variables:
145 * mode: C
146 * c-file-style: "BSD"
147 * c-basic-offset: 4
148 * indent-tabs-mode: nil
149 * End:
150 */
151