]> git.karo-electronics.de Git - linux-beck.git/commitdiff
bzip2/lzma: x86 kernel compression support
authorAlain Knaff <alain@knaff.lu>
Sun, 4 Jan 2009 21:46:17 +0000 (22:46 +0100)
committerH. Peter Anvin <hpa@zytor.com>
Sun, 4 Jan 2009 23:53:35 +0000 (15:53 -0800)
Impact: Replaces x86 kernel decompressor with new code

This is the third part of the bzip2/lzma patch

The bzip patch is based on an idea by Christian Ludwig, includes support for
compressing the kernel with bzip2 or lzma rather than gzip. Both
compressors give smaller sizes than gzip.  Lzma's decompresses faster
than bzip2.

It also supports ramdisks and initramfs' compressed using these two
compressors.

The functionality has been successfully used for a couple of years by
the udpcast project

This version applies to "tip" kernel 2.6.28

This part contains:
- support for new bzip2 and lzma kernel compression for x86

Signed-off-by: Alain Knaff <alain@knaff.lu>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/misc.c
arch/x86/include/asm/boot.h

index 1771c804e02f57b26d5d4f9f1db8cdb1f7a4ed62..3ca4c194b8e588217dabef4dc5da54bcb2489edd 100644 (file)
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -47,18 +47,35 @@ ifeq ($(CONFIG_X86_32),y)
 ifdef CONFIG_RELOCATABLE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
        $(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE
+       $(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE
+       $(call if_changed,lzma)
 else
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,lzma)
 endif
 LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
 
 else
+
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,bzip2)
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,lzma)
 
 LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
 endif
 
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+suffix_$(CONFIG_KERNEL_GZIP)  = gz
+suffix_$(CONFIG_KERNEL_BZIP2) = bz2
+suffix_$(CONFIG_KERNEL_LZMA)  = lzma
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE
        $(call if_changed,ld)
index da062216948a6951990f354fa11ee9125b865fe7..e45be73684ffe3bd5559029eb86cf66ec00ff250 100644 (file)
 /*
  * gzip declarations
  */
-
-#define OF(args)       args
 #define STATIC         static
 
 #undef memset
 #undef memcpy
 #define memzero(s, n)  memset((s), 0, (n))
 
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-/*
- * Window size must be at least 32k, and a power of two.
- * We don't actually have a window just a huge output buffer,
- * so we report a 2G window size, as that should always be
- * larger than our output buffer:
- */
-#define WSIZE          0x80000000
-
-/* Input buffer: */
-static unsigned char   *inbuf;
-
-/* Sliding window buffer (and final output buffer): */
-static unsigned char   *window;
-
-/* Valid bytes in inbuf: */
-static unsigned                insize;
-
-/* Index of next byte to be processed in inbuf: */
-static unsigned                inptr;
-
-/* Bytes in output buffer: */
-static unsigned                outcnt;
-
-/* gzip flag byte */
-#define ASCII_FLAG     0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION   0x02 /* bit 1 set: continuation of multi-part gz file */
-#define EXTRA_FIELD    0x04 /* bit 2 set: extra field present */
-#define ORIG_NAM       0x08 /* bit 3 set: original file name present */
-#define COMMENT                0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED      0x20 /* bit 5 set: file is encrypted */
-#define RESERVED       0xC0 /* bit 6, 7:  reserved */
-
-#define get_byte()     (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0)
-#  define Trace(x)     do { fprintf x; } while (0)
-#  define Tracev(x)    do { if (verbose) fprintf x ; } while (0)
-#  define Tracevv(x)   do { if (verbose > 1) fprintf x ; } while (0)
-#  define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0)
-#  define Tracecv(c, x)        do { if (verbose > 1 && (c)) fprintf x ; } while (0)
-#else
-#  define Assert(cond, msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c, x)
-#  define Tracecv(c, x)
-#endif
 
-static int  fill_inbuf(void);
-static void flush_window(void);
 static void error(char *m);
 
 /*
@@ -189,13 +131,8 @@ static void error(char *m);
 static struct boot_params *real_mode;          /* Pointer to real-mode data */
 static int quiet;
 
-extern unsigned char input_data[];
-extern int input_len;
-
-static long bytes_out;
-
 static void *memset(void *s, int c, unsigned n);
-static void *memcpy(void *dest, const void *src, unsigned n);
+void *memcpy(void *dest, const void *src, unsigned n);
 
 static void __putstr(int, const char *);
 #define putstr(__x)  __putstr(0, __x)
@@ -213,7 +150,17 @@ static char *vidmem;
 static int vidport;
 static int lines, cols;
 
-#include "../../../../lib/inflate.c"
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
 
 static void scroll(void)
 {
@@ -282,7 +229,7 @@ static void *memset(void *s, int c, unsigned n)
        return s;
 }
 
-static void *memcpy(void *dest, const void *src, unsigned n)
+void *memcpy(void *dest, const void *src, unsigned n)
 {
        int i;
        const char *s = src;
@@ -293,38 +240,6 @@ static void *memcpy(void *dest, const void *src, unsigned n)
        return dest;
 }
 
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-       error("ran out of input data");
-       return 0;
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-       /* With my window equal to my output buffer
-        * I only need to compute the crc here.
-        */
-       unsigned long c = crc;         /* temporary variable */
-       unsigned n;
-       unsigned char *in, ch;
-
-       in = window;
-       for (n = 0; n < outcnt; n++) {
-               ch = *in++;
-               c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-       }
-       crc = c;
-       bytes_out += (unsigned long)outcnt;
-       outcnt = 0;
-}
 
 static void error(char *x)
 {
@@ -407,12 +322,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        lines = real_mode->screen_info.orig_video_lines;
        cols = real_mode->screen_info.orig_video_cols;
 
-       window = output;                /* Output buffer (Normally at 1M) */
        free_mem_ptr     = heap;        /* Heap */
        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
-       inbuf  = input_data;            /* Input buffer */
-       insize = input_len;
-       inptr  = 0;
 
 #ifdef CONFIG_X86_64
        if ((unsigned long)output & (__KERNEL_ALIGN - 1))
@@ -430,10 +341,9 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 #endif
 #endif
 
-       makecrc();
        if (!quiet)
                putstr("\nDecompressing Linux... ");
-       gunzip();
+       decompress(input_data, input_len, NULL, NULL, output, NULL, error);
        parse_elf(output);
        if (!quiet)
                putstr("done.\nBooting the kernel.\n");
index dd61616cb73d1d3aab1bb7d5c2dfd8923ec6e672..c0e8e68a31fbe239dfc12d6ee4e5b1665e8e6510 100644 (file)
                                + (CONFIG_PHYSICAL_ALIGN - 1)) \
                                & ~(CONFIG_PHYSICAL_ALIGN - 1))
 
+#if (defined CONFIG_KERNEL_BZIP2)
+#define BOOT_HEAP_SIZE             0x400000
+#else
+
 #ifdef CONFIG_X86_64
 #define BOOT_HEAP_SIZE 0x7000
-#define BOOT_STACK_SIZE        0x4000
 #else
 #define BOOT_HEAP_SIZE 0x4000
+#endif
+
+#endif
+
+#ifdef CONFIG_X86_64
+#define BOOT_STACK_SIZE        0x4000
+#else
 #define BOOT_STACK_SIZE        0x1000
 #endif