11da177e4SLinus Torvalds 21da177e4SLinus Torvalds #include <linux/kernel.h> 31da177e4SLinus Torvalds #include <linux/fs.h> 41da177e4SLinus Torvalds #include <linux/minix_fs.h> 51da177e4SLinus Torvalds #include <linux/ext2_fs.h> 61da177e4SLinus Torvalds #include <linux/romfs_fs.h> 71da177e4SLinus Torvalds #include <linux/cramfs_fs.h> 81da177e4SLinus Torvalds #include <linux/initrd.h> 91da177e4SLinus Torvalds #include <linux/string.h> 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include "do_mounts.h" 121da177e4SLinus Torvalds 13*30d65dbfSAlain Knaff #include <linux/decompress/generic.h> 14*30d65dbfSAlain Knaff 15*30d65dbfSAlain Knaff #include <linux/decompress/bunzip2.h> 16*30d65dbfSAlain Knaff #include <linux/decompress/unlzma.h> 17*30d65dbfSAlain Knaff #include <linux/decompress/inflate.h> 18*30d65dbfSAlain Knaff 191da177e4SLinus Torvalds int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds static int __init prompt_ramdisk(char *str) 221da177e4SLinus Torvalds { 231da177e4SLinus Torvalds rd_prompt = simple_strtol(str,NULL,0) & 1; 241da177e4SLinus Torvalds return 1; 251da177e4SLinus Torvalds } 261da177e4SLinus Torvalds __setup("prompt_ramdisk=", prompt_ramdisk); 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds int __initdata rd_image_start; /* starting block # of image */ 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds static int __init ramdisk_start_setup(char *str) 311da177e4SLinus Torvalds { 321da177e4SLinus Torvalds rd_image_start = simple_strtol(str,NULL,0); 331da177e4SLinus Torvalds return 1; 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds __setup("ramdisk_start=", ramdisk_start_setup); 361da177e4SLinus Torvalds 37*30d65dbfSAlain Knaff static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds /* 401da177e4SLinus Torvalds * This routine tries to find a RAM disk image to load, and returns the 411da177e4SLinus Torvalds * number of blocks to read for a non-compressed image, 0 if the image 421da177e4SLinus Torvalds * is a compressed image, and -1 if an image with the right magic 431da177e4SLinus Torvalds * numbers could not be found. 441da177e4SLinus Torvalds * 451da177e4SLinus Torvalds * We currently check for the following magic numbers: 461da177e4SLinus Torvalds * minix 471da177e4SLinus Torvalds * ext2 481da177e4SLinus Torvalds * romfs 491da177e4SLinus Torvalds * cramfs 501da177e4SLinus Torvalds * gzip 511da177e4SLinus Torvalds */ 521da177e4SLinus Torvalds static int __init 53*30d65dbfSAlain Knaff identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds const int size = 512; 561da177e4SLinus Torvalds struct minix_super_block *minixsb; 571da177e4SLinus Torvalds struct ext2_super_block *ext2sb; 581da177e4SLinus Torvalds struct romfs_super_block *romfsb; 591da177e4SLinus Torvalds struct cramfs_super *cramfsb; 601da177e4SLinus Torvalds int nblocks = -1; 611da177e4SLinus Torvalds unsigned char *buf; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds buf = kmalloc(size, GFP_KERNEL); 64c80544dcSStephen Hemminger if (!buf) 651da177e4SLinus Torvalds return -1; 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds minixsb = (struct minix_super_block *) buf; 681da177e4SLinus Torvalds ext2sb = (struct ext2_super_block *) buf; 691da177e4SLinus Torvalds romfsb = (struct romfs_super_block *) buf; 701da177e4SLinus Torvalds cramfsb = (struct cramfs_super *) buf; 711da177e4SLinus Torvalds memset(buf, 0xe5, size); 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds /* 741da177e4SLinus Torvalds * Read block 0 to test for gzipped kernel 751da177e4SLinus Torvalds */ 761da177e4SLinus Torvalds sys_lseek(fd, start_block * BLOCK_SIZE, 0); 771da177e4SLinus Torvalds sys_read(fd, buf, size); 781da177e4SLinus Torvalds 79*30d65dbfSAlain Knaff #ifdef CONFIG_RD_GZIP 801da177e4SLinus Torvalds /* 8193fd85d0SGeert Uytterhoeven * If it matches the gzip magic numbers, return 0 821da177e4SLinus Torvalds */ 831da177e4SLinus Torvalds if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { 841da177e4SLinus Torvalds printk(KERN_NOTICE 851da177e4SLinus Torvalds "RAMDISK: Compressed image found at block %d\n", 861da177e4SLinus Torvalds start_block); 87*30d65dbfSAlain Knaff *decompressor = gunzip; 881da177e4SLinus Torvalds nblocks = 0; 891da177e4SLinus Torvalds goto done; 901da177e4SLinus Torvalds } 91*30d65dbfSAlain Knaff #endif 92*30d65dbfSAlain Knaff 93*30d65dbfSAlain Knaff #ifdef CONFIG_RD_BZIP2 94*30d65dbfSAlain Knaff /* 95*30d65dbfSAlain Knaff * If it matches the bzip2 magic numbers, return -1 96*30d65dbfSAlain Knaff */ 97*30d65dbfSAlain Knaff if (buf[0] == 0x42 && (buf[1] == 0x5a)) { 98*30d65dbfSAlain Knaff printk(KERN_NOTICE 99*30d65dbfSAlain Knaff "RAMDISK: Bzipped image found at block %d\n", 100*30d65dbfSAlain Knaff start_block); 101*30d65dbfSAlain Knaff *decompressor = bunzip2; 102*30d65dbfSAlain Knaff nblocks = 0; 103*30d65dbfSAlain Knaff goto done; 104*30d65dbfSAlain Knaff } 105*30d65dbfSAlain Knaff #endif 106*30d65dbfSAlain Knaff 107*30d65dbfSAlain Knaff #ifdef CONFIG_RD_LZMA 108*30d65dbfSAlain Knaff /* 109*30d65dbfSAlain Knaff * If it matches the lzma magic numbers, return -1 110*30d65dbfSAlain Knaff */ 111*30d65dbfSAlain Knaff if (buf[0] == 0x5d && (buf[1] == 0x00)) { 112*30d65dbfSAlain Knaff printk(KERN_NOTICE 113*30d65dbfSAlain Knaff "RAMDISK: Lzma image found at block %d\n", 114*30d65dbfSAlain Knaff start_block); 115*30d65dbfSAlain Knaff *decompressor = unlzma; 116*30d65dbfSAlain Knaff nblocks = 0; 117*30d65dbfSAlain Knaff goto done; 118*30d65dbfSAlain Knaff } 119*30d65dbfSAlain Knaff #endif 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds /* romfs is at block zero too */ 1221da177e4SLinus Torvalds if (romfsb->word0 == ROMSB_WORD0 && 1231da177e4SLinus Torvalds romfsb->word1 == ROMSB_WORD1) { 1241da177e4SLinus Torvalds printk(KERN_NOTICE 1251da177e4SLinus Torvalds "RAMDISK: romfs filesystem found at block %d\n", 1261da177e4SLinus Torvalds start_block); 1271da177e4SLinus Torvalds nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; 1281da177e4SLinus Torvalds goto done; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds if (cramfsb->magic == CRAMFS_MAGIC) { 1321da177e4SLinus Torvalds printk(KERN_NOTICE 1331da177e4SLinus Torvalds "RAMDISK: cramfs filesystem found at block %d\n", 1341da177e4SLinus Torvalds start_block); 1351da177e4SLinus Torvalds nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; 1361da177e4SLinus Torvalds goto done; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds /* 1401da177e4SLinus Torvalds * Read block 1 to test for minix and ext2 superblock 1411da177e4SLinus Torvalds */ 1421da177e4SLinus Torvalds sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0); 1431da177e4SLinus Torvalds sys_read(fd, buf, size); 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds /* Try minix */ 1461da177e4SLinus Torvalds if (minixsb->s_magic == MINIX_SUPER_MAGIC || 1471da177e4SLinus Torvalds minixsb->s_magic == MINIX_SUPER_MAGIC2) { 1481da177e4SLinus Torvalds printk(KERN_NOTICE 1491da177e4SLinus Torvalds "RAMDISK: Minix filesystem found at block %d\n", 1501da177e4SLinus Torvalds start_block); 1511da177e4SLinus Torvalds nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; 1521da177e4SLinus Torvalds goto done; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds /* Try ext2 */ 1561da177e4SLinus Torvalds if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { 1571da177e4SLinus Torvalds printk(KERN_NOTICE 1581da177e4SLinus Torvalds "RAMDISK: ext2 filesystem found at block %d\n", 1591da177e4SLinus Torvalds start_block); 1601da177e4SLinus Torvalds nblocks = le32_to_cpu(ext2sb->s_blocks_count) << 1611da177e4SLinus Torvalds le32_to_cpu(ext2sb->s_log_block_size); 1621da177e4SLinus Torvalds goto done; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds printk(KERN_NOTICE 1661da177e4SLinus Torvalds "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", 1671da177e4SLinus Torvalds start_block); 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds done: 1701da177e4SLinus Torvalds sys_lseek(fd, start_block * BLOCK_SIZE, 0); 1711da177e4SLinus Torvalds kfree(buf); 1721da177e4SLinus Torvalds return nblocks; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds int __init rd_load_image(char *from) 1761da177e4SLinus Torvalds { 1771da177e4SLinus Torvalds int res = 0; 1781da177e4SLinus Torvalds int in_fd, out_fd; 1791da177e4SLinus Torvalds unsigned long rd_blocks, devblocks; 1801da177e4SLinus Torvalds int nblocks, i, disk; 1811da177e4SLinus Torvalds char *buf = NULL; 1821da177e4SLinus Torvalds unsigned short rotate = 0; 183*30d65dbfSAlain Knaff decompress_fn decompressor = NULL; 184347a8dc3SMartin Schwidefsky #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) 1851da177e4SLinus Torvalds char rotator[4] = { '|' , '/' , '-' , '\\' }; 1861da177e4SLinus Torvalds #endif 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds out_fd = sys_open("/dev/ram", O_RDWR, 0); 1891da177e4SLinus Torvalds if (out_fd < 0) 1901da177e4SLinus Torvalds goto out; 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds in_fd = sys_open(from, O_RDONLY, 0); 1931da177e4SLinus Torvalds if (in_fd < 0) 1941da177e4SLinus Torvalds goto noclose_input; 1951da177e4SLinus Torvalds 196*30d65dbfSAlain Knaff nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); 1971da177e4SLinus Torvalds if (nblocks < 0) 1981da177e4SLinus Torvalds goto done; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds if (nblocks == 0) { 201*30d65dbfSAlain Knaff if (crd_load(in_fd, out_fd, decompressor) == 0) 2021da177e4SLinus Torvalds goto successful_load; 2031da177e4SLinus Torvalds goto done; 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds /* 2071da177e4SLinus Torvalds * NOTE NOTE: nblocks is not actually blocks but 2081da177e4SLinus Torvalds * the number of kibibytes of data to load into a ramdisk. 2091da177e4SLinus Torvalds * So any ramdisk block size that is a multiple of 1KiB should 2101da177e4SLinus Torvalds * work when the appropriate ramdisk_blocksize is specified 2111da177e4SLinus Torvalds * on the command line. 2121da177e4SLinus Torvalds * 2131da177e4SLinus Torvalds * The default ramdisk_blocksize is 1KiB and it is generally 2141da177e4SLinus Torvalds * silly to use anything else, so make sure to use 1KiB 2151da177e4SLinus Torvalds * blocksize while generating ext2fs ramdisk-images. 2161da177e4SLinus Torvalds */ 2171da177e4SLinus Torvalds if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) 2181da177e4SLinus Torvalds rd_blocks = 0; 2191da177e4SLinus Torvalds else 2201da177e4SLinus Torvalds rd_blocks >>= 1; 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds if (nblocks > rd_blocks) { 2231da177e4SLinus Torvalds printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", 2241da177e4SLinus Torvalds nblocks, rd_blocks); 2251da177e4SLinus Torvalds goto done; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds /* 2291da177e4SLinus Torvalds * OK, time to copy in the data 2301da177e4SLinus Torvalds */ 2311da177e4SLinus Torvalds if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) 2321da177e4SLinus Torvalds devblocks = 0; 2331da177e4SLinus Torvalds else 2341da177e4SLinus Torvalds devblocks >>= 1; 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds if (strcmp(from, "/initrd.image") == 0) 2371da177e4SLinus Torvalds devblocks = nblocks; 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds if (devblocks == 0) { 2401da177e4SLinus Torvalds printk(KERN_ERR "RAMDISK: could not determine device size\n"); 2411da177e4SLinus Torvalds goto done; 2421da177e4SLinus Torvalds } 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); 245d613c3e2SHarvey Harrison if (!buf) { 2461da177e4SLinus Torvalds printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); 2471da177e4SLinus Torvalds goto done; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", 2511da177e4SLinus Torvalds nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); 2521da177e4SLinus Torvalds for (i = 0, disk = 1; i < nblocks; i++) { 2531da177e4SLinus Torvalds if (i && (i % devblocks == 0)) { 2541da177e4SLinus Torvalds printk("done disk #%d.\n", disk++); 2551da177e4SLinus Torvalds rotate = 0; 2561da177e4SLinus Torvalds if (sys_close(in_fd)) { 2571da177e4SLinus Torvalds printk("Error closing the disk.\n"); 2581da177e4SLinus Torvalds goto noclose_input; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds change_floppy("disk #%d", disk); 2611da177e4SLinus Torvalds in_fd = sys_open(from, O_RDONLY, 0); 2621da177e4SLinus Torvalds if (in_fd < 0) { 2631da177e4SLinus Torvalds printk("Error opening disk.\n"); 2641da177e4SLinus Torvalds goto noclose_input; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds printk("Loading disk #%d... ", disk); 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds sys_read(in_fd, buf, BLOCK_SIZE); 2691da177e4SLinus Torvalds sys_write(out_fd, buf, BLOCK_SIZE); 270347a8dc3SMartin Schwidefsky #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) 2711da177e4SLinus Torvalds if (!(i % 16)) { 2721da177e4SLinus Torvalds printk("%c\b", rotator[rotate & 0x3]); 2731da177e4SLinus Torvalds rotate++; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds #endif 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds printk("done.\n"); 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds successful_load: 2801da177e4SLinus Torvalds res = 1; 2811da177e4SLinus Torvalds done: 2821da177e4SLinus Torvalds sys_close(in_fd); 2831da177e4SLinus Torvalds noclose_input: 2841da177e4SLinus Torvalds sys_close(out_fd); 2851da177e4SLinus Torvalds out: 2861da177e4SLinus Torvalds kfree(buf); 2871da177e4SLinus Torvalds sys_unlink("/dev/ram"); 2881da177e4SLinus Torvalds return res; 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds int __init rd_load_disk(int n) 2921da177e4SLinus Torvalds { 2931da177e4SLinus Torvalds if (rd_prompt) 2941da177e4SLinus Torvalds change_floppy("root floppy disk to be loaded into RAM disk"); 295bdaf8529SGreg Kroah-Hartman create_dev("/dev/root", ROOT_DEV); 296bdaf8529SGreg Kroah-Hartman create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); 2971da177e4SLinus Torvalds return rd_load_image("/dev/root"); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds static int exit_code; 301*30d65dbfSAlain Knaff static int decompress_error; 3021da177e4SLinus Torvalds static int crd_infd, crd_outfd; 3031da177e4SLinus Torvalds 304*30d65dbfSAlain Knaff static int __init compr_fill(void *buf, unsigned int len) 3051da177e4SLinus Torvalds { 306*30d65dbfSAlain Knaff int r = sys_read(crd_infd, buf, len); 307*30d65dbfSAlain Knaff if (r < 0) 308*30d65dbfSAlain Knaff printk(KERN_ERR "RAMDISK: error while reading compressed data"); 309*30d65dbfSAlain Knaff else if (r == 0) 310*30d65dbfSAlain Knaff printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); 311*30d65dbfSAlain Knaff return r; 312*30d65dbfSAlain Knaff } 3131da177e4SLinus Torvalds 314*30d65dbfSAlain Knaff static int __init compr_flush(void *window, unsigned int outcnt) 315*30d65dbfSAlain Knaff { 316*30d65dbfSAlain Knaff int written = sys_write(crd_outfd, window, outcnt); 317*30d65dbfSAlain Knaff if (written != outcnt) { 318*30d65dbfSAlain Knaff if (decompress_error == 0) 319*30d65dbfSAlain Knaff printk(KERN_ERR 320*30d65dbfSAlain Knaff "RAMDISK: incomplete write (%d != %d)\n", 321*30d65dbfSAlain Knaff written, outcnt); 322*30d65dbfSAlain Knaff decompress_error = 1; 3231da177e4SLinus Torvalds return -1; 3241da177e4SLinus Torvalds } 325*30d65dbfSAlain Knaff return outcnt; 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds static void __init error(char *x) 3291da177e4SLinus Torvalds { 3301da177e4SLinus Torvalds printk(KERN_ERR "%s\n", x); 3311da177e4SLinus Torvalds exit_code = 1; 332*30d65dbfSAlain Knaff decompress_error = 1; 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds 335*30d65dbfSAlain Knaff static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) 3361da177e4SLinus Torvalds { 3371da177e4SLinus Torvalds int result; 3381da177e4SLinus Torvalds crd_infd = in_fd; 3391da177e4SLinus Torvalds crd_outfd = out_fd; 340*30d65dbfSAlain Knaff result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); 341*30d65dbfSAlain Knaff if (decompress_error) 3421da177e4SLinus Torvalds result = 1; 3431da177e4SLinus Torvalds return result; 3441da177e4SLinus Torvalds } 345