diff -ubNr linux-2.5.9.orig/drivers/block/Config.in linux-2.5.9.new/drivers/block/Config.in --- linux-2.5.9.orig/drivers/block/Config.in Tue Apr 23 00:28:23 2002 +++ linux-2.5.9.new/drivers/block/Config.in Sun Apr 28 14:47:37 2002 @@ -46,5 +46,6 @@ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 fi dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM +dep_bool ' Initial RAM fs (initramfs) support' CONFIG_BLK_DEV_INITRAMFS $CONFIG_BLK_DEV_INITRD endmenu diff -ubNr linux-2.5.9.orig/include/linux/initramfs.h linux-2.5.9.new/include/linux/initramfs.h --- linux-2.5.9.orig/include/linux/initramfs.h Thu Jan 1 01:00:00 1970 +++ linux-2.5.9.new/include/linux/initramfs.h Thu Apr 25 02:38:36 2002 @@ -0,0 +1,25 @@ +#ifndef _LINUX_INITRAMFS_H +#define _LINUX_INITRAMFS_H + +struct cpio_header { + char c_magic[6]; //The string "070701" or "070702" + char c_ino[8]; //File inode number + char c_mode[8]; //File mode and permissions + char c_uid[8]; //File uid + char c_gid[8]; //File gid + char c_nlink[8]; //Number of links + char c_mtime[8]; //Modification time + char c_filesize[8]; //Size of data field + char c_maj[8]; //Major part of file device number + char c_min[8]; //Minor part of file device number + char c_rmaj[8]; //Major part of device node reference + char c_rmin[8]; //Minor part of device node reference + char c_namesize[8]; //Length of filename, including final \0 + char c_chksum[8]; //Checksum of data field if c_magic is 070702; +}; + +#define CPIO_MAGIC "070701" +#define CPIO_MAGIC_CRC "070702" +#define CPIO_TRAILER "TRAILER!!!" + +#endif diff -ubNr linux-2.5.9.orig/init/do_mounts.c linux-2.5.9.new/init/do_mounts.c --- linux-2.5.9.orig/init/do_mounts.c Tue Apr 23 00:28:49 2002 +++ linux-2.5.9.new/init/do_mounts.c Sat May 4 19:12:57 2002 @@ -17,6 +17,7 @@ #include #include #include +#include #define BUILD_CRAMDISK @@ -34,6 +35,9 @@ asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg); #ifdef CONFIG_BLK_DEV_INITRD +#ifdef CONFIG_BLK_DEV_INITRAMFS +static off_t initramfs_size = 0; +#endif unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ static int __initdata mount_initrd = 1; @@ -414,6 +418,178 @@ static int __init crd_load(int in_fd, int out_fd); +#ifdef CONFIG_BLK_DEV_INITRAMFS + +static unsigned int __init ascii2int(const char *ascii) +{ + unsigned int res = 0; + int i; + for(i=0;i<8;i++) { + if(ascii[i] >= '0' && ascii[i] <= '9') + res += (ascii[i] - '0') << (4 * (7-i)); + else if(ascii[i] >= 'a' && ascii[i] <= 'f') + res += (ascii[i] - 'a' + 10) << (4 * (7-i)); + else if(ascii[i] >= 'A' && ascii[i] <= 'F') + res += (ascii[i] - 'A' + 10) << (4 * (7-i)); + else { + printk("INITRAMFS: ASCII field in CPIO header contains illegar char!\n"); + return res; + } + } + return res; +} + +static unsigned int __init align_cpio(unsigned long pos) +{ + if (pos & 3) + return (pos & ~3) + 4; + return pos; +} + +static int __init initramfs_magic(struct cpio_header *header) +{ + if (!strncmp(header->c_magic,CPIO_MAGIC,strlen(CPIO_MAGIC))) + return 1; + if (!strncmp(header->c_magic,CPIO_MAGIC,strlen(CPIO_MAGIC_CRC))) { + return 1; + } + return 0; +} + +static int __init do_initramfs(void *name) +{ + int file_count = 0; + int in_fd; + off_t cur = 0; + char *buf; + + in_fd = open(name, O_RDONLY, 0); + if (in_fd < 0) { + return 0; + } + + buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); + if (!buf) + goto out; + + sys_chdir("/root"); + sys_chroot("."); + + while(cur < initramfs_size) { + struct cpio_header header; + char *filename; + int out_fd; + long filesize; + long bytes_read; + + cur = align_cpio(cur); + lseek(in_fd, cur, 0); + if(read(in_fd, (void *)&header, sizeof (struct cpio_header)) <= 0) { + printk(KERN_NOTICE "INITRAMFS: EOF reached aborting extraction!\n"); + goto out; + } + cur += sizeof (struct cpio_header); + + if (!initramfs_magic(&header)) { + printk(KERN_NOTICE "INITRAMFS: No valid CPIO header found aborting extraction!\n"); + goto out; + } + + filename = kmalloc(ascii2int(header.c_namesize), GFP_KERNEL); + filesize = ascii2int(header.c_filesize); + + lseek(in_fd, cur, 0); + if(read(in_fd, filename, ascii2int(header.c_namesize)) <= 0) { + printk(KERN_NOTICE "INITRAMFS: EOF reached aborting extraction!\n"); + goto out; + } + cur += ascii2int(header.c_namesize); + + + printk("INITRAMFS: FileName: %s Size:%ld\n",filename,filesize); + cur = align_cpio(cur); + lseek(in_fd, cur, 0); + cur += filesize; + + switch (ascii2int(header.c_mode) & S_IFMT) { + case S_IFREG: { + out_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, ascii2int(header.c_mode)); + if (out_fd < 0) { + printk("INITRAMFS: Error opening out file %d\n",out_fd); + kfree(filename); + goto out; + } + while(filesize) { + bytes_read = read(in_fd, buf, (filesize < BLOCK_SIZE) ? filesize : BLOCK_SIZE); + if(bytes_read < 0) { + printk(KERN_NOTICE "INITRAMFS: EOF reached aborting extraction!\n"); + kfree(filename); + goto out; + } + write(out_fd, buf, bytes_read); + filesize -= bytes_read; + } + close(out_fd); + break; + } + case S_IFDIR: { + sys_mkdir(filename, ascii2int(header.c_mode) & ~S_IFMT); + break; + } + case S_IFLNK: { + bytes_read = read(in_fd, buf, (filesize < BLOCK_SIZE) ? filesize : BLOCK_SIZE); + buf[bytes_read] = 0; + sys_symlink(buf,filename); + break; + } + case 0: { + if(strcmp(filename,CPIO_TRAILER) == 0) + while((read(in_fd, buf, 1) == 1) && (*buf == 0) && (cur < initramfs_size)) + cur++; + } + } + kfree(filename); + file_count++; + } + kfree(buf); +out: + close(in_fd); + return file_count; +} + +static int __init initramfs_load_image(char *name) +{ + int pid,i,fd; + unsigned char *buf; + + buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); + if (buf == 0) + return 0; + + fd = open(name, O_RDONLY, 0); + if (fd < 0) { + kfree(buf); + return 0; + } + read(fd, buf, BLOCK_SIZE); + close(fd); + + if (!initramfs_magic((struct cpio_header *)buf)) + return 0; + + printk("INITRAMFS: CPIO Image found starting extraction....\n"); + sys_mount("ramfs", "/root", "ramfs", 0, NULL); + + pid = kernel_thread(do_initramfs, name, SIGCHLD); + if (pid > 0) { + while (pid != wait(&i)) + yield(); + } + return i; +} + +#endif + /* * 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 @@ -472,6 +648,17 @@ goto done; } +#ifdef CONFIG_BLK_DEV_INITRAMFS + /* check for cpio header */ + if (initramfs_magic((struct cpio_header *)buf)) { + printk(KERN_NOTICE + "RAMDISK: cpio header found at block %d\n", + start_block); + nblocks = (initrd_end - initrd_start)>>BLOCK_SIZE_BITS; + goto done; + } +#endif + /* * Read block 1 to test for minix and ext2 superblock */ @@ -615,6 +802,9 @@ kfree(buf); successful_load: +#ifdef CONFIG_BLK_DEV_INITRAMFS + initramfs_size = lseek(out_fd, 0, 1); +#endif res = 1; done: close(in_fd); @@ -754,6 +944,7 @@ int i, pid; create_dev("/dev/root.old", ram0, NULL); + if(!initramfs_load_image("/dev/root.old")) mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); sys_chdir("/old");