^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * LZO decompressor for the Linux kernel. Code borrowed from the lzo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * implementation by Markus Franz Xaver Johannes Oberhumer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Linux kernel adaptation:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Original code:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Markus F.X.J. Oberhumer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * <markus@oberhumer.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * http://www.oberhumer.com/opensource/lzop/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #ifdef STATIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "lzo/lzo1x_decompress_safe.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/decompress/unlzo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/lzo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/decompress/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static const unsigned char lzop_magic[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define LZO_BLOCK_SIZE (256*1024l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define HEADER_HAS_FILTER 0x00000800L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define HEADER_SIZE_MIN (9 + 7 + 4 + 8 + 1 + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define HEADER_SIZE_MAX (9 + 7 + 1 + 8 + 8 + 4 + 1 + 255 + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) STATIC inline long INIT parse_header(u8 *input, long *skip, long in_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u8 *parse = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u8 *end = input + in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u8 level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u16 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Check that there's enough input to possibly have a valid header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Then it is possible to parse several fields until the minimum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * size may have been used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (in_len < HEADER_SIZE_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* read magic: 9 first bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) for (l = 0; l < 9; l++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (*parse++ != lzop_magic[l])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* get version (2bytes), skip library version (2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * 'need to be extracted' version (2) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * method (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) version = get_unaligned_be16(parse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) parse += 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (version >= 0x0940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) level = *parse++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (get_unaligned_be32(parse) & HEADER_HAS_FILTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) parse += 8; /* flags + filter info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) parse += 4; /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * At least mode, mtime_low, filename length, and checksum must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * be left to be parsed. If also mtime_high is present, it's OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * because the next input buffer check is after reading the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * filename length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (end - parse < 8 + 1 + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* skip mode and mtime_low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) parse += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (version >= 0x0940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) parse += 4; /* skip mtime_high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) l = *parse++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* don't care about the file name, and skip checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (end - parse < l + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) parse += l + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *skip = parse - input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) STATIC int INIT unlzo(u8 *input, long in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) long (*fill)(void *, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) long (*flush)(void *, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 *output, long *posp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void (*error) (char *x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u8 r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) long skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 src_len, dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) size_t tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u8 *in_buf, *in_buf_save, *out_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) out_buf = output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) } else if (!flush) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) error("NULL output pointer and no flush function provided");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) out_buf = malloc(LZO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!out_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) error("Could not allocate output buffer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (input && fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) error("Both input pointer and fill function provided, don't know what to do");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } else if (input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) in_buf = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) } else if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) error("NULL input pointer and missing fill function");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!in_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) error("Could not allocate input buffer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) in_buf_save = in_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) *posp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * Start from in_buf + HEADER_SIZE_MAX to make it possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * to use memcpy() to copy the unused data to the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * of the buffer. This way memmove() isn't needed which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * is missing from pre-boot environments of most archs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) in_buf += HEADER_SIZE_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) in_len = fill(in_buf, HEADER_SIZE_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!parse_header(in_buf, &skip, in_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) error("invalid header");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) in_buf += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) in_len -= skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* Move the unused data to the beginning of the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) memcpy(in_buf_save, in_buf, in_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) in_buf = in_buf_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *posp = skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* read uncompressed block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (fill && in_len < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) skip = fill(in_buf + in_len, 4 - in_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (skip > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) in_len += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (in_len < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) error("file corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dst_len = get_unaligned_be32(in_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) in_buf += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) in_len -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* exit if last block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (dst_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *posp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (dst_len > LZO_BLOCK_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) error("dest len longer than block size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* read compressed block size, and skip block checksum info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (fill && in_len < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) skip = fill(in_buf + in_len, 8 - in_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (skip > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) in_len += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (in_len < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) error("file corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) src_len = get_unaligned_be32(in_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) in_buf += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) in_len -= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (src_len <= 0 || src_len > dst_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) error("file corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* decompress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (fill && in_len < src_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) skip = fill(in_buf + in_len, src_len - in_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (skip > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) in_len += skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (in_len < src_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) error("file corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) tmp = dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* When the input data is not compressed at all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * lzo1x_decompress_safe will fail, so call memcpy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (unlikely(dst_len == src_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) memcpy(out_buf, in_buf, src_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) r = lzo1x_decompress_safe((u8 *) in_buf, src_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) out_buf, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (r != LZO_E_OK || dst_len != tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) error("Compressed data violation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (flush && flush(out_buf, dst_len) != dst_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) out_buf += dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *posp += src_len + 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) in_buf += src_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) in_len -= src_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * If there happens to still be unused data left in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * in_buf, move it to the beginning of the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Use a loop to avoid memmove() dependency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (in_len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) for (skip = 0; skip < in_len; ++skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) in_buf_save[skip] = in_buf[skip];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) in_buf = in_buf_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) exit_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (!input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) free(in_buf_save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) exit_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) free(out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) #ifdef PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) STATIC int INIT __decompress(unsigned char *buf, long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) long (*fill)(void*, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) long (*flush)(void*, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) unsigned char *out_buf, long olen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) long *pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) void (*error)(char *x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return unlzo(buf, len, fill, flush, out_buf, pos, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #endif