uboot/lib/lzma/LzmaTools.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
   4 *
   5 * Copyright (C) 2007-2009 Industrie Dial Face S.p.A.
   6 * Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
   7 *
   8 * Copyright (C) 1999-2005 Igor Pavlov
   9 */
  10
  11/*
  12 * LZMA_Alone stream format:
  13 *
  14 * uchar   Properties[5]
  15 * uint64  Uncompressed size
  16 * uchar   data[*]
  17 *
  18 */
  19
  20#include <config.h>
  21#include <common.h>
  22#include <watchdog.h>
  23
  24#ifdef CONFIG_LZMA
  25
  26#define LZMA_PROPERTIES_OFFSET 0
  27#define LZMA_SIZE_OFFSET       LZMA_PROPS_SIZE
  28#define LZMA_DATA_OFFSET       LZMA_SIZE_OFFSET+sizeof(uint64_t)
  29
  30#include "LzmaTools.h"
  31#include "LzmaDec.h"
  32
  33#include <linux/string.h>
  34#include <malloc.h>
  35
  36static void *SzAlloc(void *p, size_t size) { return malloc(size); }
  37static void SzFree(void *p, void *address) { free(address); }
  38
  39int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
  40                  unsigned char *inStream,  SizeT  length)
  41{
  42    int res = SZ_ERROR_DATA;
  43    int i;
  44    ISzAlloc g_Alloc;
  45
  46    SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */
  47    SizeT outProcessed;
  48    SizeT outSize;
  49    SizeT outSizeHigh;
  50    ELzmaStatus state;
  51    SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE);
  52
  53    debug ("LZMA: Image address............... 0x%p\n", inStream);
  54    debug ("LZMA: Properties address.......... 0x%p\n", inStream + LZMA_PROPERTIES_OFFSET);
  55    debug ("LZMA: Uncompressed size address... 0x%p\n", inStream + LZMA_SIZE_OFFSET);
  56    debug ("LZMA: Compressed data address..... 0x%p\n", inStream + LZMA_DATA_OFFSET);
  57    debug ("LZMA: Destination address......... 0x%p\n", outStream);
  58
  59    memset(&state, 0, sizeof(state));
  60
  61    outSize = 0;
  62    outSizeHigh = 0;
  63    /* Read the uncompressed size */
  64    for (i = 0; i < 8; i++) {
  65        unsigned char b = inStream[LZMA_SIZE_OFFSET + i];
  66            if (i < 4) {
  67                outSize     += (UInt32)(b) << (i * 8);
  68        } else {
  69                outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
  70        }
  71    }
  72
  73    outSizeFull = (SizeT)outSize;
  74    if (sizeof(SizeT) >= 8) {
  75        /*
  76         * SizeT is a 64 bit uint => We can manage files larger than 4GB!
  77         *
  78         */
  79            outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
  80    } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) {
  81        /*
  82         * SizeT is a 32 bit uint => We cannot manage files larger than
  83         * 4GB!  Assume however that all 0xf values is "unknown size" and
  84         * not actually a file of 2^64 bits.
  85         *
  86         */
  87        if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) {
  88            debug ("LZMA: 64bit support not enabled.\n");
  89            return SZ_ERROR_DATA;
  90        }
  91    }
  92
  93    debug("LZMA: Uncompresed size............ 0x%zx\n", outSizeFull);
  94    debug("LZMA: Compresed size.............. 0x%zx\n", compressedSize);
  95
  96    g_Alloc.Alloc = SzAlloc;
  97    g_Alloc.Free = SzFree;
  98
  99    /* Short-circuit early if we know the buffer can't hold the results. */
 100    if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull)
 101        return SZ_ERROR_OUTPUT_EOF;
 102
 103    /* Decompress */
 104    outProcessed = min(outSizeFull, *uncompressedSize);
 105
 106    WATCHDOG_RESET();
 107
 108    res = LzmaDecode(
 109        outStream, &outProcessed,
 110        inStream + LZMA_DATA_OFFSET, &compressedSize,
 111        inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc);
 112    *uncompressedSize = outProcessed;
 113
 114    debug("LZMA: Uncompressed ............... 0x%zx\n", outProcessed);
 115
 116    if (res != SZ_OK)  {
 117        return res;
 118    }
 119
 120    return res;
 121}
 122
 123#endif
 124