LzmaTools.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. * LZMA_Alone stream format:
  12. *
  13. * uchar Properties[5]
  14. * uint64 Uncompressed size
  15. * uchar data[*]
  16. *
  17. */
  18. #include <config.h>
  19. #include <common.h>
  20. #include <watchdog.h>
  21. #ifdef CONFIG_LZMA
  22. #define LZMA_PROPERTIES_OFFSET 0
  23. #define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE
  24. #define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t)
  25. #include "LzmaTools.h"
  26. #include "LzmaDec.h"
  27. #include <linux/string.h>
  28. #include <malloc.h>
  29. static void *SzAlloc(void *p, size_t size) { return malloc(size); }
  30. static void SzFree(void *p, void *address) { free(address); }
  31. int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
  32. unsigned char *inStream, SizeT length)
  33. {
  34. int res = SZ_ERROR_DATA;
  35. int i;
  36. ISzAlloc g_Alloc;
  37. SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */
  38. SizeT outProcessed;
  39. SizeT outSize;
  40. SizeT outSizeHigh;
  41. ELzmaStatus state;
  42. SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE);
  43. debug ("LZMA: Image address............... 0x%p\n", inStream);
  44. debug ("LZMA: Properties address.......... 0x%p\n", inStream + LZMA_PROPERTIES_OFFSET);
  45. debug ("LZMA: Uncompressed size address... 0x%p\n", inStream + LZMA_SIZE_OFFSET);
  46. debug ("LZMA: Compressed data address..... 0x%p\n", inStream + LZMA_DATA_OFFSET);
  47. debug ("LZMA: Destination address......... 0x%p\n", outStream);
  48. memset(&state, 0, sizeof(state));
  49. outSize = 0;
  50. outSizeHigh = 0;
  51. /* Read the uncompressed size */
  52. for (i = 0; i < 8; i++) {
  53. unsigned char b = inStream[LZMA_SIZE_OFFSET + i];
  54. if (i < 4) {
  55. outSize += (UInt32)(b) << (i * 8);
  56. } else {
  57. outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
  58. }
  59. }
  60. outSizeFull = (SizeT)outSize;
  61. if (sizeof(SizeT) >= 8) {
  62. /*
  63. * SizeT is a 64 bit uint => We can manage files larger than 4GB!
  64. *
  65. */
  66. outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
  67. } else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) {
  68. /*
  69. * SizeT is a 32 bit uint => We cannot manage files larger than
  70. * 4GB! Assume however that all 0xf values is "unknown size" and
  71. * not actually a file of 2^64 bits.
  72. *
  73. */
  74. if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) {
  75. debug ("LZMA: 64bit support not enabled.\n");
  76. return SZ_ERROR_DATA;
  77. }
  78. }
  79. debug("LZMA: Uncompresed size............ 0x%zx\n", outSizeFull);
  80. debug("LZMA: Compresed size.............. 0x%zx\n", compressedSize);
  81. g_Alloc.Alloc = SzAlloc;
  82. g_Alloc.Free = SzFree;
  83. /* Short-circuit early if we know the buffer can't hold the results. */
  84. if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull)
  85. return SZ_ERROR_OUTPUT_EOF;
  86. /* Decompress */
  87. outProcessed = min(outSizeFull, *uncompressedSize);
  88. WATCHDOG_RESET();
  89. res = LzmaDecode(
  90. outStream, &outProcessed,
  91. inStream + LZMA_DATA_OFFSET, &compressedSize,
  92. inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc);
  93. *uncompressedSize = outProcessed;
  94. debug("LZMA: Uncompressed ............... 0x%zx\n", outProcessed);
  95. if (res != SZ_OK) {
  96. return res;
  97. }
  98. return res;
  99. }
  100. #endif