decompress_inflate.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // SPDX-License-Identifier: GPL-2.0
  2. #ifdef STATIC
  3. #define PREBOOT
  4. /* Pre-boot environment: included */
  5. /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
  6. * errors about console_printk etc... on ARM */
  7. #define _LINUX_KERNEL_H
  8. #include "zlib_inflate/inftrees.c"
  9. #include "zlib_inflate/inffast.c"
  10. #include "zlib_inflate/inflate.c"
  11. #ifdef CONFIG_ZLIB_DFLTCC
  12. #include "zlib_dfltcc/dfltcc.c"
  13. #include "zlib_dfltcc/dfltcc_inflate.c"
  14. #endif
  15. #else /* STATIC */
  16. /* initramfs et al: linked */
  17. #include <linux/zutil.h>
  18. #include "zlib_inflate/inftrees.h"
  19. #include "zlib_inflate/inffast.h"
  20. #include "zlib_inflate/inflate.h"
  21. #include "zlib_inflate/infutil.h"
  22. #include <linux/decompress/inflate.h>
  23. #endif /* STATIC */
  24. #include <linux/decompress/mm.h>
  25. #define GZIP_IOBUF_SIZE (16*1024)
  26. static long INIT nofill(void *buffer, unsigned long len)
  27. {
  28. return -1;
  29. }
  30. /* Included from initramfs et al code */
  31. STATIC int INIT __gunzip(unsigned char *buf, long len,
  32. long (*fill)(void*, unsigned long),
  33. long (*flush)(void*, unsigned long),
  34. unsigned char *out_buf, long out_len,
  35. long *pos,
  36. void(*error)(char *x)) {
  37. u8 *zbuf;
  38. struct z_stream_s *strm;
  39. int rc;
  40. rc = -1;
  41. if (flush) {
  42. out_len = 0x8000; /* 32 K */
  43. out_buf = malloc(out_len);
  44. } else {
  45. if (!out_len)
  46. out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
  47. }
  48. if (!out_buf) {
  49. error("Out of memory while allocating output buffer");
  50. goto gunzip_nomem1;
  51. }
  52. if (buf)
  53. zbuf = buf;
  54. else {
  55. zbuf = malloc(GZIP_IOBUF_SIZE);
  56. len = 0;
  57. }
  58. if (!zbuf) {
  59. error("Out of memory while allocating input buffer");
  60. goto gunzip_nomem2;
  61. }
  62. strm = malloc(sizeof(*strm));
  63. if (strm == NULL) {
  64. error("Out of memory while allocating z_stream");
  65. goto gunzip_nomem3;
  66. }
  67. strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
  68. #ifdef CONFIG_ZLIB_DFLTCC
  69. /* Always allocate the full workspace for DFLTCC */
  70. zlib_inflate_workspacesize());
  71. #else
  72. sizeof(struct inflate_state));
  73. #endif
  74. if (strm->workspace == NULL) {
  75. error("Out of memory while allocating workspace");
  76. goto gunzip_nomem4;
  77. }
  78. if (!fill)
  79. fill = nofill;
  80. if (len == 0)
  81. len = fill(zbuf, GZIP_IOBUF_SIZE);
  82. /* verify the gzip header */
  83. if (len < 10 ||
  84. zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
  85. if (pos)
  86. *pos = 0;
  87. error("Not a gzip file");
  88. goto gunzip_5;
  89. }
  90. /* skip over gzip header (1f,8b,08... 10 bytes total +
  91. * possible asciz filename)
  92. */
  93. strm->next_in = zbuf + 10;
  94. strm->avail_in = len - 10;
  95. /* skip over asciz filename */
  96. if (zbuf[3] & 0x8) {
  97. do {
  98. /*
  99. * If the filename doesn't fit into the buffer,
  100. * the file is very probably corrupt. Don't try
  101. * to read more data.
  102. */
  103. if (strm->avail_in == 0) {
  104. error("header error");
  105. goto gunzip_5;
  106. }
  107. --strm->avail_in;
  108. } while (*strm->next_in++);
  109. }
  110. strm->next_out = out_buf;
  111. strm->avail_out = out_len;
  112. rc = zlib_inflateInit2(strm, -MAX_WBITS);
  113. #ifdef CONFIG_ZLIB_DFLTCC
  114. /* Always keep the window for DFLTCC */
  115. #else
  116. if (!flush) {
  117. WS(strm)->inflate_state.wsize = 0;
  118. WS(strm)->inflate_state.window = NULL;
  119. }
  120. #endif
  121. while (rc == Z_OK) {
  122. if (strm->avail_in == 0) {
  123. /* TODO: handle case where both pos and fill are set */
  124. len = fill(zbuf, GZIP_IOBUF_SIZE);
  125. if (len < 0) {
  126. rc = -1;
  127. error("read error");
  128. break;
  129. }
  130. strm->next_in = zbuf;
  131. strm->avail_in = len;
  132. }
  133. rc = zlib_inflate(strm, 0);
  134. /* Write any data generated */
  135. if (flush && strm->next_out > out_buf) {
  136. long l = strm->next_out - out_buf;
  137. if (l != flush(out_buf, l)) {
  138. rc = -1;
  139. error("write error");
  140. break;
  141. }
  142. strm->next_out = out_buf;
  143. strm->avail_out = out_len;
  144. }
  145. /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
  146. if (rc == Z_STREAM_END) {
  147. rc = 0;
  148. break;
  149. } else if (rc != Z_OK) {
  150. error("uncompression error");
  151. rc = -1;
  152. }
  153. }
  154. zlib_inflateEnd(strm);
  155. if (pos)
  156. /* add + 8 to skip over trailer */
  157. *pos = strm->next_in - zbuf+8;
  158. gunzip_5:
  159. free(strm->workspace);
  160. gunzip_nomem4:
  161. free(strm);
  162. gunzip_nomem3:
  163. if (!buf)
  164. free(zbuf);
  165. gunzip_nomem2:
  166. if (flush)
  167. free(out_buf);
  168. gunzip_nomem1:
  169. return rc; /* returns Z_OK (0) if successful */
  170. }
  171. #ifndef PREBOOT
  172. STATIC int INIT gunzip(unsigned char *buf, long len,
  173. long (*fill)(void*, unsigned long),
  174. long (*flush)(void*, unsigned long),
  175. unsigned char *out_buf,
  176. long *pos,
  177. void (*error)(char *x))
  178. {
  179. return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
  180. }
  181. #else
  182. STATIC int INIT __decompress(unsigned char *buf, long len,
  183. long (*fill)(void*, unsigned long),
  184. long (*flush)(void*, unsigned long),
  185. unsigned char *out_buf, long out_len,
  186. long *pos,
  187. void (*error)(char *x))
  188. {
  189. return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
  190. }
  191. #endif