100 lines
2.7 KiB
C
100 lines
2.7 KiB
C
/*
|
|
* 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_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
|