From 30d65dbfe3add7f010a075991dc0bfeaebb7d9e1 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Sun, 4 Jan 2009 22:46:17 +0100 Subject: bzip2/lzma: config and initramfs support for bzip2/lzma decompression Impact: New code for initramfs decompression, new features This is the second 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 compressions (bzip2 and lzma) in initramfs and old-style ramdisk - config dialog for kernel compression (but new kernel compressions not yet supported) Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- init/Kconfig | 50 +++++++++++++++ init/do_mounts_rd.c | 182 +++++++++++++++++++--------------------------------- init/initramfs.c | 123 ++++++++++++----------------------- 3 files changed, 157 insertions(+), 198 deletions(-) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index f6281711166d..df84625b1373 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -101,6 +101,56 @@ config LOCALVERSION_AUTO which is done within the script "scripts/setlocalversion".) +choice + prompt "Kernel compression mode" + default KERNEL_GZIP + help + The linux kernel is a kind of self-extracting executable. + Several compression algorithms are available, which differ + in efficiency, compression and decompression speed. + Compression speed is only relevant when building a kernel. + Decompression speed is relevant at each boot. + + If you have any problems with bzip2 or lzma compressed + kernels, mail me (Alain Knaff) . (An older + version of this functionality (bzip2 only), for 2.4, was + supplied by Christian Ludwig) + + High compression options are mostly useful for users, who + are low on disk space (embedded systems), but for whom ram + size matters less. + + If in doubt, select 'gzip' + +config KERNEL_GZIP + bool "Gzip" + help + The old and tried gzip compression. Its compression ratio is + the poorest among the 3 choices; however its speed (both + compression and decompression) is the fastest. + +config KERNEL_BZIP2 + bool "Bzip2" + help + Its compression ratio and speed is intermediate. + Decompression speed is slowest among the 3. + The kernel size is about 10 per cent smaller with bzip2, + in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels + you will need at least 8MB RAM or more for booting. + +config KERNEL_LZMA + bool "LZMA" + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other + 2. Compression is slowest. + The kernel size is about 33 per cent smaller with lzma, + in comparison to gzip. + +endchoice + + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index a7c748fa977a..dcaeb1f90b32 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -10,6 +10,12 @@ #include "do_mounts.h" +#include + +#include +#include +#include + int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ static int __init prompt_ramdisk(char *str) @@ -28,7 +34,7 @@ static int __init ramdisk_start_setup(char *str) } __setup("ramdisk_start=", ramdisk_start_setup); -static int __init crd_load(int in_fd, int out_fd); +static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); /* * This routine tries to find a RAM disk image to load, and returns the @@ -44,7 +50,7 @@ static int __init crd_load(int in_fd, int out_fd); * gzip */ static int __init -identify_ramdisk_image(int fd, int start_block) +identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { const int size = 512; struct minix_super_block *minixsb; @@ -70,6 +76,7 @@ identify_ramdisk_image(int fd, int start_block) sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); +#ifdef CONFIG_RD_GZIP /* * If it matches the gzip magic numbers, return 0 */ @@ -77,9 +84,39 @@ identify_ramdisk_image(int fd, int start_block) printk(KERN_NOTICE "RAMDISK: Compressed image found at block %d\n", start_block); + *decompressor = gunzip; + nblocks = 0; + goto done; + } +#endif + +#ifdef CONFIG_RD_BZIP2 + /* + * If it matches the bzip2 magic numbers, return -1 + */ + if (buf[0] == 0x42 && (buf[1] == 0x5a)) { + printk(KERN_NOTICE + "RAMDISK: Bzipped image found at block %d\n", + start_block); + *decompressor = bunzip2; + nblocks = 0; + goto done; + } +#endif + +#ifdef CONFIG_RD_LZMA + /* + * If it matches the lzma magic numbers, return -1 + */ + if (buf[0] == 0x5d && (buf[1] == 0x00)) { + printk(KERN_NOTICE + "RAMDISK: Lzma image found at block %d\n", + start_block); + *decompressor = unlzma; nblocks = 0; goto done; } +#endif /* romfs is at block zero too */ if (romfsb->word0 == ROMSB_WORD0 && @@ -143,6 +180,7 @@ int __init rd_load_image(char *from) int nblocks, i, disk; char *buf = NULL; unsigned short rotate = 0; + decompress_fn decompressor = NULL; #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) char rotator[4] = { '|' , '/' , '-' , '\\' }; #endif @@ -155,12 +193,12 @@ int __init rd_load_image(char *from) if (in_fd < 0) goto noclose_input; - nblocks = identify_ramdisk_image(in_fd, rd_image_start); + nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); if (nblocks < 0) goto done; if (nblocks == 0) { - if (crd_load(in_fd, out_fd) == 0) + if (crd_load(in_fd, out_fd, decompressor) == 0) goto successful_load; goto done; } @@ -259,138 +297,48 @@ int __init rd_load_disk(int n) return rd_load_image("/dev/root"); } -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -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 */ static int exit_code; -static int unzip_error; -static long bytes_out; +static int decompress_error; static int crd_infd, crd_outfd; -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static int __init fill_inbuf(void); -static void __init flush_window(void); -static void __init error(char *m); - -#define NO_INFLATE_MALLOC - -#include "../lib/inflate.c" - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - * Returning -1 does not guarantee that gunzip() will ever return. - */ -static int __init fill_inbuf(void) +static int __init compr_fill(void *buf, unsigned int len) { - if (exit_code) return -1; - - insize = sys_read(crd_infd, inbuf, INBUFSIZ); - if (insize == 0) { - error("RAMDISK: ran out of compressed data"); - return -1; - } - - inptr = 1; - - return inbuf[0]; + int r = sys_read(crd_infd, buf, len); + if (r < 0) + printk(KERN_ERR "RAMDISK: error while reading compressed data"); + else if (r == 0) + printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); + return r; } -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) +static int __init compr_flush(void *window, unsigned int outcnt) { - ulg c = crc; /* temporary variable */ - unsigned n, written; - uch *in, ch; - - written = sys_write(crd_outfd, window, outcnt); - if (written != outcnt && unzip_error == 0) { - printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", - written, outcnt, bytes_out); - unzip_error = 1; - } - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; + int written = sys_write(crd_outfd, window, outcnt); + if (written != outcnt) { + if (decompress_error == 0) + printk(KERN_ERR + "RAMDISK: incomplete write (%d != %d)\n", + written, outcnt); + decompress_error = 1; + return -1; + } + return outcnt; } static void __init error(char *x) { printk(KERN_ERR "%s\n", x); exit_code = 1; - unzip_error = 1; + decompress_error = 1; } -static int __init crd_load(int in_fd, int out_fd) +static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) { int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - crd_infd = in_fd; crd_outfd = out_fd; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (!inbuf) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (!window) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - if (unzip_error) + result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); + if (decompress_error) result = 1; - kfree(inbuf); - kfree(window); return result; } diff --git a/init/initramfs.c b/init/initramfs.c index 4f5ba75aaa7c..40bd4fb95788 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -389,11 +389,14 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } -static void __init flush_buffer(char *buf, unsigned len) + +static int __init flush_buffer(void *bufv, unsigned len) { + char *buf = (char *) bufv; int written; + int origLen = len; if (message) - return; + return -1; while ((written = write_buffer(buf, len)) < len && !message) { char c = buf[written]; if (c == '0') { @@ -407,73 +410,14 @@ static void __init flush_buffer(char *buf, unsigned len) } else error("junk in compressed archive"); } + return origLen; } -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -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 */ -static long bytes_out; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : -1) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static void __init flush_window(void); -static void __init error(char *m); - -#define NO_INFLATE_MALLOC +static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -#include "../lib/inflate.c" - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, ch; - - flush_buffer(window, outcnt); - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} +#include +#include +#include static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { @@ -482,9 +426,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) header_buf = kmalloc(110, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); - window = kmalloc(WSIZE, GFP_KERNEL); - if (!window || !header_buf || !symlink_buf || !name_buf) + + if (!header_buf || !symlink_buf || !name_buf) panic("can't allocate buffers"); + state = Start; this_header = 0; message = NULL; @@ -504,22 +449,38 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; - insize = len; - inbuf = buf; - inptr = 0; - outcnt = 0; /* bytes in output buffer */ - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - makecrc(); - gunzip(); + if (!gunzip(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) + goto ok; + +#ifdef CONFIG_RD_BZIP2 + message = NULL; /* Zero out message, or else cpio will + think an error has already occured */ + if (!bunzip2(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) { + goto ok; + } +#endif + +#ifdef CONFIG_RD_LZMA + message = NULL; /* Zero out message, or else cpio will + think an error has already occured */ + if (!unlzma(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error) && + message == NULL) { + goto ok; + } +#endif +ok: if (state != Reset) - error("junk in gzipped archive"); - this_header = saved_offset + inptr; - buf += inptr; - len -= inptr; + error("junk in compressed archive"); + this_header = saved_offset + my_inptr; + buf += my_inptr; + len -= my_inptr; } dir_utime(); - kfree(window); kfree(name_buf); kfree(symlink_buf); kfree(header_buf); -- cgit v1.2.3 From b172fd882d201cf8aa67cddd9c1a023421fd4956 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Sun, 4 Jan 2009 14:42:52 -0800 Subject: bzip2/lzma: use a table to search for initramfs compression formats Impact: Code simplification Instead of open-coding testing for initramfs compression formats, use a table. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 82 +++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 47 deletions(-) (limited to 'init') diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index dcaeb1f90b32..9c9d7dbcf9ca 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -43,13 +43,31 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); * numbers could not be found. * * We currently check for the following magic numbers: - * minix - * ext2 + * minix + * ext2 * romfs * cramfs - * gzip + * gzip */ -static int __init +static const struct compress_format { + unsigned char magic[2]; + const char *name; + decompress_fn decompressor; +} compressed_formats[] = { +#ifdef CONFIG_RD_GZIP + { {037, 0213}, "gzip", gunzip }, + { {037, 0236}, "gzip", gunzip }, +#endif +#ifdef CONFIG_RD_BZIP2 + { {0x42, 0x5a}, "bzip2", bunzip2 }, +#endif +#ifdef CONFIG_RD_LZMA + { {0x5d, 0x00}, "lzma", unlzma }, +#endif + { {0, 0}, NULL, NULL } +}; + +static int __init identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { const int size = 512; @@ -59,6 +77,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; + const struct compress_format *cf; buf = kmalloc(size, GFP_KERNEL); if (!buf) @@ -71,52 +90,21 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) memset(buf, 0xe5, size); /* - * Read block 0 to test for gzipped kernel + * Read block 0 to test for compressed kernel */ sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); -#ifdef CONFIG_RD_GZIP - /* - * If it matches the gzip magic numbers, return 0 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - *decompressor = gunzip; - nblocks = 0; - goto done; - } -#endif - -#ifdef CONFIG_RD_BZIP2 - /* - * If it matches the bzip2 magic numbers, return -1 - */ - if (buf[0] == 0x42 && (buf[1] == 0x5a)) { - printk(KERN_NOTICE - "RAMDISK: Bzipped image found at block %d\n", - start_block); - *decompressor = bunzip2; - nblocks = 0; - goto done; - } -#endif - -#ifdef CONFIG_RD_LZMA - /* - * If it matches the lzma magic numbers, return -1 - */ - if (buf[0] == 0x5d && (buf[1] == 0x00)) { - printk(KERN_NOTICE - "RAMDISK: Lzma image found at block %d\n", - start_block); - *decompressor = unlzma; - nblocks = 0; - goto done; + for (cf = compressed_formats; cf->decompressor; cf++) { + if (buf[0] == cf->magic[0] && buf[1] == cf->magic[1]) { + printk(KERN_NOTICE + "RAMDISK: %s image found at block %d\n", + cf->name, start_block); + *decompressor = cf->decompressor; + nblocks = 0; + goto done; + } } -#endif /* romfs is at block zero too */ if (romfsb->word0 == ROMSB_WORD0 && @@ -165,7 +153,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) printk(KERN_NOTICE "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", start_block); - + done: sys_lseek(fd, start_block * BLOCK_SIZE, 0); kfree(buf); @@ -224,7 +212,7 @@ int __init rd_load_image(char *from) nblocks, rd_blocks); goto done; } - + /* * OK, time to copy in the data */ -- cgit v1.2.3 From 2e9f3bddcbc711bb14d86c6f068a779bf3710247 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Sun, 4 Jan 2009 15:41:25 -0800 Subject: bzip2/lzma: make config machinery an arch configurable Impact: Bug fix (we should not show this menu on irrelevant architectures) Make the config machinery to drive the gzip/bzip2/lzma selection dependent on the architecture advertising HAVE_KERNEL_* so that we don't display this for architectures where it doesn't matter. Signed-off-by: H. Peter Anvin --- arch/x86/Kconfig | 3 +++ init/Kconfig | 52 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 21 deletions(-) (limited to 'init') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 862adb9bf0d4..7b66c34d0aae 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -39,6 +39,9 @@ config X86 select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS select USER_STACKTRACE_SUPPORT + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA config ARCH_DEFCONFIG string diff --git a/init/Kconfig b/init/Kconfig index df84625b1373..f9633c03cb12 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -101,10 +101,20 @@ config LOCALVERSION_AUTO which is done within the script "scripts/setlocalversion".) +config HAVE_KERNEL_GZIP + bool + +config HAVE_KERNEL_BZIP2 + bool + +config HAVE_KERNEL_LZMA + bool + choice - prompt "Kernel compression mode" - default KERNEL_GZIP - help + prompt "Kernel compression mode" + default KERNEL_GZIP + depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA + help The linux kernel is a kind of self-extracting executable. Several compression algorithms are available, which differ in efficiency, compression and decompression speed. @@ -123,34 +133,34 @@ choice If in doubt, select 'gzip' config KERNEL_GZIP - bool "Gzip" - help - The old and tried gzip compression. Its compression ratio is - the poorest among the 3 choices; however its speed (both - compression and decompression) is the fastest. + bool "Gzip" + depends on HAVE_KERNEL_GZIP + help + The old and tried gzip compression. Its compression ratio is + the poorest among the 3 choices; however its speed (both + compression and decompression) is the fastest. config KERNEL_BZIP2 bool "Bzip2" + depends on HAVE_KERNEL_BZIP2 help Its compression ratio and speed is intermediate. - Decompression speed is slowest among the 3. - The kernel size is about 10 per cent smaller with bzip2, - in comparison to gzip. - Bzip2 uses a large amount of memory. For modern kernels - you will need at least 8MB RAM or more for booting. + Decompression speed is slowest among the three. The kernel + size is about 10% smaller with bzip2, in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels you + will need at least 8MB RAM or more for booting. config KERNEL_LZMA - bool "LZMA" - help - The most recent compression algorithm. - Its ratio is best, decompression speed is between the other - 2. Compression is slowest. - The kernel size is about 33 per cent smaller with lzma, - in comparison to gzip. + bool "LZMA" + depends on HAVE_KERNEL_LZMA + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other + two. Compression is slowest. The kernel size is about 33% + smaller with LZMA in comparison to gzip. endchoice - config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK -- cgit v1.2.3 From a26ee60f90daffe1de6be0d093af86e7279b3dfd Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Wed, 7 Jan 2009 00:10:27 -0800 Subject: bzip2/lzma: fix built-in initramfs vs CONFIG_RD_GZIP Impact: Resolves build failures in some configurations Makes it possible to disable CONFIG_RD_GZIP . In that case, the built-in initramfs will be compressed by whatever compressor is available (bzip2 or lzma) or left uncompressed if none is available. It also removes a couple of warnings which occur when no ramdisk compression at all is chosen. It also restores the select ZLIB_INFLATE in drivers/block/Kconfig which somehow came missing. This is needed to activate compilation of the stuff in zlib_deflate. Signed-off-by: Alain Knaff Signed-off-by: H. Peter Anvin --- init/initramfs.c | 7 ++++++- scripts/gen_initramfs_list.sh | 17 +++++++++++------ usr/Makefile | 42 ++++++++++++++++++++++++++++++------------ usr/initramfs_data.S | 2 +- usr/initramfs_data.bz2.S | 29 +++++++++++++++++++++++++++++ usr/initramfs_data.gz.S | 29 +++++++++++++++++++++++++++++ usr/initramfs_data.lzma.S | 29 +++++++++++++++++++++++++++++ 7 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 usr/initramfs_data.bz2.S create mode 100644 usr/initramfs_data.gz.S create mode 100644 usr/initramfs_data.lzma.S (limited to 'init') diff --git a/init/initramfs.c b/init/initramfs.c index 40bd4fb95788..a3ba91cdab89 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -389,7 +389,7 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } - +#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA static int __init flush_buffer(void *bufv, unsigned len) { char *buf = (char *) bufv; @@ -412,6 +412,7 @@ static int __init flush_buffer(void *bufv, unsigned len) } return origLen; } +#endif static unsigned my_inptr; /* index of next byte to be processed in inbuf */ @@ -449,10 +450,12 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; +#ifdef CONFIG_RD_GZIP if (!gunzip(buf, len, NULL, flush_buffer, NULL, &my_inptr, error) && message == NULL) goto ok; +#endif #ifdef CONFIG_RD_BZIP2 message = NULL; /* Zero out message, or else cpio will @@ -473,7 +476,9 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) goto ok; } #endif +#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA ok: +#endif if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 5f3415f28736..41041e4923f7 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -5,7 +5,7 @@ # Released under the terms of the GNU GPL # # Generate a cpio packed initramfs. It uses gen_init_cpio to generate -# the cpio archive, and gzip to pack it. +# the cpio archive, and then compresses it. # The script may also be used to generate the inputfile used for gen_init_cpio # This script assumes that gen_init_cpio is located in usr/ directory @@ -16,8 +16,8 @@ usage() { cat << EOF Usage: $0 [-o ] [-u ] [-g ] {-d | } ... - -o Create gzipped initramfs file named using - gen_init_cpio and gzip + -o Create compressed initramfs file named using + gen_init_cpio and compressor depending on the extension -u User ID to map to user ID 0 (root). is only meaningful if is a directory. "squash" forces all files to uid 0. @@ -225,6 +225,7 @@ cpio_list= output="/dev/stdout" output_file="" is_cpio_compressed= +compr="gzip -9 -f" arg="$1" case "$arg" in @@ -233,11 +234,15 @@ case "$arg" in echo "deps_initramfs := \\" shift ;; - "-o") # generate gzipped cpio image named $1 + "-o") # generate compressed cpio image named $1 shift output_file="$1" cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)" output=${cpio_list} + echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f" + echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f" + echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f" + echo "$output_file" | grep -q "\.cpio$" && compr="cat" shift ;; esac @@ -274,7 +279,7 @@ while [ $# -gt 0 ]; do esac done -# If output_file is set we will generate cpio archive and gzip it +# If output_file is set we will generate cpio archive and compress it # we are carefull to delete tmp files if [ ! -z ${output_file} ]; then if [ -z ${cpio_file} ]; then @@ -287,7 +292,7 @@ if [ ! -z ${output_file} ]; then if [ "${is_cpio_compressed}" = "compressed" ]; then cat ${cpio_tfile} > ${output_file} else - cat ${cpio_tfile} | gzip -f -9 - > ${output_file} + cat ${cpio_tfile} | ${compr} - > ${output_file} fi [ -z ${cpio_file} ] && rm ${cpio_tfile} fi diff --git a/usr/Makefile b/usr/Makefile index 201f27f8cbaf..451cdff7dff9 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -5,14 +5,32 @@ klibcdirs:; PHONY += klibcdirs +# Find out "preferred" ramdisk compressor. Order of preference is +# 1. bzip2 efficient, and likely to be present +# 2. gzip former default +# 3. lzma +# 4. none + +# None of the above +suffix_y = + +# Lzma, but no gzip nor bzip2 +suffix_$(CONFIG_RD_LZMA) = .lzma + +# Gzip, but no bzip2 +suffix_$(CONFIG_RD_GZIP) = .gz + +# Bzip2 +suffix_$(CONFIG_RD_BZIP2) = .bz2 + # Generate builtin.o based on initramfs_data.o -obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o +obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data$(suffix_y).o -# initramfs_data.o contains the initramfs_data.cpio.gz image. +# initramfs_data.o contains the compressed initramfs_data.cpio image. # The image is included using .incbin, a dependency which is not # tracked automatically. -$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE +$(obj)/initramfs_data$(suffix_y).o: $(obj)/initramfs_data.cpio$(suffix_y) FORCE ##### # Generate the initramfs cpio archive @@ -25,28 +43,28 @@ ramfs-args := \ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) -# .initramfs_data.cpio.gz.d is used to identify all files included +# .initramfs_data.cpio.d is used to identify all files included # in initramfs and to detect if any files are added/removed. # Removed files are identified by directory timestamp being updated # The dependency list is generated by gen_initramfs.sh -l -ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),) - include $(obj)/.initramfs_data.cpio.gz.d +ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),) + include $(obj)/.initramfs_data.cpio.d endif quiet_cmd_initfs = GEN $@ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) -targets := initramfs_data.cpio.gz +targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio # do not try to update files included in initramfs $(deps_initramfs): ; $(deps_initramfs): klibcdirs -# We rebuild initramfs_data.cpio.gz if: -# 1) Any included file is newer then initramfs_data.cpio.gz +# We rebuild initramfs_data.cpio if: +# 1) Any included file is newer then initramfs_data.cpio # 2) There are changes in which files are included (added or deleted) -# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz +# 3) If gen_init_cpio are newer than initramfs_data.cpio # 4) arguments to gen_initramfs.sh changes -$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs - $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d +$(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs + $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d $(call if_changed,initfs) diff --git a/usr/initramfs_data.S b/usr/initramfs_data.S index c2e1ad424f4a..7c6973d8d829 100644 --- a/usr/initramfs_data.S +++ b/usr/initramfs_data.S @@ -26,5 +26,5 @@ SECTIONS */ .section .init.ramfs,"a" -.incbin "usr/initramfs_data.cpio.gz" +.incbin "usr/initramfs_data.cpio" diff --git a/usr/initramfs_data.bz2.S b/usr/initramfs_data.bz2.S new file mode 100644 index 000000000000..bc54d090365c --- /dev/null +++ b/usr/initramfs_data.bz2.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.bz2" diff --git a/usr/initramfs_data.gz.S b/usr/initramfs_data.gz.S new file mode 100644 index 000000000000..890c8dd1d6bd --- /dev/null +++ b/usr/initramfs_data.gz.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.gz" diff --git a/usr/initramfs_data.lzma.S b/usr/initramfs_data.lzma.S new file mode 100644 index 000000000000..e11469e48562 --- /dev/null +++ b/usr/initramfs_data.lzma.S @@ -0,0 +1,29 @@ +/* + initramfs_data includes the compressed binary that is the + filesystem used for early user space. + Note: Older versions of "as" (prior to binutils 2.11.90.0.23 + released on 2001-07-14) dit not support .incbin. + If you are forced to use older binutils than that then the + following trick can be applied to create the resulting binary: + + + ld -m elf_i386 --format binary --oformat elf32-i386 -r \ + -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o + ld -m elf_i386 -r -o built-in.o initramfs_data.o + + initramfs_data.scr looks like this: +SECTIONS +{ + .init.ramfs : { *(.data) } +} + + The above example is for i386 - the parameters vary from architectures. + Eventually look up LDFLAGS_BLOB in an older version of the + arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. + + Using .incbin has the advantage over ld that the correct flags are set + in the ELF header, as required by certain architectures. +*/ + +.section .init.ramfs,"a" +.incbin "usr/initramfs_data.cpio.lzma" -- cgit v1.2.3 From 889c92d21db40be0b7d22a59395060237895bb85 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Thu, 8 Jan 2009 15:14:17 -0800 Subject: bzip2/lzma: centralize format detection Centralize the compression format detection to a common routine in the lib directory, and use it for both initramfs and initrd. Signed-off-by: H. Peter Anvin --- include/linux/decompress/generic.h | 3 +++ init/do_mounts_rd.c | 38 ++++++----------------------- init/initramfs.c | 39 ++++++----------------------- lib/Makefile | 9 ++++--- lib/decompress.c | 50 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 67 deletions(-) create mode 100644 lib/decompress.c (limited to 'init') diff --git a/include/linux/decompress/generic.h b/include/linux/decompress/generic.h index f847f514f78e..6dfb856327bb 100644 --- a/include/linux/decompress/generic.h +++ b/include/linux/decompress/generic.h @@ -26,5 +26,8 @@ typedef int (*decompress_fn) (unsigned char *inbuf, int len, *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE */ +/* Utility routine to detect the decompression method */ +decompress_fn decompress_method(const unsigned char *inbuf, int len, + const char **name); #endif diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 9c9d7dbcf9ca..a06ed4f92e0e 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -12,9 +12,6 @@ #include -#include -#include -#include int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ @@ -49,24 +46,6 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); * cramfs * gzip */ -static const struct compress_format { - unsigned char magic[2]; - const char *name; - decompress_fn decompressor; -} compressed_formats[] = { -#ifdef CONFIG_RD_GZIP - { {037, 0213}, "gzip", gunzip }, - { {037, 0236}, "gzip", gunzip }, -#endif -#ifdef CONFIG_RD_BZIP2 - { {0x42, 0x5a}, "bzip2", bunzip2 }, -#endif -#ifdef CONFIG_RD_LZMA - { {0x5d, 0x00}, "lzma", unlzma }, -#endif - { {0, 0}, NULL, NULL } -}; - static int __init identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) { @@ -77,7 +56,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; - const struct compress_format *cf; + const char *compress_name; buf = kmalloc(size, GFP_KERNEL); if (!buf) @@ -95,15 +74,12 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) sys_lseek(fd, start_block * BLOCK_SIZE, 0); sys_read(fd, buf, size); - for (cf = compressed_formats; cf->decompressor; cf++) { - if (buf[0] == cf->magic[0] && buf[1] == cf->magic[1]) { - printk(KERN_NOTICE - "RAMDISK: %s image found at block %d\n", - cf->name, start_block); - *decompressor = cf->decompressor; - nblocks = 0; - goto done; - } + *decompressor = decompress_method(buf, size, &compress_name); + if (*decompressor) { + printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", + compress_name, start_block); + nblocks = 0; + goto done; } /* romfs is at block zero too */ diff --git a/init/initramfs.c b/init/initramfs.c index a3ba91cdab89..2f42984e5582 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -416,13 +416,13 @@ static int __init flush_buffer(void *bufv, unsigned len) static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -#include -#include -#include +#include static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { int written; + decompress_fn decompress; + dry_run = check_only; header_buf = kmalloc(110, GFP_KERNEL); symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); @@ -450,35 +450,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; -#ifdef CONFIG_RD_GZIP - if (!gunzip(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) - goto ok; -#endif - -#ifdef CONFIG_RD_BZIP2 - message = NULL; /* Zero out message, or else cpio will - think an error has already occured */ - if (!bunzip2(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) { - goto ok; - } -#endif - -#ifdef CONFIG_RD_LZMA - message = NULL; /* Zero out message, or else cpio will - think an error has already occured */ - if (!unlzma(buf, len, NULL, flush_buffer, NULL, - &my_inptr, error) && - message == NULL) { - goto ok; - } -#endif -#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA -ok: -#endif + decompress = decompress_method(buf, len, NULL); + if (decompress) + decompress(buf, len, NULL, flush_buffer, NULL, + &my_inptr, error); if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/lib/Makefile b/lib/Makefile index d9ac5a414fa7..790de7c25d0d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ - proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o + proportions.o prio_heap.o ratelimit.o show_mem.o \ + is_single_threaded.o decompress.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -65,9 +66,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ -obj-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o -obj-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o -obj-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o +lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o +lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o +lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o obj-$(CONFIG_TEXTSEARCH) += textsearch.o obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o diff --git a/lib/decompress.c b/lib/decompress.c new file mode 100644 index 000000000000..edac55cc7823 --- /dev/null +++ b/lib/decompress.c @@ -0,0 +1,50 @@ +/* + * decompress.c + * + * Detect the decompression method based on magic number + */ + +#include + +#include +#include +#include + +#include +#include + +static const struct compress_format { + unsigned char magic[2]; + const char *name; + decompress_fn decompressor; +} compressed_formats[] = { +#ifdef CONFIG_DECOMPRESS_GZIP + { {037, 0213}, "gzip", gunzip }, + { {037, 0236}, "gzip", gunzip }, +#endif +#ifdef CONFIG_DECOMPRESS_BZIP2 + { {0x42, 0x5a}, "bzip2", bunzip2 }, +#endif +#ifdef CONFIG_DECOMPRESS_LZMA + { {0x5d, 0x00}, "lzma", unlzma }, +#endif + { {0, 0}, NULL, NULL } +}; + +decompress_fn decompress_method(const unsigned char *inbuf, int len, + const char **name) +{ + const struct compress_format *cf; + + if (len < 2) + return NULL; /* Need at least this much... */ + + for (cf = compressed_formats; cf->decompressor; cf++) { + if (!memcmp(inbuf, cf->magic, 2)) + break; + + } + if (name) + *name = cf->name; + return cf->decompressor; +} -- cgit v1.2.3 From 736f93236ce786d1bcf09ad4dcb38a360d35ea1b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 10 Jan 2009 12:06:19 +0100 Subject: bzip2/lzma: make flush_buffer() unconditional Impact: build fix flush_buffer() is used unconditionally: init/initramfs.c:456: error: 'flush_buffer' undeclared (first use in this function) init/initramfs.c:456: error: (Each undeclared identifier is reported only once init/initramfs.c:456: error: for each function it appears in.) So remove the decompressor #ifdefs from around it. Signed-off-by: Ingo Molnar --- init/initramfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'init') diff --git a/init/initramfs.c b/init/initramfs.c index f8241e832aa3..76f4a0125338 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -390,7 +390,6 @@ static int __init write_buffer(char *buf, unsigned len) return len - count; } -#if defined CONFIG_RD_GZIP || defined CONFIG_RD_BZIP2 || defined CONFIG_RD_LZMA static int __init flush_buffer(void *bufv, unsigned len) { char *buf = (char *) bufv; @@ -413,7 +412,6 @@ static int __init flush_buffer(void *bufv, unsigned len) } return origLen; } -#endif static unsigned my_inptr; /* index of next byte to be processed in inbuf */ -- cgit v1.2.3 From 23a22d57a8962479ca630c9542e62d6f86fdf927 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Mon, 12 Jan 2009 14:24:04 -0800 Subject: bzip2/lzma: comprehensible error messages for missing decompressor Instead of failing to identify a compressed image with a decompressor that we don't have compiled in, identify it and fail with a comprehensible panic message. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 5 ++++- init/initramfs.c | 12 +++++++++++- lib/decompress.c | 16 ++++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) (limited to 'init') diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index a015e267fd17..91d0cfca5071 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -79,9 +79,12 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) sys_read(fd, buf, size); *decompressor = decompress_method(buf, size, &compress_name); - if (*decompressor) { + if (compress_name) { printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", compress_name, start_block); + if (!*decompressor) + printk(KERN_CRIT "RAMDISK: %s decompressor not configured!\n", + compress_name); nblocks = 0; goto done; } diff --git a/init/initramfs.c b/init/initramfs.c index 76f4a0125338..9a7290ec8187 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -421,6 +421,8 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { int written; decompress_fn decompress; + const char *compress_name; + static __initdata char msg_buf[64]; dry_run = check_only; header_buf = kmalloc(110, GFP_KERNEL); @@ -449,10 +451,18 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) continue; } this_header = 0; - decompress = decompress_method(buf, len, NULL); + decompress = decompress_method(buf, len, &compress_name); if (decompress) decompress(buf, len, NULL, flush_buffer, NULL, &my_inptr, error); + else if (compress_name) { + if (!message) { + snprintf(msg_buf, sizeof msg_buf, + "compression method %s not configured", + compress_name); + message = msg_buf; + } + } if (state != Reset) error("junk in compressed archive"); this_header = saved_offset + my_inptr; diff --git a/lib/decompress.c b/lib/decompress.c index edac55cc7823..961f367320fc 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -13,21 +13,25 @@ #include #include +#ifndef CONFIG_DECOMPRESS_GZIP +# define gunzip NULL +#endif +#ifndef CONFIG_DECOMPRESS_BZIP2 +# define bunzip2 NULL +#endif +#ifndef CONFIG_DECOMPRESS_LZMA +# define unlzma NULL +#endif + static const struct compress_format { unsigned char magic[2]; const char *name; decompress_fn decompressor; } compressed_formats[] = { -#ifdef CONFIG_DECOMPRESS_GZIP { {037, 0213}, "gzip", gunzip }, { {037, 0236}, "gzip", gunzip }, -#endif -#ifdef CONFIG_DECOMPRESS_BZIP2 { {0x42, 0x5a}, "bzip2", bunzip2 }, -#endif -#ifdef CONFIG_DECOMPRESS_LZMA { {0x5d, 0x00}, "lzma", unlzma }, -#endif { {0, 0}, NULL, NULL } }; -- cgit v1.2.3 From 73310a169aebe257efdd35a763cce1c7658f40c9 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin Date: Wed, 14 Jan 2009 11:28:35 -0800 Subject: init: make initrd/initramfs decompression failure a KERN_EMERG event Impact: More consistent behaviour, avoid policy in the kernel Upgrade/downgrade initrd/initramfs decompression failure from inconsistently a panic or a KERN_ALERT message to a KERN_EMERG event. It is, however, possible do design a system which can recover from this (using the kernel builtin code and/or the internal initramfs), which means this is policy, not a technical necessity. A good way to handle this would be to have a panic-level=X option, to force a panic on a printk above a certain level. That is a separate patch, however. Signed-off-by: H. Peter Anvin --- init/do_mounts_rd.c | 3 ++- init/initramfs.c | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'init') diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 91d0cfca5071..027a402708de 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -83,7 +83,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", compress_name, start_block); if (!*decompressor) - printk(KERN_CRIT "RAMDISK: %s decompressor not configured!\n", + printk(KERN_EMERG + "RAMDISK: %s decompressor not configured!\n", compress_name); nblocks = 0; goto done; diff --git a/init/initramfs.c b/init/initramfs.c index 9a7290ec8187..7dcde7ea6603 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -528,7 +528,7 @@ static int __init populate_rootfs(void) char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); if (err) - panic(err); + panic(err); /* Failed to decompress INTERNAL initramfs */ if (initrd_start) { #ifdef CONFIG_BLK_DEV_RAM int fd; @@ -554,9 +554,12 @@ static int __init populate_rootfs(void) printk(KERN_INFO "Unpacking initramfs..."); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 0); - if (err) - panic(err); - printk(" done\n"); + if (err) { + printk(" failed!\n"); + printk(KERN_EMERG "%s\n", err); + } else { + printk(" done\n"); + } free_initrd(); #endif } -- cgit v1.2.3 From 155b25bcc28631a5b5230191aa3f56c40dfffa3f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 2 Mar 2009 14:14:06 -0800 Subject: menu: fix embedded menu snafu The COMPAT_BRK kconfig symbol does not depend on EMBEDDED, but it is in the midst of the EMBEDDED menu symbols, so it mucks up the EMBEDDED menu. Fix by moving it to just after all of the EMBEDDED menu symbols. Also, surround all of the EMBEDDED symbols with "if EMBEDDED"/"endif" so that this EMBEDDED block is clearer. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- init/Kconfig | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index f068071fcc5d..90003163e557 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -683,6 +683,8 @@ menuconfig EMBEDDED environments which can tolerate a "non-standard" kernel. Only use this if you really know what you are doing. +if EMBEDDED + config UID16 bool "Enable 16-bit UID system calls" if EMBEDDED depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) @@ -780,18 +782,6 @@ config PCSPKR_PLATFORM This option allows to disable the internal PC-Speaker support, saving some memory. -config COMPAT_BRK - bool "Disable heap randomization" - default y - help - Randomizing heap placement makes heap exploits harder, but it - also breaks ancient binaries (including anything libc5 based). - This option changes the bootup default to heap randomization - disabled, and can be overriden runtime by setting - /proc/sys/kernel/randomize_va_space to 2. - - On non-ancient distros (post-2000 ones) N is usually a safe choice. - config BASE_FULL default y bool "Enable full-sized data structures for core" if EMBEDDED @@ -897,6 +887,20 @@ config SLUB_DEBUG SLUB sysfs support. /sys/slab will not exist and there will be no support for cache validation etc. +endif # EMBEDDED + +config COMPAT_BRK + bool "Disable heap randomization" + default y + help + Randomizing heap placement makes heap exploits harder, but it + also breaks ancient binaries (including anything libc5 based). + This option changes the bootup default to heap randomization + disabled, and can be overriden runtime by setting + /proc/sys/kernel/randomize_va_space to 2. + + On non-ancient distros (post-2000 ones) N is usually a safe choice. + choice prompt "Choose SLAB allocator" default SLUB -- cgit v1.2.3 From 2450cf51a1bdba7037e91b1bcc494b01c58aaf66 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 2 Mar 2009 16:23:33 -0800 Subject: Revert "menu: fix embedded menu snafu" This reverts commit 155b25bcc28631a5b5230191aa3f56c40dfffa3f, which was totally wrong - the "embedded" options still exists (very much so) even on non-embedded platforms. It's just that we don't bother with actually asking about them when we're not embedded, we just take their default values (which is usually 'y' - the options add features that may not be worth it in a constrained environment). Noticed-by: Andrew Morton Cc: Randy Dunlap Signed-off-by: Linus Torvalds --- init/Kconfig | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'init') diff --git a/init/Kconfig b/init/Kconfig index 90003163e557..f068071fcc5d 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -683,8 +683,6 @@ menuconfig EMBEDDED environments which can tolerate a "non-standard" kernel. Only use this if you really know what you are doing. -if EMBEDDED - config UID16 bool "Enable 16-bit UID system calls" if EMBEDDED depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) @@ -782,6 +780,18 @@ config PCSPKR_PLATFORM This option allows to disable the internal PC-Speaker support, saving some memory. +config COMPAT_BRK + bool "Disable heap randomization" + default y + help + Randomizing heap placement makes heap exploits harder, but it + also breaks ancient binaries (including anything libc5 based). + This option changes the bootup default to heap randomization + disabled, and can be overriden runtime by setting + /proc/sys/kernel/randomize_va_space to 2. + + On non-ancient distros (post-2000 ones) N is usually a safe choice. + config BASE_FULL default y bool "Enable full-sized data structures for core" if EMBEDDED @@ -887,20 +897,6 @@ config SLUB_DEBUG SLUB sysfs support. /sys/slab will not exist and there will be no support for cache validation etc. -endif # EMBEDDED - -config COMPAT_BRK - bool "Disable heap randomization" - default y - help - Randomizing heap placement makes heap exploits harder, but it - also breaks ancient binaries (including anything libc5 based). - This option changes the bootup default to heap randomization - disabled, and can be overriden runtime by setting - /proc/sys/kernel/randomize_va_space to 2. - - On non-ancient distros (post-2000 ones) N is usually a safe choice. - choice prompt "Choose SLAB allocator" default SLUB -- cgit v1.2.3