1 #ifdef STATIC 2 #define PREBOOT 3 /* Pre-boot environment: included */ 4 5 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots 6 * errors about console_printk etc... on ARM */ 7 #define _LINUX_KERNEL_H 8 9 #include "zlib_inflate/inftrees.c" 10 #include "zlib_inflate/inffast.c" 11 #include "zlib_inflate/inflate.c" 12 13 #else /* STATIC */ 14 /* initramfs et al: linked */ 15 16 #include <linux/zutil.h> 17 18 #include "zlib_inflate/inftrees.h" 19 #include "zlib_inflate/inffast.h" 20 #include "zlib_inflate/inflate.h" 21 22 #include "zlib_inflate/infutil.h" 23 #include <linux/decompress/inflate.h> 24 25 #endif /* STATIC */ 26 27 #include <linux/decompress/mm.h> 28 29 #define GZIP_IOBUF_SIZE (16*1024) 30 31 static long INIT nofill(void *buffer, unsigned long len) 32 { 33 return -1; 34 } 35 36 /* Included from initramfs et al code */ 37 STATIC int INIT __gunzip(unsigned char *buf, long len, 38 long (*fill)(void*, unsigned long), 39 long (*flush)(void*, unsigned long), 40 unsigned char *out_buf, long out_len, 41 long *pos, 42 void(*error)(char *x)) { 43 u8 *zbuf; 44 struct z_stream_s *strm; 45 int rc; 46 47 rc = -1; 48 if (flush) { 49 out_len = 0x8000; /* 32 K */ 50 out_buf = malloc(out_len); 51 } else { 52 if (!out_len) 53 out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */ 54 } 55 if (!out_buf) { 56 error("Out of memory while allocating output buffer"); 57 goto gunzip_nomem1; 58 } 59 60 if (buf) 61 zbuf = buf; 62 else { 63 zbuf = malloc(GZIP_IOBUF_SIZE); 64 len = 0; 65 } 66 if (!zbuf) { 67 error("Out of memory while allocating input buffer"); 68 goto gunzip_nomem2; 69 } 70 71 strm = malloc(sizeof(*strm)); 72 if (strm == NULL) { 73 error("Out of memory while allocating z_stream"); 74 goto gunzip_nomem3; 75 } 76 77 strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : 78 sizeof(struct inflate_state)); 79 if (strm->workspace == NULL) { 80 error("Out of memory while allocating workspace"); 81 goto gunzip_nomem4; 82 } 83 84 if (!fill) 85 fill = nofill; 86 87 if (len == 0) 88 len = fill(zbuf, GZIP_IOBUF_SIZE); 89 90 /* verify the gzip header */ 91 if (len < 10 || 92 zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) { 93 if (pos) 94 *pos = 0; 95 error("Not a gzip file"); 96 goto gunzip_5; 97 } 98 99 /* skip over gzip header (1f,8b,08... 10 bytes total + 100 * possible asciz filename) 101 */ 102 strm->next_in = zbuf + 10; 103 strm->avail_in = len - 10; 104 /* skip over asciz filename */ 105 if (zbuf[3] & 0x8) { 106 do { 107 /* 108 * If the filename doesn't fit into the buffer, 109 * the file is very probably corrupt. Don't try 110 * to read more data. 111 */ 112 if (strm->avail_in == 0) { 113 error("header error"); 114 goto gunzip_5; 115 } 116 --strm->avail_in; 117 } while (*strm->next_in++); 118 } 119 120 strm->next_out = out_buf; 121 strm->avail_out = out_len; 122 123 rc = zlib_inflateInit2(strm, -MAX_WBITS); 124 125 if (!flush) { 126 WS(strm)->inflate_state.wsize = 0; 127 WS(strm)->inflate_state.window = NULL; 128 } 129 130 while (rc == Z_OK) { 131 if (strm->avail_in == 0) { 132 /* TODO: handle case where both pos and fill are set */ 133 len = fill(zbuf, GZIP_IOBUF_SIZE); 134 if (len < 0) { 135 rc = -1; 136 error("read error"); 137 break; 138 } 139 strm->next_in = zbuf; 140 strm->avail_in = len; 141 } 142 rc = zlib_inflate(strm, 0); 143 144 /* Write any data generated */ 145 if (flush && strm->next_out > out_buf) { 146 long l = strm->next_out - out_buf; 147 if (l != flush(out_buf, l)) { 148 rc = -1; 149 error("write error"); 150 break; 151 } 152 strm->next_out = out_buf; 153 strm->avail_out = out_len; 154 } 155 156 /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ 157 if (rc == Z_STREAM_END) { 158 rc = 0; 159 break; 160 } else if (rc != Z_OK) { 161 error("uncompression error"); 162 rc = -1; 163 } 164 } 165 166 zlib_inflateEnd(strm); 167 if (pos) 168 /* add + 8 to skip over trailer */ 169 *pos = strm->next_in - zbuf+8; 170 171 gunzip_5: 172 free(strm->workspace); 173 gunzip_nomem4: 174 free(strm); 175 gunzip_nomem3: 176 if (!buf) 177 free(zbuf); 178 gunzip_nomem2: 179 if (flush) 180 free(out_buf); 181 gunzip_nomem1: 182 return rc; /* returns Z_OK (0) if successful */ 183 } 184 185 #ifndef PREBOOT 186 STATIC int INIT gunzip(unsigned char *buf, long len, 187 long (*fill)(void*, unsigned long), 188 long (*flush)(void*, unsigned long), 189 unsigned char *out_buf, 190 long *pos, 191 void (*error)(char *x)) 192 { 193 return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error); 194 } 195 #else 196 STATIC int INIT __decompress(unsigned char *buf, long len, 197 long (*fill)(void*, unsigned long), 198 long (*flush)(void*, unsigned long), 199 unsigned char *out_buf, long out_len, 200 long *pos, 201 void (*error)(char *x)) 202 { 203 return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error); 204 } 205 #endif 206