root/drivers/block/ramdisk.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_rd_request
  2. rd_init
  3. do_load
  4. rd_load

   1 /*
   2  *  linux/kernel/blk_drv/ramdisk.c
   3  *
   4  *  Written by Theodore Ts'o, 12/2/91
   5  *
   6  * Modifications by Fred N. van Kempen to allow for bootable root
   7  * disks (which are used in LINUX/Pro).  Also some cleanups.  03/03/93
   8  */
   9 
  10 
  11 #include <linux/sched.h>
  12 #include <linux/minix_fs.h>
  13 #include <linux/ext2_fs.h>
  14 #include <linux/fs.h>
  15 #include <linux/kernel.h>
  16 #include <linux/string.h>
  17 #include <linux/mm.h>
  18 
  19 #include <asm/system.h>
  20 #include <asm/segment.h>
  21 
  22 #define MAJOR_NR  MEM_MAJOR
  23 #include "blk.h"
  24 
  25 #define RAMDISK_MINOR   1
  26 
  27 extern void wait_for_keypress(void);
  28 
  29 char    *rd_start;
  30 int     rd_length = 0;
  31 static int rd_blocksizes[2] = {0, 0};
  32 
  33 static void do_rd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35         int     len;
  36         char    *addr;
  37 
  38 repeat:
  39         INIT_REQUEST;
  40         addr = rd_start + (CURRENT->sector << 9);
  41         len = CURRENT->current_nr_sectors << 9;
  42 
  43         if ((MINOR(CURRENT->dev) != RAMDISK_MINOR) ||
  44             (addr+len > rd_start+rd_length)) {
  45                 end_request(0);
  46                 goto repeat;
  47         }
  48         if (CURRENT-> cmd == WRITE) {
  49                 (void ) memcpy(addr,
  50                               CURRENT->buffer,
  51                               len);
  52         } else if (CURRENT->cmd == READ) {
  53                 (void) memcpy(CURRENT->buffer, 
  54                               addr,
  55                               len);
  56         } else
  57                 panic("RAMDISK: unknown RAM disk command !\n");
  58         end_request(1);
  59         goto repeat;
  60 }
  61 
  62 static struct file_operations rd_fops = {
  63         NULL,                   /* lseek - default */
  64         block_read,             /* read - general block-dev read */
  65         block_write,            /* write - general block-dev write */
  66         NULL,                   /* readdir - bad */
  67         NULL,                   /* select */
  68         NULL,                   /* ioctl */
  69         NULL,                   /* mmap */
  70         NULL,                   /* no special open code */
  71         NULL,                   /* no special release code */
  72         block_fsync             /* fsync */
  73 };
  74 
  75 /*
  76  * Returns amount of memory which needs to be reserved.
  77  */
  78 long rd_init(long mem_start, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         int     i;
  81         char    *cp;
  82 
  83         if (register_blkdev(MEM_MAJOR,"rd",&rd_fops)) {
  84                 printk("RAMDISK: Unable to get major %d.\n", MEM_MAJOR);
  85                 return 0;
  86         }
  87         blk_dev[MEM_MAJOR].request_fn = DEVICE_REQUEST;
  88         rd_start = (char *) mem_start;
  89         rd_length = length;
  90         cp = rd_start;
  91         for (i=0; i < length; i++)
  92                 *cp++ = '\0';
  93 
  94         for(i=0;i<2;i++) rd_blocksizes[i] = 1024;
  95         blksize_size[MAJOR_NR] = rd_blocksizes;
  96 
  97         return(length);
  98 }
  99 
 100 static void do_load(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         struct buffer_head *bh;
 103         struct super_block {
 104           union
 105           {
 106             char minix [sizeof (struct minix_super_block)];
 107             char ext2 [sizeof (struct ext2_super_block)];
 108           } record;
 109         } sb;
 110         struct minix_super_block *minixsb =
 111                 (struct minix_super_block *)&sb;
 112         struct ext2_super_block *ext2sb =
 113                 (struct ext2_super_block *)&sb;
 114         int             block, tries;
 115         int             i = 1;
 116         int             nblocks;
 117         char            *cp;
 118         
 119         /*
 120          * Check for a super block on the diskette.
 121          * The old-style boot/root diskettes had their RAM image
 122          * starting at block 512 of the boot diskette.  LINUX/Pro
 123          * uses the entire diskette as a file system, so in that
 124          * case, we have to look at block 0.  Be intelligent about
 125          * this, and check both... - FvK
 126          */
 127         for (tries = 0; tries < 1000; tries += 512) {
 128                 block = tries;
 129                 bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0,  PAGE_SIZE);
 130                 if (!bh) {
 131                         printk("RAMDISK: I/O error while looking for super block!\n");
 132                         return;
 133                 }
 134 
 135                 /* This is silly- why do we require it to be a MINIX FS? */
 136                 *((struct super_block *) &sb) =
 137                         *((struct super_block *) bh->b_data);
 138                 brelse(bh);
 139 
 140 
 141                 /* Try Minix */
 142                 nblocks = -1;
 143                 if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
 144                     minixsb->s_magic == MINIX_SUPER_MAGIC2) {
 145                         printk("RAMDISK: Minix filesystem found at block %d\n",
 146                                 block);
 147                         nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
 148                 }
 149 
 150                 /* Try ext2 */
 151                 if (nblocks == -1 && (ext2sb->s_magic ==
 152                         EXT2_PRE_02B_MAGIC ||
 153                         ext2sb->s_magic == EXT2_SUPER_MAGIC))
 154                 {
 155                         printk("RAMDISK: Ext2 filesystem found at block %d\n",
 156                                 block);
 157                         nblocks = ext2sb->s_blocks_count;
 158                 }
 159 
 160                 if (nblocks == -1)
 161                 {
 162                         printk("RAMDISK: trying old-style RAM image.\n");
 163                         continue;
 164                 }
 165 
 166                 if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
 167                         printk("RAMDISK: image too big! (%d/%d blocks)\n",
 168                                         nblocks, rd_length >> BLOCK_SIZE_BITS);
 169                         return;
 170                 }
 171                 printk("RAMDISK: Loading %d blocks into RAM disk", nblocks);
 172 
 173                 /* We found an image file system.  Load it into core! */
 174                 cp = rd_start;
 175                 while (nblocks) {
 176                         if (nblocks > 2) 
 177                                 bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0,  PAGE_SIZE);
 178                         else
 179                                 bh = bread(ROOT_DEV, block, BLOCK_SIZE);
 180                         if (!bh) {
 181                                 printk("RAMDISK: I/O error on block %d, aborting!\n", 
 182                                 block);
 183                                 return;
 184                         }
 185                         (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
 186                         brelse(bh);
 187                         if (!(nblocks-- & 15)) printk(".");
 188                         cp += BLOCK_SIZE;
 189                         block++;
 190                         i++;
 191                 }
 192                 printk("\ndone\n");
 193 
 194                 /* We loaded the file system image.  Prepare for mounting it. */
 195                 ROOT_DEV = ((MEM_MAJOR << 8) | RAMDISK_MINOR);
 196                 return;
 197         }
 198 }
 199 
 200 /*
 201  * If the root device is the RAM disk, try to load it.
 202  * In order to do this, the root device is originally set to the
 203  * floppy, and we later change it to be RAM disk.
 204  */
 205 void rd_load(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207         struct inode inode;
 208         struct file filp;
 209 
 210         /* If no RAM disk specified, give up early. */
 211         if (!rd_length)
 212                 return;
 213         printk("RAMDISK: %d bytes, starting at 0x%p\n",
 214                         rd_length, rd_start);
 215 
 216         /* If we are doing a diskette boot, we might have to pre-load it. */
 217         if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR)
 218                 return;
 219 
 220         /* for Slackware install disks */
 221         printk(KERN_NOTICE "VFS: Insert ramdisk floppy and press ENTER\n");
 222         wait_for_keypress();
 223 
 224         memset(&filp, 0, sizeof(filp));
 225         memset(&inode, 0, sizeof(inode));
 226         inode.i_rdev = ROOT_DEV;
 227         filp.f_mode = 1; /* read only */
 228         filp.f_inode = &inode;
 229         if(blkdev_open(&inode, &filp) == 0 ){
 230                 do_load();
 231                 if(filp.f_op && filp.f_op->release)
 232                         filp.f_op->release(&inode,&filp);
 233         }
 234 }

/* [previous][next][first][last][top][bottom][index][help] */