OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [init/] [do_mounts.c] - Blame information for rev 83

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <linux/module.h>
2
#include <linux/sched.h>
3
#include <linux/ctype.h>
4
#include <linux/fd.h>
5
#include <linux/tty.h>
6
#include <linux/suspend.h>
7
#include <linux/root_dev.h>
8
#include <linux/security.h>
9
#include <linux/delay.h>
10
#include <linux/genhd.h>
11
#include <linux/mount.h>
12
#include <linux/device.h>
13
#include <linux/init.h>
14
 
15
#include <linux/nfs_fs.h>
16
#include <linux/nfs_fs_sb.h>
17
#include <linux/nfs_mount.h>
18
 
19
#include "do_mounts.h"
20
 
21
extern int get_filesystem_list(char * buf);
22
 
23
int __initdata rd_doload;       /* 1 = load RAM disk, 0 = don't load */
24
 
25
int root_mountflags = MS_RDONLY | MS_SILENT;
26
char * __initdata root_device_name;
27
static char __initdata saved_root_name[64];
28
static int __initdata root_wait;
29
 
30
dev_t ROOT_DEV;
31
 
32
static int __init load_ramdisk(char *str)
33
{
34
        rd_doload = simple_strtol(str,NULL,0) & 3;
35
        return 1;
36
}
37
__setup("load_ramdisk=", load_ramdisk);
38
 
39
static int __init readonly(char *str)
40
{
41
        if (*str)
42
                return 0;
43
        root_mountflags |= MS_RDONLY;
44
        return 1;
45
}
46
 
47
static int __init readwrite(char *str)
48
{
49
        if (*str)
50
                return 0;
51
        root_mountflags &= ~MS_RDONLY;
52
        return 1;
53
}
54
 
55
__setup("ro", readonly);
56
__setup("rw", readwrite);
57
 
58
static dev_t try_name(char *name, int part)
59
{
60
        char path[64];
61
        char buf[32];
62
        int range;
63
        dev_t res;
64
        char *s;
65
        int len;
66
        int fd;
67
        unsigned int maj, min;
68
 
69
        /* read device number from .../dev */
70
 
71
        sprintf(path, "/sys/block/%s/dev", name);
72
        fd = sys_open(path, 0, 0);
73
        if (fd < 0)
74
                goto fail;
75
        len = sys_read(fd, buf, 32);
76
        sys_close(fd);
77
        if (len <= 0 || len == 32 || buf[len - 1] != '\n')
78
                goto fail;
79
        buf[len - 1] = '\0';
80
        if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
81
                /*
82
                 * Try the %u:%u format -- see print_dev_t()
83
                 */
84
                res = MKDEV(maj, min);
85
                if (maj != MAJOR(res) || min != MINOR(res))
86
                        goto fail;
87
        } else {
88
                /*
89
                 * Nope.  Try old-style "0321"
90
                 */
91
                res = new_decode_dev(simple_strtoul(buf, &s, 16));
92
                if (*s)
93
                        goto fail;
94
        }
95
 
96
        /* if it's there and we are not looking for a partition - that's it */
97
        if (!part)
98
                return res;
99
 
100
        /* otherwise read range from .../range */
101
        sprintf(path, "/sys/block/%s/range", name);
102
        fd = sys_open(path, 0, 0);
103
        if (fd < 0)
104
                goto fail;
105
        len = sys_read(fd, buf, 32);
106
        sys_close(fd);
107
        if (len <= 0 || len == 32 || buf[len - 1] != '\n')
108
                goto fail;
109
        buf[len - 1] = '\0';
110
        range = simple_strtoul(buf, &s, 10);
111
        if (*s)
112
                goto fail;
113
 
114
        /* if partition is within range - we got it */
115
        if (part < range)
116
                return res + part;
117
fail:
118
        return 0;
119
}
120
 
121
/*
122
 *      Convert a name into device number.  We accept the following variants:
123
 *
124
 *      1) device number in hexadecimal represents itself
125
 *      2) /dev/nfs represents Root_NFS (0xff)
126
 *      3) /dev/<disk_name> represents the device number of disk
127
 *      4) /dev/<disk_name><decimal> represents the device number
128
 *         of partition - device number of disk plus the partition number
129
 *      5) /dev/<disk_name>p<decimal> - same as the above, that form is
130
 *         used when disk name of partitioned disk ends on a digit.
131
 *
132
 *      If name doesn't have fall into the categories above, we return 0.
133
 *      Sysfs is used to check if something is a disk name - it has
134
 *      all known disks under bus/block/devices.  If the disk name
135
 *      contains slashes, name of sysfs node has them replaced with
136
 *      bangs.  try_name() does the actual checks, assuming that sysfs
137
 *      is mounted on rootfs /sys.
138
 */
139
 
