diff options
Diffstat (limited to 'init/do_mounts_rd.c')
-rw-r--r-- | init/do_mounts_rd.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c new file mode 100644 index 000000000000..c10b08a80982 --- /dev/null +++ b/init/do_mounts_rd.c | |||
@@ -0,0 +1,429 @@ | |||
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 | |||
15 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ | ||
16 | |||
17 | static 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 | |||
24 | int __initdata rd_image_start; /* starting block # of image */ | ||
25 | |||
26 | static 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 | |||
33 | static 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 | */ | ||
48 | static int __init | ||
49 | identify_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 == 0) | ||
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 | |||
134 | done: | ||
135 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); | ||
136 | kfree(buf); | ||
137 | return nblocks; | ||
138 | } | ||
139 | |||
140 | int __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_ARCH_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_ARCH_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 | |||
249 | successful_load: | ||
250 | res = 1; | ||
251 | done: | ||
252 | sys_close(in_fd); | ||
253 | noclose_input: | ||
254 | sys_close(out_fd); | ||
255 | out: | ||
256 | kfree(buf); | ||
257 | sys_unlink("/dev/ram"); | ||
258 | return res; | ||
259 | } | ||
260 | |||
261 | int __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, root_device_name); | ||
266 | create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); | ||
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 | |||
282 | typedef unsigned char uch; | ||
283 | typedef unsigned short ush; | ||
284 | typedef 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 | |||
290 | static uch *inbuf; | ||
291 | static uch *window; | ||
292 | |||
293 | static unsigned insize; /* valid bytes in inbuf */ | ||
294 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
295 | static unsigned outcnt; /* bytes in output buffer */ | ||
296 | static int exit_code; | ||
297 | static int unzip_error; | ||
298 | static long bytes_out; | ||
299 | static 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 | |||
314 | static int __init fill_inbuf(void); | ||
315 | static void __init flush_window(void); | ||
316 | static void __init *malloc(size_t size); | ||
317 | static void __init free(void *where); | ||
318 | static void __init error(char *m); | ||
319 | static void __init gzip_mark(void **); | ||
320 | static void __init gzip_release(void **); | ||
321 | |||
322 | #include "../lib/inflate.c" | ||
323 | |||
324 | static void __init *malloc(size_t size) | ||
325 | { | ||
326 | return kmalloc(size, GFP_KERNEL); | ||
327 | } | ||
328 | |||
329 | static void __init free(void *where) | ||
330 | { | ||
331 | kfree(where); | ||
332 | } | ||
333 | |||
334 | static void __init gzip_mark(void **ptr) | ||
335 | { | ||
336 | } | ||
337 | |||
338 | static 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 | */ | ||
348 | static 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 | */ | ||
367 | static 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 | |||
389 | static void __init error(char *x) | ||
390 | { | ||
391 | printk(KERN_ERR "%s\n", x); | ||
392 | exit_code = 1; | ||
393 | unzip_error = 1; | ||
394 | } | ||
395 | |||
396 | static 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 == 0) { | ||
411 | printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); | ||
412 | return -1; | ||
413 | } | ||
414 | window = kmalloc(WSIZE, GFP_KERNEL); | ||
415 | if (window == 0) { | ||
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 */ | ||