b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * uncompress.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * (C) Copyright 1999 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * cramfs interfaces to the uncompression library. There's really just
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * three entrypoints:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * - cramfs_uncompress_init() - called to initialize the thing.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * - cramfs_uncompress_exit() - tell me when you're done
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) * - cramfs_uncompress_block() - uncompress a block.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) * only have one stream, and we'll initialize it only once even if it
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * then is used by multiple filesystems.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18)
4f21e1ea09e1e (Fabian Frederick 2014-08-08 14:22:50 -0700 19) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4f21e1ea09e1e (Fabian Frederick 2014-08-08 14:22:50 -0700 20)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) #include <linux/vmalloc.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) #include <linux/zlib.h>
f7f4f4dd6948e (Al Viro 2013-12-10 16:54:28 -0500 25) #include "internal.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) static z_stream stream;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) static int initialized;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) /* Returns length of decompressed data. */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) stream.next_in = src;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) stream.avail_in = srclen;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 37)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 38) stream.next_out = dst;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) stream.avail_out = dstlen;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) err = zlib_inflateReset(&stream);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) if (err != Z_OK) {
f175ff8100eef (Fabian Frederick 2014-08-08 14:22:48 -0700 43) pr_err("zlib_inflateReset error %d\n", err);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) zlib_inflateEnd(&stream);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) zlib_inflateInit(&stream);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) err = zlib_inflate(&stream, Z_FINISH);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) if (err != Z_STREAM_END)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) goto err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51) return stream.total_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 53) err:
f175ff8100eef (Fabian Frederick 2014-08-08 14:22:48 -0700 54) pr_err("Error %d while decompressing!\n", err);
f175ff8100eef (Fabian Frederick 2014-08-08 14:22:48 -0700 55) pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
98310e581e098 (David VomLehn 2009-04-02 16:59:15 -0700 56) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) int cramfs_uncompress_init(void)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) if (!initialized++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) stream.workspace = vmalloc(zlib_inflate_workspacesize());
31d92e55198d4 (Fabian Frederick 2014-08-08 14:22:52 -0700 63) if (!stream.workspace) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) initialized = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) stream.next_in = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) stream.avail_in = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) zlib_inflateInit(&stream);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73)
368bdb3d616fa (Alexey Dobriyan 2006-09-29 02:01:05 -0700 74) void cramfs_uncompress_exit(void)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) if (!--initialized) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) zlib_inflateEnd(&stream);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) vfree(stream.workspace);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) }