123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // SPDX-License-Identifier: GPL-2.0
- #ifdef STATIC
- #define PREBOOT
- /* Pre-boot environment: included */
- /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
- * errors about console_printk etc... on ARM */
- #define _LINUX_KERNEL_H
- #include "zlib_inflate/inftrees.c"
- #include "zlib_inflate/inffast.c"
- #include "zlib_inflate/inflate.c"
- #else /* STATIC */
- /* initramfs et al: linked */
- #include <linux/zutil.h>
- #include "zlib_inflate/inftrees.h"
- #include "zlib_inflate/inffast.h"
- #include "zlib_inflate/inflate.h"
- #include "zlib_inflate/infutil.h"
- #include <linux/decompress/inflate.h>
- #endif /* STATIC */
- #include <linux/decompress/mm.h>
- #define GZIP_IOBUF_SIZE (16*1024)
- static long INIT nofill(void *buffer, unsigned long len)
- {
- return -1;
- }
- /* Included from initramfs et al code */
- STATIC int INIT __gunzip(unsigned char *buf, long len,
- long (*fill)(void*, unsigned long),
- long (*flush)(void*, unsigned long),
- unsigned char *out_buf, long out_len,
- long *pos,
- void(*error)(char *x)) {
- u8 *zbuf;
- struct z_stream_s *strm;
- int rc;
- rc = -1;
- if (flush) {
- out_len = 0x8000; /* 32 K */
- out_buf = malloc(out_len);
- } else {
- if (!out_len)
- out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
- }
- if (!out_buf) {
- error("Out of memory while allocating output buffer");
- goto gunzip_nomem1;
- }
- if (buf)
- zbuf = buf;
- else {
- zbuf = malloc(GZIP_IOBUF_SIZE);
- len = 0;
- }
- if (!zbuf) {
- error("Out of memory while allocating input buffer");
- goto gunzip_nomem2;
- }
- strm = malloc(sizeof(*strm));
- if (strm == NULL) {
- error("Out of memory while allocating z_stream");
- goto gunzip_nomem3;
- }
- strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
- sizeof(struct inflate_state));
- if (strm->workspace == NULL) {
- error("Out of memory while allocating workspace");
- goto gunzip_nomem4;
- }
- if (!fill)
- fill = nofill;
- if (len == 0)
- len = fill(zbuf, GZIP_IOBUF_SIZE);
- /* verify the gzip header */
- if (len < 10 ||
- zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
- if (pos)
- *pos = 0;
- error("Not a gzip file");
- goto gunzip_5;
- }
- /* skip over gzip header (1f,8b,08... 10 bytes total +
- * possible asciz filename)
- */
- strm->next_in = zbuf + 10;
- strm->avail_in = len - 10;
- /* skip over asciz filename */
- if (zbuf[3] & 0x8) {
- do {
- /*
- * If the filename doesn't fit into the buffer,
- * the file is very probably corrupt. Don't try
- * to read more data.
- */
- if (strm->avail_in == 0) {
- error("header error");
- goto gunzip_5;
- }
- --strm->avail_in;
- } while (*strm->next_in++);
- }
- strm->next_out = out_buf;
- strm->avail_out = out_len;
- rc = zlib_inflateInit2(strm, -MAX_WBITS);
- if (!flush) {
- WS(strm)->inflate_state.wsize = 0;
- WS(strm)->inflate_state.window = NULL;
- }
- while (rc == Z_OK) {
- if (strm->avail_in == 0) {
- /* TODO: handle case where both pos and fill are set */
- len = fill(zbuf, GZIP_IOBUF_SIZE);
- if (len < 0) {
- rc = -1;
- error("read error");
- break;
- }
- strm->next_in = zbuf;
- strm->avail_in = len;
- }
- rc = zlib_inflate(strm, 0);
- /* Write any data generated */
- if (flush && strm->next_out > out_buf) {
- long l = strm->next_out - out_buf;
- if (l != flush(out_buf, l)) {
- rc = -1;
- error("write error");
- break;
- }
- strm->next_out = out_buf;
- strm->avail_out = out_len;
- }
- /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
- if (rc == Z_STREAM_END) {
- rc = 0;
- break;
- } else if (rc != Z_OK) {
- error("uncompression error");
- rc = -1;
- }
- }
- zlib_inflateEnd(strm);
- if (pos)
- /* add + 8 to skip over trailer */
- *pos = strm->next_in - zbuf+8;
- gunzip_5:
- free(strm->workspace);
- gunzip_nomem4:
- free(strm);
- gunzip_nomem3:
- if (!buf)
- free(zbuf);
- gunzip_nomem2:
- if (flush)
- free(out_buf);
- gunzip_nomem1:
- return rc; /* returns Z_OK (0) if successful */
- }
- #ifndef PREBOOT
- STATIC int INIT gunzip(unsigned char *buf, long len,
- long (*fill)(void*, unsigned long),
- long (*flush)(void*, unsigned long),
- unsigned char *out_buf,
- long *pos,
- void (*error)(char *x))
- {
- return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
- }
- #else
- STATIC int INIT __decompress(unsigned char *buf, long len,
- long (*fill)(void*, unsigned long),
- long (*flush)(void*, unsigned long),
- unsigned char *out_buf, long out_len,
- long *pos,
- void (*error)(char *x))
- {
- return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
- }
- #endif
|