The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/init/do_mounts_rd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Many of the syscalls used in this file expect some of the arguments
    3  * to be __user pointers not __kernel pointers.  To limit the sparse
    4  * noise, turn off sparse checking for this file.
    5  */
    6 #ifdef __CHECKER__
    7 #undef __CHECKER__
    8 #warning "Sparse checking disabled for this file"
    9 #endif
   10 
   11 #include <linux/kernel.h>
   12 #include <linux/fs.h>
   13 #include <linux/minix_fs.h>
   14 #include <linux/ext2_fs.h>
   15 #include <linux/romfs_fs.h>
   16 #include <linux/cramfs_fs.h>
   17 #include <linux/initrd.h>
   18 #include <linux/string.h>
   19 #include <linux/slab.h>
   20 
   21 #include "do_mounts.h"
   22 #include "../fs/squashfs/squashfs_fs.h"
   23 
   24 #include <linux/decompress/generic.h>
   25 
   26 
   27 int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
   28 
   29 static int __init prompt_ramdisk(char *str)
   30 {
   31         rd_prompt = simple_strtol(str,NULL,0) & 1;
   32         return 1;
   33 }
   34 __setup("prompt_ramdisk=", prompt_ramdisk);
   35 
   36 int __initdata rd_image_start;          /* starting block # of image */
   37 
   38 static int __init ramdisk_start_setup(char *str)
   39 {
   40         rd_image_start = simple_strtol(str,NULL,0);
   41         return 1;
   42 }
   43 __setup("ramdisk_start=", ramdisk_start_setup);
   44 
   45 static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
   46 
   47 /*
   48  * This routine tries to find a RAM disk image to load, and returns the
   49  * number of blocks to read for a non-compressed image, 0 if the image
   50  * is a compressed image, and -1 if an image with the right magic
   51  * numbers could not be found.
   52  *
   53  * We currently check for the following magic numbers:
   54  *      minix
   55  *      ext2
   56  *      romfs
   57  *      cramfs
   58  *      squashfs
   59  *      gzip
   60  */
   61 static int __init
   62 identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
   63 {
   64         const int size = 512;
   65         struct minix_super_block *minixsb;
   66         struct romfs_super_block *romfsb;
   67         struct cramfs_super *cramfsb;
   68         struct squashfs_super_block *squashfsb;
   69         int nblocks = -1;
   70         unsigned char *buf;
   71         const char *compress_name;
   72         unsigned long n;
   73 
   74         buf = kmalloc(size, GFP_KERNEL);
   75         if (!buf)
   76                 return -ENOMEM;
   77 
   78         minixsb = (struct minix_super_block *) buf;
   79         romfsb = (struct romfs_super_block *) buf;
   80         cramfsb = (struct cramfs_super *) buf;
   81         squashfsb = (struct squashfs_super_block *) buf;
   82         memset(buf, 0xe5, size);
   83 
   84         /*
   85          * Read block 0 to test for compressed kernel
   86          */
   87         sys_lseek(fd, start_block * BLOCK_SIZE, 0);
   88         sys_read(fd, buf, size);
   89 
   90         *decompressor = decompress_method(buf, size, &compress_name);
   91         if (compress_name) {
   92                 printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n",
   93                        compress_name, start_block);
   94                 if (!*decompressor)
   95                         printk(KERN_EMERG
   96                                "RAMDISK: %s decompressor not configured!\n",
   97                                compress_name);
   98                 nblocks = 0;
   99                 goto done;
  100         }
  101 
  102         /* romfs is at block zero too */
  103         if (romfsb->word0 == ROMSB_WORD0 &&
  104             romfsb->word1 == ROMSB_WORD1) {
  105                 printk(KERN_NOTICE
  106                        "RAMDISK: romfs filesystem found at block %d\n",
  107                        start_block);
  108                 nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  109                 goto done;
  110         }
  111 
  112         if (cramfsb->magic == CRAMFS_MAGIC) {
  113                 printk(KERN_NOTICE
  114                        "RAMDISK: cramfs filesystem found at block %d\n",
  115                        start_block);
  116                 nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  117                 goto done;
  118         }
  119 
  120         /* squashfs is at block zero too */
  121         if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) {
  122                 printk(KERN_NOTICE
  123                        "RAMDISK: squashfs filesystem found at block %d\n",
  124                        start_block);
  125                 nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1)
  126                          >> BLOCK_SIZE_BITS;
  127                 goto done;
  128         }
  129 
  130         /*
  131          * Read 512 bytes further to check if cramfs is padded
  132          */
  133         sys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0);
  134         sys_read(fd, buf, size);
  135 
  136         if (cramfsb->magic == CRAMFS_MAGIC) {
  137                 printk(KERN_NOTICE
  138                        "RAMDISK: cramfs filesystem found at block %d\n",
  139                        start_block);
  140                 nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  141                 goto done;
  142         }
  143 
  144         /*
  145          * Read block 1 to test for minix and ext2 superblock
  146          */
  147         sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
  148         sys_read(fd, buf, size);
  149 
  150         /* Try minix */
  151         if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
  152             minixsb->s_magic == MINIX_SUPER_MAGIC2) {
  153                 printk(KERN_NOTICE
  154                        "RAMDISK: Minix filesystem found at block %d\n",
  155                        start_block);
  156                 nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
  157                 goto done;
  158         }
  159 
  160         /* Try ext2 */
  161         n = ext2_image_size(buf);
  162         if (n) {
  163                 printk(KERN_NOTICE
  164                        "RAMDISK: ext2 filesystem found at block %d\n",
  165                        start_block);
  166                 nblocks = n;
  167                 goto done;
  168         }
  169 
  170         printk(KERN_NOTICE
  171                "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n",
  172                start_block);
  173 
  174 done:
  175         sys_lseek(fd, start_block * BLOCK_SIZE, 0);
  176         kfree(buf);
  177         return nblocks;
  178 }
  179 
  180 int __init rd_load_image(char *from)
  181 {
  182         int res = 0;
  183         int in_fd, out_fd;
  184         unsigned long rd_blocks, devblocks;
  185         int nblocks, i, disk;
  186         char *buf = NULL;
  187         unsigned short rotate = 0;
  188         decompress_fn decompressor = NULL;
  189 #if !defined(CONFIG_S390)
  190         char rotator[4] = { '|' , '/' , '-' , '\\' };
  191 #endif
  192 
  193         out_fd = sys_open("/dev/ram", O_RDWR, 0);
  194         if (out_fd < 0)
  195                 goto out;
  196 
  197         in_fd = sys_open(from, O_RDONLY, 0);
  198         if (in_fd < 0)
  199                 goto noclose_input;
  200 
  201         nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor);
  202         if (nblocks < 0)
  203                 goto done;
  204 
  205         if (nblocks == 0) {
  206                 if (crd_load(in_fd, out_fd, decompressor) == 0)
  207                         goto successful_load;
  208                 goto done;
  209         }
  210 
  211         /*
  212          * NOTE NOTE: nblocks is not actually blocks but
  213          * the number of kibibytes of data to load into a ramdisk.
  214          * So any ramdisk block size that is a multiple of 1KiB should
  215          * work when the appropriate ramdisk_blocksize is specified
  216          * on the command line.
  217          *
  218          * The default ramdisk_blocksize is 1KiB and it is generally
  219          * silly to use anything else, so make sure to use 1KiB
  220          * blocksize while generating ext2fs ramdisk-images.
  221          */
  222         if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
  223                 rd_blocks = 0;
  224         else
  225                 rd_blocks >>= 1;
  226 
  227         if (nblocks > rd_blocks) {
  228                 printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
  229                        nblocks, rd_blocks);
  230                 goto done;
  231         }
  232 
  233         /*
  234          * OK, time to copy in the data
  235          */
  236         if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0)
  237                 devblocks = 0;
  238         else
  239                 devblocks >>= 1;
  240 
  241         if (strcmp(from, "/initrd.image") == 0)
  242                 devblocks = nblocks;
  243 
  244         if (devblocks == 0) {
  245                 printk(KERN_ERR "RAMDISK: could not determine device size\n");
  246                 goto done;
  247         }
  248 
  249         buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
  250         if (!buf) {
  251                 printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
  252                 goto done;
  253         }
  254 
  255         printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
  256                 nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
  257         for (i = 0, disk = 1; i < nblocks; i++) {
  258                 if (i && (i % devblocks == 0)) {
  259                         printk("done disk #%d.\n", disk++);
  260                         rotate = 0;
  261                         if (sys_close(in_fd)) {
  262                                 printk("Error closing the disk.\n");
  263                                 goto noclose_input;
  264                         }
  265                         change_floppy("disk #%d", disk);
  266                         in_fd = sys_open(from, O_RDONLY, 0);
  267                         if (in_fd < 0)  {
  268                                 printk("Error opening disk.\n");
  269                                 goto noclose_input;
  270                         }
  271                         printk("Loading disk #%d... ", disk);
  272                 }
  273                 sys_read(in_fd, buf, BLOCK_SIZE);
  274                 sys_write(out_fd, buf, BLOCK_SIZE);
  275 #if !defined(CONFIG_S390)
  276                 if (!(i % 16)) {
  277                         printk("%c\b", rotator[rotate & 0x3]);
  278                         rotate++;
  279                 }
  280 #endif
  281         }
  282         printk("done.\n");
  283 
  284 successful_load:
  285         res = 1;
  286 done:
  287         sys_close(in_fd);
  288 noclose_input:
  289         sys_close(out_fd);
  290 out:
  291         kfree(buf);
  292         sys_unlink("/dev/ram");
  293         return res;
  294 }
  295 
  296 int __init rd_load_disk(int n)
  297 {
  298         if (rd_prompt)
  299                 change_floppy("root floppy disk to be loaded into RAM disk");
  300         create_dev("/dev/root", ROOT_DEV);
  301         create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
  302         return rd_load_image("/dev/root");
  303 }
  304 
  305 static int exit_code;
  306 static int decompress_error;
  307 static int crd_infd, crd_outfd;
  308 
  309 static int __init compr_fill(void *buf, unsigned int len)
  310 {
  311         int r = sys_read(crd_infd, buf, len);
  312         if (r < 0)
  313                 printk(KERN_ERR "RAMDISK: error while reading compressed data");
  314         else if (r == 0)
  315                 printk(KERN_ERR "RAMDISK: EOF while reading compressed data");
  316         return r;
  317 }
  318 
  319 static int __init compr_flush(void *window, unsigned int outcnt)
  320 {
  321         int written = sys_write(crd_outfd, window, outcnt);
  322         if (written != outcnt) {
  323                 if (decompress_error == 0)
  324                         printk(KERN_ERR
  325                                "RAMDISK: incomplete write (%d != %d)\n",
  326                                written, outcnt);
  327                 decompress_error = 1;
  328                 return -1;
  329         }
  330         return outcnt;
  331 }
  332 
  333 static void __init error(char *x)
  334 {
  335         printk(KERN_ERR "%s\n", x);
  336         exit_code = 1;
  337         decompress_error = 1;
  338 }
  339 
  340 static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)
  341 {
  342         int result;
  343         crd_infd = in_fd;
  344         crd_outfd = out_fd;
  345         result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);
  346         if (decompress_error)
  347                 result = 1;
  348         return result;
  349 }

Cache object: 2ff9f6d975559a4e4a85c0da78f86b24


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.