Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Wrapper for decompressing LZ4-compressed kernel, initramfs, and initrd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #ifdef STATIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #define PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include "lz4/lz4_decompress.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/decompress/unlz4.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/lz4.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/decompress/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Note: Uncompressed chunk size is used in the compressor side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * (userspace side for compression).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * It is hardcoded because there is not proper way to extract it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * from the binary stream which is generated by the preliminary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * version of LZ4 tool so far.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define ARCHIVE_MAGICNUMBER 0x184C2102
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) STATIC inline int INIT unlz4(u8 *input, long in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 				long (*fill)(void *, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 				long (*flush)(void *, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 				u8 *output, long *posp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 				void (*error) (char *x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	size_t chunksize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	u8 *inp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	u8 *inp_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	u8 *outp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	long size = in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #ifdef PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	size_t out_len = get_unaligned_le32(input + in_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	size_t dest_len;
^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) 	if (output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		outp = output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	} else if (!flush) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		error("NULL output pointer and no flush function provided");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		goto exit_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		outp = large_malloc(uncomp_chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		if (!outp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			error("Could not allocate output buffer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			goto exit_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (input && fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		error("Both input pointer and fill function provided,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	} else if (input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		inp = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	} else if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		error("NULL input pointer and missing fill function");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		inp = large_malloc(LZ4_compressBound(uncomp_chunksize));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		if (!inp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			error("Could not allocate input buffer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			goto exit_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	inp_start = inp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		*posp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		size = fill(inp, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		if (size < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			error("data corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	chunksize = get_unaligned_le32(inp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (chunksize == ARCHIVE_MAGICNUMBER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			inp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		error("invalid header");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		*posp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		if (fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			size = fill(inp, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			if (size < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				error("data corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 				goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		} else if (size < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			/* empty or end-of-file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			goto exit_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		chunksize = get_unaligned_le32(inp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		if (chunksize == ARCHIVE_MAGICNUMBER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 				inp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 				*posp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		if (!fill && chunksize == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			/* empty or end-of-file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			goto exit_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			*posp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			inp += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			if (chunksize > LZ4_compressBound(uncomp_chunksize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 				error("chunk length is longer than allocated");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 				goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			size = fill(inp, chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			if (size < chunksize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				error("data corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #ifdef PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		if (out_len >= uncomp_chunksize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			dest_len = uncomp_chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			out_len -= dest_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			dest_len = out_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		ret = LZ4_decompress_fast(inp, outp, dest_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		chunksize = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		dest_len = uncomp_chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		ret = LZ4_decompress_safe(inp, outp, chunksize, dest_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		dest_len = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			error("Decoding failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		if (flush && flush(outp, dest_len) != dest_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		if (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			outp += dest_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (posp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			*posp += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		if (!fill) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			size -= chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			else if (size < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 				error("data corrupted");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				goto exit_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			inp += chunksize;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) exit_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) exit_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (!input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		large_free(inp_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) exit_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (!output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		large_free(outp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) exit_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #ifdef PREBOOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) STATIC int INIT __decompress(unsigned char *buf, long in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			      long (*fill)(void*, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			      long (*flush)(void*, unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			      unsigned char *output, long out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			      long *posp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			      void (*error)(char *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #endif