int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 {
-       return decompress(input, len, NULL, NULL, output, NULL, error);
+       return __decompress(input, len, NULL, NULL, output, 0, NULL, error);
 }
 
        free_mem_ptr = (unsigned long)&_end;
        free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
 
-       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+       __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
 }
 
        free_mem_end_ptr = free_mem_ptr + BOOT_HEAP_SIZE;
 
        puts("\nDecompressing Linux... ");
-       decompress(input_data, input_len, NULL, NULL, output_data, NULL, error);
+       __decompress(input_data, input_len, NULL, NULL, output_data, 0,
+                       NULL, error);
        puts("done.\nBooting the kernel.\n");
 }
 
        puts("\n");
 
        /* Decompress the kernel with according algorithm */
-       decompress((char *)zimage_start, zimage_size, 0, 0,
-                  (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);
+       __decompress((char *)zimage_start, zimage_size, 0, 0,
+                  (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, 0, error);
 
        /* FIXME: should we flush cache here? */
        puts("Now, booting the kernel...\n");
 
 #endif
 
        puts("Uncompressing Linux... ");
-       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+       __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
        puts("Ok, booting the kernel.\n");
        return (unsigned long) output;
 }
 
 
        puts("Uncompressing Linux... ");
        cache_control(CACHE_ENABLE);
-       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+       __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
        cache_control(CACHE_DISABLE);
        puts("Ok, booting the kernel.\n");
 }
 
        output_ptr = get_unaligned_le32(tmp);
 
        arch_decomp_puts("Uncompressing Linux...");
-       decompress(input_data, input_data_end - input_data, NULL, NULL,
-                       output_data, NULL, error);
+       __decompress(input_data, input_data_end - input_data, NULL, NULL,
+                       output_data, 0, NULL, error);
        arch_decomp_puts(" done, booting the kernel.\n");
        return output_ptr;
 }
 
 #endif
 
        debug_putstr("\nDecompressing Linux... ");
-       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
+       __decompress(input_data, input_len, NULL, NULL, output, output_len,
+                       NULL, error);
        parse_elf(output);
        /*
         * 32-bit always performs relocations. 64-bit relocations are only
 
 }
 
 #ifdef PREBOOT
-STATIC int INIT decompress(unsigned char *buf, long len,
+STATIC int INIT __decompress(unsigned char *buf, long len,
                        long (*fill)(void*, unsigned long),
                        long (*flush)(void*, unsigned long),
-                       unsigned char *outbuf,
+                       unsigned char *outbuf, long olen,
                        long *pos,
-                       void(*error)(char *x))
+                       void (*error)(char *x))
 {
        return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error);
 }
 
 #ifdef STATIC
+#define PREBOOT
 /* Pre-boot environment: included */
 
 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
 }
 
 /* Included from initramfs et al code */
-STATIC int INIT gunzip(unsigned char *buf, long len,
+STATIC int INIT __gunzip(unsigned char *buf, long len,
                       long (*fill)(void*, unsigned long),
                       long (*flush)(void*, unsigned long),
-                      unsigned char *out_buf,
+                      unsigned char *out_buf, long out_len,
                       long *pos,
                       void(*error)(char *x)) {
        u8 *zbuf;
        struct z_stream_s *strm;
        int rc;
-       size_t out_len;
 
        rc = -1;
        if (flush) {
                out_len = 0x8000; /* 32 K */
                out_buf = malloc(out_len);
        } else {
-               out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
+               if (!out_len)
+                       out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
        }
        if (!out_buf) {
                error("Out of memory while allocating output buffer");
        return rc; /* returns Z_OK (0) if successful */
 }
 
-#define decompress gunzip
+#ifndef PREBOOT
+STATIC int INIT gunzip(unsigned char *buf, long len,
+                      long (*fill)(void*, unsigned long),
+                      long (*flush)(void*, unsigned long),
+                      unsigned char *out_buf,
+                      long *pos,
+                      void (*error)(char *x))
+{
+       return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
+}
+#else
+STATIC int INIT __decompress(unsigned char *buf, long len,
+                          long (*fill)(void*, unsigned long),
+                          long (*flush)(void*, unsigned long),
+                          unsigned char *out_buf, long out_len,
+                          long *pos,
+                          void (*error)(char *x))
+{
+       return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
+}
+#endif
 
 }
 
 #ifdef PREBOOT
-STATIC int INIT decompress(unsigned char *buf, long in_len,
+STATIC int INIT __decompress(unsigned char *buf, long in_len,
                              long (*fill)(void*, unsigned long),
                              long (*flush)(void*, unsigned long),
-                             unsigned char *output,
+                             unsigned char *output, long out_len,
                              long *posp,
-                             void(*error)(char *x)
+                             void (*error)(char *x)
        )
 {
        return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
 
 }
 
 #ifdef PREBOOT
-STATIC int INIT decompress(unsigned char *buf, long in_len,
+STATIC int INIT __decompress(unsigned char *buf, long in_len,
                              long (*fill)(void*, unsigned long),
                              long (*flush)(void*, unsigned long),
-                             unsigned char *output,
+                             unsigned char *output, long out_len,
                              long *posp,
-                             void(*error)(char *x)
-       )
+                             void (*error)(char *x))
 {
        return unlzma(buf, in_len - 4, fill, flush, output, posp, error);
 }
 
  */
 
 #ifdef STATIC
+#define PREBOOT
 #include "lzo/lzo1x_decompress_safe.c"
 #else
 #include <linux/decompress/unlzo.h>
        return ret;
 }
 
-#define decompress unlzo
+#ifdef PREBOOT
+STATIC int INIT __decompress(unsigned char *buf, long len,
+                          long (*fill)(void*, unsigned long),
+                          long (*flush)(void*, unsigned long),
+                          unsigned char *out_buf, long olen,
+                          long *pos,
+                          void (*error)(char *x))
+{
+       return unlzo(buf, len, fill, flush, out_buf, pos, error);
+}
+#endif
 
  * This macro is used by architecture-specific files to decompress
  * the kernel image.
  */
-#define decompress unxz
+#ifdef XZ_PREBOOT
+STATIC int INIT __decompress(unsigned char *buf, long len,
+                          long (*fill)(void*, unsigned long),
+                          long (*flush)(void*, unsigned long),
+                          unsigned char *out_buf, long olen,
+                          long *pos,
+                          void (*error)(char *x))
+{
+       return unxz(buf, len, fill, flush, out_buf, pos, error);
+}
+#endif