diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/Kconfig | 50 | ||||
-rw-r--r-- | init/do_mounts_rd.c | 182 | ||||
-rw-r--r-- | init/initramfs.c | 123 |
3 files changed, 157 insertions, 198 deletions
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 | |||
101 | 101 | ||
102 | which is done within the script "scripts/setlocalversion".) | 102 | which is done within the script "scripts/setlocalversion".) |
103 | 103 | ||
104 | choice | ||
105 | prompt "Kernel compression mode" | ||
106 | default KERNEL_GZIP | ||
107 | help | ||
108 | The linux kernel is a kind of self-extracting executable. | ||
109 | Several compression algorithms are available, which differ | ||
110 | in efficiency, compression and decompression speed. | ||
111 | Compression speed is only relevant when building a kernel. | ||
112 | Decompression speed is relevant at each boot. | ||
113 | |||
114 | If you have any problems with bzip2 or lzma compressed | ||
115 | kernels, mail me (Alain Knaff) <alain@knaff.lu>. (An older | ||
116 | version of this functionality (bzip2 only), for 2.4, was | ||
117 | supplied by Christian Ludwig) | ||
118 | |||
119 | High compression options are mostly useful for users, who | ||
120 | are low on disk space (embedded systems), but for whom ram | ||
121 | size matters less. | ||
122 | |||
123 | If in doubt, select 'gzip' | ||
124 | |||
125 | config KERNEL_GZIP | ||
126 | bool "Gzip" | ||
127 | help | ||
128 | The old and tried gzip compression. Its compression ratio is | ||
129 | the poorest among the 3 choices; however its speed (both | ||
130 | compression and decompression) is the fastest. | ||
131 | |||
132 | config KERNEL_BZIP2 | ||
133 | bool "Bzip2" | ||
134 | help | ||
135 | Its compression ratio and speed is intermediate. | ||
136 | Decompression speed is slowest among the 3. | ||
137 | The kernel size is about 10 per cent smaller with bzip2, | ||
138 | in comparison to gzip. | ||
139 | Bzip2 uses a large amount of memory. For modern kernels | ||
140 | you will need at least 8MB RAM or more for booting. | ||
141 | |||
142 | config KERNEL_LZMA | ||
143 | bool "LZMA" | ||
144 | help | ||
145 | The most recent compression algorithm. | ||
146 | Its ratio is best, decompression speed is between the other | ||
147 | 2. Compression is slowest. | ||
148 | The kernel size is about 33 per cent smaller with lzma, | ||
149 | in comparison to gzip. | ||
150 | |||
151 | endchoice | ||
152 | |||
153 | |||
104 | config SWAP | 154 | config SWAP |
105 | bool "Support for paging of anonymous memory (swap)" | 155 | bool "Support for paging of anonymous memory (swap)" |
106 | depends on MMU && BLOCK | 156 | 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 @@ | |||
10 | 10 | ||
11 | #include "do_mounts.h" | 11 | #include "do_mounts.h" |
12 | 12 | ||
13 | #include <linux/decompress/generic.h> | ||
14 | |||
15 | #include <linux/decompress/bunzip2.h> | ||
16 | #include <linux/decompress/unlzma.h> | ||
17 | #include <linux/decompress/inflate.h> | ||
18 | |||
13 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ | 19 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ |
14 | 20 | ||
15 | static int __init prompt_ramdisk(char *str) | 21 | static int __init prompt_ramdisk(char *str) |
@@ -28,7 +34,7 @@ static int __init ramdisk_start_setup(char *str) | |||
28 | } | 34 | } |
29 | __setup("ramdisk_start=", ramdisk_start_setup); | 35 | __setup("ramdisk_start=", ramdisk_start_setup); |
30 | 36 | ||
31 | static int __init crd_load(int in_fd, int out_fd); | 37 | static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); |
32 | 38 | ||
33 | /* | 39 | /* |
34 | * This routine tries to find a RAM disk image to load, and returns the | 40 | * 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); | |||
44 | * gzip | 50 | * gzip |
45 | */ | 51 | */ |
46 | static int __init | 52 | static int __init |
47 | identify_ramdisk_image(int fd, int start_block) | 53 | identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) |
48 | { | 54 | { |
49 | const int size = 512; | 55 | const int size = 512; |
50 | struct minix_super_block *minixsb; | 56 | struct minix_super_block *minixsb; |
@@ -70,6 +76,7 @@ identify_ramdisk_image(int fd, int start_block) | |||
70 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); | 76 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); |
71 | sys_read(fd, buf, size); | 77 | sys_read(fd, buf, size); |
72 | 78 | ||
79 | #ifdef CONFIG_RD_GZIP | ||
73 | /* | 80 | /* |
74 | * If it matches the gzip magic numbers, return 0 | 81 | * If it matches the gzip magic numbers, return 0 |
75 | */ | 82 | */ |
@@ -77,9 +84,39 @@ identify_ramdisk_image(int fd, int start_block) | |||
77 | printk(KERN_NOTICE | 84 | printk(KERN_NOTICE |
78 | "RAMDISK: Compressed image found at block %d\n", | 85 | "RAMDISK: Compressed image found at block %d\n", |
79 | start_block); | 86 | start_block); |
87 | *decompressor = gunzip; | ||
88 | nblocks = 0; | ||
89 | goto done; | ||
90 | } | ||
91 | #endif | ||
92 | |||
93 | #ifdef CONFIG_RD_BZIP2 | ||
94 | /* | ||
95 | * If it matches the bzip2 magic numbers, return -1 | ||
96 | */ | ||
97 | if (buf[0] == 0x42 && (buf[1] == 0x5a)) { | ||
98 | printk(KERN_NOTICE | ||
99 | "RAMDISK: Bzipped image found at block %d\n", | ||
100 | start_block); | ||
101 | *decompressor = bunzip2; | ||
102 | nblocks = 0; | ||
103 | goto done; | ||
104 | } | ||
105 | #endif | ||
106 | |||
107 | #ifdef CONFIG_RD_LZMA | ||
108 | /* | ||
109 | * If it matches the lzma magic numbers, return -1 | ||
110 | */ | ||
111 | if (buf[0] == 0x5d && (buf[1] == 0x00)) { | ||
112 | printk(KERN_NOTICE | ||
113 | "RAMDISK: Lzma image found at block %d\n", | ||
114 | start_block); | ||
115 | *decompressor = unlzma; | ||
80 | nblocks = 0; | 116 | nblocks = 0; |
81 | goto done; | 117 | goto done; |
82 | } | 118 | } |
119 | #endif | ||
83 | 120 | ||
84 | /* romfs is at block zero too */ | 121 | /* romfs is at block zero too */ |
85 | if (romfsb->word0 == ROMSB_WORD0 && | 122 | if (romfsb->word0 == ROMSB_WORD0 && |
@@ -143,6 +180,7 @@ int __init rd_load_image(char *from) | |||
143 | int nblocks, i, disk; | 180 | int nblocks, i, disk; |
144 | char *buf = NULL; | 181 | char *buf = NULL; |
145 | unsigned short rotate = 0; | 182 | unsigned short rotate = 0; |
183 | decompress_fn decompressor = NULL; | ||
146 | #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) | 184 | #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) |
147 | char rotator[4] = { '|' , '/' , '-' , '\\' }; | 185 | char rotator[4] = { '|' , '/' , '-' , '\\' }; |
148 | #endif | 186 | #endif |
@@ -155,12 +193,12 @@ int __init rd_load_image(char *from) | |||
155 | if (in_fd < 0) | 193 | if (in_fd < 0) |
156 | goto noclose_input; | 194 | goto noclose_input; |
157 | 195 | ||
158 | nblocks = identify_ramdisk_image(in_fd, rd_image_start); | 196 | nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); |
159 | if (nblocks < 0) | 197 | if (nblocks < 0) |
160 | goto done; | 198 | goto done; |
161 | 199 | ||
162 | if (nblocks == 0) { | 200 | if (nblocks == 0) { |
163 | if (crd_load(in_fd, out_fd) == 0) | 201 | if (crd_load(in_fd, out_fd, decompressor) == 0) |
164 | goto successful_load; | 202 | goto successful_load; |
165 | goto done; | 203 | goto done; |
166 | } | 204 | } |
@@ -259,138 +297,48 @@ int __init rd_load_disk(int n) | |||
259 | return rd_load_image("/dev/root"); | 297 | return rd_load_image("/dev/root"); |
260 | } | 298 | } |
261 | 299 | ||
262 | /* | ||
263 | * gzip declarations | ||
264 | */ | ||
265 | |||
266 | #define OF(args) args | ||
267 | |||
268 | #ifndef memzero | ||
269 | #define memzero(s, n) memset ((s), 0, (n)) | ||
270 | #endif | ||
271 | |||
272 | typedef unsigned char uch; | ||
273 | typedef unsigned short ush; | ||
274 | typedef unsigned long ulg; | ||
275 | |||
276 | #define INBUFSIZ 4096 | ||
277 | #define WSIZE 0x8000 /* window size--must be a power of two, and */ | ||
278 | /* at least 32K for zip's deflate method */ | ||
279 | |||
280 | static uch *inbuf; | ||
281 | static uch *window; | ||
282 | |||
283 | static unsigned insize; /* valid bytes in inbuf */ | ||
284 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
285 | static unsigned outcnt; /* bytes in output buffer */ | ||
286 | static int exit_code; | 300 | static int exit_code; |
287 | static int unzip_error; | 301 | static int decompress_error; |
288 | static long bytes_out; | ||
289 | static int crd_infd, crd_outfd; | 302 | static int crd_infd, crd_outfd; |
290 | 303 | ||
291 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | 304 | static int __init compr_fill(void *buf, unsigned int len) |
292 | |||
293 | /* Diagnostic functions (stubbed out) */ | ||
294 | #define Assert(cond,msg) | ||
295 | #define Trace(x) | ||
296 | #define Tracev(x) | ||
297 | #define Tracevv(x) | ||
298 | #define Tracec(c,x) | ||
299 | #define Tracecv(c,x) | ||
300 | |||
301 | #define STATIC static | ||
302 | #define INIT __init | ||
303 | |||
304 | static int __init fill_inbuf(void); | ||
305 | static void __init flush_window(void); | ||
306 | static void __init error(char *m); | ||
307 | |||
308 | #define NO_INFLATE_MALLOC | ||
309 | |||
310 | #include "../lib/inflate.c" | ||
311 | |||
312 | /* =========================================================================== | ||
313 | * Fill the input buffer. This is called only when the buffer is empty | ||
314 | * and at least one byte is really needed. | ||
315 | * Returning -1 does not guarantee that gunzip() will ever return. | ||
316 | */ | ||
317 | static int __init fill_inbuf(void) | ||
318 | { | 305 | { |
319 | if (exit_code) return -1; | 306 | int r = sys_read(crd_infd, buf, len); |
320 | 307 | if (r < 0) | |
321 | insize = sys_read(crd_infd, inbuf, INBUFSIZ); | 308 | printk(KERN_ERR "RAMDISK: error while reading compressed data"); |
322 | if (insize == 0) { | 309 | else if (r == 0) |
323 | error("RAMDISK: ran out of compressed data"); | 310 | printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); |
324 | return -1; | 311 | return r; |
325 | } | ||
326 | |||
327 | inptr = 1; | ||
328 | |||
329 | return inbuf[0]; | ||
330 | } | 312 | } |
331 | 313 | ||
332 | /* =========================================================================== | 314 | static int __init compr_flush(void *window, unsigned int outcnt) |
333 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
334 | * (Used for the decompressed data only.) | ||
335 | */ | ||
336 | static void __init flush_window(void) | ||
337 | { | 315 | { |
338 | ulg c = crc; /* temporary variable */ | 316 | int written = sys_write(crd_outfd, window, outcnt); |
339 | unsigned n, written; | 317 | if (written != outcnt) { |
340 | uch *in, ch; | 318 | if (decompress_error == 0) |
341 | 319 | printk(KERN_ERR | |
342 | written = sys_write(crd_outfd, window, outcnt); | 320 | "RAMDISK: incomplete write (%d != %d)\n", |
343 | if (written != outcnt && unzip_error == 0) { | 321 | written, outcnt); |
344 | printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", | 322 | decompress_error = 1; |
345 | written, outcnt, bytes_out); | 323 | return -1; |
346 | unzip_error = 1; | 324 | } |
347 | } | 325 | return outcnt; |
348 | in = window; | ||
349 | for (n = 0; n < outcnt; n++) { | ||
350 | ch = *in++; | ||
351 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
352 | } | ||
353 | crc = c; | ||
354 | bytes_out += (ulg)outcnt; | ||
355 | outcnt = 0; | ||
356 | } | 326 | } |
357 | 327 | ||
358 | static void __init error(char *x) | 328 | static void __init error(char *x) |
359 | { | 329 | { |
360 | printk(KERN_ERR "%s\n", x); | 330 | printk(KERN_ERR "%s\n", x); |
361 | exit_code = 1; | 331 | exit_code = 1; |
362 | unzip_error = 1; | 332 | decompress_error = 1; |
363 | } | 333 | } |
364 | 334 | ||
365 | static int __init crd_load(int in_fd, int out_fd) | 335 | static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) |
366 | { | 336 | { |
367 | int result; | 337 | int result; |
368 | |||
369 | insize = 0; /* valid bytes in inbuf */ | ||
370 | inptr = 0; /* index of next byte to be processed in inbuf */ | ||
371 | outcnt = 0; /* bytes in output buffer */ | ||
372 | exit_code = 0; | ||
373 | bytes_out = 0; | ||
374 | crc = (ulg)0xffffffffL; /* shift register contents */ | ||
375 | |||
376 | crd_infd = in_fd; | 338 | crd_infd = in_fd; |
377 | crd_outfd = out_fd; | 339 | crd_outfd = out_fd; |
378 | inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); | 340 | result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); |
379 | if (!inbuf) { | 341 | if (decompress_error) |
380 | printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); | ||
381 | return -1; | ||
382 | } | ||
383 | window = kmalloc(WSIZE, GFP_KERNEL); | ||
384 | if (!window) { | ||
385 | printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); | ||
386 | kfree(inbuf); | ||
387 | return -1; | ||
388 | } | ||
389 | makecrc(); | ||
390 | result = gunzip(); | ||
391 | if (unzip_error) | ||
392 | result = 1; | 342 | result = 1; |
393 | kfree(inbuf); | ||
394 | kfree(window); | ||
395 | return result; | 343 | return result; |
396 | } | 344 | } |
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) | |||
389 | return len - count; | 389 | return len - count; |
390 | } | 390 | } |
391 | 391 | ||
392 | static void __init flush_buffer(char *buf, unsigned len) | 392 | |
393 | static int __init flush_buffer(void *bufv, unsigned len) | ||
393 | { | 394 | { |
395 | char *buf = (char *) bufv; | ||
394 | int written; | 396 | int written; |
397 | int origLen = len; | ||
395 | if (message) | 398 | if (message) |
396 | return; | 399 | return -1; |
397 | while ((written = write_buffer(buf, len)) < len && !message) { | 400 | while ((written = write_buffer(buf, len)) < len && !message) { |
398 | char c = buf[written]; | 401 | char c = buf[written]; |
399 | if (c == '0') { | 402 | if (c == '0') { |
@@ -407,73 +410,14 @@ static void __init flush_buffer(char *buf, unsigned len) | |||
407 | } else | 410 | } else |
408 | error("junk in compressed archive"); | 411 | error("junk in compressed archive"); |
409 | } | 412 | } |
413 | return origLen; | ||
410 | } | 414 | } |
411 | 415 | ||
412 | /* | 416 | static unsigned my_inptr; /* index of next byte to be processed in inbuf */ |
413 | * gzip declarations | ||
414 | */ | ||
415 | |||
416 | #define OF(args) args | ||
417 | |||
418 | #ifndef memzero | ||
419 | #define memzero(s, n) memset ((s), 0, (n)) | ||
420 | #endif | ||
421 | |||
422 | typedef unsigned char uch; | ||
423 | typedef unsigned short ush; | ||
424 | typedef unsigned long ulg; | ||
425 | |||
426 | #define WSIZE 0x8000 /* window size--must be a power of two, and */ | ||
427 | /* at least 32K for zip's deflate method */ | ||
428 | |||
429 | static uch *inbuf; | ||
430 | static uch *window; | ||
431 | |||
432 | static unsigned insize; /* valid bytes in inbuf */ | ||
433 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
434 | static unsigned outcnt; /* bytes in output buffer */ | ||
435 | static long bytes_out; | ||
436 | |||
437 | #define get_byte() (inptr < insize ? inbuf[inptr++] : -1) | ||
438 | |||
439 | /* Diagnostic functions (stubbed out) */ | ||
440 | #define Assert(cond,msg) | ||
441 | #define Trace(x) | ||
442 | #define Tracev(x) | ||
443 | #define Tracevv(x) | ||
444 | #define Tracec(c,x) | ||
445 | #define Tracecv(c,x) | ||
446 | |||
447 | #define STATIC static | ||
448 | #define INIT __init | ||
449 | |||
450 | static void __init flush_window(void); | ||
451 | static void __init error(char *m); | ||
452 | |||
453 | #define NO_INFLATE_MALLOC | ||
454 | 417 | ||
455 | #include "../lib/inflate.c" | 418 | #include <linux/decompress/bunzip2.h> |
456 | 419 | #include <linux/decompress/unlzma.h> | |
457 | /* =========================================================================== | 420 | #include <linux/decompress/inflate.h> |
458 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
459 | * (Used for the decompressed data only.) | ||
460 | */ | ||
461 | static void __init flush_window(void) | ||
462 | { | ||
463 | ulg c = crc; /* temporary variable */ | ||
464 | unsigned n; | ||
465 | uch *in, ch; | ||
466 | |||
467 | flush_buffer(window, outcnt); | ||
468 | in = window; | ||
469 | for (n = 0; n < outcnt; n++) { | ||
470 | ch = *in++; | ||
471 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
472 | } | ||
473 | crc = c; | ||
474 | bytes_out += (ulg)outcnt; | ||
475 | outcnt = 0; | ||
476 | } | ||
477 | 421 | ||
478 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | 422 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) |
479 | { | 423 | { |
@@ -482,9 +426,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | |||
482 | header_buf = kmalloc(110, GFP_KERNEL); | 426 | header_buf = kmalloc(110, GFP_KERNEL); |
483 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); | 427 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); |
484 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); | 428 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); |
485 | window = kmalloc(WSIZE, GFP_KERNEL); | 429 | |
486 | if (!window || !header_buf || !symlink_buf || !name_buf) | 430 | if (!header_buf || !symlink_buf || !name_buf) |
487 | panic("can't allocate buffers"); | 431 | panic("can't allocate buffers"); |
432 | |||
488 | state = Start; | 433 | state = Start; |
489 | this_header = 0; | 434 | this_header = 0; |
490 | message = NULL; | 435 | message = NULL; |
@@ -504,22 +449,38 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | |||
504 | continue; | 449 | continue; |
505 | } | 450 | } |
506 | this_header = 0; | 451 | this_header = 0; |
507 | insize = len; | 452 | if (!gunzip(buf, len, NULL, flush_buffer, NULL, |
508 | inbuf = buf; | 453 | &my_inptr, error) && |
509 | inptr = 0; | 454 | message == NULL) |
510 | outcnt = 0; /* bytes in output buffer */ | 455 | goto ok; |
511 | bytes_out = 0; | 456 | |
512 | crc = (ulg)0xffffffffL; /* shift register contents */ | 457 | #ifdef CONFIG_RD_BZIP2 |
513 | makecrc(); | 458 | message = NULL; /* Zero out message, or else cpio will |
514 | gunzip(); | 459 | think an error has already occured */ |
460 | if (!bunzip2(buf, len, NULL, flush_buffer, NULL, | ||
461 | &my_inptr, error) && | ||
462 | message == NULL) { | ||
463 | goto ok; | ||
464 | } | ||
465 | #endif | ||
466 | |||
467 | #ifdef CONFIG_RD_LZMA | ||
468 | message = NULL; /* Zero out message, or else cpio will | ||
469 | think an error has already occured */ | ||
470 | if (!unlzma(buf, len, NULL, flush_buffer, NULL, | ||
471 | &my_inptr, error) && | ||
472 | message == NULL) { | ||
473 | goto ok; | ||
474 | } | ||
475 | #endif | ||
476 | ok: | ||
515 | if (state != Reset) | 477 | if (state != Reset) |
516 | error("junk in gzipped archive"); | 478 | error("junk in compressed archive"); |
517 | this_header = saved_offset + inptr; | 479 | this_header = saved_offset + my_inptr; |
518 | buf += inptr; | 480 | buf += my_inptr; |
519 | len -= inptr; | 481 | len -= my_inptr; |
520 | } | 482 | } |
521 | dir_utime(); | 483 | dir_utime(); |
522 | kfree(window); | ||
523 | kfree(name_buf); | 484 | kfree(name_buf); |
524 | kfree(symlink_buf); | 485 | kfree(symlink_buf); |
525 | kfree(header_buf); | 486 | kfree(header_buf); |