linux/init/do_mounts_rd.c
<<
>>
Prefs
   1
   2#include <linux/kernel.h>
   3#include <linux/fs.h>
   4#include <linux/minix_fs.h>
   5#include <linux/ext2_fs.h>
   6#include <linux/romfs_fs.h>
   7#include <linux/cramfs_fs.h>
   8#include <linux/initrd.h>
   9#include <linux/string.h>
  10
  11#include "do_mounts.h"
  12
  13#define BUILD_CRAMDISK
  14
  15int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
  16
  17static int __init prompt_ramdisk(char *str)
  18{
  19        rd_prompt = simple_strtol(str,NULL,0) & 1;
  20        return 1;
  21}
  22__setup("prompt_ramdisk=", prompt_ramdisk);
  23
  24int __initdata rd_image_start;          /* starting block # of image */
  25
  26static int __init ramdisk_start_setup(char *str)
  27{
  28        rd_image_start = simple_strtol(str,NULL,0);
  29        return 1;
  30}
  31__setup("ramdisk_start=", ramdisk_start_setup);
  32
  33static int __init crd_load(int in_fd, int out_fd);
  34
  35/*
  36 * This routine tries to find a RAM disk image to load, and returns the
  37 * number of blocks to read for a non-compressed image, 0 if the image
  38 * is a compressed image, and -1 if an image with the right magic
  39 * numbers could not be found.
  40 *
  41 * We currently check for the following magic numbers:
  42 *      minix
  43 *      ext2
  44 *      romfs
  45 *      cramfs
  46 *      gzip
  47 */
  48static int __init 
  49identify_ramdisk_image(int fd, int start_block)
  50{
  51        const int size = 512;
  52        struct minix_super_block *minixsb;
  53        struct ext2_super_block *ext2sb;
  54        struct romfs_super_block *romfsb;
  55        struct cramfs_super *cramfsb;
  56        int nblocks = -1;
  57        unsigned char *buf;
  58
  59        buf = kmalloc(size, GFP_KERNEL);
  60        if (!buf)
  61                return -1;
  62
  63        minixsb = (struct minix_super_block *) buf;
  64        ext2sb = (struct ext2_super_block *) buf;
  65        romfsb = (struct romfs_super_block *) buf;
  66        cramfsb = (struct cramfs_super *) buf;
  67        memset(buf, 0xe5, size);
  68
  69        /*
  70         * Read block 0 to test for gzipped kernel
  71         */
  72        sys_lseek(fd, start_block * BLOCK_SIZE, 0);
  73        sys_read(fd, buf, size);
  74
  75        /*
  76         * If it matches the gzip magic numbers, return -1
  77         */
  78        if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
  79                printk(KERN_NOTICE
  80                       "RAMDISK: Compressed image found at block %d\n",
  81                       start_block);
  82                nblocks = 0;
  83                goto done;
  84        }
  85
  86        /* romfs is at block zero too */
  87        if (romfsb->word0 == ROMSB_WORD0 &&
  88            romfsb->word1 == ROMSB_WORD1) {
  89                printk(KERN_NOTICE
  90                       "RAMDISK: romfs filesystem found at block %d\n",
  91                       start_block);
  92                nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  93                goto done;
  94        }
  95
  96        if (cramfsb->magic == CRAMFS_MAGIC) {
  97                printk(KERN_NOTICE
  98                       "RAMDISK: cramfs filesystem found at block %d\n",
  99                       start_block);
 100                nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
 101                goto done;
 102        }
 103
 104        /*
 105         * Read block 1 to test for minix and ext2 superblock
 106         */
 107        sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
 108        sys_read(fd, buf, size);
 109
 110        /* Try minix */
 111        if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
 112            minixsb->s_magic == MINIX_SUPER_MAGIC2) {
 113                printk(KERN_NOTICE
 114                       "RAMDISK: Minix filesystem found at block %d\n",
 115                       start_block);
 116                nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
 117                goto done;
 118        }
 119
 120        /* Try ext2 */
 121        if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
 122                printk(KERN_NOTICE
 123                       "RAMDISK: ext2 filesystem found at block %d\n",
 124                       start_block);
 125                nblocks = le32_to_cpu(ext2sb->s_blocks_count) <<
 126                        le32_to_cpu(ext2sb->s_log_block_size);
 127                goto done;
 128        }
 129
 130        printk(KERN_NOTICE
 131               "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n",
 132               start_block);
 133        
 134done:
 135        sys_lseek(fd, start_block * BLOCK_SIZE, 0);
 136        kfree(buf);
 137        return nblocks;
 138}
 139
 140int __init rd_load_image(char *from)
 141{
 142        int res = 0;
 143        int in_fd, out_fd;
 144        unsigned long rd_blocks, devblocks;
 145        int nblocks, i, disk;
 146        char *buf = NULL;
 147        unsigned short rotate = 0;
 148#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
 149        char rotator[4] = { '|' , '/' , '-' , '\\' };
 150#endif
 151
 152        out_fd = sys_open("/dev/ram", O_RDWR, 0);
 153        if (out_fd < 0)
 154                goto out;
 155
 156        in_fd = sys_open(from, O_RDONLY, 0);
 157        if (in_fd < 0)
 158                goto noclose_input;
 159
 160        nblocks = identify_ramdisk_image(in_fd, rd_image_start);
 161        if (nblocks < 0)
 162                goto done;
 163
 164        if (nblocks == 0) {
 165#ifdef BUILD_CRAMDISK
 166                if (crd_load(in_fd, out_fd) == 0)
 167                        goto successful_load;
 168#else
 169                printk(KERN_NOTICE
 170                       "RAMDISK: Kernel does not support compressed "
 171                       "RAM disk images\n");
 172#endif
 173                goto done;
 174        }
 175
 176        /*
 177         * NOTE NOTE: nblocks is not actually blocks but
 178         * the number of kibibytes of data to load into a ramdisk.
 179         * So any ramdisk block size that is a multiple of 1KiB should
 180         * work when the appropriate ramdisk_blocksize is specified
 181         * on the command line.
 182         *
 183         * The default ramdisk_blocksize is 1KiB and it is generally
 184         * silly to use anything else, so make sure to use 1KiB
 185         * blocksize while generating ext2fs ramdisk-images.
 186         */
 187        if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
 188                rd_blocks = 0;
 189        else
 190                rd_blocks >>= 1;
 191
 192        if (nblocks > rd_blocks) {
 193                printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
 194                       nblocks, rd_blocks);
 195                goto done;
 196        }
 197                
 198        /*
 199         * OK, time to copy in the data
 200         */
 201        if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0)
 202                devblocks = 0;
 203        else
 204                devblocks >>= 1;
 205
 206        if (strcmp(from, "/initrd.image") == 0)
 207                devblocks = nblocks;
 208
 209        if (devblocks == 0) {
 210                printk(KERN_ERR "RAMDISK: could not determine device size\n");
 211                goto done;
 212        }
 213
 214        buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
 215        if (buf == 0) {
 216                printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
 217                goto done;
 218        }
 219
 220        printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
 221                nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
 222        for (i = 0, disk = 1; i < nblocks; i++) {
 223                if (i && (i % devblocks == 0)) {
 224                        printk("done disk #%d.\n", disk++);
 225                        rotate = 0;
 226                        if (sys_close(in_fd)) {
 227                                printk("Error closing the disk.\n");
 228                                goto noclose_input;
 229                        }
 230                        change_floppy("disk #%d", disk);
 231                        in_fd = sys_open(from, O_RDONLY, 0);
 232                        if (in_fd < 0)  {
 233                                printk("Error opening disk.\n");
 234                                goto noclose_input;
 235                        }
 236                        printk("Loading disk #%d... ", disk);
 237                }
 238                sys_read(in_fd, buf, BLOCK_SIZE);
 239                sys_write(out_fd, buf, BLOCK_SIZE);
 240#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
 241                if (!(i % 16)) {
 242                        printk("%c\b", rotator[rotate & 0x3]);
 243                        rotate++;
 244                }
 245#endif
 246        }
 247        printk("done.\n");
 248
 249successful_load:
 250        res = 1;
 251done:
 252        sys_close(in_fd);
 253noclose_input:
 254        sys_close(out_fd);
 255out:
 256        kfree(buf);
 257        sys_unlink("/dev/ram");
 258        return res;
 259}
 260
 261int __init rd_load_disk(int n)
 262{
 263        if (rd_prompt)
 264                change_floppy("root floppy disk to be loaded into RAM disk");
 265        create_dev("/dev/root", ROOT_DEV);
 266        create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
 267        return rd_load_image("/dev/root");
 268}
 269
 270#ifdef BUILD_CRAMDISK
 271
 272/*
 273 * gzip declarations
 274 */
 275
 276#define OF(args)  args
 277
 278#ifndef memzero
 279#define memzero(s, n)     memset ((s), 0, (n))
 280#endif
 281
 282typedef unsigned char  uch;
 283typedef unsigned short ush;
 284typedef unsigned long  ulg;
 285
 286#define INBUFSIZ 4096
 287#define WSIZE 0x8000    /* window size--must be a power of two, and */
 288                        /*  at least 32K for zip's deflate method */
 289
 290static uch *inbuf;
 291static uch *window;
 292
 293static unsigned insize;  /* valid bytes in inbuf */
 294static unsigned inptr;   /* index of next byte to be processed in inbuf */
 295static unsigned outcnt;  /* bytes in output buffer */
 296static int exit_code;
 297static int unzip_error;
 298static long bytes_out;
 299static int crd_infd, crd_outfd;
 300
 301#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
 302                
 303/* Diagnostic functions (stubbed out) */
 304#define Assert(cond,msg)
 305#define Trace(x)
 306#define Tracev(x)
 307#define Tracevv(x)
 308#define Tracec(c,x)
 309#define Tracecv(c,x)
 310
 311#define STATIC static
 312#define INIT __init
 313
 314static int  __init fill_inbuf(void);
 315static void __init flush_window(void);
 316static void __init *malloc(size_t size);
 317static void __init free(void *where);
 318static void __init error(char *m);
 319static void __init gzip_mark(void **);
 320static void __init gzip_release(void **);
 321
 322#include "../lib/inflate.c"
 323
 324static void __init *malloc(size_t size)
 325{
 326        return kmalloc(size, GFP_KERNEL);
 327}
 328
 329static void __init free(void *where)
 330{
 331        kfree(where);
 332}
 333
 334static void __init gzip_mark(void **ptr)
 335{
 336}
 337
 338static void __init gzip_release(void **ptr)
 339{
 340}
 341
 342
 343/* ===========================================================================
 344 * Fill the input buffer. This is called only when the buffer is empty
 345 * and at least one byte is really needed.
 346 * Returning -1 does not guarantee that gunzip() will ever return.
 347 */
 348static int __init fill_inbuf(void)
 349{
 350        if (exit_code) return -1;
 351        
 352        insize = sys_read(crd_infd, inbuf, INBUFSIZ);
 353        if (insize == 0) {
 354                error("RAMDISK: ran out of compressed data");
 355                return -1;
 356        }
 357
 358        inptr = 1;
 359
 360        return inbuf[0];
 361}
 362
 363/* ===========================================================================
 364 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 365 * (Used for the decompressed data only.)
 366 */
 367static void __init flush_window(void)
 368{
 369    ulg c = crc;         /* temporary variable */
 370    unsigned n, written;
 371    uch *in, ch;
 372    
 373    written = sys_write(crd_outfd, window, outcnt);
 374    if (written != outcnt && unzip_error == 0) {
 375        printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n",
 376               written, outcnt, bytes_out);
 377        unzip_error = 1;
 378    }
 379    in = window;
 380    for (n = 0; n < outcnt; n++) {
 381            ch = *in++;
 382            c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 383    }
 384    crc = c;
 385    bytes_out += (ulg)outcnt;
 386    outcnt = 0;
 387}
 388
 389static void __init error(char *x)
 390{
 391        printk(KERN_ERR "%s\n", x);
 392        exit_code = 1;
 393        unzip_error = 1;
 394}
 395
 396static int __init crd_load(int in_fd, int out_fd)
 397{
 398        int result;
 399
 400        insize = 0;             /* valid bytes in inbuf */
 401        inptr = 0;              /* index of next byte to be processed in inbuf */
 402        outcnt = 0;             /* bytes in output buffer */
 403        exit_code = 0;
 404        bytes_out = 0;
 405        crc = (ulg)0xffffffffL; /* shift register contents */
 406
 407        crd_infd = in_fd;
 408        crd_outfd = out_fd;
 409        inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
 410        if (!inbuf) {
 411                printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
 412                return -1;
 413        }
 414        window = kmalloc(WSIZE, GFP_KERNEL);
 415        if (!window) {
 416                printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
 417                kfree(inbuf);
 418                return -1;
 419        }
 420        makecrc();
 421        result = gunzip();
 422        if (unzip_error)
 423                result = 1;
 424        kfree(inbuf);
 425        kfree(window);
 426        return result;
 427}
 428
 429#endif  /* BUILD_CRAMDISK */
 430