/* * Wrapper for decompressing LZIP-compressed kernel, initramfs, and initrd * * Copyright (C) 2016-2024 Antonio Diaz Diaz. * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ #ifdef STATIC #define PREBOOT #include "lzip_decompress.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 include/linux/decompress/generic.h) should have an * out_size argument to prevent overflowing 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