summaryrefslogtreecommitdiffstats
path: root/decompress_lunzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'decompress_lunzip.c')
-rw-r--r--decompress_lunzip.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/decompress_lunzip.c b/decompress_lunzip.c
new file mode 100644
index 0000000..106c95b
--- /dev/null
+++ b/decompress_lunzip.c
@@ -0,0 +1,100 @@
+/*
+ * Wrapper for decompressing LZIP-compressed kernel, initramfs, and initrd
+ *
+ * Copyright (C) 2016-2018 Antonio Diaz Diaz.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#ifdef STATIC
+#define PREBOOT
+#include "lzip.c"
+#else
+#include "linux_lzip.h"
+#include "linux_lunzip.h"
+#include "linux_mm.h"
+#endif
+
+STATIC int INIT __lunzip(unsigned char *inbuf, long in_len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+ unsigned char *outbuf, long out_size,
+ long *in_posp, long *out_posp,
+ void (*error)(char *x))
+{
+ const int retval = lzip_decompress(inbuf, in_len, fill, flush,
+ outbuf, out_size, in_posp, out_posp);
+ switch (retval) {
+ case 0: break;
+ case LZIP_OOM_INBUF:
+ error("Out of memory while allocating input buffer.");
+ break;
+ case LZIP_HEADER1_EOF:
+ error("File ends unexpectedly at member header.");
+ break;
+ case LZIP_HEADER2_EOF:
+ error("Truncated header in multimember file.");
+ break;
+ case LZIP_BAD_MAGIC1:
+ error("Bad magic number (file not in lzip format).");
+ break;
+ case LZIP_BAD_MAGIC2:
+ error("Corrupt header in multimember file.");
+ break;
+ case LZIP_BAD_VERSION:
+ error("Version of lzip member format not supported.");
+ break;
+ case LZIP_BAD_DICT_SIZE:
+ error("Invalid dictionary size in member header.");
+ break;
+ case LZIP_OOM_OUTBUF:
+ error("Out of memory while allocating output buffer.");
+ break;
+ case LZIP_WRITE_ERROR:
+ error("Write error.");
+ break;
+ case LZIP_BAD_DATA:
+ error("LZIP-compressed data is corrupt.");
+ break;
+ case LZIP_DATA_EOF:
+ error("LZIP-compressed data ends unexpectedly.");
+ break;
+ case LZIP_BAD_CRC:
+ error("CRC mismatch in LZIP-compressed data.");
+ break;
+ default:
+ error("Bug in the LZIP decompressor.");
+ }
+ return retval;
+}
+
+#ifndef PREBOOT
+/* decompress_fn (see linux/decompress/generic.h) should have an out_size
+ * argument to prevent overrunning outbuf in case of corruption of the
+ * compressed data.
+ */
+STATIC int INIT lunzip(unsigned char *inbuf, long in_len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+ unsigned char *outbuf,
+ long *in_posp,
+ void (*error)(char *x))
+{
+ return __lunzip(inbuf, in_len, fill, flush, outbuf, LONG_MAX,
+ in_posp, 0, error);
+}
+#else
+STATIC int INIT __decompress(unsigned char *inbuf, long in_len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+ unsigned char *outbuf, long out_size,
+ long *in_posp,
+ void (*error)(char *x))
+{
+/* Some archs pass out_size = 0 (to mean unlimited size), which is unsafe
+ * in case of corruption of the compressed data.
+ */
+ return __lunzip(inbuf, in_len - 4, fill, flush, outbuf,
+ out_size ? out_size : LONG_MAX, in_posp, 0, error);
+}
+#endif