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