Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / init / do_mounts_rd.c
index be82c3f..6212586 100644 (file)
@@ -4,10 +4,16 @@
 #include <linux/minix_fs.h>
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
+#include <linux/cramfs_fs.h>
+#include <linux/initrd.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "do_mounts.h"
+#include "../fs/squashfs/squashfs_fs.h"
+
+#include <linux/decompress/generic.h>
 
-#define BUILD_CRAMDISK
 
 int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
 
@@ -27,7 +33,7 @@ static int __init ramdisk_start_setup(char *str)
 }
 __setup("ramdisk_start=", ramdisk_start_setup);
 
-static int __init crd_load(int in_fd, int out_fd);
+static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
 
 /*
  * This routine tries to find a RAM disk image to load, and returns the
@@ -36,43 +42,50 @@ static int __init crd_load(int in_fd, int out_fd);
  * numbers could not be found.
  *
  * We currently check for the following magic numbers:
- *     minix
- *     ext2
+ *     minix
+ *     ext2
  *     romfs
- *     gzip
+ *     cramfs
+ *     squashfs
+ *     gzip
  */
-static int __init 
-identify_ramdisk_image(int fd, int start_block)
+static int __init
+identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
 {
        const int size = 512;
        struct minix_super_block *minixsb;
-       struct ext2_super_block *ext2sb;
        struct romfs_super_block *romfsb;
+       struct cramfs_super *cramfsb;
+       struct squashfs_super_block *squashfsb;
        int nblocks = -1;
        unsigned char *buf;
+       const char *compress_name;
+       unsigned long n;
 
        buf = kmalloc(size, GFP_KERNEL);
-       if (buf == 0)
-               return -1;
+       if (!buf)
+               return -ENOMEM;
 
        minixsb = (struct minix_super_block *) buf;
-       ext2sb = (struct ext2_super_block *) buf;
        romfsb = (struct romfs_super_block *) buf;
+       cramfsb = (struct cramfs_super *) buf;
+       squashfsb = (struct squashfs_super_block *) buf;
        memset(buf, 0xe5, size);
 
        /*
-        * Read block 0 to test for gzipped kernel
-        */
-       lseek(fd, start_block * BLOCK_SIZE, 0);
-       read(fd, buf, size);
-
-       /*
-        * If it matches the gzip magic numbers, return -1
+        * Read block 0 to test for compressed kernel
         */
-       if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
-               printk(KERN_NOTICE
-                      "RAMDISK: Compressed image found at block %d\n",
-                      start_block);
+       sys_lseek(fd, start_block * BLOCK_SIZE, 0);
+       sys_read(fd, buf, size);
+
+       *decompressor = decompress_method(buf, size, &compress_name);
+       if (compress_name) {
+               printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n",
+                      compress_name, start_block);
+               if (!*decompressor)
+                       printk(KERN_EMERG
+                              "RAMDISK: %s decompressor not configured!\n",
+                              compress_name);
                nblocks = 0;
                goto done;
        }
@@ -87,11 +100,43 @@ identify_ramdisk_image(int fd, int start_block)
                goto done;
        }
 
+       if (cramfsb->magic == CRAMFS_MAGIC) {
+               printk(KERN_NOTICE
+                      "RAMDISK: cramfs filesystem found at block %d\n",
+                      start_block);
+               nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+               goto done;
+       }
+
+       /* squashfs is at block zero too */
+       if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) {
+               printk(KERN_NOTICE
+                      "RAMDISK: squashfs filesystem found at block %d\n",
+                      start_block);
+               nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1)
+                        >> BLOCK_SIZE_BITS;
+               goto done;
+       }
+
+       /*
+        * Read 512 bytes further to check if cramfs is padded
+        */
+       sys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0);
+       sys_read(fd, buf, size);
+
+       if (cramfsb->magic == CRAMFS_MAGIC) {
+               printk(KERN_NOTICE
+                      "RAMDISK: cramfs filesystem found at block %d\n",
+                      start_block);
+               nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+               goto done;
+       }
+
        /*
         * Read block 1 to test for minix and ext2 superblock
         */
-       lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
-       read(fd, buf, size);
+       sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
+       sys_read(fd, buf, size);
 
        /* Try minix */
        if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
@@ -104,20 +149,21 @@ identify_ramdisk_image(int fd, int start_block)
        }
 
        /* Try ext2 */