140
dev_t name_to_dev_t(char *name)
141
{
142
        char s[32];
143
        char *p;
144
        dev_t res = 0;
145
        int part;
146
 
147
#ifdef CONFIG_SYSFS
148
        int mkdir_err = sys_mkdir("/sys", 0700);
149
        if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
150
                goto out;
151
#endif
152
 
153
        if (strncmp(name, "/dev/", 5) != 0) {
154
                unsigned maj, min;
155
 
156
                if (sscanf(name, "%u:%u", &maj, &min) == 2) {
157
                        res = MKDEV(maj, min);
158
                        if (maj != MAJOR(res) || min != MINOR(res))
159
                                goto fail;
160
                } else {
161
                        res = new_decode_dev(simple_strtoul(name, &p, 16));
162
                        if (*p)
163
                                goto fail;
164
                }
165
                goto done;
166
        }
167
        name += 5;
168
        res = Root_NFS;
169
        if (strcmp(name, "nfs") == 0)
170
                goto done;
171
        res = Root_RAM0;
172
        if (strcmp(name, "ram") == 0)
173
                goto done;
174
 
175
        if (strlen(name) > 31)
176
                goto fail;
177
        strcpy(s, name);
178
        for (p = s; *p; p++)
179
                if (*p == '/')
180
                        *p = '!';
181
        res = try_name(s, 0);
182
        if (res)
183
                goto done;
184
 
185
        while (p > s && isdigit(p[-1]))
186
                p--;
187
        if (p == s || !*p || *p == '0')
188
                goto fail;
189
        part = simple_strtoul(p, NULL, 10);
190
        *p = '\0';
191
        res = try_name(s, part);
192
        if (res)
193
                goto done;
194
 
195
        if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
196
                goto fail;
197
        p[-1] = '\0';
198
        res = try_name(s, part);
199
done:
200
#ifdef CONFIG_SYSFS
201
        sys_umount("/sys", 0);
202
out:
203
        if (!mkdir_err)
204
                sys_rmdir("/sys");
205
#endif
206
        return res;
207
fail:
208
        res = 0;
209
        goto done;
210
}
211
 
212
static int __init root_dev_setup(char *line)
213
{
214
        strlcpy(saved_root_name, line, sizeof(saved_root_name));
215
        return 1;
216
}
217
 
218
__setup("root=", root_dev_setup);
219
 
220
static int __init rootwait_setup(char *str)
221
{
222
        if (*str)
223
                return 0;
224
        root_wait = 1;
225
        return 1;
226
}
227
 
228
__setup("rootwait", rootwait_setup);
229
 
230
static char * __initdata root_mount_data;
231
static int __init root_data_setup(char *str)
232
{
233
        root_mount_data = str;
234
        return 1;
235
}
236
 
237
static char * __initdata root_fs_names;
238
static int __init fs_names_setup(char *str)
239
{
240
        root_fs_names = str;
241
        return 1;
242
}
243
 
244
static unsigned int __initdata root_delay;
245
static int __init root_delay_setup(char *str)
246
{
247
        root_delay = simple_strtoul(str, NULL, 0);
248
        return 1;
249
}
250
 
251
__setup("rootflags=", root_data_setup);
252
__setup("rootfstype=", fs_names_setup);
253
__setup("rootdelay=", root_delay_setup);
254
 
255
static void __init get_fs_names(char *page)
256
{
257
        char *s = page;
258
 
259
        if (root_fs_names) {
260
                strcpy(page, root_fs_names);
261
                while (*s++) {
262
                        if (s[-1] == ',')
263
                                s[-1] = '\0';
264
                }
265
        } else {
266
                int len = get_filesystem_list(page);
267
                char *p, *next;
268
 
269
                page[len] = '\0';
270
                for (p = page-1; p; p = next) {
271
                        next = strchr(++p, '\n');
272
                        if (*p++ != '\t')
273
                                continue;
274
                        while ((*s++ = *p++) != '\n')
275
                                ;
276
                        s[-1] = '\0';
277
                }
278
        }
279
        *s = '\0';
280
}
281
 
282
static int __init do_mount_root(char *name, char *fs, int flags, void *data)
283
{
284
        int err = sys_mount(name, "/root", fs, flags, data);
285
        if (err)
286
                return err;
287
 
288
        sys_chdir("/root");
289
        ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
290
        printk("VFS: Mounted root (%s filesystem)%s.\n",
291
               current->fs->pwdmnt->mnt_sb->s_type->name,
292
               current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ?
293
               " readonly" : "");
294
        return 0;
295
}
296
 
