Luna/apps/preinit.cpp
apio 36fad85396
All checks were successful
continuous-integration/drone/push Build is passing
kernel+init+preinit+wind: Remove the kernel TTY and support only userspace terminals
Still allow printing text to the console, but without text input or ANSI escape fancy stuff.
2023-09-21 19:31:54 +02:00

83 lines
1.9 KiB
C++

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
// FIXME: Make this configurable.
#define LUNA_ROOT_PARTITION "/dev/cd0p2"
static void mount_devfs()
{
if (mkdir("/dev", 0755) < 0 && errno != EEXIST && errno != EROFS) exit(255);
if (mount("/dev", "devfs", "devfs") < 0) exit(255);
}
static void open_std_streams()
{
stdin = fopen("/dev/null", "r");
stdout = fopen("/dev/kmsg", "w");
stderr = fopen("/dev/kmsg", "w");
}
static void fail(const char* message)
{
open_std_streams();
fprintf(stderr, "preinit: fatal error: %s\n", message);
exit(255);
}
static void fail_errno(const char* message)
{
int err = errno;
open_std_streams();
fprintf(stderr, "preinit: fatal error: %s (%s)\n", message, strerror(err));
exit(255);
}
static void mount_rootfs()
{
if (mkdir("/osroot", 0755) < 0 && errno != EEXIST) exit(255);
if (mount("/osroot", "ext2", LUNA_ROOT_PARTITION) < 0) fail_errno("Cannot mount the root partition");
}
int main()
{
if (getpid() != 1)
{
fprintf(stderr, "error: preinit must be run as the init process.\n");
return 1;
}
mount_devfs();
mount_rootfs();
struct stat st;
if (stat("/osroot/mnt", &st) < 0 || !S_ISDIR(st.st_mode)) fail("No suitable temporary mountpoint for pivot_root");
// Now that we have mounted the root file system, remove the /dev mount on the current ramfs root.
umount("/dev");
long rc = syscall(SYS_pivot_root, "/osroot", "/osroot/mnt");
if (rc < 0) exit(255);
chdir("/");
umount("/mnt");
// Now, mount the /dev file system on the new root.
mount_devfs();
char* argv[] = { "/usr/bin/init", nullptr };
char* envp[] = { nullptr };
execve(argv[0], argv, envp);
fail_errno("Failed to execute init");
return 255;
}