1 #ifdef STATIC 2 /* Pre-boot environment: included */ 3 4 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots 5 * errors about console_printk etc... on ARM */ 6 #define _LINUX_KERNEL_H 7 8 #include "zlib_inflate/inftrees.c" 9 #include "zlib_inflate/inffast.c" 10 #include "zlib_inflate/inflate.c" 11 12 #else /* STATIC */ 13 /* initramfs et al: linked */ 14 15 #include <linux/zutil.h> 16 17 #include "zlib_inflate/inftrees.h" 18 #include "zlib_inflate/inffast.h" 19 #include "zlib_inflate/inflate.h" 20 21 #include "zlib_inflate/infutil.h" 22 #include <linux/slab.h> 23 24 #endif /* STATIC */ 25 26 #include <linux/decompress/mm.h> 27 28 #define GZIP_IOBUF_SIZE (16*1024) 29 30 static int nofill(void *buffer, unsigned int len) 31 { 32 return -1; 33 } 34 35 /* Included from initramfs et al code */ 36 STATIC int INIT gunzip(unsigned char *buf, int len, 37 int(*fill)(void*, unsigned int), 38 int(*flush)(void*, unsigned int), 39 unsigned char *out_buf, 40 int *pos, 41 void(*error_fn)(char *x)) { 42 u8 *zbuf; 43 struct z_stream_s *strm; 44 int rc; 45 size_t out_len; 46 47 set_error_fn(error_fn); 48 rc = -1; 49 if (flush) { 50 out_len = 0x8000; /* 32 K */ 51 out_buf = malloc(out_len); 52 } else { 53 out_len = 0x7fffffff; /* 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 /* skip over asciz filename */ 104 if (zbuf[3] & 0x8) { 105 while (strm->next_in[0]) 106 strm->next_in++; 107 strm->next_in++; 108 } 109 strm->avail_in = len - (strm->next_in - zbuf); 110 111 strm->next_out = out_buf; 112 strm->avail_out = out_len; 113 114 rc = zlib_inflateInit2(strm, -MAX_WBITS); 115 116 if (!flush) { 117 WS(strm)->inflate_state.wsize = 0; 118 WS(strm)->inflate_state.window = NULL; 119 } 120 121 while (rc == Z_OK) { 122 if (strm->avail_in == 0) { 123 /* TODO: handle case where both pos and fill are set */ 124 len = fill(zbuf, GZIP_IOBUF_SIZE); 125 if (len < 0) { 126 rc = -1; 127 error("read error"); 128 break; 129 } 130 strm->next_in = zbuf; 131 strm->avail_in = len; 132 } 133 rc = zlib_inflate(strm, 0); 134 135 /* Write any data generated */ 136 if (flush && strm->next_out > out_buf) { 137 int l = strm->next_out - out_buf; 138 if (l != flush(out_buf, l)) { 139 rc = -1; 140 error("write error"); 141 break; 142 } 143 strm->next_out = out_buf; 144 strm->avail_out = out_len; 145 } 146 147 /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ 148 if (rc == Z_STREAM_END) { 149 rc = 0; 150 break; 151 } else if (rc != Z_OK) { 152 error("uncompression error"); 153 rc = -1; 154 } 155 } 156 157 zlib_inflateEnd(strm); 158 if (pos) 159 /* add + 8 to skip over trailer */ 160 *pos = strm->next_in - zbuf+8; 161 162 gunzip_5: 163 free(strm->workspace); 164 gunzip_nomem4: 165 free(strm); 166 gunzip_nomem3: 167 if (!buf) 168 free(zbuf); 169 gunzip_nomem2: 170 if (flush) 171 free(out_buf); 172 gunzip_nomem1: 173 return rc; /* returns Z_OK (0) if successful */ 174 } 175 176 #define decompress gunzip 177