From: Alain Knaff <alain@knaff.lu>
This is an updated version of my bzip2/lzma patch
It 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.27-rc5
Changes since last version (update3):
- Support for ARM architecture
- Minor cleanup
Signed-off-by: Alain Knaff <alain@knaff.lu>
---
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/Makefile linux.trees.git.udpcast/arch/arm/boot/compressed/Makefile
--- linux.trees.git.0/arch/arm/boot/compressed/Makefile 2008-09-07 11:29:10.000000000 +0200
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/Makefile 2008-09-10 23:58:06.000000000 +0200
@@ -67,8 +67,15 @@ endif
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
-targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
- head.o misc.o $(OBJS)
+suffix_$(CONFIG_KERNEL_GZIP) = gz
+suffix_$(CONFIG_KERNEL_BZIP2) = bz2
+suffix_$(CONFIG_KERNEL_LZMA) = lzma
+
+targets := vmlinux vmlinux.lds \
+ piggy.gz piggy.gz.o \
+ piggy.bz2 piggy.bz2.o \
+ piggy.lzma piggy.lzma.o \
+ font.o font.c head.o misc.o $(OBJS)
ifeq ($(CONFIG_FTRACE),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -95,7 +102,7 @@ LDFLAGS_vmlinux += -p --no-undefined -X
# would otherwise mess up our GOT table
CFLAGS_misc.o := -Dstatic=
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
$(addprefix $(obj)/, $(OBJS)) FORCE
$(call if_changed,ld)
@:
@@ -103,7 +110,17 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj
$(obj)/piggy.gz: $(obj)/../Image FORCE
$(call if_changed,gzip)
-$(obj)/piggy.o: $(obj)/piggy.gz FORCE
+$(obj)/piggy.bz2: $(obj)/../Image FORCE
+ $(call if_changed,bzip2)
+
+$(obj)/piggy.lzma: $(obj)/../Image FORCE
+ $(call if_changed,lzma)
+
+$(obj)/piggy.gz.o: $(obj)/piggy.gz FORCE
+
+$(obj)/piggy.bz2.o: $(obj)/piggy.bz2 FORCE
+
+$(obj)/piggy.lzma.o: $(obj)/piggy.lzma FORCE
CFLAGS_font.o := -Dstatic=
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/misc.c linux.trees.git.udpcast/arch/arm/boot/compressed/misc.c
--- linux.trees.git.0/arch/arm/boot/compressed/misc.c 2008-09-07 11:29:10.000000000 +0200
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/misc.c 2008-09-10 23:38:49.000000000 +0200
@@ -169,116 +169,31 @@ static inline __ptr_t memcpy(__ptr_t __d
/*
* gzip delarations
*/
-#define OF(args) args
#define STATIC static
-typedef unsigned char uch;
-typedef unsigned short ush;
typedef unsigned long ulg;
-
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
- /* and a power of two */
-
-static uch *inbuf; /* input buffer */
-static uch window[WSIZE]; /* Sliding window buffer */
-
-static unsigned insize; /* valid bytes in inbuf */
-static unsigned inptr; /* index of next byte to be processed in inbuf */
-static unsigned outcnt; /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 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) {if(!(cond)) error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#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);
+typedef ulg memptr ;
extern char input_data[];
extern char input_data_end[];
-static uch *output_data;
-static ulg output_ptr;
-static ulg bytes_out;
-
-static void error(char *m);
-
-static void putstr(const char *);
-
-extern int end;
-static ulg free_mem_ptr;
-static ulg free_mem_end_ptr;
-
-#ifdef STANDALONE_DEBUG
-#define NO_INFLATE_MALLOC
-#endif
-
#define ARCH_HAS_DECOMP_WDOG
+static void error(char *x);
+
+#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/inflate.c"
+#endif
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-int fill_inbuf(void)
-{
- if (insize != 0)
- error("ran out of input data");
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
- inbuf = input_data;
- insize = &input_data_end[0] - &input_data[0];
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
- inptr = 1;
- return inbuf[0];
-}
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-void flush_window(void)
-{
- ulg c = crc;
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out++ = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
- putstr(".");
-}
#ifndef arch_error
#define arch_error(x)
@@ -301,17 +216,26 @@ ulg
decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
int arch_id)
{
- output_data = (uch *)output_start; /* Points to kernel start */
- free_mem_ptr = free_mem_ptr_p;
- free_mem_end_ptr = free_mem_ptr_end_p;
+ ulg output_ptr;
+ ulg *ptr;
+ size_t input_len = input_data_end - input_data;
+ size_t pos = 0;
+
__machine_arch_type = arch_id;
arch_decomp_setup();
- makecrc();
- putstr("Uncompressing Linux...");
- gunzip();
+ ptr = (ulg *) (((long)input_data_end) - 4);
+ output_ptr = output_start + *ptr;
+
+ free_mem_ptr = output_ptr;
+ free_mem_end_ptr = output_ptr + 0x4000000;
+
+ putstr("Decompressing Linux...");
+ decompress(input_data, input_len,
+ NULL, NULL, (unsigned char *) output_start, &pos, error);
putstr(" done, booting the kernel.\n");
+
return output_ptr;
}
#else
@@ -320,11 +244,12 @@ char output_buffer[1500*1024];
int main()
{
- output_data = output_buffer;
-
- makecrc();
putstr("Uncompressing Linux...");
- gunzip();
+#ifdef CONFIG_KERNEL_BZIP2
+ /* Fake decompressed length for bzip2 */
+ input_len -= 4;
+#endif
+ decompress(input_data, input_len, NULL, output_buffer, NULL);
putstr("done.\n");
return 0;
}
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/piggy.bz2.S linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.bz2.S
--- linux.trees.git.0/arch/arm/boot/compressed/piggy.bz2.S 1970-01-01 01:00:00.000000000 +0100
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.bz2.S 2008-09-10 23:31:36.000000000 +0200
@@ -0,0 +1,6 @@
+ .section .piggydata,#alloc
+ .globl input_data
+input_data:
+ .incbin "arch/arm/boot/compressed/piggy.bz2"
+ .globl input_data_end
+input_data_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/piggy.gz.S linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.gz.S
--- linux.trees.git.0/arch/arm/boot/compressed/piggy.gz.S 1970-01-01 01:00:00.000000000 +0100
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.gz.S 2008-09-10 23:25:48.000000000 +0200
@@ -0,0 +1,6 @@
+ .section .piggydata,#alloc
+ .globl input_data
+input_data:
+ .incbin "arch/arm/boot/compressed/piggy.gz"
+ .globl input_data_end
+input_data_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/piggy.lzma.S linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.lzma.S
--- linux.trees.git.0/arch/arm/boot/compressed/piggy.lzma.S 1970-01-01 01:00:00.000000000 +0100
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.lzma.S 2008-09-10 23:25:49.000000000 +0200
@@ -0,0 +1,6 @@
+ .section .piggydata,#alloc
+ .globl input_data
+input_data:
+ .incbin "arch/arm/boot/compressed/piggy.lzma"
+ .globl input_data_end
+input_data_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/arm/boot/compressed/piggy.S linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.S
--- linux.trees.git.0/arch/arm/boot/compressed/piggy.S 2008-09-07 11:29:10.000000000 +0200
+++ linux.trees.git.udpcast/arch/arm/boot/compressed/piggy.S 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
- .section .piggydata,#alloc
- .globl input_data
-input_data:
- .incbin "arch/arm/boot/compressed/piggy.gz"
- .globl input_data_end
-input_data_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/x86/boot/compressed/head_32.S linux.trees.git.udpcast/arch/x86/boot/compressed/head_32.S
--- linux.trees.git.0/arch/x86/boot/compressed/head_32.S 2008-09-07 11:29:12.000000000 +0200
+++ linux.trees.git.udpcast/arch/x86/boot/compressed/head_32.S 2008-09-09 00:41:04.000000000 +0200
@@ -143,7 +143,7 @@ relocated:
pushl %eax # input_len
leal input_data(%ebx), %eax
pushl %eax # input_data
- leal boot_heap(%ebx), %eax
+ leal _end(%ebx), %eax
pushl %eax # heap area
pushl %esi # real mode pointer
call decompress_kernel
@@ -184,8 +184,6 @@ relocated:
.bss
/* Stack and heap for uncompression */
.balign 4
-boot_heap:
- .fill BOOT_HEAP_SIZE, 1, 0
boot_stack:
.fill BOOT_STACK_SIZE, 1, 0
boot_stack_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/x86/boot/compressed/head_64.S linux.trees.git.udpcast/arch/x86/boot/compressed/head_64.S
--- linux.trees.git.0/arch/x86/boot/compressed/head_64.S 2008-09-07 11:29:12.000000000 +0200
+++ linux.trees.git.udpcast/arch/x86/boot/compressed/head_64.S 2008-09-09 00:41:09.000000000 +0200
@@ -287,7 +287,7 @@ relocated:
*/
pushq %rsi # Save the real mode argument
movq %rsi, %rdi # real mode address
- leaq boot_heap(%rip), %rsi # malloc area for uncompression
+ leaq _end(%rip), %rsi # malloc area for uncompression
leaq input_data(%rip), %rdx # input_data
movl input_len(%rip), %eax
movq %rax, %rcx # input_len
@@ -316,8 +316,6 @@ gdt_end:
.bss
/* Stack and heap for uncompression */
.balign 4
-boot_heap:
- .fill BOOT_HEAP_SIZE, 1, 0
boot_stack:
.fill BOOT_STACK_SIZE, 1, 0
boot_stack_end:
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/x86/boot/compressed/Makefile linux.trees.git.udpcast/arch/x86/boot/compressed/Makefile
--- linux.trees.git.0/arch/x86/boot/compressed/Makefile 2008-09-07 11:29:12.000000000 +0200
+++ linux.trees.git.udpcast/arch/x86/boot/compressed/Makefile 2008-09-07 11:41:54.000000000 +0200
@@ -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,34 @@ 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)
diff -urNp -X linux.trees.git.udpcast/Documentation/dontdiff linux.trees.git.0/arch/x86/boot/compressed/misc.c linux.trees.git.udpcast/arch/x86/boot/compressed/misc.c
--- linux.trees.git.0/arch/x86/boot/compressed/misc.c 2008-09-07 11:29:12.000000000 +0200
+++ linux.trees.git.udpcast/arch/x86/boot/compressed/misc.c 2008-09-10 22:49:28.000000000 +0200
@@ -116,71 +116,13 @@
/*
* 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,11 +131,6 @@ 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);
@@ -206,14 +143,21 @@ static void __putstr(int, const char *);
#define memptr unsigned
#endif
-static memptr free_mem_ptr;
-static memptr free_mem_end_ptr;
-
static char *vidmem;
static int vidport;
static int lines, cols;
+#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/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)
{
@@ -293,38 +237,6 @@ static void *memcpy(void *dest, const vo
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)
{
@@ -360,7 +272,7 @@ static void parse_elf(void *output)
if (!quiet)
putstr("Parsing ELF... ");
- phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
+ phdrs = (void *) malloc(sizeof(*phdrs) * ehdr.e_phnum);
if (!phdrs)
error("Failed to allocate space for phdrs");
@@ -407,12 +319,8 @@ asmlinkage void decompress_kernel(void *
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 +338,9 @@ asmlinkage void decompress_kernel(void *
#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");
Les fichiers binaires linux.trees.git.0/arch/x86/vdso/vdso32-int80.so.dbg et linux.trees.git.udpcast/arch/x86/vdso/vdso32-int80.so.dbg sont diff| Sunil Naidu | Re: Linux 2.6.20-rc6 |
| david | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Jan Engelhardt | intel iommu (Re: -mm merge plans for 2.6.23) |
| Linus Torvalds | Re: init's children list is long and slows reaping children. |
| David Miller | Re: [GIT]: Networking |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Gerrit Renker | [PATCH 27/37] dccp: Integration of dynamic feature activation - part 2 (server side) |
| Andrew Morton | Re: [BUG] New Kernel Bugs |
git: | |
