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 * 978acc472SPeter Tyser * See file CREDITS for list of people who contributed to this 1078acc472SPeter Tyser * project. 1178acc472SPeter Tyser * 1278acc472SPeter Tyser * This program is free software; you can redistribute it and/or 1378acc472SPeter Tyser * modify it under the terms of the GNU General Public License as 1478acc472SPeter Tyser * published by the Free Software Foundation; either version 2 of 1578acc472SPeter Tyser * the License, or (at your option) any later version. 1678acc472SPeter Tyser * 1778acc472SPeter Tyser * This program is distributed in the hope that it will be useful, 1878acc472SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 1978acc472SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2078acc472SPeter Tyser * GNU General Public License for more details. 2178acc472SPeter Tyser * 2278acc472SPeter Tyser * You should have received a copy of the GNU General Public License 2378acc472SPeter Tyser * along with this program; if not, write to the Free Software 2478acc472SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2578acc472SPeter Tyser * MA 02111-1307 USA 2678acc472SPeter Tyser */ 2778acc472SPeter Tyser 2878acc472SPeter Tyser /* 2978acc472SPeter Tyser * LZMA_Alone stream format: 3078acc472SPeter Tyser * 3178acc472SPeter Tyser * uchar Properties[5] 3278acc472SPeter Tyser * uint64 Uncompressed size 3378acc472SPeter Tyser * uchar data[*] 3478acc472SPeter Tyser * 3578acc472SPeter Tyser */ 3678acc472SPeter Tyser 3778acc472SPeter Tyser #include <config.h> 3878acc472SPeter Tyser #include <common.h> 3978acc472SPeter Tyser #include <watchdog.h> 4078acc472SPeter Tyser 4178acc472SPeter Tyser #ifdef CONFIG_LZMA 4278acc472SPeter Tyser 4378acc472SPeter Tyser #define LZMA_PROPERTIES_OFFSET 0 4478acc472SPeter Tyser #define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE 4578acc472SPeter Tyser #define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t) 4678acc472SPeter Tyser 4778acc472SPeter Tyser #include "LzmaTools.h" 4878acc472SPeter Tyser #include "LzmaDec.h" 4978acc472SPeter Tyser 5078acc472SPeter Tyser #include <linux/string.h> 5178acc472SPeter Tyser #include <malloc.h> 5278acc472SPeter Tyser 5378acc472SPeter Tyser static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } 5478acc472SPeter Tyser static void SzFree(void *p, void *address) { p = p; free(address); } 5578acc472SPeter Tyser 5678acc472SPeter Tyser int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize, 5778acc472SPeter Tyser unsigned char *inStream, SizeT length) 5878acc472SPeter Tyser { 5978acc472SPeter Tyser int res = SZ_ERROR_DATA; 6078acc472SPeter Tyser int i; 6178acc472SPeter Tyser ISzAlloc g_Alloc; 6278acc472SPeter Tyser 6378acc472SPeter Tyser SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */ 6478acc472SPeter Tyser SizeT outProcessed; 6578acc472SPeter Tyser SizeT outSize; 6678acc472SPeter Tyser SizeT outSizeHigh; 6778acc472SPeter Tyser ELzmaStatus state; 6878acc472SPeter Tyser SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE); 6978acc472SPeter Tyser 70dd059842SMarek Vasut debug ("LZMA: Image address............... 0x%p\n", inStream); 71dd059842SMarek Vasut debug ("LZMA: Properties address.......... 0x%p\n", inStream + LZMA_PROPERTIES_OFFSET); 72dd059842SMarek Vasut debug ("LZMA: Uncompressed size address... 0x%p\n", inStream + LZMA_SIZE_OFFSET); 73dd059842SMarek Vasut debug ("LZMA: Compressed data address..... 0x%p\n", inStream + LZMA_DATA_OFFSET); 74dd059842SMarek Vasut debug ("LZMA: Destination address......... 0x%p\n", outStream); 7578acc472SPeter Tyser 7678acc472SPeter Tyser memset(&state, 0, sizeof(state)); 7778acc472SPeter Tyser 7878acc472SPeter Tyser outSize = 0; 7978acc472SPeter Tyser outSizeHigh = 0; 8078acc472SPeter Tyser /* Read the uncompressed size */ 8178acc472SPeter Tyser for (i = 0; i < 8; i++) { 8278acc472SPeter Tyser unsigned char b = inStream[LZMA_SIZE_OFFSET + i]; 8378acc472SPeter Tyser if (i < 4) { 8478acc472SPeter Tyser outSize += (UInt32)(b) << (i * 8); 8578acc472SPeter Tyser } else { 8678acc472SPeter Tyser outSizeHigh += (UInt32)(b) << ((i - 4) * 8); 8778acc472SPeter Tyser } 8878acc472SPeter Tyser } 8978acc472SPeter Tyser 9078acc472SPeter Tyser outSizeFull = (SizeT)outSize; 9178acc472SPeter Tyser if (sizeof(SizeT) >= 8) { 9278acc472SPeter Tyser /* 9378acc472SPeter Tyser * SizeT is a 64 bit uint => We can manage files larger than 4GB! 9478acc472SPeter Tyser * 9578acc472SPeter Tyser */ 9678acc472SPeter Tyser outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); 9778acc472SPeter Tyser } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) { 9878acc472SPeter Tyser /* 9978acc472SPeter Tyser * SizeT is a 32 bit uint => We cannot manage files larger than 10078acc472SPeter Tyser * 4GB! Assume however that all 0xf values is "unknown size" and 10178acc472SPeter Tyser * not actually a file of 2^64 bits. 10278acc472SPeter Tyser * 10378acc472SPeter Tyser */ 10478acc472SPeter Tyser if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) { 10578acc472SPeter Tyser debug ("LZMA: 64bit support not enabled.\n"); 10678acc472SPeter Tyser return SZ_ERROR_DATA; 10778acc472SPeter Tyser } 10878acc472SPeter Tyser } 10978acc472SPeter Tyser 110*f3e6110aSMike Frysinger debug("LZMA: Uncompresed size............ 0x%zx\n", outSizeFull); 111*f3e6110aSMike Frysinger debug("LZMA: Compresed size.............. 0x%zx\n", compressedSize); 11278acc472SPeter Tyser 11378acc472SPeter Tyser g_Alloc.Alloc = SzAlloc; 11478acc472SPeter Tyser g_Alloc.Free = SzFree; 11578acc472SPeter Tyser 11678acc472SPeter Tyser /* Decompress */ 11778acc472SPeter Tyser outProcessed = outSizeFull; 11878acc472SPeter Tyser 11978acc472SPeter Tyser WATCHDOG_RESET(); 12078acc472SPeter Tyser 12178acc472SPeter Tyser res = LzmaDecode( 12278acc472SPeter Tyser outStream, &outProcessed, 12378acc472SPeter Tyser inStream + LZMA_DATA_OFFSET, &compressedSize, 12478acc472SPeter Tyser inStream, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &state, &g_Alloc); 12578acc472SPeter Tyser *uncompressedSize = outProcessed; 12678acc472SPeter Tyser if (res != SZ_OK) { 12778acc472SPeter Tyser return res; 12878acc472SPeter Tyser } 12978acc472SPeter Tyser 13078acc472SPeter Tyser return res; 13178acc472SPeter Tyser } 13278acc472SPeter Tyser 13378acc472SPeter Tyser #endif 134