aboutsummaryrefslogtreecommitdiffstats
path: root/init/initramfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/initramfs.c')
-rw-r--r--init/initramfs.c200
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;
166static __initdata unsigned count; 167static __initdata unsigned count;
167static __initdata loff_t this_header, next_header; 168static __initdata loff_t this_header, next_header;
168 169
169static __initdata int dry_run;
170
171static inline void __init eat(unsigned n) 170static 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
393static void __init flush_buffer(char *buf, unsigned len) 386static 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/* 409static 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
423typedef unsigned char uch;
424typedef unsigned short ush;
425typedef 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
430static uch *inbuf;
431static uch *window;
432
433static unsigned insize; /* valid bytes in inbuf */
434static unsigned inptr; /* index of next byte to be processed in inbuf */
435static unsigned outcnt; /* bytes in output buffer */
436static 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
451static void __init flush_window(void);
452static 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 */
462static 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
479static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) 413static 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
519static 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
577static int __init populate_rootfs(void) 565static 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 }