diff options
Diffstat (limited to 'init/initramfs.c')
-rw-r--r-- | init/initramfs.c | 200 |
1 files changed, 97 insertions, 103 deletions
diff --git a/init/initramfs.c b/init/initramfs.c index d9c941c0c3ca..80cd713f6cc5 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/fcntl.h> | 5 | #include <linux/fcntl.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <linux/dirent.h> | ||
8 | #include <linux/syscalls.h> | 9 | #include <linux/syscalls.h> |
9 | #include <linux/utime.h> | 10 | #include <linux/utime.h> |
10 | 11 | ||
@@ -166,8 +167,6 @@ static __initdata char *victim; | |||
166 | static __initdata unsigned count; | 167 | static __initdata unsigned count; |
167 | static __initdata loff_t this_header, next_header; | 168 | static __initdata loff_t this_header, next_header; |
168 | 169 | ||
169 | static __initdata int dry_run; | ||
170 | |||
171 | static inline void __init eat(unsigned n) | 170 | static inline void __init eat(unsigned n) |
172 | { | 171 | { |
173 | victim += n; | 172 | victim += n; |
@@ -229,10 +228,6 @@ static int __init do_header(void) | |||
229 | parse_header(collected); | 228 | parse_header(collected); |
230 | next_header = this_header + N_ALIGN(name_len) + body_len; | 229 | next_header = this_header + N_ALIGN(name_len) + body_len; |
231 | next_header = (next_header + 3) & ~3; | 230 | next_header = (next_header + 3) & ~3; |
232 | if (dry_run) { | ||
233 | read_into(name_buf, N_ALIGN(name_len), GotName); | ||
234 | return 0; | ||
235 | } | ||
236 | state = SkipIt; | 231 | state = SkipIt; |
237 | if (name_len <= 0 || name_len > PATH_MAX) | 232 | if (name_len <= 0 || name_len > PATH_MAX) |
238 | return 0; | 233 | return 0; |
@@ -303,8 +298,6 @@ static int __init do_name(void) | |||
303 | free_hash(); | 298 | free_hash(); |
304 | return 0; | 299 | return 0; |
305 | } | 300 | } |
306 | if (dry_run) | ||
307 | return 0; | ||
308 | clean_path(collected, mode); | 301 | clean_path(collected, mode); |
309 | if (S_ISREG(mode)) { | 302 | if (S_ISREG(mode)) { |
310 | int ml = maybe_link(); | 303 | int ml = maybe_link(); |
@@ -390,11 +383,13 @@ static int __init write_buffer(char *buf, unsigned len) | |||
390 | return len - count; | 383 | return len - count; |
391 | } | 384 | } |
392 | 385 | ||
393 | static void __init flush_buffer(char *buf, unsigned len) | 386 | static int __init flush_buffer(void *bufv, unsigned len) |
394 | { | 387 | { |
388 | char *buf = (char *) bufv; | ||
395 | int written; | 389 | int written; |
390 | int origLen = len; | ||
396 | if (message) | 391 | if (message) |
397 | return; | 392 | return -1; |
398 | while ((written = write_buffer(buf, len)) < len && !message) { | 393 | while ((written = write_buffer(buf, len)) < len && !message) { |
399 | char c = buf[written]; | 394 | char c = buf[written]; |
400 | if (c == '0') { | 395 | if (c == '0') { |
@@ -408,84 +403,27 @@ static void __init flush_buffer(char *buf, unsigned len) | |||
408 | } else | 403 | } else |
409 | error("junk in compressed archive"); | 404 | error("junk in compressed archive"); |
410 | } | 405 | } |
406 | return origLen; | ||
411 | } | 407 | } |
412 | 408 | ||
413 | /* | 409 | static unsigned my_inptr; /* index of next byte to be processed in inbuf */ |
414 | * gzip declarations | ||
415 | */ | ||
416 | |||
417 | #define OF(args) args | ||
418 | |||
419 | #ifndef memzero | ||
420 | #define memzero(s, n) memset ((s), 0, (n)) | ||
421 | #endif | ||
422 | |||
423 | typedef unsigned char uch; | ||
424 | typedef unsigned short ush; | ||
425 | typedef unsigned long ulg; | ||
426 | 410 | ||
427 | #define WSIZE 0x8000 /* window size--must be a power of two, and */ | 411 | #include <linux/decompress/generic.h> |
428 | /* at least 32K for zip's deflate method */ | ||
429 | |||
430 | static uch *inbuf; | ||
431 | static uch *window; | ||
432 | |||
433 | static unsigned insize; /* valid bytes in inbuf */ | ||
434 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
435 | static unsigned outcnt; /* bytes in output buffer */ | ||
436 | static long bytes_out; | ||
437 | |||
438 | #define get_byte() (inptr < insize ? inbuf[inptr++] : -1) | ||
439 | |||
440 | /* Diagnostic functions (stubbed out) */ | ||
441 | #define Assert(cond,msg) | ||
442 | #define Trace(x) | ||
443 | #define Tracev(x) | ||
444 | #define Tracevv(x) | ||
445 | #define Tracec(c,x) | ||
446 | #define Tracecv(c,x) | ||
447 | |||
448 | #define STATIC static | ||
449 | #define INIT __init | ||
450 | |||
451 | static void __init flush_window(void); | ||
452 | static void __init error(char *m); | ||
453 | |||
454 | #define NO_INFLATE_MALLOC | ||
455 | |||
456 | #include "../lib/inflate.c" | ||
457 | |||
458 | /* =========================================================================== | ||
459 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
460 | * (Used for the decompressed data only.) | ||
461 | */ | ||
462 | static void __init flush_window(void) | ||
463 | { | ||
464 | ulg c = crc; /* temporary variable */ | ||
465 | unsigned n; | ||
466 | uch *in, ch; | ||
467 | |||
468 | flush_buffer(window, outcnt); | ||
469 | in = window; | ||
470 | for (n = 0; n < outcnt; n++) { | ||
471 | ch = *in++; | ||
472 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
473 | } | ||
474 | crc = c; | ||
475 | bytes_out += (ulg)outcnt; | ||
476 | outcnt = 0; | ||
477 | } | ||
478 | 412 | ||
479 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | 413 | static char * __init unpack_to_rootfs(char *buf, unsigned len) |
480 | { | 414 | { |
481 | int written; | 415 | int written; |
482 | dry_run = check_only; | 416 | decompress_fn decompress; |
417 | const char *compress_name; | ||
418 | static __initdata char msg_buf[64]; | ||
419 | |||
483 | header_buf = kmalloc(110, GFP_KERNEL); | 420 | header_buf = kmalloc(110, GFP_KERNEL); |
484 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); | 421 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); |
485 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); | 422 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); |
486 | window = kmalloc(WSIZE, GFP_KERNEL); | 423 | |
487 | if (!window || !header_buf || !symlink_buf || !name_buf) | 424 | if (!header_buf || !symlink_buf || !name_buf) |
488 | panic("can't allocate buffers"); | 425 | panic("can't allocate buffers"); |
426 | |||
489 | state = Start; | 427 | state = Start; |
490 | this_header = 0; | 428 | this_header = 0; |
491 | message = NULL; | 429 | message = NULL; |
@@ -505,22 +443,25 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | |||
505 | continue; | 443 | continue; |
506 | } | 444 | } |
507 | this_header = 0; | 445 | this_header = 0; |
508 | insize = len; | 446 | decompress = decompress_method(buf, len, &compress_name); |
509 | inbuf = buf; | 447 | if (decompress) |
510 | inptr = 0; | 448 | decompress(buf, len, NULL, flush_buffer, NULL, |
511 | outcnt = 0; /* bytes in output buffer */ | 449 | &my_inptr, error); |
512 | bytes_out = 0; | 450 | else if (compress_name) { |
513 | crc = (ulg)0xffffffffL; /* shift register contents */ | 451 | if (!message) { |
514 | makecrc(); | 452 | snprintf(msg_buf, sizeof msg_buf, |
515 | gunzip(); | 453 | "compression method %s not configured", |
454 | compress_name); | ||
455 | message = msg_buf; | ||
456 | } | ||
457 | } | ||
516 | if (state != Reset) | 458 | if (state != Reset) |
517 | error("junk in gzipped archive"); | 459 | error("junk in compressed archive"); |
518 | this_header = saved_offset + inptr; | 460 | this_header = saved_offset + my_inptr; |
519 | buf += inptr; | 461 | buf += my_inptr; |
520 | len -= inptr; | 462 | len -= my_inptr; |
521 | } | 463 | } |
522 | dir_utime(); | 464 | dir_utime(); |
523 | kfree(window); | ||
524 | kfree(name_buf); | 465 | kfree(name_buf); |
525 | kfree(symlink_buf); | 466 | kfree(symlink_buf); |
526 | kfree(header_buf); | 467 | kfree(header_buf); |
@@ -574,26 +515,76 @@ skip: | |||
574 | initrd_end = 0; | 515 | initrd_end = 0; |
575 | } | 516 | } |
576 | 517 | ||
518 | #define BUF_SIZE 1024 | ||
519 | static void __init clean_rootfs(void) | ||
520 | { | ||
521 | int fd; | ||
522 | void *buf; | ||
523 | struct linux_dirent64 *dirp; | ||
524 | int count; | ||
525 | |||
526 | fd = sys_open("/", O_RDONLY, 0); | ||
527 | WARN_ON(fd < 0); | ||
528 | if (fd < 0) | ||
529 | return; | ||
530 | buf = kzalloc(BUF_SIZE, GFP_KERNEL); | ||
531 | WARN_ON(!buf); | ||
532 | if (!buf) { | ||
533 | sys_close(fd); | ||
534 | return; | ||
535 | } | ||
536 | |||
537 | dirp = buf; | ||
538 | count = sys_getdents64(fd, dirp, BUF_SIZE); | ||
539 | while (count > 0) { | ||
540 | while (count > 0) { | ||
541 | struct stat st; | ||
542 | int ret; | ||
543 | |||
544 | ret = sys_newlstat(dirp->d_name, &st); | ||
545 | WARN_ON_ONCE(ret); | ||
546 | if (!ret) { | ||
547 | if (S_ISDIR(st.st_mode)) | ||
548 | sys_rmdir(dirp->d_name); | ||
549 | else | ||
550 | sys_unlink(dirp->d_name); | ||
551 | } | ||
552 | |||
553 | count -= dirp->d_reclen; | ||
554 | dirp = (void *)dirp + dirp->d_reclen; | ||
555 | } | ||
556 | dirp = buf; | ||
557 | memset(buf, 0, BUF_SIZE); | ||
558 | count = sys_getdents64(fd, dirp, BUF_SIZE); | ||
559 | } | ||
560 | |||
561 | sys_close(fd); | ||
562 | kfree(buf); | ||
563 | } | ||
564 | |||
577 | static int __init populate_rootfs(void) | 565 | static int __init populate_rootfs(void) |
578 | { | 566 | { |
579 | char *err = unpack_to_rootfs(__initramfs_start, | 567 | char *err = unpack_to_rootfs(__initramfs_start, |
580 | __initramfs_end - __initramfs_start, 0); | 568 | __initramfs_end - __initramfs_start); |
581 | if (err) | 569 | if (err) |
582 | panic(err); | 570 | panic(err); /* Failed to decompress INTERNAL initramfs */ |
583 | if (initrd_start) { | 571 | if (initrd_start) { |
584 | #ifdef CONFIG_BLK_DEV_RAM | 572 | #ifdef CONFIG_BLK_DEV_RAM |
585 | int fd; | 573 | int fd; |
586 | printk(KERN_INFO "checking if image is initramfs..."); | 574 | printk(KERN_INFO "checking if image is initramfs...\n"); |
587 | err = unpack_to_rootfs((char *)initrd_start, | 575 | err = unpack_to_rootfs((char *)initrd_start, |
588 | initrd_end - initrd_start, 1); | 576 | initrd_end - initrd_start); |
589 | if (!err) { | 577 | if (!err) { |
590 | printk(" it is\n"); | 578 | printk(KERN_INFO "rootfs image is initramfs; unpacking...\n"); |
591 | unpack_to_rootfs((char *)initrd_start, | ||
592 | initrd_end - initrd_start, 0); | ||
593 | free_initrd(); | 579 | free_initrd(); |
594 | return 0; | 580 | return 0; |
581 | } else { | ||
582 | clean_rootfs(); | ||
583 | unpack_to_rootfs(__initramfs_start, | ||
584 | __initramfs_end - __initramfs_start); | ||
595 | } | 585 | } |
596 | printk("it isn't (%s); looks like an initrd\n", err); | 586 | printk(KERN_INFO "rootfs image is not initramfs (%s)" |
587 | "; looks like an initrd\n", err); | ||
597 | fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); | 588 | fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); |
598 | if (fd >= 0) { | 589 | if (fd >= 0) { |
599 | sys_write(fd, (char *)initrd_start, | 590 | sys_write(fd, (char *)initrd_start, |
@@ -604,10 +595,13 @@ static int __init populate_rootfs(void) | |||
604 | #else | 595 | #else |
605 | printk(KERN_INFO "Unpacking initramfs..."); | 596 | printk(KERN_INFO "Unpacking initramfs..."); |
606 | err = unpack_to_rootfs((char *)initrd_start, | 597 | err = unpack_to_rootfs((char *)initrd_start, |
607 | initrd_end - initrd_start, 0); | 598 | initrd_end - initrd_start); |
608 | if (err) | 599 | if (err) { |
609 | panic(err); | 600 | printk(" failed!\n"); |
610 | printk(" done\n"); | 601 | printk(KERN_EMERG "%s\n", err); |
602 | } else { | ||
603 | printk(" done\n"); | ||
604 | } | ||
611 | free_initrd(); | 605 | free_initrd(); |
612 | #endif | 606 | #endif |
613 | } | 607 | } |