0001
0002 #include <linux/unistd.h>
0003 #include <linux/kernel.h>
0004 #include <linux/fs.h>
0005 #include <linux/minix_fs.h>
0006 #include <linux/romfs_fs.h>
0007 #include <linux/initrd.h>
0008 #include <linux/sched.h>
0009 #include <linux/freezer.h>
0010 #include <linux/kmod.h>
0011 #include <uapi/linux/mount.h>
0012
0013 #include "do_mounts.h"
0014
0015 unsigned long initrd_start, initrd_end;
0016 int initrd_below_start_ok;
0017 static unsigned int real_root_dev;
0018 static int __initdata mount_initrd = 1;
0019
0020 phys_addr_t phys_initrd_start __initdata;
0021 unsigned long phys_initrd_size __initdata;
0022
0023 #ifdef CONFIG_SYSCTL
0024 static struct ctl_table kern_do_mounts_initrd_table[] = {
0025 {
0026 .procname = "real-root-dev",
0027 .data = &real_root_dev,
0028 .maxlen = sizeof(int),
0029 .mode = 0644,
0030 .proc_handler = proc_dointvec,
0031 },
0032 { }
0033 };
0034
0035 static __init int kernel_do_mounts_initrd_sysctls_init(void)
0036 {
0037 register_sysctl_init("kernel", kern_do_mounts_initrd_table);
0038 return 0;
0039 }
0040 late_initcall(kernel_do_mounts_initrd_sysctls_init);
0041 #endif
0042
0043 static int __init no_initrd(char *str)
0044 {
0045 mount_initrd = 0;
0046 return 1;
0047 }
0048
0049 __setup("noinitrd", no_initrd);
0050
0051 static int __init early_initrdmem(char *p)
0052 {
0053 phys_addr_t start;
0054 unsigned long size;
0055 char *endp;
0056
0057 start = memparse(p, &endp);
0058 if (*endp == ',') {
0059 size = memparse(endp + 1, NULL);
0060
0061 phys_initrd_start = start;
0062 phys_initrd_size = size;
0063 }
0064 return 0;
0065 }
0066 early_param("initrdmem", early_initrdmem);
0067
0068 static int __init early_initrd(char *p)
0069 {
0070 return early_initrdmem(p);
0071 }
0072 early_param("initrd", early_initrd);
0073
0074 static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
0075 {
0076 ksys_unshare(CLONE_FS | CLONE_FILES);
0077 console_on_rootfs();
0078
0079 init_chdir("/root");
0080 init_mount(".", "/", NULL, MS_MOVE, NULL);
0081 init_chroot(".");
0082 ksys_setsid();
0083 return 0;
0084 }
0085
0086 static void __init handle_initrd(void)
0087 {
0088 struct subprocess_info *info;
0089 static char *argv[] = { "linuxrc", NULL, };
0090 extern char *envp_init[];
0091 int error;
0092
0093 pr_warn("using deprecated initrd support, will be removed in 2021.\n");
0094
0095 real_root_dev = new_encode_dev(ROOT_DEV);
0096 create_dev("/dev/root.old", Root_RAM0);
0097
0098 mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
0099 init_mkdir("/old", 0700);
0100 init_chdir("/old");
0101
0102
0103
0104
0105
0106 current->flags |= PF_FREEZER_SKIP;
0107
0108 info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
0109 GFP_KERNEL, init_linuxrc, NULL, NULL);
0110 if (!info)
0111 return;
0112 call_usermodehelper_exec(info, UMH_WAIT_PROC);
0113
0114 current->flags &= ~PF_FREEZER_SKIP;
0115
0116
0117 init_mount("..", ".", NULL, MS_MOVE, NULL);
0118
0119 init_chroot("..");
0120
0121 if (new_decode_dev(real_root_dev) == Root_RAM0) {
0122 init_chdir("/old");
0123 return;
0124 }
0125
0126 init_chdir("/");
0127 ROOT_DEV = new_decode_dev(real_root_dev);
0128 mount_root();
0129
0130 printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
0131 error = init_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
0132 if (!error)
0133 printk("okay\n");
0134 else {
0135 if (error == -ENOENT)
0136 printk("/initrd does not exist. Ignored.\n");
0137 else
0138 printk("failed\n");
0139 printk(KERN_NOTICE "Unmounting old root\n");
0140 init_umount("/old", MNT_DETACH);
0141 }
0142 }
0143
0144 bool __init initrd_load(void)
0145 {
0146 if (mount_initrd) {
0147 create_dev("/dev/ram", Root_RAM0);
0148
0149
0150
0151
0152
0153
0154 if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
0155 init_unlink("/initrd.image");
0156 handle_initrd();
0157 return true;
0158 }
0159 }
0160 init_unlink("/initrd.image");
0161 return false;
0162 }