diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 23:59:01 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 23:59:01 -0800 |
| commit | fe0976511d3b5cf2894da54bc451e561bd6b1482 (patch) | |
| tree | 92bbccc5167568aa5b48d466891fb0dab40ba8bd /init | |
| parent | 800446073f02f3035bffad7f1ced654ff6b474c9 (diff) | |
v2.5.0.10 -> v2.5.0.11
- Jeff Garzik: no longer support old cards in tulip driver
(see separate driver for old tulip chips)
- Pat Mochel: driverfs/device model documentation
- Ballabio Dario: update eata driver to new IO locking
- Ingo Molnar: raid resync with new bio structures (much more efficient)
and mempool_resize()
- Jens Axboe: bio queue locking
Diffstat (limited to 'init')
| -rw-r--r-- | init/do_mounts.c | 781 |
1 files changed, 559 insertions, 222 deletions
diff --git a/init/do_mounts.c b/init/do_mounts.c index d34fdd7ae7f8..e6a94292c2b4 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -14,37 +14,44 @@ #include <linux/nfs_fs.h> #include <linux/nfs_fs_sb.h> #include <linux/nfs_mount.h> +#include <linux/minix_fs.h> +#include <linux/ext2_fs.h> +#include <linux/romfs_fs.h> #include <asm/uaccess.h> -/* syscalls missing from unistd.h */ - -static inline _syscall2(int,mkdir,char *,name,int,mode); -static inline _syscall1(int,chdir,char *,name); -static inline _syscall1(int,chroot,char *,name); -static inline _syscall1(int,unlink,char *,name); -static inline _syscall3(int,mknod,char *,name,int,mode,dev_t,dev); -static inline _syscall5(int,mount,char *,dev,char *,dir,char *,type, - unsigned long,flags,void *,data); -static inline _syscall2(int,umount,char *,name,int,flags); - -extern void rd_load(void); -extern void initrd_load(void); +#define BUILD_CRAMDISK + extern int get_filesystem_list(char * buf); extern void wait_for_keypress(void); -asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long flags, void * data); +asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, + unsigned long flags, void *data); +asmlinkage long sys_mkdir(char *name, int mode); +asmlinkage long sys_chdir(char *name); +asmlinkage long sys_chroot(char *name); +asmlinkage long sys_unlink(char *name); +asmlinkage long sys_symlink(char *old, char *new); +asmlinkage long sys_mknod(char *name, int mode, dev_t dev); +asmlinkage long sys_umount(char *name, int flags); +asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg); #ifdef CONFIG_BLK_DEV_INITRD unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ #endif -int root_mountflags = MS_RDONLY; -char root_device_name[64]; +#ifdef CONFIG_BLK_DEV_RAM +extern int rd_doload; +#else +static int rd_doload = 0; +#endif +int root_mountflags = MS_RDONLY | MS_VERBOSE; +static char root_device_name[64]; /* this is initialized in init/main.c */ kdev_t ROOT_DEV; +static int do_devfs = 0; + static int __init readonly(char *str) { if (*str) @@ -275,91 +282,20 @@ static void __init get_fs_names(char *page) } *s = '\0'; } - -static void __init mount_root(void) +static void __init mount_block_root(char *name, int flags) { - void *handle; - char path[64]; - char *name = "/dev/root"; - char *fs_names, *p; - int do_devfs = 0; + char *fs_names = __getname(); + char *p; - root_mountflags |= MS_VERBOSE; - - fs_names = __getname(); get_fs_names(fs_names); - -#ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { - void *data; - data = nfs_root_data(); - if (data) { - int err = mount("/dev/root", "/root", "nfs", root_mountflags, data); - if (!err) - goto done; - } - printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); - ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); - } -#endif - -#ifdef CONFIG_BLK_DEV_FD - if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { -#ifdef CONFIG_BLK_DEV_RAM - extern int rd_doload; - extern void rd_load_secondary(void); -#endif - floppy_eject(); -#ifndef CONFIG_BLK_DEV_RAM - printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n"); -#else - /* rd_doload is 2 for a dual initrd/ramload setup */ - if(rd_doload==2) - rd_load_secondary(); - else -#endif - { - printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n"); - wait_for_keypress(); - } - } -#endif - - devfs_make_root (root_device_name); - handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME, - MAJOR (ROOT_DEV), MINOR (ROOT_DEV), - DEVFS_SPECIAL_BLK, 1); - if (handle) { - int n; - unsigned major, minor; - - devfs_get_maj_min (handle, &major, &minor); - ROOT_DEV = MKDEV (major, minor); - if (!ROOT_DEV) - panic("I have no root and I want to scream"); - n = devfs_generate_path (handle, path + 5, sizeof (path) - 5); - if (n >= 0) { - name = path + n; - devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT, - name + 5, NULL, NULL); - memcpy (name, "/dev/", 5); - do_devfs = 1; - } - } - chdir("/dev"); - unlink("root"); - mknod("root", S_IFBLK|0600, kdev_t_to_nr(ROOT_DEV)); - if (do_devfs) - mount("devfs", ".", "devfs", 0, NULL); retry: for (p = fs_names; *p; p += strlen(p)+1) { - int err; - err = sys_mount(name,"/root",p,root_mountflags,root_mount_data); + int err = sys_mount(name, "/root", p, flags, root_mount_data); switch (err) { case 0: - goto done; + goto out; case -EACCES: - root_mountflags |= MS_RDONLY; + flags |= MS_RDONLY; goto retry; case -EINVAL: continue; @@ -375,94 +311,324 @@ retry: kdevname(ROOT_DEV)); } panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); - -done: +out: putname(fs_names); - if (do_devfs) - umount(".", 0); + sys_chdir("/root"); + ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; + printk("VFS: Mounted root (%s filesystem)%s.\n", + current->fs->pwdmnt->mnt_sb->s_type->name, + (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : ""); } + +#ifdef CONFIG_ROOT_NFS +static int __init mount_nfs_root(void) +{ + void *data = nfs_root_data(); -#ifdef CONFIG_BLK_DEV_INITRD + if (data && sys_mount("/dev/root","/root","nfs",root_mountflags,data) == 0) + return 1; + return 0; +} +#endif -static int __init change_root(kdev_t new_root_dev,const char *put_old) +static int __init create_dev(char *name, kdev_t dev, char *devfs_name) +{ + void *handle; + char path[64]; + int n; + + sys_unlink(name); + if (!do_devfs) + return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev)); + + handle = devfs_find_handle(NULL, dev ? NULL : devfs_name, + MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); + if (!handle) + return -1; + n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); + if (n < 0) + return -1; + return sys_symlink(path + n + 5, name); +} + +#ifdef CONFIG_MAC_FLOPPY +int swim3_fd_eject(int devnum); +#endif +static void __init change_floppy(char *fmt, ...) { - struct vfsmount *old_rootmnt; - struct nameidata devfs_nd; - char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL); - int error = 0; - - if (new_devname) - strcpy(new_devname, "/dev/root.old"); - - /* .. here is directory mounted over root */ - mount("..", ".", NULL, MS_MOVE, NULL); - chdir("/old"); - - read_lock(¤t->fs->lock); - old_rootmnt = mntget(current->fs->pwdmnt); - read_unlock(¤t->fs->lock); - - /* First unmount devfs if mounted */ - if (path_init("/old/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd)) - error = path_walk("/old/dev", &devfs_nd); - if (!error) { - if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC && - devfs_nd.dentry == devfs_nd.mnt->mnt_root) - umount("/old/dev", 0); - path_release(&devfs_nd); + extern void wait_for_keypress(void); + char buf[80]; + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); +#ifdef CONFIG_BLK_DEV_FD + floppy_eject(); +#endif +#ifdef CONFIG_MAC_FLOPPY + swim3_fd_eject(MINOR(ROOT_DEV)); +#endif + printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); + wait_for_keypress(); +} + +#ifdef CONFIG_BLK_DEV_RAM + +static int __init crd_load(int in_fd, int out_fd); + +/* + * This routine tries to find a RAM disk image to load, and returns the + * number of blocks to read for a non-compressed image, 0 if the image + * is a compressed image, and -1 if an image with the right magic + * numbers could not be found. + * + * We currently check for the following magic numbers: + * minix + * ext2 + * romfs + * gzip + */ +static int __init +identify_ramdisk_image(int fd, int start_block) +{ + const int size = 512; + struct minix_super_block *minixsb; + struct ext2_super_block *ext2sb; + struct romfs_super_block *romfsb; + int nblocks = -1; + unsigned char *buf; + + buf = kmalloc(size, GFP_KERNEL); + if (buf == 0) + return -1; + + minixsb = (struct minix_super_block *) buf; + ext2sb = (struct ext2_super_block *) buf; + romfsb = (struct romfs_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 + */ + if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { + printk(KERN_NOTICE + "RAMDISK: Compressed image found at block %d\n", + start_block); + nblocks = 0; + goto done; } - ROOT_DEV = new_root_dev; - mount_root(); + /* romfs is at block zero too */ + if (romfsb->word0 == ROMSB_WORD0 && + romfsb->word1 == ROMSB_WORD1) { + printk(KERN_NOTICE + "RAMDISK: romfs filesystem found at block %d\n", + start_block); + nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } - chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : ""); + /* + * Read block 1 to test for minix and ext2 superblock + */ + lseek(fd, (start_block+1) * BLOCK_SIZE, 0); + read(fd, buf, size); + + /* Try minix */ + if (minixsb->s_magic == MINIX_SUPER_MAGIC || + minixsb->s_magic == MINIX_SUPER_MAGIC2) { + printk(KERN_NOTICE + "RAMDISK: Minix filesystem found at block %d\n", + start_block); + nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; + goto done; + } + + /* Try ext2 */ + if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { + printk(KERN_NOTICE + "RAMDISK: ext2 filesystem found at block %d\n", + start_block); + nblocks = le32_to_cpu(ext2sb->s_blocks_count); + goto done; + } -#if 1 - shrink_dcache(); - printk("change_root: old root has d_count=%d\n", - atomic_read(&old_rootmnt->mnt_root->d_count)); + 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); + kfree(buf); + return nblocks; +} #endif - error = mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); - if (error) { - int blivet; - struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev; - - atomic_inc(&ramdisk->bd_count); - blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS); - printk(KERN_NOTICE "Trying to unmount old root ... "); - umount("/old", MNT_DETACH); - if (!blivet) { - blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0); - blkdev_put(ramdisk, BDEV_FS); - } - if (blivet) { - printk(KERN_ERR "error %d\n", blivet); - } else { - printk("okay\n"); - error = 0; +static int __init rd_load_image(char *from) +{ + int res = 0; + +#ifdef CONFIG_BLK_DEV_RAM + int in_fd, out_fd; + int nblocks, rd_blocks, devblocks, i; + char *buf; + unsigned short rotate = 0; +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) + char rotator[4] = { '|' , '/' , '-' , '\\' }; +#endif + + out_fd = open("/dev/ram", O_RDWR, 0); + if (out_fd < 0) + goto out; + + in_fd = open(from, O_RDONLY, 0); + if (in_fd < 0) + goto noclose_input; + + nblocks = identify_ramdisk_image(in_fd, rd_image_start); + if (nblocks < 0) + goto done; + + if (nblocks == 0) { +#ifdef BUILD_CRAMDISK + if (crd_load(in_fd, out_fd) == 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. + */ + if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) + rd_blocks = 0; + else + rd_blocks >>= 1; + + if (nblocks > rd_blocks) { + printk("RAMDISK: image too big! (%d/%d blocks)\n", + nblocks, rd_blocks); + goto done; + } + + /* + * OK, time to copy in the data + */ + buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); + if (buf == 0) { + printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); + goto done; + } + + if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) + devblocks = 0; + else + devblocks >>= 1; + + if (strcmp(from, "/dev/initrd") == 0) + devblocks = nblocks; + + if (devblocks == 0) { + printk(KERN_ERR "RAMDISK: could not determine device size\n"); + goto done; + } + + printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%d disk%s] into ram disk... ", + nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); + for (i=0; i < nblocks; i++) { + if (i && (i % devblocks == 0)) { + printk("done disk #%d.\n", i/devblocks); + rotate = 0; + if (close(in_fd)) { + printk("Error closing the disk.\n"); + goto noclose_input; + } + change_floppy("disk #%d", i/devblocks+1); + in_fd = open(from, O_RDONLY, 0); + if (in_fd < 0) { + printk("Error opening disk.\n"); + goto noclose_input; + } + printk("Loading disk #%d... ", i/devblocks+1); } - } else { - spin_lock(&dcache_lock); - if (new_devname) { - void *p = old_rootmnt->mnt_devname; - old_rootmnt->mnt_devname = new_devname; - new_devname = p; + read(in_fd, buf, BLOCK_SIZE); + write(out_fd, buf, BLOCK_SIZE); +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) + if (!(i % 16)) { + printk("%c\b", rotator[rotate & 0x3]); + rotate++; } - spin_unlock(&dcache_lock); +#endif } + printk("done.\n"); + kfree(buf); - /* put the old stuff */ - mntput(old_rootmnt); - kfree(new_devname); - return error; +successful_load: + res = 1; +done: + close(in_fd); +noclose_input: + close(out_fd); +out: + sys_unlink("/dev/ram"); +#endif + return res; +} + +static int __init rd_load_disk(int n) +{ +#ifdef CONFIG_BLK_DEV_RAM + extern int rd_prompt; + if (rd_prompt) + change_floppy("root floppy disk to be loaded into RAM disk"); + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); +#endif + return rd_load_image("/dev/root"); } +static void __init mount_root(void) +{ +#ifdef CONFIG_ROOT_NFS + if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { + if (mount_nfs_root()) { + sys_chdir("/root"); + ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; + printk("VFS: Mounted root (nfs filesystem).\n"); + return; + } + printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); + ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); + } #endif + devfs_make_root(root_device_name); + create_dev("/dev/root", ROOT_DEV, root_device_name); +#ifdef CONFIG_BLK_DEV_FD + if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { + /* rd_doload is 2 for a dual initrd/ramload setup */ + if (rd_doload==2) { + if (rd_load_disk(1)) { + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 1); + create_dev("/dev/root", ROOT_DEV, NULL); + } + } else + change_floppy("root floppy"); + } +#endif + mount_block_root("/dev/root", root_mountflags); +} #ifdef CONFIG_BLK_DEV_INITRD static int do_linuxrc(void * shell) @@ -470,9 +636,9 @@ static int do_linuxrc(void * shell) static char *argv[] = { "linuxrc", NULL, }; extern char * envp_init[]; - chdir("/root"); - mount(".", "/", NULL, MS_MOVE, NULL); - chroot("."); + sys_chdir("/root"); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); mount_devfs_fs (); @@ -486,76 +652,247 @@ static int do_linuxrc(void * shell) #endif +static void __init handle_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + int ram0 = kdev_t_to_nr(MKDEV(RAMDISK_MAJOR,0)); + int error; + int i, pid; + + create_dev("/dev/root.old", ram0, NULL); + mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); + sys_mkdir("/old", 0700); + sys_chdir("/old"); + + pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); + if (pid > 0) { + while (pid != wait(&i)) { + current->policy |= SCHED_YIELD; + schedule(); + } + } + + sys_mount("..", ".", NULL, MS_MOVE, NULL); + sys_umount("/old/dev", 0); + + if (real_root_dev == 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"); + } +#endif +} + +static int __init initrd_load(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL); + create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL); +#endif + return rd_load_image("/dev/initrd"); +} + /* * Prepare the namespace - decide what/where to mount, load ramdisks, etc. */ void prepare_namespace(void) { + int do_initrd = 0; + int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; #ifdef CONFIG_BLK_DEV_INITRD - int real_root_mountflags = root_mountflags; if (!initrd_start) mount_initrd = 0; if (mount_initrd) - root_mountflags &= ~MS_RDONLY; + do_initrd = 1; real_root_dev = ROOT_DEV; #endif - mkdir("/dev", 0700); - mkdir("/root", 0700); - -#ifdef CONFIG_BLK_DEV_RAM -#ifdef CONFIG_BLK_DEV_INITRD - if (mount_initrd) - initrd_load(); - else -#endif - rd_load(); + sys_mkdir("/dev", 0700); + sys_mkdir("/root", 0700); +#ifdef CONFIG_DEVFS_FS + sys_mount("devfs", "/dev", "devfs", 0, NULL); + do_devfs = 1; #endif - /* Mount the root filesystem.. */ + create_dev("/dev/root", ROOT_DEV, NULL); + if (do_initrd) { + if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) { + handle_initrd(); + goto out; + } + } else if (is_floppy && rd_doload && rd_load_disk(0)) + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); mount_root(); - chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : ""); +out: + sys_umount("/dev", 0); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); + mount_devfs_fs (); +} -#ifdef CONFIG_BLK_DEV_INITRD - root_mountflags = real_root_mountflags; - if (mount_initrd && ROOT_DEV != real_root_dev - && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) { - int error; - int i, pid; - mkdir("/old", 0700); - chdir("/old"); - - pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); - if (pid > 0) { - while (pid != wait(&i)) { - current->policy |= SCHED_YIELD; - schedule(); - } - } - if (MAJOR(real_root_dev) != RAMDISK_MAJOR - || MINOR(real_root_dev) != 0) { - error = change_root(real_root_dev,"/initrd"); - if (error) - printk(KERN_ERR "Change root to /initrd: " - "error %d\n",error); - - chdir("/root"); - mount(".", "/", NULL, MS_MOVE, NULL); - chroot("."); - - mount_devfs_fs (); - return; - } - chroot(".."); - chdir("/"); - return; - } +#ifdef BUILD_CRAMDISK + +/* + * gzip declarations + */ + +#define OF(args) args + +#ifndef memzero +#define memzero(s, n) memset ((s), 0, (n)) #endif - mount(".", "/", NULL, MS_MOVE, NULL); - chroot("."); - mount_devfs_fs (); +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 long bytes_out; +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 void __init gzip_release(void **ptr) +{ +} + + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +static int __init fill_inbuf(void) +{ + if (exit_code) return -1; + + insize = read(crd_infd, inbuf, INBUFSIZ); + if (insize == 0) 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; + uch *in, ch; + + write(crd_outfd, window, outcnt); + 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; +} + +static void __init error(char *x) +{ + printk(KERN_ERR "%s", x); + exit_code = 1; +} + +static int __init crd_load(int in_fd, int out_fd) +{ + 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(); + kfree(inbuf); + kfree(window); + return result; +} + +#endif /* BUILD_CRAMDISK */ |
