Blame view

init/do_mounts_rd.c 8.42 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  
  #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>
5a0e3ad6a   Tejun Heo   include cleanup: ...
10
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
  
  #include "do_mounts.h"
b8fed87d3   Phillip Lougher   Squashfs: initrd ...
13
  #include "../fs/squashfs/squashfs_fs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14

30d65dbfe   Alain Knaff   bzip2/lzma: confi...
15
  #include <linux/decompress/generic.h>
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
16

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  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);
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
34
  static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
42
  
  /*
   * 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:
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
43
44
   *	minix
   *	ext2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
   *	romfs
   *	cramfs
b8fed87d3   Phillip Lougher   Squashfs: initrd ...
47
   *	squashfs
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
48
   *	gzip
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
   */
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
50
  static int __init
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
51
  identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
  {
  	const int size = 512;
  	struct minix_super_block *minixsb;
  	struct ext2_super_block *ext2sb;
  	struct romfs_super_block *romfsb;
  	struct cramfs_super *cramfsb;
b8fed87d3   Phillip Lougher   Squashfs: initrd ...
58
  	struct squashfs_super_block *squashfsb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
  	int nblocks = -1;
  	unsigned char *buf;
889c92d21   H. Peter Anvin   bzip2/lzma: centr...
61
  	const char *compress_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  
  	buf = kmalloc(size, GFP_KERNEL);
c80544dc0   Stephen Hemminger   sparse pointer us...
64
  	if (!buf)
ea611b269   Davidlohr Bueso   init: return prop...
65
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
  
  	minixsb = (struct minix_super_block *) buf;
  	ext2sb = (struct ext2_super_block *) buf;
  	romfsb = (struct romfs_super_block *) buf;
  	cramfsb = (struct cramfs_super *) buf;
b8fed87d3   Phillip Lougher   Squashfs: initrd ...
71
  	squashfsb = (struct squashfs_super_block *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
  	memset(buf, 0xe5, size);
  
  	/*
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
75
  	 * Read block 0 to test for compressed kernel
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
  	 */
  	sys_lseek(fd, start_block * BLOCK_SIZE, 0);
  	sys_read(fd, buf, size);
889c92d21   H. Peter Anvin   bzip2/lzma: centr...
79
  	*decompressor = decompress_method(buf, size, &compress_name);
23a22d57a   H. Peter Anvin   bzip2/lzma: compr...
80
  	if (compress_name) {
889c92d21   H. Peter Anvin   bzip2/lzma: centr...
81
82
83
  		printk(KERN_NOTICE "RAMDISK: %s image found at block %d
  ",
  		       compress_name, start_block);
23a22d57a   H. Peter Anvin   bzip2/lzma: compr...
84
  		if (!*decompressor)
73310a169   H. Peter Anvin   init: make initrd...
85
86
87
  			printk(KERN_EMERG
  			       "RAMDISK: %s decompressor not configured!
  ",
23a22d57a   H. Peter Anvin   bzip2/lzma: compr...
88
  			       compress_name);
889c92d21   H. Peter Anvin   bzip2/lzma: centr...
89
90
  		nblocks = 0;
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  	}
  
  	/* 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;
  	}
b8fed87d3   Phillip Lougher   Squashfs: initrd ...
112
113
114
115
116
117
118
119
120
121
  	/* squashfs is at block zero too */
  	if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) {
  		printk(KERN_NOTICE
  		       "RAMDISK: squashfs filesystem found at block %d
  ",
  		       start_block);
  		nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1)
  			 >> BLOCK_SIZE_BITS;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  	/*
f919b9235   Neil Armstrong   init/do_mounts_rd...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  	 * Read 512 bytes further to check if cramfs is padded
  	 */
  	sys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0);
  	sys_read(fd, buf, size);
  
  	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;
  	}
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  	 * 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);
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
169

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  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;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
184
  	decompress_fn decompressor = NULL;
347a8dc3b   Martin Schwidefsky   [PATCH] s390: cle...
185
  #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
  	char rotator[4] = { '|' , '/' , '-' , '\\' };
  #endif
562f5e638   Namhyung Kim   init: mark __user...
188
  	out_fd = sys_open((const char __user __force *) "/dev/ram", O_RDWR, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
  	if (out_fd < 0)
  		goto out;
  
  	in_fd = sys_open(from, O_RDONLY, 0);
  	if (in_fd < 0)
  		goto noclose_input;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
195
  	nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
  	if (nblocks < 0)
  		goto done;
  
  	if (nblocks == 0) {
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
200
  		if (crd_load(in_fd, out_fd, decompressor) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  			goto successful_load;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  		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;
  	}
b172fd882   H. Peter Anvin   bzip2/lzma: use a...
227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  	/*
  	 * 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...
246
  	if (!buf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  		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...
275
  #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  		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);
562f5e638   Namhyung Kim   init: mark __user...
293
  	sys_unlink((const char __user __force *) "/dev/ram");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
297
298
299
300
  	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...
301
302
  	create_dev("/dev/root", ROOT_DEV);
  	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
  	return rd_load_image("/dev/root");
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  static int exit_code;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
306
  static int decompress_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  static int crd_infd, crd_outfd;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
308
  static int __init compr_fill(void *buf, unsigned int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  {
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
310
311
312
313
314
315
  	int r = sys_read(crd_infd, buf, len);
  	if (r < 0)
  		printk(KERN_ERR "RAMDISK: error while reading compressed data");
  	else if (r == 0)
  		printk(KERN_ERR "RAMDISK: EOF while reading compressed data");
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  }
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
317
  static int __init compr_flush(void *window, unsigned int outcnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  {
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
319
320
321
322
323
324
325
326
327
328
329
  	int written = sys_write(crd_outfd, window, outcnt);
  	if (written != outcnt) {
  		if (decompress_error == 0)
  			printk(KERN_ERR
  			       "RAMDISK: incomplete write (%d != %d)
  ",
  			       written, outcnt);
  		decompress_error = 1;
  		return -1;
  	}
  	return outcnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
334
335
336
  }
  
  static void __init error(char *x)
  {
  	printk(KERN_ERR "%s
  ", x);
  	exit_code = 1;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
337
  	decompress_error = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  }
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
339
  static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
  {
  	int result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  	crd_infd = in_fd;
  	crd_outfd = out_fd;
30d65dbfe   Alain Knaff   bzip2/lzma: confi...
344
345
  	result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);
  	if (decompress_error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		result = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
  	return result;
  }