LzmaTools.c 3.5 KB

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