1/*-
2 * Copyright (c) 2022, Netflix, Inc.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7/*
8 * Mini-init(8) so we can run as init/pid 1 in a LinuxBoot environment.
9 */
10
11#include "stand.h"
12#include "host_syscall.h"
13#include "kboot.h"
14
15/*
16 * Create a 'standard' early boot environment. Cribbed from the things that
17 * sysvinit, u-root, and initramfs-tools do. This is a minimal environment
18 * for modern Linux systems, though the /tmp, /run and /var stuff can likely
19 * be done inside the initrd image itself (as can creating the mount points
20 * for /proc, /dev and /sys).
21 *
22 * Note: We ignore errors here. There's no stderr to report them to yet. These
23 * operations generally can't fail, but if they do, we may not have the ability
24 * to report them later.
25 */
26static void
27init_fs_env(void)
28{
29	/*
30	 * Create directories for mandatory filesystems and mount them.
31	 */
32	host_mkdir("/proc", 0555);
33	host_mount("proc", "/proc", "proc", MS_RELATIME, "");
34	host_mkdir("/sys", 0555);
35	host_mount("sysfs", "/sys", "sysfs", MS_RELATIME, "");
36	host_mkdir("/dev", 0755);
37	host_mount("devtmpfs", "/dev", "devtmpfs", MS_RELATIME,
38	    "mode=0755,nr_inodes=0");
39
40	/*
41	 * Create compat links: /dev/fd lives in /proc, and needs some help to
42	 * get setup.
43	 */
44	host_symlink("/proc/self/fd", "/dev/fd");
45	host_symlink("fd/0", "/dev/stdin");
46	host_symlink("fd/1", "/dev/stdout");
47	host_symlink("fd/2", "/dev/stderr");
48
49
50	/*
51	 * Unsure if we need this, but create a sane /tmp just in case that's useful.
52	 * and point /run over to it.
53	 */
54	host_mkdir("/tmp", 01777);
55	host_mount("tmpfs", "/tmp", "tmpfs", MS_RELATIME, "size=10%,mode=1777");
56	host_symlink("/tmp", "/run");
57
58	/*
59	 * Unsure the loader needs /var and /var/log, but they are easy to
60	 * create.
61	 */
62	host_mkdir("/var", 0555);
63	host_mkdir("/var/lock", 0555);
64	host_symlink("/tmp", "/var/tmp");
65}
66
67static void
68init_tty(void)
69{
70	int fd;
71
72	/*
73	 * sysvinit asks the linux kernel to convert the CTRL-ALT-DEL to a SIGINT,
74	 * but we skip that.
75	 */
76
77	/*
78	 * Setup /dev/console as stdin/out/err
79	 */
80	host_close(0);
81	host_close(1);
82	host_close(2);
83	fd = host_open("/dev/console", HOST_O_RDWR | HOST_O_NOCTTY, 0);
84	host_dup(fd);
85	host_dup(fd);
86#if 0
87	/*
88	 * I think we may need to put it in 'raw' mode, but maybe not. Linux
89	 * sysvinit sets it into 'sane' mode with several tweaks. Not enabled at
90	 * the moment since host console initialization seems sufficient.
91	 */
92	struct host_termios tty;
93
94	host_cfmakeraw(&tty);
95	host_tcsetattr(fd, HOST_TCANOW, &tty);
96	host_tcflush(fd, HOST_TCIOFLUSH)
97#endif
98}
99
100static void
101init_sig(void)
102{
103	/*
104	 * since we're running as init, we need to catch some signals
105	 */
106
107	/*
108	 * setup signals here
109	 *
110	 * sysvinit catches a lot of signals, but the boot loader needn't catch
111	 * so many since we don't do as much as it does. If we need to, put the
112	 * signal catching / ignoring code here. If we implement a 'shell'
113	 * function to spawn a sub-shell, we'll likely need to do a lot more.
114	 */
115}
116
117void
118do_init(void)
119{
120	/*
121	 * Only pid 1 is init
122	 */
123	if (host_getpid() != 1)
124		return;
125
126	init_fs_env();
127	init_tty();
128	init_sig();
129}
130