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/config.h>
12 #include <linux/sched.h>
13 #include <linux/minix_fs.h>
14 #include <linux/fs.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <asm/system.h>
18 #include <asm/segment.h>
19
20 #define MAJOR_NR MEM_MAJOR
21 #include "blk.h"
22
23 #define RAMDISK_MINOR 1
24
25
26 char *rd_start;
27 int rd_length = 0;
28 static int rd_blocksizes[2] = {0, 0};
29
30 static void do_rd_request(void)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
31 {
32 int len;
33 char *addr;
34
35 repeat:
36 INIT_REQUEST;
37 addr = rd_start + (CURRENT->sector << 9);
38 len = CURRENT->current_nr_sectors << 9;
39
40 if ((MINOR(CURRENT->dev) != RAMDISK_MINOR) ||
41 (addr+len > rd_start+rd_length)) {
42 end_request(0);
43 goto repeat;
44 }
45 if (CURRENT-> cmd == WRITE) {
46 (void ) memcpy(addr,
47 CURRENT->buffer,
48 len);
49 } else if (CURRENT->cmd == READ) {
50 (void) memcpy(CURRENT->buffer,
51 addr,
52 len);
53 } else
54 panic("RAMDISK: unknown RAM disk command !\n");
55 end_request(1);
56 goto repeat;
57 }
58
59 static struct file_operations rd_fops = {
60 NULL, /* lseek - default */
61 block_read, /* read - general block-dev read */
62 block_write, /* write - general block-dev write */
63 NULL, /* readdir - bad */
64 NULL, /* select */
65 NULL, /* ioctl */
66 NULL, /* mmap */
67 NULL, /* no special open code */
68 NULL, /* no special release code */
69 block_fsync /* fsync */
70 };
71
72 /*
73 * Returns amount of memory which needs to be reserved.
74 */
75 long rd_init(long mem_start, int length)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
76 {
77 int i;
78 char *cp;
79
80 if (register_blkdev(MEM_MAJOR,"rd",&rd_fops)) {
81 printk("RAMDISK: Unable to get major %d.\n", MEM_MAJOR);
82 return 0;
83 }
84 blk_dev[MEM_MAJOR].request_fn = DEVICE_REQUEST;
85 rd_start = (char *) mem_start;
86 rd_length = length;
87 cp = rd_start;
88 for (i=0; i < length; i++)
89 *cp++ = '\0';
90
91 for(i=0;i<2;i++) rd_blocksizes[i] = 1024;
92 blksize_size[MAJOR_NR] = rd_blocksizes;
93
94 return(length);
95 }
96
97 /*
98 * If the root device is the RAM disk, try to load it.
99 * In order to do this, the root device is originally set to the
100 * floppy, and we later change it to be RAM disk.
101 */
102 void rd_load(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
103 {
104 struct buffer_head *bh;
105 struct minix_super_block s;
106 int block, tries;
107 int i = 1;
108 int nblocks;
109 char *cp;
110
111 /* If no RAM disk specified, give up early. */
112 if (!rd_length) return;
113 printk("RAMDISK: %d bytes, starting at 0x%x\n",
114 rd_length, (int) rd_start);
115
116 /* If we are doing a diskette boot, we might have to pre-load it. */
117 if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return;
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 enire 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,block+2,-1);
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 minix_super_block *) &s) =
137 *((struct minix_super_block *) bh->b_data);
138 brelse(bh);
139 nblocks = s.s_nzones << s.s_log_zone_size;
140 if (s.s_magic != MINIX_SUPER_MAGIC &&
141 s.s_magic != MINIX_SUPER_MAGIC2) {
142 printk("RAMDISK: trying old-style RAM image.\n");
143 continue;
144 }
145
146 if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
147 printk("RAMDISK: image too big! (%d/%d blocks)\n",
148 nblocks, rd_length >> BLOCK_SIZE_BITS);
149 return;
150 }
151 printk("RAMDISK: Loading %d blocks into RAM disk", nblocks);
152
153 /* We found an image file system. Load it into core! */
154 cp = rd_start;
155 while (nblocks) {
156 if (nblocks > 2)
157 bh = breada(ROOT_DEV, block, block+1, block+2, -1);
158 else
159 bh = bread(ROOT_DEV, block, BLOCK_SIZE);
160 if (!bh) {
161 printk("RAMDISK: I/O error on block %d, aborting!\n",
162 block);
163 return;
164 }
165 (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
166 brelse(bh);
167 if (!(nblocks-- & 15)) printk(".");
168 cp += BLOCK_SIZE;
169 block++;
170 i++;
171 }
172 printk("\ndone\n");
173
174 /* We loaded the file system image. Prepare for mounting it. */
175 ROOT_DEV = ((MEM_MAJOR << 8) | RAMDISK_MINOR);
176 return;
177 }
178 }