aboutsummaryrefslogtreecommitdiffstats
path: root/init/initramfs.c
diff options
context:
space:
mode:
authorAlain Knaff <alain@knaff.lu>2009-01-04 16:46:17 -0500
committerH. Peter Anvin <hpa@zytor.com>2009-01-04 18:53:35 -0500
commit30d65dbfe3add7f010a075991dc0bfeaebb7d9e1 (patch)
treec60ce6748eea43d1e74d96ef03990b1e23f33b1d /init/initramfs.c
parentbc22c17e12c130dc929218a95aa347e0f3fd05dc (diff)
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 <alain@knaff.lu> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'init/initramfs.c')
-rw-r--r--init/initramfs.c123
1 files changed, 42 insertions, 81 deletions
diff --git a/init/initramfs.c b/init/initramfs.c
index 4f5ba75aaa7..40bd4fb9578 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
392static void __init flush_buffer(char *buf, unsigned len) 392
393static 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/* 416static 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
422typedef unsigned char uch;
423typedef unsigned short ush;
424typedef 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
429static uch *inbuf;
430static uch *window;
431
432static unsigned insize; /* valid bytes in inbuf */
433static unsigned inptr; /* index of next byte to be processed in inbuf */
434static unsigned outcnt; /* bytes in output buffer */
435static 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
450static void __init flush_window(void);
451static 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 */
461static 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
478static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) 422static 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
476ok:
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);