aboutsummaryrefslogtreecommitdiffstats
path: root/init/do_mounts_rd.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/do_mounts_rd.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/do_mounts_rd.c')
-rw-r--r--init/do_mounts_rd.c182
1 files changed, 65 insertions, 117 deletions
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
13int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ 19int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
14 20
15static int __init prompt_ramdisk(char *str) 21static 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
31static int __init crd_load(int in_fd, int out_fd); 37static 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 */
46static int __init 52static int __init
47identify_ramdisk_image(int fd, int start_block) 53identify_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
272typedef unsigned char uch;
273typedef unsigned short ush;
274typedef 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
280static uch *inbuf;
281static uch *window;
282
283static unsigned insize; /* valid bytes in inbuf */
284static unsigned inptr; /* index of next byte to be processed in inbuf */
285static unsigned outcnt; /* bytes in output buffer */
286static int exit_code; 300static int exit_code;
287static int unzip_error; 301static int decompress_error;
288static long bytes_out;
289static int crd_infd, crd_outfd; 302static int crd_infd, crd_outfd;
290 303
291#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) 304static 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
304static int __init fill_inbuf(void);
305static void __init flush_window(void);
306static 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 */
317static 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/* =========================================================================== 314static 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 */
336static 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
358static void __init error(char *x) 328static 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
365static int __init crd_load(int in_fd, int out_fd) 335static 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}