57f90cf813
It is desirable to run kboot as the first program in some LinuxBoot environments. This is the traditional "pid 1" or "init" program. When running as pid 1. rovide a minimal environment based on what sysvinit, u-root, initramfs-tools and other like projects do. We mount /dev, /sys, /proc, make symlinks from /dev/fd to /dev/proc, and create /tmp, /run, and /var. We also setup stdin/out/err to the console, set the tty characteristics of same and block the appropriate signals. This is indended as an environment that never does a fork/exec. If that's required, the process groups, session leaders and all things POSIX terminal handlers will need to be added. Unlike the general purpose linux projects in this area, no attempt is made to support very old kernels. When not pid 1, we skip all of the above. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D36368
130 lines
3.0 KiB
C
130 lines
3.0 KiB
C
/*-
|
|
* Copyright (c) 2022, Netflix, Inc.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
/*
|
|
* Mini-init(8) so we can run as init/pid 1 in a LinuxBoot environment.
|
|
*/
|
|
|
|
#include "stand.h"
|
|
#include "host_syscall.h"
|
|
#include "kboot.h"
|
|
|
|
/*
|
|
* Create a 'standard' early boot environment. Cribbed from the things that
|
|
* sysvinit, u-root, and initramfs-tools do. This is a minimal environment
|
|
* for modern Linux systems, though the /tmp, /run and /var stuff can likely
|
|
* be done inside the initrd image itself (as can creating the mount points
|
|
* for /proc, /dev and /sys).
|
|
*
|
|
* Note: We ignore errors here. There's no stderr to report them to yet. These
|
|
* operations generally can't fail, but if they do, we may not have the ability
|
|
* to report them later.
|
|
*/
|
|
static void
|
|
init_fs_env(void)
|
|
{
|
|
/*
|
|
* Create directories for mandatory filesystems and mount them.
|
|
*/
|
|
host_mkdir("/proc", 0555);
|
|
host_mount("proc", "/proc", "proc", MS_RELATIME, "");
|
|
host_mkdir("/sys", 0555);
|
|
host_mount("sysfs", "/sys", "sysfs", MS_RELATIME, "");
|
|
host_mkdir("/dev", 0755);
|
|
host_mount("devtmpfs", "/dev", "devtmpfs", MS_RELATIME,
|
|
"mode=0755,nr_inodes=0");
|
|
|
|
/*
|
|
* Create compat links: /dev/fd lives in /proc, and needs some help to
|
|
* get setup.
|
|
*/
|
|
host_symlink("/proc/self/fd", "/dev/fd");
|
|
host_symlink("fd/0", "/dev/stdin");
|
|
host_symlink("fd/1", "/dev/stdout");
|
|
host_symlink("fd/2", "/dev/stderr");
|
|
|
|
|
|
/*
|
|
* Unsure if we need this, but create a sane /tmp just in case that's useful.
|
|
* and point /run over to it.
|
|
*/
|
|
host_mkdir("/tmp", 01777);
|
|
host_mount("tmpfs", "/tmp", "tmpfs", MS_RELATIME, "size=10%,mode=1777");
|
|
host_symlink("/tmp", "/run");
|
|
|
|
/*
|
|
* Unsure the loader needs /var and /var/log, but they are easy to
|
|
* create.
|
|
*/
|
|
host_mkdir("/var", 0555);
|
|
host_mkdir("/var/lock", 0555);
|
|
host_symlink("/tmp", "/var/tmp");
|
|
}
|
|
|
|
static void
|
|
init_tty(void)
|
|
{
|
|
int fd;
|
|
|
|
/*
|
|
* sysvinit asks the linux kernel to convert the CTRL-ALT-DEL to a SIGINT,
|
|
* but we skip that.
|
|
*/
|
|
|
|
/*
|
|
* Setup /dev/console as stdin/out/err
|
|
*/
|
|
host_close(0);
|
|
host_close(1);
|
|
host_close(2);
|
|
fd = host_open("/dev/console", HOST_O_RDWR | HOST_O_NOCTTY, 0);
|
|
host_dup(fd);
|
|
host_dup(fd);
|
|
#if 0
|
|
/*
|
|
* I think we may need to put it in 'raw' mode, but maybe not. Linux
|
|
* sysvinit sets it into 'sane' mode with several tweaks. Not enabled at
|
|
* the moment since host console initialization seems sufficient.
|
|
*/
|
|
struct host_termios tty;
|
|
|
|
host_cfmakeraw(&tty);
|
|
host_tcsetattr(fd, HOST_TCANOW, &tty);
|
|
host_tcflush(fd, HOST_TCIOFLUSH)
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
init_sig(void)
|
|
{
|
|
/*
|
|
* since we're running as init, we need to catch some signals
|
|
*/
|
|
|
|
/*
|
|
* setup signals here
|
|
*
|
|
* sysvinit catches a lot of signals, but the boot loader needn't catch
|
|
* so many since we don't do as much as it does. If we need to, put the
|
|
* signal catching / ignoring code here. If we implement a 'shell'
|
|
* function to spawn a sub-shell, we'll likely need to do a lot more.
|
|
*/
|
|
}
|
|
|
|
void
|
|
do_init(void)
|
|
{
|
|
/*
|
|
* Only pid 1 is init
|
|
*/
|
|
if (host_getpid() != 1)
|
|
return;
|
|
|
|
init_fs_env();
|
|
init_tty();
|
|
init_sig();
|
|
}
|