Blame view

init/do_mounts_rd.c 9.39 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  
  #include <linux/kernel.h>
  #include <linux/fs.h>
  #include <linux/minix_fs.h>
  #include <linux/ext2_fs.h>
  #include <linux/romfs_fs.h>
  #include <linux/cramfs_fs.h>
  #include <linux/initrd.h>
  #include <linux/string.h>
  
  #include "do_mounts.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
  
  static int __init prompt_ramdisk(char *str)
  {
  	rd_prompt = simple_strtol(str,NULL,0) & 1;
  	return 1;
  }
  __setup("prompt_ramdisk=", prompt_ramdisk);
  
  int __initdata rd_image_start;		/* starting block # of image */
  
  static int __init ramdisk_start_setup(char *str)
  {
  	rd_image_start = simple_strtol(str,NULL,0);
  	return 1;
  }
  __setup("ramdisk_start=", ramdisk_start_setup);
  
  static int __init crd_load(int in_fd, int out_fd);
  
  /*
   * This routine tries to find a RAM disk image to load, and returns the
   * number of blocks to read for a non-compressed image, 0 if the image
   * is a compressed image, and -1 if an image with the right magic
   * numbers could not be found.
   *
   * We currently check for the following magic numbers:
   * 	minix
   * 	ext2
   *	romfs
   *	cramfs
   * 	gzip
   */
  static int __init 
  identify_ramdisk_image(int fd, int start_block)
  {
  	const int size = 512;
  	struct minix_super_block *minixsb;
  	struct ext2_super_block *ext2sb;
  	struct romfs_super_block *romfsb;
  	struct cramfs_super *cramfsb;
  	int nblocks = -1;
  	unsigned char *buf;
  
  	buf = kmalloc(size, GFP_KERNEL);
c80544dc0   Stephen Hemminger   sparse pointer us...
57
  	if (!buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  		return -1;
  
  	minixsb = (struct minix_super_block *) buf;
  	ext2sb = (struct ext2_super_block *) buf;
  	romfsb = (struct romfs_super_block *) buf;
  	cramfsb = (struct cramfs_super *) buf;
  	memset(buf, 0xe5, size);
  
  	/*
  	 * Read block 0 to test for gzipped kernel
  	 */
  	sys_lseek(fd, start_block * BLOCK_SIZE, 0);
  	sys_read(fd, buf, size);
  
  	/*
93fd85d00   Geert Uytterhoeven   identify_ramdisk_...
73
  	 * If it matches the gzip magic numbers, return 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	 */
  	if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
  		printk(KERN_NOTICE
  		       "RAMDISK: Compressed image found at block %d
  ",
  		       start_block);
  		nblocks = 0;
  		goto done;
  	}
  
  	/* romfs is at block zero too */
  	if (romfsb->word0 == ROMSB_WORD0 &&
  	    romfsb->word1 == ROMSB_WORD1) {
  		printk(KERN_NOTICE
  		       "RAMDISK: romfs filesystem found at block %d
  ",
  		       start_block);
  		nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  		goto done;
  	}
  
  	if (cramfsb->magic == CRAMFS_MAGIC) {
  		printk(KERN_NOTICE
  		       "RAMDISK: cramfs filesystem found at block %d
  ",
  		       start_block);
  		nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  		goto done;
  	}
  
  	/*
  	 * Read block 1 to test for minix and ext2 superblock
  	 */
  	sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
  	sys_read(fd, buf, size);
  
  	/* Try minix */
  	if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
  	    minixsb->s_magic == MINIX_SUPER_MAGIC2) {
  		printk(KERN_NOTICE
  		       "RAMDISK: Minix filesystem found at block %d
  ",
  		       start_block);
  		nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
  		goto done;
  	}
  
  	/* Try ext2 */
  	if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
  		printk(KERN_NOTICE
  		       "RAMDISK: ext2 filesystem found at block %d
  ",
  		       start_block);
  		nblocks = le32_to_cpu(ext2sb->s_blocks_count) <<
  			le32_to_cpu(ext2sb->s_log_block_size);
  		goto done;
  	}
  
  	printk(KERN_NOTICE
  	       "RAMDISK: Couldn't find valid RAM disk image starting at %d.
  ",
  	       start_block);
  	
  done:
  	sys_lseek(fd, start_block * BLOCK_SIZE, 0);
  	kfree(buf);
  	return nblocks;
  }
  
  int __init rd_load_image(char *from)
  {
  	int res = 0;
  	int in_fd, out_fd;
  	unsigned long rd_blocks, devblocks;
  	int nblocks, i, disk;
  	char *buf = NULL;
  	unsigned short rotate = 0;
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
151
  #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  	char rotator[4] = { '|' , '/' , '-' , '\\' };
  #endif
  
  	out_fd = sys_open("/dev/ram", O_RDWR, 0);
  	if (out_fd < 0)
  		goto out;
  
  	in_fd = sys_open(from, O_RDONLY, 0);
  	if (in_fd < 0)
  		goto noclose_input;
  
  	nblocks = identify_ramdisk_image(in_fd, rd_image_start);
  	if (nblocks < 0)
  		goto done;
  
  	if (nblocks == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  		if (crd_load(in_fd, out_fd) == 0)
  			goto successful_load;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  		goto done;
  	}
  
  	/*
  	 * NOTE NOTE: nblocks is not actually blocks but
  	 * the number of kibibytes of data to load into a ramdisk.
  	 * So any ramdisk block size that is a multiple of 1KiB should
  	 * work when the appropriate ramdisk_blocksize is specified
  	 * on the command line.
  	 *
  	 * The default ramdisk_blocksize is 1KiB and it is generally
  	 * silly to use anything else, so make sure to use 1KiB
  	 * blocksize while generating ext2fs ramdisk-images.
  	 */
  	if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
  		rd_blocks = 0;
  	else
  		rd_blocks >>= 1;
  
  	if (nblocks > rd_blocks) {
  		printk("RAMDISK: image too big! (%dKiB/%ldKiB)
  ",
  		       nblocks, rd_blocks);
  		goto done;
  	}
  		
  	/*
  	 * OK, time to copy in the data
  	 */
  	if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0)
  		devblocks = 0;
  	else
  		devblocks >>= 1;
  
  	if (strcmp(from, "/initrd.image") == 0)
  		devblocks = nblocks;
  
  	if (devblocks == 0) {
  		printk(KERN_ERR "RAMDISK: could not determine device size
  ");
  		goto done;
  	}
  
  	buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
d613c3e2d   Harvey Harrison   init: fix integer...
214
  	if (!buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  		printk(KERN_ERR "RAMDISK: could not allocate buffer
  ");
  		goto done;
  	}
  
  	printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
  		nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
  	for (i = 0, disk = 1; i < nblocks; i++) {
  		if (i && (i % devblocks == 0)) {
  			printk("done disk #%d.
  ", disk++);
  			rotate = 0;
  			if (sys_close(in_fd)) {
  				printk("Error closing the disk.
  ");
  				goto noclose_input;
  			}
  			change_floppy("disk #%d", disk);
  			in_fd = sys_open(from, O_RDONLY, 0);
  			if (in_fd < 0)  {
  				printk("Error opening disk.
  ");
  				goto noclose_input;
  			}
  			printk("Loading disk #%d... ", disk);
  		}
  		sys_read(in_fd, buf, BLOCK_SIZE);
  		sys_write(out_fd, buf, BLOCK_SIZE);
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
243
  #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  		if (!(i % 16)) {
  			printk("%c\b", rotator[rotate & 0x3]);
  			rotate++;
  		}
  #endif
  	}
  	printk("done.
  ");
  
  successful_load:
  	res = 1;
  done:
  	sys_close(in_fd);
  noclose_input:
  	sys_close(out_fd);
  out:
  	kfree(buf);
  	sys_unlink("/dev/ram");
  	return res;
  }
  
  int __init rd_load_disk(int n)
  {
  	if (rd_prompt)
  		change_floppy("root floppy disk to be loaded into RAM disk");
bdaf85293   Greg Kroah-Hartman   [PATCH] devfs: Re...
269
270
  	create_dev("/dev/root", ROOT_DEV);
  	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
  	return rd_load_image("/dev/root");
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  /*
   * gzip declarations
   */
  
  #define OF(args)  args
  
  #ifndef memzero
  #define memzero(s, n)     memset ((s), 0, (n))
  #endif
  
  typedef unsigned char  uch;
  typedef unsigned short ush;
  typedef unsigned long  ulg;
  
  #define INBUFSIZ 4096
  #define WSIZE 0x8000    /* window size--must be a power of two, and */
  			/*  at least 32K for zip's deflate method */
  
  static uch *inbuf;
  static uch *window;
  
  static unsigned insize;  /* valid bytes in inbuf */
  static unsigned inptr;   /* index of next byte to be processed in inbuf */
  static unsigned outcnt;  /* bytes in output buffer */
  static int exit_code;
  static int unzip_error;
  static long bytes_out;
  static int crd_infd, crd_outfd;
  
  #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  		
  /* Diagnostic functions (stubbed out) */
  #define Assert(cond,msg)
  #define Trace(x)
  #define Tracev(x)
  #define Tracevv(x)
  #define Tracec(c,x)
  #define Tracecv(c,x)
  
  #define STATIC static
  #define INIT __init
  
  static int  __init fill_inbuf(void);
  static void __init flush_window(void);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  static void __init error(char *m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

2d6ffcca6   Thomas Petazzoni   inflate: refactor...
319
  #define NO_INFLATE_MALLOC
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

2d6ffcca6   Thomas Petazzoni   inflate: refactor...
321
  #include "../lib/inflate.c"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  
  /* ===========================================================================
   * Fill the input buffer. This is called only when the buffer is empty
   * and at least one byte is really needed.
   * Returning -1 does not guarantee that gunzip() will ever return.
   */
  static int __init fill_inbuf(void)
  {
  	if (exit_code) return -1;
  	
  	insize = sys_read(crd_infd, inbuf, INBUFSIZ);
  	if (insize == 0) {
  		error("RAMDISK: ran out of compressed data");
  		return -1;
  	}
  
  	inptr = 1;
  
  	return inbuf[0];
  }
  
  /* ===========================================================================
   * Write the output window window[0..outcnt-1] and update crc and bytes_out.
   * (Used for the decompressed data only.)
   */
  static void __init flush_window(void)
  {
      ulg c = crc;         /* temporary variable */
      unsigned n, written;
      uch *in, ch;
      
      written = sys_write(crd_outfd, window, outcnt);
      if (written != outcnt && unzip_error == 0) {
  	printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld
  ",
  	       written, outcnt, bytes_out);
  	unzip_error = 1;
      }
      in = window;
      for (n = 0; n < outcnt; n++) {
  	    ch = *in++;
  	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
      }
      crc = c;
      bytes_out += (ulg)outcnt;
      outcnt = 0;
  }
  
  static void __init error(char *x)
  {
  	printk(KERN_ERR "%s
  ", x);
  	exit_code = 1;
  	unzip_error = 1;
  }
  
  static int __init crd_load(int in_fd, int out_fd)
  {
  	int result;
  
  	insize = 0;		/* valid bytes in inbuf */
  	inptr = 0;		/* index of next byte to be processed in inbuf */
  	outcnt = 0;		/* bytes in output buffer */
  	exit_code = 0;
  	bytes_out = 0;
  	crc = (ulg)0xffffffffL; /* shift register contents */
  
  	crd_infd = in_fd;
  	crd_outfd = out_fd;
  	inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
c80544dc0   Stephen Hemminger   sparse pointer us...
392
  	if (!inbuf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
  		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer
  ");
  		return -1;
  	}
  	window = kmalloc(WSIZE, GFP_KERNEL);
c80544dc0   Stephen Hemminger   sparse pointer us...
398
  	if (!window) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
402
403
404
405
406
407
408
409
410
411
  		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window
  ");
  		kfree(inbuf);
  		return -1;
  	}
  	makecrc();
  	result = gunzip();
  	if (unzip_error)
  		result = 1;
  	kfree(inbuf);
  	kfree(window);
  	return result;
  }