Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #ifdef STATIC
0003 #define PREBOOT
0004 /* Pre-boot environment: included */
0005 
0006 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
0007  * errors about console_printk etc... on ARM */
0008 #define _LINUX_KERNEL_H
0009 
0010 #include "zlib_inflate/inftrees.c"
0011 #include "zlib_inflate/inffast.c"
0012 #include "zlib_inflate/inflate.c"
0013 #ifdef CONFIG_ZLIB_DFLTCC
0014 #include "zlib_dfltcc/dfltcc.c"
0015 #include "zlib_dfltcc/dfltcc_inflate.c"
0016 #endif
0017 
0018 #else /* STATIC */
0019 /* initramfs et al: linked */
0020 
0021 #include <linux/zutil.h>
0022 
0023 #include "zlib_inflate/inftrees.h"
0024 #include "zlib_inflate/inffast.h"
0025 #include "zlib_inflate/inflate.h"
0026 
0027 #include "zlib_inflate/infutil.h"
0028 #include <linux/decompress/inflate.h>
0029 
0030 #endif /* STATIC */
0031 
0032 #include <linux/decompress/mm.h>
0033 
0034 #define GZIP_IOBUF_SIZE (16*1024)
0035 
0036 static long INIT nofill(void *buffer, unsigned long len)
0037 {
0038     return -1;
0039 }
0040 
0041 /* Included from initramfs et al code */
0042 STATIC int INIT __gunzip(unsigned char *buf, long len,
0043                long (*fill)(void*, unsigned long),
0044                long (*flush)(void*, unsigned long),
0045                unsigned char *out_buf, long out_len,
0046                long *pos,
0047                void(*error)(char *x)) {
0048     u8 *zbuf;
0049     struct z_stream_s *strm;
0050     int rc;
0051 
0052     rc = -1;
0053     if (flush) {
0054         out_len = 0x8000; /* 32 K */
0055         out_buf = malloc(out_len);
0056     } else {
0057         if (!out_len)
0058             out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
0059     }
0060     if (!out_buf) {
0061         error("Out of memory while allocating output buffer");
0062         goto gunzip_nomem1;
0063     }
0064 
0065     if (buf)
0066         zbuf = buf;
0067     else {
0068         zbuf = malloc(GZIP_IOBUF_SIZE);
0069         len = 0;
0070     }
0071     if (!zbuf) {
0072         error("Out of memory while allocating input buffer");
0073         goto gunzip_nomem2;
0074     }
0075 
0076     strm = malloc(sizeof(*strm));
0077     if (strm == NULL) {
0078         error("Out of memory while allocating z_stream");
0079         goto gunzip_nomem3;
0080     }
0081 
0082     strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
0083 #ifdef CONFIG_ZLIB_DFLTCC
0084     /* Always allocate the full workspace for DFLTCC */
0085                  zlib_inflate_workspacesize());
0086 #else
0087                  sizeof(struct inflate_state));
0088 #endif
0089     if (strm->workspace == NULL) {
0090         error("Out of memory while allocating workspace");
0091         goto gunzip_nomem4;
0092     }
0093 
0094     if (!fill)
0095         fill = nofill;
0096 
0097     if (len == 0)
0098         len = fill(zbuf, GZIP_IOBUF_SIZE);
0099 
0100     /* verify the gzip header */
0101     if (len < 10 ||
0102        zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
0103         if (pos)
0104             *pos = 0;
0105         error("Not a gzip file");
0106         goto gunzip_5;
0107     }
0108 
0109     /* skip over gzip header (1f,8b,08... 10 bytes total +
0110      * possible asciz filename)
0111      */
0112     strm->next_in = zbuf + 10;
0113     strm->avail_in = len - 10;
0114     /* skip over asciz filename */
0115     if (zbuf[3] & 0x8) {
0116         do {
0117             /*
0118              * If the filename doesn't fit into the buffer,
0119              * the file is very probably corrupt. Don't try
0120              * to read more data.
0121              */
0122             if (strm->avail_in == 0) {
0123                 error("header error");
0124                 goto gunzip_5;
0125             }
0126             --strm->avail_in;
0127         } while (*strm->next_in++);
0128     }
0129 
0130     strm->next_out = out_buf;
0131     strm->avail_out = out_len;
0132 
0133     rc = zlib_inflateInit2(strm, -MAX_WBITS);
0134 
0135 #ifdef CONFIG_ZLIB_DFLTCC
0136     /* Always keep the window for DFLTCC */
0137 #else
0138     if (!flush) {
0139         WS(strm)->inflate_state.wsize = 0;
0140         WS(strm)->inflate_state.window = NULL;
0141     }
0142 #endif
0143 
0144     while (rc == Z_OK) {
0145         if (strm->avail_in == 0) {
0146             /* TODO: handle case where both pos and fill are set */
0147             len = fill(zbuf, GZIP_IOBUF_SIZE);
0148             if (len < 0) {
0149                 rc = -1;
0150                 error("read error");
0151                 break;
0152             }
0153             strm->next_in = zbuf;
0154             strm->avail_in = len;
0155         }
0156         rc = zlib_inflate(strm, 0);
0157 
0158         /* Write any data generated */
0159         if (flush && strm->next_out > out_buf) {
0160             long l = strm->next_out - out_buf;
0161             if (l != flush(out_buf, l)) {
0162                 rc = -1;
0163                 error("write error");
0164                 break;
0165             }
0166             strm->next_out = out_buf;
0167             strm->avail_out = out_len;
0168         }
0169 
0170         /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
0171         if (rc == Z_STREAM_END) {
0172             rc = 0;
0173             break;
0174         } else if (rc != Z_OK) {
0175             error("uncompression error");
0176             rc = -1;
0177         }
0178     }
0179 
0180     zlib_inflateEnd(strm);
0181     if (pos)
0182         /* add + 8 to skip over trailer */
0183         *pos = strm->next_in - zbuf+8;
0184 
0185 gunzip_5:
0186     free(strm->workspace);
0187 gunzip_nomem4:
0188     free(strm);
0189 gunzip_nomem3:
0190     if (!buf)
0191         free(zbuf);
0192 gunzip_nomem2:
0193     if (flush)
0194         free(out_buf);
0195 gunzip_nomem1:
0196     return rc; /* returns Z_OK (0) if successful */
0197 }
0198 
0199 #ifndef PREBOOT
0200 STATIC int INIT gunzip(unsigned char *buf, long len,
0201                long (*fill)(void*, unsigned long),
0202                long (*flush)(void*, unsigned long),
0203                unsigned char *out_buf,
0204                long *pos,
0205                void (*error)(char *x))
0206 {
0207     return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
0208 }
0209 #else
0210 STATIC int INIT __decompress(unsigned char *buf, long len,
0211                long (*fill)(void*, unsigned long),
0212                long (*flush)(void*, unsigned long),
0213                unsigned char *out_buf, long out_len,
0214                long *pos,
0215                void (*error)(char *x))
0216 {
0217     return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
0218 }
0219 #endif