diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile --- a/stand/kboot/Makefile +++ b/stand/kboot/Makefile @@ -19,6 +19,7 @@ # Architecture-specific loader code SRCS= crt1.c conf.c vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c +SRCS+= init.c SRCS+= termios.c CFLAGS.gfx_fb_stub.c += -I${SRCTOP}/contrib/pnglite -I${SRCTOP}/sys/teken diff --git a/stand/kboot/init.c b/stand/kboot/init.c new file mode 100644 --- /dev/null +++ b/stand/kboot/init.c @@ -0,0 +1,129 @@ +/*- + * 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(); +} diff --git a/stand/kboot/kboot.h b/stand/kboot/kboot.h new file mode 100644 --- /dev/null +++ b/stand/kboot/kboot.h @@ -0,0 +1,12 @@ +/*- + * Copyright (c) 2022, Netflix, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef KBOOT_H +#define KBOOT_H + +void do_init(void); + +#endif /* KBOOT_H */ diff --git a/stand/kboot/main.c b/stand/kboot/main.c --- a/stand/kboot/main.c +++ b/stand/kboot/main.c @@ -34,7 +34,7 @@ #include #include #include "host_syscall.h" - +#include "kboot.h" struct arch_switch archsw; extern void *_end; @@ -261,8 +261,11 @@ const size_t heapsize = 15*1024*1024; const char *bootdev; + /* Give us a sane world if we're running as init */ + do_init(); + /* - * Set the heap to one page after the end of the loader. + * Setup the heap 15MB should be plenty */ heapbase = host_getmem(heapsize); setheap(heapbase, heapbase + heapsize);