297
void __init mount_block_root(char *name, int flags)
298
{
299
        char *fs_names = __getname();
300
        char *p;
301
#ifdef CONFIG_BLOCK
302
        char b[BDEVNAME_SIZE];
303
#else
304
        const char *b = name;
305
#endif
306
 
307
        get_fs_names(fs_names);
308
retry:
309
        for (p = fs_names; *p; p += strlen(p)+1) {
310
                int err = do_mount_root(name, p, flags, root_mount_data);
311
                switch (err) {
312
                        case 0:
313
                                goto out;
314
                        case -EACCES:
315
                                flags |= MS_RDONLY;
316
                                goto retry;
317
                        case -EINVAL:
318
                                continue;
319
                }
320
                /*
321
                 * Allow the user to distinguish between failed sys_open
322
                 * and bad superblock on root device.
323
                 * and give them a list of the available devices
324
                 */
325
#ifdef CONFIG_BLOCK
326
                __bdevname(ROOT_DEV, b);
327
#endif
328
                printk("VFS: Cannot open root device \"%s\" or %s\n",
329
                                root_device_name, b);
330
                printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");
331
 
332
                printk_all_partitions();
333
                panic("VFS: Unable to mount root fs on %s", b);
334
        }
335
 
336
        printk("List of all partitions:\n");
337
        printk_all_partitions();
338
        printk("No filesystem could mount root, tried: ");
339
        for (p = fs_names; *p; p += strlen(p)+1)
340
                printk(" %s", p);
341
        printk("\n");
342
#ifdef CONFIG_BLOCK
343
        __bdevname(ROOT_DEV, b);
344
#endif
345
        panic("VFS: Unable to mount root fs on %s", b);
346
out:
347
        putname(fs_names);
348
}
349
 
350
#ifdef CONFIG_ROOT_NFS
351
static int __init mount_nfs_root(void)
352
{
353
        void *data = nfs_root_data();
354
 
355
        create_dev("/dev/root", ROOT_DEV);
356
        if (data &&
357
            do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
358
                return 1;
359
        return 0;
360
}
361
#endif
362
 
363
#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
364
void __init change_floppy(char *fmt, ...)
365
{
366
        struct termios termios;
367
        char buf[80];
368
        char c;
369
        int fd;
370
        va_list args;
371
        va_start(args, fmt);
372
        vsprintf(buf, fmt, args);
373
        va_end(args);
374
        fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
375
        if (fd >= 0) {
376
                sys_ioctl(fd, FDEJECT, 0);
377
                sys_close(fd);
378
        }
379
        printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
380
        fd = sys_open("/dev/console", O_RDWR, 0);
381
        if (fd >= 0) {
382
                sys_ioctl(fd, TCGETS, (long)&termios);
383
                termios.c_lflag &= ~ICANON;
384
                sys_ioctl(fd, TCSETSF, (long)&termios);
385
                sys_read(fd, &c, 1);
386
                termios.c_lflag |= ICANON;
387
                sys_ioctl(fd, TCSETSF, (long)&termios);
388
                sys_close(fd);
389
        }
390
}
391
#endif
392
 
393
void __init mount_root(void)
394
{
395
#ifdef CONFIG_ROOT_NFS
396
        if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
397
                if (mount_nfs_root())
398
                        return;
399
 
400
                printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
401
                ROOT_DEV = Root_FD0;
402
        }
403
#endif
404
#ifdef CONFIG_BLK_DEV_FD
405
        if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
406
                /* rd_doload is 2 for a dual initrd/ramload setup */
407
                if (rd_doload==2) {
408
                        if (rd_load_disk(1)) {
409
                                ROOT_DEV = Root_RAM1;
410
                                root_device_name = NULL;
411
                        }
412
                } else
413
                        change_floppy("root floppy");
414
        }
415
#endif
416
#ifdef CONFIG_BLOCK
417
        create_dev("/dev/root", ROOT_DEV);
418
        mount_block_root("/dev/root", root_mountflags);
419
#endif
420
}
421
 
422
/*
423
 * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
424
 */
425
void __init prepare_namespace(void)
426
{
427
        int is_floppy;
428
 
429
        if (root_delay) {
430
                printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
431
                       root_delay);
432
                ssleep(root_delay);
433
        }
434
 
435
        /* wait for the known devices to complete their probing */
436
        while (driver_probe_done() != 0)
437
                msleep(100);
438
 
439
        md_run_setup();
440
 
441
        if (saved_root_name[0]) {
442
                root_device_name = saved_root_name;
443
                if (!strncmp(root_device_name, "mtd", 3)) {
444
                        mount_block_root(root_device_name, root_mountflags);
445
                        goto out;
446
                }
447
                ROOT_DEV = name_to_dev_t(root_device_name);
448
                if (strncmp(root_device_name, "/dev/", 5) == 0)
449
                        root_device_name += 5;
450
        }
451
 
452
        if (initrd_load())
453
                goto out;
454
 
455
        /* wait for any asynchronous scanning to complete */
456
        if ((ROOT_DEV == 0) && root_wait) {
457
                printk(KERN_INFO "Waiting for root device %s...\n",
458
                        saved_root_name);
459
                while (driver_probe_done() != 0 ||
460
                        (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
461
                        msleep(100);
462
        }
463
 
464
        is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
465
 
466
        if (is_floppy && rd_doload && rd_load_disk(0))
467
                ROOT_DEV = Root_RAM0;
468
 
469
        mount_root();
470
out:
471
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
472
        sys_chroot(".");
473
        security_sb_post_mountroot();
474
}
475
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.