summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/Kconfig60
-rw-r--r--init/do_mounts_rd.c178
-rw-r--r--init/initramfs.c122
3 files changed, 144 insertions, 216 deletions
diff --git a/init/Kconfig b/init/Kconfig
index f068071fcc5d..95a66131403a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -101,6 +101,66 @@ 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
+ 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.
+ 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) <alain@knaff.lu>. (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"
+ 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 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"
+ 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
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 0f0f0cf3ba9a..027a402708de 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -11,6 +11,9 @@
#include "do_mounts.h"
#include "../fs/squashfs/squashfs_fs.h"
+#include <linux/decompress/generic.h>
+
+
int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
static int __init prompt_ramdisk(char *str)
@@ -29,7 +32,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
@@ -38,15 +41,15 @@ static int __init crd_load(int in_fd, int out_fd);
* numbers could not be found.
*
* We currently check for the following magic numbers:
- * minix
- * ext2
+ * minix
+ * ext2
* romfs
* cramfs
* squashfs
- * gzip
+ * gzip
*/
-static int __init
-identify_ramdisk_image(int fd, int start_block)
+static int __init
+identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
{
const int size = 512;
struct minix_super_block *minixsb;
@@ -56,6 +59,7 @@ identify_ramdisk_image(int fd, int start_block)
struct squashfs_super_block *squashfsb;
int nblocks = -1;
unsigned char *buf;
+ const char *compress_name;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
@@ -69,18 +73,19 @@ identify_ramdisk_image(int fd, int start_block)
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);
- /*
- * 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 = decompress_method(buf, size, &compress_name);
+ if (compress_name) {
+ printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n",
+ compress_name, start_block);
+ if (!*decompressor)
+ printk(KERN_EMERG
+ "RAMDISK: %s decompressor not configured!\n",
+ compress_name);
nblocks = 0;
goto done;
}
@@ -142,7 +147,7 @@ identify_ramdisk_image(int fd, int start_block)
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);
@@ -157,6 +162,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
@@ -169,12 +175,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;
}
@@ -200,7 +206,7 @@ int __init rd_load_image(char *from)
nblocks, rd_blocks);
goto done;
}
-
+
/*
* OK, time to copy in the data
*/
@@ -273,138 +279,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 d9c941c0c3ca..7dcde7ea6603 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -390,11 +390,13 @@ 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') {
@@ -408,84 +410,28 @@ static void __init flush_buffer(char *buf, unsigned len)
} else
error("junk in compressed archive");
}
+ return origLen;
}
-/*
- * gzip declarations
- */
+static unsigned my_inptr; /* index of next byte to be processed in inbuf */
-#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
-
-#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 <linux/decompress/generic.h>
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);
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;
@@ -505,22 +451,25 @@ 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();
+ 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 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);
@@ -579,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;
@@ -605,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
}