Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : #include <linux/unistd.h>
3 : #include <linux/kernel.h>
4 : #include <linux/fs.h>
5 : #include <linux/minix_fs.h>
6 : #include <linux/romfs_fs.h>
7 : #include <linux/initrd.h>
8 : #include <linux/sched.h>
9 : #include <linux/freezer.h>
10 : #include <linux/kmod.h>
11 : #include <uapi/linux/mount.h>
12 :
13 : #include "do_mounts.h"
14 :
15 : unsigned long initrd_start, initrd_end;
16 : int initrd_below_start_ok;
17 : unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
18 : static int __initdata mount_initrd = 1;
19 :
20 : phys_addr_t phys_initrd_start __initdata;
21 : unsigned long phys_initrd_size __initdata;
22 :
23 0 : static int __init no_initrd(char *str)
24 : {
25 0 : mount_initrd = 0;
26 0 : return 1;
27 : }
28 :
29 : __setup("noinitrd", no_initrd);
30 :
31 0 : static int __init early_initrdmem(char *p)
32 : {
33 0 : phys_addr_t start;
34 0 : unsigned long size;
35 0 : char *endp;
36 :
37 0 : start = memparse(p, &endp);
38 0 : if (*endp == ',') {
39 0 : size = memparse(endp + 1, NULL);
40 :
41 0 : phys_initrd_start = start;
42 0 : phys_initrd_size = size;
43 : }
44 0 : return 0;
45 : }
46 : early_param("initrdmem", early_initrdmem);
47 :
48 0 : static int __init early_initrd(char *p)
49 : {
50 0 : return early_initrdmem(p);
51 : }
52 : early_param("initrd", early_initrd);
53 :
54 : static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
55 : {
56 : ksys_unshare(CLONE_FS | CLONE_FILES);
57 : console_on_rootfs();
58 : /* move initrd over / and chdir/chroot in initrd root */
59 : init_chdir("/root");
60 : init_mount(".", "/", NULL, MS_MOVE, NULL);
61 : init_chroot(".");
62 : ksys_setsid();
63 : return 0;
64 : }
65 :
66 : static void __init handle_initrd(void)
67 : {
68 : struct subprocess_info *info;
69 : static char *argv[] = { "linuxrc", NULL, };
70 : extern char *envp_init[];
71 : int error;
72 :
73 : pr_warn("using deprecated initrd support, will be removed in 2021.\n");
74 :
75 : real_root_dev = new_encode_dev(ROOT_DEV);
76 : create_dev("/dev/root.old", Root_RAM0);
77 : /* mount initrd on rootfs' /root */
78 : mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
79 : init_mkdir("/old", 0700);
80 : init_chdir("/old");
81 :
82 : /*
83 : * In case that a resume from disk is carried out by linuxrc or one of
84 : * its children, we need to tell the freezer not to wait for us.
85 : */
86 : current->flags |= PF_FREEZER_SKIP;
87 :
88 : info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
89 : GFP_KERNEL, init_linuxrc, NULL, NULL);
90 : if (!info)
91 : return;
92 : call_usermodehelper_exec(info, UMH_WAIT_PROC);
93 :
94 : current->flags &= ~PF_FREEZER_SKIP;
95 :
96 : /* move initrd to rootfs' /old */
97 : init_mount("..", ".", NULL, MS_MOVE, NULL);
98 : /* switch root and cwd back to / of rootfs */
99 : init_chroot("..");
100 :
101 : if (new_decode_dev(real_root_dev) == Root_RAM0) {
102 : init_chdir("/old");
103 : return;
104 : }
105 :
106 : init_chdir("/");
107 : ROOT_DEV = new_decode_dev(real_root_dev);
108 : mount_root();
109 :
110 : printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
111 : error = init_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
112 : if (!error)
113 : printk("okay\n");
114 : else {
115 : if (error == -ENOENT)
116 : printk("/initrd does not exist. Ignored.\n");
117 : else
118 : printk("failed\n");
119 : printk(KERN_NOTICE "Unmounting old root\n");
120 : init_umount("/old", MNT_DETACH);
121 : }
122 : }
123 :
124 1 : bool __init initrd_load(void)
125 : {
126 1 : if (mount_initrd) {
127 1 : create_dev("/dev/ram", Root_RAM0);
128 : /*
129 : * Load the initrd data into /dev/ram0. Execute it as initrd
130 : * unless /dev/ram0 is supposed to be our actual root device,
131 : * in that case the ram disk is just set up here, and gets
132 : * mounted in the normal path.
133 : */
134 1 : if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
135 : init_unlink("/initrd.image");
136 : handle_initrd();
137 : return true;
138 : }
139 : }
140 1 : init_unlink("/initrd.image");
141 1 : return false;
142 : }
|