178acc472SPeter Tyser /* 278acc472SPeter Tyser * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65 378acc472SPeter Tyser * 478acc472SPeter Tyser * Copyright (C) 2007-2009 Industrie Dial Face S.p.A. 578acc472SPeter Tyser * Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com) 678acc472SPeter Tyser * 778acc472SPeter Tyser * Copyright (C) 1999-2005 Igor Pavlov 878acc472SPeter Tyser * 91a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1078acc472SPeter Tyser */ 1178acc472SPeter Tyser 1278acc472SPeter Tyser /* 1378acc472SPeter Tyser * LZMA_Alone stream format: 1478acc472SPeter Tyser * 1578acc472SPeter Tyser * uchar Properties[5] 1678acc472SPeter Tyser * uint64 Uncompressed size 1778acc472SPeter Tyser * uchar data[*] 1878acc472SPeter Tyser * 1978acc472SPeter Tyser */ 2078acc472SPeter Tyser 2178acc472SPeter Tyser #include <config.h> 2278acc472SPeter Tyser #include <common.h> 2378acc472SPeter Tyser #include <watchdog.h> 2478acc472SPeter Tyser 2578acc472SPeter Tyser #ifdef CONFIG_LZMA 2678acc472SPeter Tyser 2778acc472SPeter Tyser #define LZMA_PROPERTIES_OFFSET 0 2878acc472SPeter Tyser #define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE 2978acc472SPeter Tyser #define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t) 3078acc472SPeter Tyser 3178acc472SPeter Tyser #include "LzmaTools.h" 3278acc472SPeter Tyser #include "LzmaDec.h" 3378acc472SPeter Tyser 3478acc472SPeter Tyser #include <linux/string.h> 3578acc472SPeter Tyser #include <malloc.h> 3678acc472SPeter Tyser 37*867abdacSJeroen Hofstee static void *SzAlloc(void *p, size_t size) { return malloc(size); } 38*867abdacSJeroen Hofstee static void SzFree(void *p, void *address) { free(address); } 3978acc472SPeter Tyser 4078acc472SPeter Tyser int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize, 4178acc472SPeter Tyser unsigned char *inStream, SizeT length) 4278acc472SPeter Tyser { 4378acc472SPeter Tyser int res = SZ_ERROR_DATA; 4478acc472SPeter Tyser int i; 4578acc472SPeter Tyser ISzAlloc g_Alloc; 4678acc472SPeter Tyser 4778acc472SPeter Tyser SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */ 4878acc472SPeter Tyser SizeT outProcessed; 4978acc472SPeter Tyser SizeT outSize; 5078acc472SPeter Tyser SizeT outSizeHigh; 5178acc472SPeter Tyser ELzmaStatus state; 5278acc472SPeter Tyser SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE); 5378acc472SPeter Tyser 54dd059842SMarek Vasut debug ("LZMA: Image address............... 0x%p\n", inStream); 55dd059842SMarek Vasut debug ("LZMA: Properties address.......... 0x%p\n", inStream + LZMA_PROPERTIES_OFFSET); 56dd059842SMarek Vasut debug ("LZMA: Uncompressed size address... 0x%p\n", inStream + LZMA_SIZE_OFFSET); 57dd059842SMarek Vasut debug ("LZMA: Compressed data address..... 0x%p\n", inStream + LZMA_DATA_OFFSET); 58dd059842SMarek Vasut debug ("LZMA: Destination address......... 0x%p\n", outStream); 5978acc472SPeter Tyser 6078acc472SPeter Tyser memset(&state, 0, sizeof(state)); 6178acc472SPeter Tyser 6278acc472SPeter Tyser outSize = 0; 6378acc472SPeter Tyser outSizeHigh = 0; 6478acc472SPeter Tyser /* Read the uncompressed size */ 6578acc472SPeter Tyser for (i = 0; i < 8; i++) { 6678acc472SPeter Tyser unsigned char b = inStream[LZMA_SIZE_OFFSET + i]; 6778acc472SPeter Tyser if (i < 4) { 6878acc472SPeter Tyser outSize += (UInt32)(b) << (i * 8); 6978acc472SPeter Tyser } else { 7078acc472SPeter Tyser outSizeHigh += (UInt32)(b) << ((i - 4) * 8); 7178acc472SPeter Tyser } 7278acc472SPeter Tyser } 7378acc472SPeter Tyser 7478acc472SPeter Tyser outSizeFull = (SizeT)outSize; 7578acc472SPeter Tyser if (sizeof(SizeT) >= 8) { 7678acc472SPeter Tyser /* 7778acc472SPeter Tyser * SizeT is a 64 bit uint => We can manage files larger than 4GB! 7878acc472SPeter Tyser * 7978acc472SPeter Tyser */ 8078acc472SPeter Tyser outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); 8178acc472SPeter Tyser } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) { 8278acc472SPeter Tyser /* 8378acc472SPeter Tyser * SizeT is a 32 bit uint => We cannot manage files larger than 8478acc472SPeter Tyser * 4GB! Assume however that all 0xf values is "unknown size" and 8578acc472SPeter Tyser * not actually a file of 2^64 bits. 8678acc472SPeter Tyser * 8778acc472SPeter Tyser */ 8878acc472SPeter Tyser if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) { 8978acc472SPeter Tyser debug ("LZMA: 64bit support not enabled.\n"); 9078acc472SPeter Tyser return SZ_ERROR_DATA; 9178acc472SPeter Tyser } 9278acc472SPeter Tyser } 9378acc472SPeter Tyser 94f3e6110aSMike Frysinger debug("LZMA: Uncompresed size............ 0x%zx\n", outSizeFull); 95f3e6110aSMike Frysinger debug("LZMA: Compresed size.............. 0x%zx\n", compressedSize); 9678acc472SPeter Tyser 9778acc472SPeter Tyser g_Alloc.Alloc = SzAlloc; 9878acc472SPeter Tyser g_Alloc.Free = SzFree; 9978acc472SPeter Tyser 100afca2942SKees Cook /* Short-circuit early if we know the buffer can't hold the results. */ 101afca2942SKees Cook if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull) 102afca2942SKees Cook return SZ_ERROR_OUTPUT_EOF; 103afca2942SKees Cook 10478acc472SPeter Tyser /* Decompress */ 1054d3b8a0dSAntonios Vamporakis outProcessed = outSizeFull; 10678acc472SPeter Tyser 10778acc472SPeter Tyser WATCHDOG_RESET(); 10878acc472SPeter Tyser 10978acc472SPeter Tyser res = LzmaDecode( 11078acc472SPeter Tyser outStream, &outProcessed, 11178acc472SPeter Tyser inStream + LZMA_DATA_OFFSET, &compressedSize, 112afca2942SKees Cook inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc); 11378acc472SPeter Tyser *uncompressedSize = outProcessed; 1144d3b8a0dSAntonios Vamporakis 1154d3b8a0dSAntonios Vamporakis debug("LZMA: Uncompresed ................ 0x%zx\n", outProcessed); 1164d3b8a0dSAntonios Vamporakis 11778acc472SPeter Tyser if (res != SZ_OK) { 11878acc472SPeter Tyser return res; 11978acc472SPeter Tyser } 12078acc472SPeter Tyser 12178acc472SPeter Tyser return res; 12278acc472SPeter Tyser } 12378acc472SPeter Tyser 12478acc472SPeter Tyser #endif 125