xref: /aosp_15_r20/external/coreboot/src/lib/lzma.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 /*
4  * coreboot interface to memory-saving variant of LZMA decoder
5  *
6  * Copyright (C) 2006 Carl-Daniel Hailfinger
7  *
8  * Parts of this file are based on C/7zip/Compress/LZMA_C/LzmaTest.c from the
9  * LZMA SDK 4.42, which is written and distributed to public domain by Igor
10  * Pavlov.
11  *
12  */
13 
14 #include <console/console.h>
15 #include <string.h>
16 #include <lib.h>
17 
18 #include "lzmadecode.h"
19 
ulzman(const void * src,size_t srcn,void * dst,size_t dstn)20 size_t ulzman(const void *src, size_t srcn, void *dst, size_t dstn)
21 {
22 	unsigned char properties[LZMA_PROPERTIES_SIZE];
23 	const int data_offset = LZMA_PROPERTIES_SIZE + 8;
24 	UInt32 outSize;
25 	SizeT inProcessed;
26 	SizeT outProcessed;
27 	int res;
28 	CLzmaDecoderState state;
29 	SizeT mallocneeds;
30 	static unsigned char scratchpad[15980];
31 	const unsigned char *cp;
32 
33 	if (srcn < data_offset) {
34 		printk(BIOS_WARNING, "lzma: Input too small.\n");
35 		return 0;
36 	}
37 
38 	memcpy(properties, src, LZMA_PROPERTIES_SIZE);
39 	/* The outSize in LZMA stream is a 64bit integer stored in little-endian
40 	 * (ref: lzma.cc@LZMACompress: put_64). To prevent accessing by
41 	 * unaligned memory address and to load in correct endianness, read each
42 	 * byte and re-construct. */
43 	cp = src + LZMA_PROPERTIES_SIZE;
44 	outSize = cp[3] << 24 | cp[2] << 16 | cp[1] << 8 | cp[0];
45 	if (outSize > dstn)
46 		outSize = dstn;
47 	if (LzmaDecodeProperties(&state.Properties, properties,
48 				 LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) {
49 		printk(BIOS_WARNING, "lzma: Incorrect stream properties.\n");
50 		return 0;
51 	}
52 	mallocneeds = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
53 	if (mallocneeds > 15980) {
54 		printk(BIOS_WARNING, "lzma: Decoder scratchpad too small!\n");
55 		return 0;
56 	}
57 	state.Probs = (CProb *)scratchpad;
58 	res = LzmaDecode(&state, src + data_offset, srcn - data_offset,
59 			 &inProcessed, dst, outSize, &outProcessed);
60 	if (res != 0) {
61 		printk(BIOS_WARNING, "lzma: Decoding error = %d\n", res);
62 		return 0;
63 	}
64 	return outProcessed;
65 }
66