-       if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
+       n = ext2_image_size(buf);
+       if (n) {
                printk(KERN_NOTICE
                       "RAMDISK: ext2 filesystem found at block %d\n",
                       start_block);
-               nblocks = le32_to_cpu(ext2sb->s_blocks_count);
+               nblocks = n;
                goto done;
        }
 
        printk(KERN_NOTICE
               "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n",
               start_block);
-       
+
 done:
-       lseek(fd, start_block * BLOCK_SIZE, 0);
+       sys_lseek(fd, start_block * BLOCK_SIZE, 0);
        kfree(buf);
        return nblocks;
 }
@@ -128,41 +174,41 @@ int __init rd_load_image(char *from)
        int in_fd, out_fd;
        unsigned long rd_blocks, devblocks;
        int nblocks, i, disk;
-       char *buf;
+       char *buf = NULL;
        unsigned short rotate = 0;
-#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
+       decompress_fn decompressor = NULL;
+#if !defined(CONFIG_S390)
        char rotator[4] = { '|' , '/' , '-' , '\\' };
 #endif
 
-       out_fd = open("/dev/ram", O_RDWR, 0);
+       out_fd = sys_open((const char __user __force *) "/dev/ram", O_RDWR, 0);
        if (out_fd < 0)
                goto out;
 
-       in_fd = open(from, O_RDONLY, 0);
+       in_fd = sys_open(from, O_RDONLY, 0);
        if (in_fd < 0)
                goto noclose_input;
 
-       nblocks = identify_ramdisk_image(in_fd, rd_image_start);
+       nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor);
        if (nblocks < 0)
                goto done;
 
        if (nblocks == 0) {
-#ifdef BUILD_CRAMDISK
-               if (crd_load(in_fd, out_fd) == 0)
+               if (crd_load(in_fd, out_fd, decompressor) == 0)
                        goto successful_load;
-#else
-               printk(KERN_NOTICE
-                      "RAMDISK: Kernel does not support compressed "
-                      "RAM disk images\n");
-#endif
                goto done;
        }
 
        /*
-        * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so
-        * rd_load_image will work only with filesystem BLOCK_SIZE wide!
-        * So make sure to use 1k blocksize while generating ext2fs
-        * ramdisk-images.
+        * NOTE NOTE: nblocks is not actually blocks but
+        * the number of kibibytes of data to load into a ramdisk.
+        * So any ramdisk block size that is a multiple of 1KiB should
+        * work when the appropriate ramdisk_blocksize is specified
+        * on the command line.
+        *
+        * The default ramdisk_blocksize is 1KiB and it is generally
+        * silly to use anything else, so make sure to use 1KiB
+        * blocksize while generating ext2fs ramdisk-images.
         */
        if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
                rd_blocks = 0;
@@ -170,11 +216,11 @@ int __init rd_load_image(char *from)
                rd_blocks >>= 1;
 
        if (nblocks > rd_blocks) {
-               printk("RAMDISK: image too big! (%d/%ld blocks)\n",
+               printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
                       nblocks, rd_blocks);
                goto done;
        }
-               
+
        /*
         * OK, time to copy in the data
         */
@@ -183,7 +229,7 @@ int __init rd_load_image(char *from)
        else
                devblocks >>= 1;
 
-       if (strcmp(from, "/dev/initrd") == 0)
+       if (strcmp(from, "/initrd.image") == 0)
                devblocks = nblocks;
 
        if (devblocks == 0) {
@@ -192,32 +238,32 @@ int __init rd_load_image(char *from)
        }
 
        buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
