1c67e5382SH Hartley Sweeten /* 2c67e5382SH Hartley Sweeten * Many of the syscalls used in this file expect some of the arguments 3c67e5382SH Hartley Sweeten * to be __user pointers not __kernel pointers. To limit the sparse 4c67e5382SH Hartley Sweeten * noise, turn off sparse checking for this file. 5c67e5382SH Hartley Sweeten */ 6c67e5382SH Hartley Sweeten #ifdef __CHECKER__ 7c67e5382SH Hartley Sweeten #undef __CHECKER__ 8c67e5382SH Hartley Sweeten #warning "Sparse checking disabled for this file" 9c67e5382SH Hartley Sweeten #endif 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/fs.h> 131da177e4SLinus Torvalds #include <linux/minix_fs.h> 141da177e4SLinus Torvalds #include <linux/ext2_fs.h> 151da177e4SLinus Torvalds #include <linux/romfs_fs.h> 16f7f4f4ddSAl Viro #include <uapi/linux/cramfs_fs.h> 171da177e4SLinus Torvalds #include <linux/initrd.h> 181da177e4SLinus Torvalds #include <linux/string.h> 195a0e3ad6STejun Heo #include <linux/slab.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include "do_mounts.h" 22b8fed87dSPhillip Lougher #include "../fs/squashfs/squashfs_fs.h" 231da177e4SLinus Torvalds 2430d65dbfSAlain Knaff #include <linux/decompress/generic.h> 2530d65dbfSAlain Knaff 2630d65dbfSAlain Knaff 271da177e4SLinus Torvalds int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds static int __init prompt_ramdisk(char *str) 301da177e4SLinus Torvalds { 311da177e4SLinus Torvalds rd_prompt = simple_strtol(str,NULL,0) & 1; 321da177e4SLinus Torvalds return 1; 331da177e4SLinus Torvalds } 341da177e4SLinus Torvalds __setup("prompt_ramdisk=", prompt_ramdisk); 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds int __initdata rd_image_start; /* starting block # of image */ 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds static int __init ramdisk_start_setup(char *str) 391da177e4SLinus Torvalds { 401da177e4SLinus Torvalds rd_image_start = simple_strtol(str,NULL,0); 411da177e4SLinus Torvalds return 1; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds __setup("ramdisk_start=", ramdisk_start_setup); 441da177e4SLinus Torvalds 4530d65dbfSAlain Knaff static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* 481da177e4SLinus Torvalds * This routine tries to find a RAM disk image to load, and returns the 491da177e4SLinus Torvalds * number of blocks to read for a non-compressed image, 0 if the image 501da177e4SLinus Torvalds * is a compressed image, and -1 if an image with the right magic 511da177e4SLinus Torvalds * numbers could not be found. 521da177e4SLinus Torvalds * 531da177e4SLinus Torvalds * We currently check for the following magic numbers: 541da177e4SLinus Torvalds * minix 551da177e4SLinus Torvalds * ext2 561da177e4SLinus Torvalds * romfs 571da177e4SLinus Torvalds * cramfs 58b8fed87dSPhillip Lougher * squashfs 591da177e4SLinus Torvalds * gzip 601bf49dd4SP J P * bzip2 611bf49dd4SP J P * lzma 621bf49dd4SP J P * xz 631bf49dd4SP J P * lzo 641bf49dd4SP J P * lz4 651da177e4SLinus Torvalds */ 661da177e4SLinus Torvalds static int __init 6730d65dbfSAlain Knaff identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) 681da177e4SLinus Torvalds { 691da177e4SLinus Torvalds const int size = 512; 701da177e4SLinus Torvalds struct minix_super_block *minixsb; 711da177e4SLinus Torvalds struct romfs_super_block *romfsb; 721da177e4SLinus Torvalds struct cramfs_super *cramfsb; 73b8fed87dSPhillip Lougher struct squashfs_super_block *squashfsb; 741da177e4SLinus Torvalds int nblocks = -1; 751da177e4SLinus Torvalds unsigned char *buf; 76889c92d2SH. Peter Anvin const char *compress_name; 7739429c5eSAl Viro unsigned long n; 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds buf = kmalloc(size, GFP_KERNEL); 80c80544dcSStephen Hemminger if (!buf) 81ea611b26SDavidlohr Bueso return -ENOMEM; 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds minixsb = (struct minix_super_block *) buf; 841da177e4SLinus Torvalds romfsb = (struct romfs_super_block *) buf; 851da177e4SLinus Torvalds cramfsb = (struct cramfs_super *) buf; 86b8fed87dSPhillip Lougher squashfsb = (struct squashfs_super_block *) buf; 871da177e4SLinus Torvalds memset(buf, 0xe5, size); 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds /* 90b172fd88SH. Peter Anvin * Read block 0 to test for compressed kernel 911da177e4SLinus Torvalds */ 921da177e4SLinus Torvalds sys_lseek(fd, start_block * BLOCK_SIZE, 0); 931da177e4SLinus Torvalds sys_read(fd, buf, size); 941da177e4SLinus Torvalds 95889c92d2SH. Peter Anvin *decompressor = decompress_method(buf, size, &compress_name); 9623a22d57SH. Peter Anvin if (compress_name) { 97889c92d2SH. Peter Anvin printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", 98889c92d2SH. Peter Anvin compress_name, start_block); 9923a22d57SH. Peter Anvin if (!*decompressor) 10073310a16SH. Peter Anvin printk(KERN_EMERG 10173310a16SH. Peter Anvin "RAMDISK: %s decompressor not configured!\n", 10223a22d57SH. Peter Anvin compress_name); 1031da177e4SLinus Torvalds nblocks = 0; 1041da177e4SLinus Torvalds goto done; 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds /* romfs is at block zero too */ 1081da177e4SLinus Torvalds if (romfsb->word0 == ROMSB_WORD0 && 1091da177e4SLinus Torvalds romfsb->word1 == ROMSB_WORD1) { 1101da177e4SLinus Torvalds printk(KERN_NOTICE 1111da177e4SLinus Torvalds "RAMDISK: romfs filesystem found at block %d\n", 1121da177e4SLinus Torvalds start_block); 1131da177e4SLinus Torvalds nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; 1141da177e4SLinus Torvalds goto done; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds if (cramfsb->magic == CRAMFS_MAGIC) { 1181da177e4SLinus Torvalds printk(KERN_NOTICE 1191da177e4SLinus Torvalds "RAMDISK: cramfs filesystem found at block %d\n", 1201da177e4SLinus Torvalds start_block); 1211da177e4SLinus Torvalds nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; 1221da177e4SLinus Torvalds goto done; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 125b8fed87dSPhillip Lougher /* squashfs is at block zero too */ 126b8fed87dSPhillip Lougher if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) { 127b8fed87dSPhillip Lougher printk(KERN_NOTICE 128b8fed87dSPhillip Lougher "RAMDISK: squashfs filesystem found at block %d\n", 129b8fed87dSPhillip Lougher start_block); 130b8fed87dSPhillip Lougher nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1) 131b8fed87dSPhillip Lougher >> BLOCK_SIZE_BITS; 132b8fed87dSPhillip Lougher goto done; 133b8fed87dSPhillip Lougher } 134b8fed87dSPhillip Lougher 1351da177e4SLinus Torvalds /* 136f919b923SNeil Armstrong * Read 512 bytes further to check if cramfs is padded 137f919b923SNeil Armstrong */ 138f919b923SNeil Armstrong sys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0); 139f919b923SNeil Armstrong sys_read(fd, buf, size); 140f919b923SNeil Armstrong 141f919b923SNeil Armstrong if (cramfsb->magic == CRAMFS_MAGIC) { 142f919b923SNeil Armstrong printk(KERN_NOTICE 143f919b923SNeil Armstrong "RAMDISK: cramfs filesystem found at block %d\n", 144f919b923SNeil Armstrong start_block); 145f919b923SNeil Armstrong nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; 146f919b923SNeil Armstrong goto done; 147f919b923SNeil Armstrong } 148f919b923SNeil Armstrong 149f919b923SNeil Armstrong /* 1501da177e4SLinus Torvalds * Read block 1 to test for minix and ext2 superblock 1511da177e4SLinus Torvalds */ 1521da177e4SLinus Torvalds sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0); 1531da177e4SLinus Torvalds sys_read(fd, buf, size); 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds /* Try minix */ 1561da177e4SLinus Torvalds if (minixsb->s_magic == MINIX_SUPER_MAGIC || 1571da177e4SLinus Torvalds minixsb->s_magic == MINIX_SUPER_MAGIC2) { 1581da177e4SLinus Torvalds printk(KERN_NOTICE 1591da177e4SLinus Torvalds "RAMDISK: Minix filesystem found at block %d\n", 1601da177e4SLinus Torvalds start_block); 1611da177e4SLinus Torvalds nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; 1621da177e4SLinus Torvalds goto done; 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds /* Try ext2 */ 16639429c5eSAl Viro n = ext2_image_size(buf); 16739429c5eSAl Viro if (n) { 1681da177e4SLinus Torvalds printk(KERN_NOTICE 1691da177e4SLinus Torvalds "RAMDISK: ext2 filesystem found at block %d\n", 1701da177e4SLinus Torvalds start_block); 17139429c5eSAl Viro nblocks = n; 1721da177e4SLinus Torvalds goto done; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds printk(KERN_NOTICE 1761da177e4SLinus Torvalds "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", 1771da177e4SLinus Torvalds start_block); 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds done: 1801da177e4SLinus Torvalds sys_lseek(fd, start_block * BLOCK_SIZE, 0); 1811da177e4SLinus Torvalds kfree(buf); 1821da177e4SLinus Torvalds return nblocks; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds int __init rd_load_image(char *from) 1861da177e4SLinus Torvalds { 1871da177e4SLinus Torvalds int res = 0; 1881da177e4SLinus Torvalds int in_fd, out_fd; 1891da177e4SLinus Torvalds unsigned long rd_blocks, devblocks; 1901da177e4SLinus Torvalds int nblocks, i, disk; 1911da177e4SLinus Torvalds char *buf = NULL; 1921da177e4SLinus Torvalds unsigned short rotate = 0; 19330d65dbfSAlain Knaff decompress_fn decompressor = NULL; 194bc58450bSStephen Rothwell #if !defined(CONFIG_S390) 1951da177e4SLinus Torvalds char rotator[4] = { '|' , '/' , '-' , '\\' }; 1961da177e4SLinus Torvalds #endif 1971da177e4SLinus Torvalds 198c67e5382SH Hartley Sweeten out_fd = sys_open("/dev/ram", O_RDWR, 0); 1991da177e4SLinus Torvalds if (out_fd < 0) 2001da177e4SLinus Torvalds goto out; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds in_fd = sys_open(from, O_RDONLY, 0); 2031da177e4SLinus Torvalds if (in_fd < 0) 2041da177e4SLinus Torvalds goto noclose_input; 2051da177e4SLinus Torvalds 20630d65dbfSAlain Knaff nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); 2071da177e4SLinus Torvalds if (nblocks < 0) 2081da177e4SLinus Torvalds goto done; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds if (nblocks == 0) { 21130d65dbfSAlain Knaff if (crd_load(in_fd, out_fd, decompressor) == 0) 2121da177e4SLinus Torvalds goto successful_load; 2131da177e4SLinus Torvalds goto done; 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds /* 2171da177e4SLinus Torvalds * NOTE NOTE: nblocks is not actually blocks but 2181da177e4SLinus Torvalds * the number of kibibytes of data to load into a ramdisk. 2191da177e4SLinus Torvalds * So any ramdisk block size that is a multiple of 1KiB should 2201da177e4SLinus Torvalds * work when the appropriate ramdisk_blocksize is specified 2211da177e4SLinus Torvalds * on the command line. 2221da177e4SLinus Torvalds * 2231da177e4SLinus Torvalds * The default ramdisk_blocksize is 1KiB and it is generally 2241da177e4SLinus Torvalds * silly to use anything else, so make sure to use 1KiB 2251da177e4SLinus Torvalds * blocksize while generating ext2fs ramdisk-images. 2261da177e4SLinus Torvalds */ 2271da177e4SLinus Torvalds if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) 2281da177e4SLinus Torvalds rd_blocks = 0; 2291da177e4SLinus Torvalds else 2301da177e4SLinus Torvalds rd_blocks >>= 1; 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds if (nblocks > rd_blocks) { 2331da177e4SLinus Torvalds printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", 2341da177e4SLinus Torvalds nblocks, rd_blocks); 2351da177e4SLinus Torvalds goto done; 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds /* 2391da177e4SLinus Torvalds * OK, time to copy in the data 2401da177e4SLinus Torvalds */ 2411da177e4SLinus Torvalds if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) 2421da177e4SLinus Torvalds devblocks = 0; 2431da177e4SLinus Torvalds else 2441da177e4SLinus Torvalds devblocks >>= 1; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds if (strcmp(from, "/initrd.image") == 0) 2471da177e4SLinus Torvalds devblocks = nblocks; 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds if (devblocks == 0) { 2501da177e4SLinus Torvalds printk(KERN_ERR "RAMDISK: could not determine device size\n"); 2511da177e4SLinus Torvalds goto done; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); 255d613c3e2SHarvey Harrison if (!buf) { 2561da177e4SLinus Torvalds printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); 2571da177e4SLinus Torvalds goto done; 2581da177e4SLinus Torvalds } 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", 2611da177e4SLinus Torvalds nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); 2621da177e4SLinus Torvalds for (i = 0, disk = 1; i < nblocks; i++) { 2631da177e4SLinus Torvalds if (i && (i % devblocks == 0)) { 2641da177e4SLinus Torvalds printk("done disk #%d.\n", disk++); 2651da177e4SLinus Torvalds rotate = 0; 2661da177e4SLinus Torvalds if (sys_close(in_fd)) { 2671da177e4SLinus Torvalds printk("Error closing the disk.\n"); 2681da177e4SLinus Torvalds goto noclose_input; 2691da177e4SLinus Torvalds } 2701da177e4SLinus Torvalds change_floppy("disk #%d", disk); 2711da177e4SLinus Torvalds in_fd = sys_open(from, O_RDONLY, 0); 2721da177e4SLinus Torvalds if (in_fd < 0) { 2731da177e4SLinus Torvalds printk("Error opening disk.\n"); 2741da177e4SLinus Torvalds goto noclose_input; 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds printk("Loading disk #%d... ", disk); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds sys_read(in_fd, buf, BLOCK_SIZE); 2791da177e4SLinus Torvalds sys_write(out_fd, buf, BLOCK_SIZE); 280bc58450bSStephen Rothwell #if !defined(CONFIG_S390) 2811da177e4SLinus Torvalds if (!(i % 16)) { 2821da177e4SLinus Torvalds printk("%c\b", rotator[rotate & 0x3]); 2831da177e4SLinus Torvalds rotate++; 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds #endif 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds printk("done.\n"); 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds successful_load: 2901da177e4SLinus Torvalds res = 1; 2911da177e4SLinus Torvalds done: 2921da177e4SLinus Torvalds sys_close(in_fd); 2931da177e4SLinus Torvalds noclose_input: 2941da177e4SLinus Torvalds sys_close(out_fd); 2951da177e4SLinus Torvalds out: 2961da177e4SLinus Torvalds kfree(buf); 297c67e5382SH Hartley Sweeten sys_unlink("/dev/ram"); 2981da177e4SLinus Torvalds return res; 2991da177e4SLinus Torvalds } 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds int __init rd_load_disk(int n) 3021da177e4SLinus Torvalds { 3031da177e4SLinus Torvalds if (rd_prompt) 3041da177e4SLinus Torvalds change_floppy("root floppy disk to be loaded into RAM disk"); 305bdaf8529SGreg Kroah-Hartman create_dev("/dev/root", ROOT_DEV); 306bdaf8529SGreg Kroah-Hartman create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); 3071da177e4SLinus Torvalds return rd_load_image("/dev/root"); 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds static int exit_code; 31130d65dbfSAlain Knaff static int decompress_error; 3121da177e4SLinus Torvalds static int crd_infd, crd_outfd; 3131da177e4SLinus Torvalds 314*d97b07c5SYinghai Lu static long __init compr_fill(void *buf, unsigned long len) 3151da177e4SLinus Torvalds { 316*d97b07c5SYinghai Lu long r = sys_read(crd_infd, buf, len); 31730d65dbfSAlain Knaff if (r < 0) 31830d65dbfSAlain Knaff printk(KERN_ERR "RAMDISK: error while reading compressed data"); 31930d65dbfSAlain Knaff else if (r == 0) 32030d65dbfSAlain Knaff printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); 32130d65dbfSAlain Knaff return r; 32230d65dbfSAlain Knaff } 3231da177e4SLinus Torvalds 324*d97b07c5SYinghai Lu static long __init compr_flush(void *window, unsigned long outcnt) 32530d65dbfSAlain Knaff { 326*d97b07c5SYinghai Lu long written = sys_write(crd_outfd, window, outcnt); 32730d65dbfSAlain Knaff if (written != outcnt) { 32830d65dbfSAlain Knaff if (decompress_error == 0) 32930d65dbfSAlain Knaff printk(KERN_ERR 330*d97b07c5SYinghai Lu "RAMDISK: incomplete write (%ld != %ld)\n", 33130d65dbfSAlain Knaff written, outcnt); 33230d65dbfSAlain Knaff decompress_error = 1; 3331da177e4SLinus Torvalds return -1; 3341da177e4SLinus Torvalds } 33530d65dbfSAlain Knaff return outcnt; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds static void __init error(char *x) 3391da177e4SLinus Torvalds { 3401da177e4SLinus Torvalds printk(KERN_ERR "%s\n", x); 3411da177e4SLinus Torvalds exit_code = 1; 34230d65dbfSAlain Knaff decompress_error = 1; 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds 34530d65dbfSAlain Knaff static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) 3461da177e4SLinus Torvalds { 3471da177e4SLinus Torvalds int result; 3481da177e4SLinus Torvalds crd_infd = in_fd; 3491da177e4SLinus Torvalds crd_outfd = out_fd; 350df3ef3afSP J P 351df3ef3afSP J P if (!deco) { 352df3ef3afSP J P pr_emerg("Invalid ramdisk decompression routine. " 353df3ef3afSP J P "Select appropriate config option.\n"); 354df3ef3afSP J P panic("Could not decompress initial ramdisk image."); 355df3ef3afSP J P } 356df3ef3afSP J P 35730d65dbfSAlain Knaff result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); 35830d65dbfSAlain Knaff if (decompress_error) 3591da177e4SLinus Torvalds result = 1; 3601da177e4SLinus Torvalds return result; 3611da177e4SLinus Torvalds } 362