-       if (buf == 0) {
+       if (!buf) {
                printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
                goto done;
        }
 
-       printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", 
+       printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
                nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
        for (i = 0, disk = 1; i < nblocks; i++) {
                if (i && (i % devblocks == 0)) {
                        printk("done disk #%d.\n", disk++);
                        rotate = 0;
-                       if (close(in_fd)) {
+                       if (sys_close(in_fd)) {
                                printk("Error closing the disk.\n");
                                goto noclose_input;
                        }
                        change_floppy("disk #%d", disk);
-                       in_fd = open(from, O_RDONLY, 0);
+                       in_fd = sys_open(from, O_RDONLY, 0);
                        if (in_fd < 0)  {
                                printk("Error opening disk.\n");
                                goto noclose_input;
                        }
                        printk("Loading disk #%d... ", disk);
                }
-               read(in_fd, buf, BLOCK_SIZE);
-               write(out_fd, buf, BLOCK_SIZE);
-#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
+               sys_read(in_fd, buf, BLOCK_SIZE);
+               sys_write(out_fd, buf, BLOCK_SIZE);
+#if !defined(CONFIG_S390)
                if (!(i % 16)) {
                        printk("%c\b", rotator[rotate & 0x3]);
                        rotate++;
@@ -225,16 +271,16 @@ int __init rd_load_image(char *from)
 #endif
        }
        printk("done.\n");
-       kfree(buf);
 
 successful_load:
        res = 1;
 done:
-       close(in_fd);
+       sys_close(in_fd);
 noclose_input:
-       close(out_fd);
+       sys_close(out_fd);
 out:
-       sys_unlink("/dev/ram");
+       kfree(buf);
+       sys_unlink((const char __user __force *) "/dev/ram");
        return res;
 }
 
@@ -242,276 +288,53 @@ int __init rd_load_disk(int n)
 {
        if (rd_prompt)
                change_floppy("root floppy disk to be loaded into RAM disk");
-       create_dev("/dev/root", ROOT_DEV, root_device_name);
-       create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
+       create_dev("/dev/root", ROOT_DEV);
+       create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
        return rd_load_image("/dev/root");
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-
-unsigned int real_root_dev;    /* do_proc_dointvec cannot handle kdev_t */
-static int __initdata old_fd, root_fd;
-static int __initdata mount_initrd = 1;
-
-static int __init no_initrd(char *str)
-{
-       mount_initrd = 0;
-       return 1;
-}
-
-__setup("noinitrd", no_initrd);
-
-static int __init do_linuxrc(void * shell)
-{
-       static char *argv[] = { "linuxrc", NULL, };
-       extern char * envp_init[];
-
-       close(old_fd);close(root_fd);
-       close(0);close(1);close(2);
-       setsid();
-       (void) open("/dev/console",O_RDWR,0);
-       (void) dup(0);
-       (void) dup(0);
-       return execve(shell, argv, envp_init);
-}
-
-static void __init handle_initrd(void)
-{
-       int error;
-       int i, pid;
-
-       real_root_dev = ROOT_DEV;
-       create_dev("/dev/root.old", Root_RAM0, NULL);
-       /* mount initrd on rootfs' /root */
-       mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
-       sys_mkdir("/old", 0700);
-       root_fd = open("/", 0, 0);
-       old_fd = open("/old", 0, 0);
-       /* move initrd over / and chdir/chroot in initrd root */
-       sys_chdir("/root");
-       sys_mount(".", "/", NULL, MS_MOVE, NULL);
-       sys_chroot(".");
-       mount_devfs_fs ();
-
-       pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
-       if (pid > 0) {
-               while (pid != waitpid(-1, &i, 0))
-                       yield();
-       }
-
-       /* move initrd to rootfs' /old */
-       sys_fchdir(old_fd);
-       sys_mount("/", ".", NULL, MS_MOVE, NULL);
-       /* switch root and cwd back to / of rootfs */
-       sys_fchdir(root_fd);
-       sys_chroot(".");
-       close(old_fd);
-       close(root_fd);
-       umount_devfs("/old/dev");
-
-       if (real_root_dev == Root_RAM0) {
-               sys_chdir("/old");
-               return;
-       }
-
-       ROOT_DEV = real_root_dev;
-       mount_root();
-
-       printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
-       error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
-       if (!error)
-               printk("okay\n");
-       else {
-               int fd = open("/dev/root.old", O_RDWR, 0);
-               printk("failed\n");
-               printk(KERN_NOTICE "Unmounting old root\n");
-               sys_umount("/old", MNT_DETACH);
-               printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
-               if (fd < 0) {
-                       error = fd;
-               } else {
-                       error = sys_ioctl(fd, BLKFLSBUF, 0);
-                       close(fd);
-               }
-               printk(!error ? "okay\n" : "failed\n");
-       }
-}
-
-int __init initrd_load(void)
-{
-       if (!mount_initrd)
-               return 0;
-
-       create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL);
-       create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL);
-       /* Load the initrd data into /dev/ram0. Execute it as initrd unless
-        * /dev/ram0 is supposed to be our actual root device, in
-        * that case the ram disk is just set up here, and gets
-        * mounted in the normal path. */
-       if (rd_load_image("/dev/initrd") && ROOT_DEV != Root_RAM0) {
-               handle_initrd();
-               return 1;
-       }
-       return 0;
-}
-#endif
-
-#ifdef BUILD_CRAMDISK
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-
-#ifndef memzero
-#define memzero(s, n)     memset ((s), 0, (n))
-#endif
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-#define INBUFSIZ 4096
-#define WSIZE 0x8000    /* window size--must be a power of two, and */
-                       /*  at least 32K for zip's deflate method */
-
-static uch *inbuf;
-static uch *window;
-
-static unsigned insize;  /* valid bytes in inbuf */
-static unsigned inptr;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt;  /* bytes in output buffer */
 static int exit_code;
-static int unzip_error;
-static long bytes_out;
+static int decompress_error;
 static int crd_infd, crd_outfd;
 
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-               
-/* Diagnostic functions (stubbed out) */
-#define Assert(cond,msg)
-#define Trace(x)
-#define Tracev(x)
-#define Tracevv(x)
-#define Tracec(c,x)
-#define Tracecv(c,x)
-
-#define STATIC static
-
-static int  fill_inbuf(void);
-static void flush_window(void);
-static void *malloc(int size);
-static void free(void *where);
-static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
-#include "../lib/inflate.c"
-
-static void __init *malloc(int size)
-{
-       return kmalloc(size, GFP_KERNEL);
-}
-
-static void __init free(void *where)
-{
-       kfree(where);
-}
-
-static void __init gzip_mark(void **ptr)
+static int __init compr_fill(void *buf, unsigned int len)
 {
+       int r = sys_read(crd_infd, buf, len);
+       if (r < 0)
+               printk(KERN_ERR "RAMDISK: error while reading compressed data");
+       else if (r == 0)
+               printk(KERN_ERR "RAMDISK: EOF while reading compressed data");
+       return r;
 }
 
-static void __init gzip_release(void **ptr)
+static int __init compr_flush(void *window, unsigned int outcnt)
 {
-}
-
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- * Returning -1 does not guarantee that gunzip() will ever return.
- */
-static int __init fill_inbuf(void)
-{
-       if (exit_code) return -1;
-       
-       insize = read(crd_infd, inbuf, INBUFSIZ);
-       if (insize == 0) {
-               error("RAMDISK: ran out of compressed data\n");
+       int written = sys_write(crd_outfd, window, outcnt);
+       if (written != outcnt) {
+               if (decompress_error == 0)
+                       printk(KERN_ERR
+                              "RAMDISK: incomplete write (%d != %d)\n",
+                              written, outcnt);
+               decompress_error = 1;
                return -1;
        }
-
-       inptr = 1;
-
-       return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void __init flush_window(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n, written;
-    uch *in, ch;
-    
-    written = write(crd_outfd, window, outcnt);
-    if (written != outcnt && unzip_error == 0) {
-       printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n",
-              written, outcnt, bytes_out);
-       unzip_error = 1;
-    }
-    in = window;
-    for (n = 0; n < outcnt; n++) {
-           ch = *in++;
-           c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    outcnt = 0;
+       return outcnt;
 }
 
 static void __init error(char *x)
 {
-       printk(KERN_ERR "%s", x);
+       printk(KERN_ERR "%s\n", x);
        exit_code = 1;
-       unzip_error = 1;
+       decompress_error = 1;
 }
 
-static int __init crd_load(int in_fd, int out_fd)
+static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)
 {
        int result;
-
-       insize = 0;             /* valid bytes in inbuf */
-       inptr = 0;              /* index of next byte to be processed in inbuf */
-       outcnt = 0;             /* bytes in output buffer */
-       exit_code = 0;
-       bytes_out = 0;
-       crc = (ulg)0xffffffffL; /* shift register contents */
-
        crd_infd = in_fd;
        crd_outfd = out_fd;
-       inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
-       if (inbuf == 0) {
-               printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
-               return -1;
-       }
-       window = kmalloc(WSIZE, GFP_KERNEL);
-       if (window == 0) {
-               printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
-               kfree(inbuf);
-               return -1;
-       }
-       makecrc();
-       result = gunzip();
-       if (unzip_error)
+       result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);
+       if (decompress_error)
                result = 1;
-       kfree(inbuf);
-       kfree(window);
        return result;
 }
-
-#endif  /* BUILD_CRAMDISK */