1// SPDX-License-Identifier: GPL-3.0-or-later
2// A stage 1 init program for the MOS kernel.
3//
4// This program is responsible for:
5// - Mounting the initrd
6// - Starting the device manager, filesystem server
7// - Starting the stage 2 init program
8
9#include "bootstrapper.h"
10
11#include <iostream>
12#include <librpc/rpc_server.h>
13#include <mos/mos_global.h>
14#include <mos/syscall/usermode.h>
15#include <stdio.h>
16#include <unistd.h>
17
18static constexpr auto MOS_ASCII_ART = R"(
19,---. ,---. ,-----. .-'''-.
20| \ / | .' .-, '. / _ \
21| , \/ , | / ,-.| \ _ \ (`' )/`--'
22| |\_ /| | ; \ '_ / | : (_ o _).
23| _( )_/ | | | _`,/ \ _/ | (_,_). '.
24| (_ o _) | | : ( '\_/ \ ; .---. \ :
25| (_,_) | | \ `"/ \ ) / \ `-' |
26| | | | '. \_/``".' \ /
27'--' '--' '-----' `-...-'
28)";
29
30s64 strntoll(const char *str, char **endptr, int base, size_t n)
31{
32 s64 result = 0;
33 bool negative = false;
34 size_t i = 0;
35
36 if (*str == '-')
37 negative = true, str++, i++;
38 else if (*str == '+')
39 str++, i++;
40
41 while (i < n && *str)
42 {
43 char c = *str;
44 if (c >= '0' && c <= '9')
45 result *= base, result += c - '0';
46 else if (c >= 'a' && c <= 'z')
47 result *= base, result += c - 'a' + 10;
48 else if (c >= 'A' && c <= 'Z')
49 result *= base, result += c - 'A' + 10;
50 else
51 break;
52 str++;
53 i++;
54 }
55 if (endptr)
56 *endptr = (char *) str;
57 return negative ? -result : result;
58}
59
60int main(int argc, char *argv[])
61{
62 MOS_UNUSED(argc);
63
64 if (getpid() != 1)
65 {
66 puts(string: "bootstrapper: not running as PID 1, exiting");
67 return 1;
68 }
69
70 std::cout << MOS_ASCII_ART << std::endl;
71 std::cout << "Welcome to the MOS operating system." << std::endl;
72
73 int statusfd[2];
74 pipe(statusfd);
75
76 const pid_t cpiofs_server_pid = fork();
77 if (cpiofs_server_pid == -1)
78 {
79 puts(string: "bootstrapper: failed to fork filesystem server");
80 return 1;
81 }
82
83 if (cpiofs_server_pid == 0)
84 {
85 close(fd: statusfd[0]);
86 syscall_thread_setname(tid: syscall_get_tid(), name: "cpiofs");
87 init_start_cpiofs_server(notifier: statusfd[1]);
88 puts(string: "bootstrapper: filesystem server exited unexpectedly");
89 return 1;
90 }
91
92 // ! TODO: migrate to pthread_cond_wait after mlibc supports cross-process condition variables
93 close(fd: statusfd[1]);
94 char buf[1] = { 0 };
95 read(fd: statusfd[0], buffer: buf, size: 1);
96 close(fd: statusfd[0]);
97 if (buf[0] != 'v')
98 {
99 puts(string: "bootstrapper: filesystem server failed to start");
100 return 1;
101 }
102
103 if (link("/lib", "/initrd/lib") != 0)
104 {
105 puts(string: "bootstrapper: failed to link /lib to /initrd/lib");
106 return 1;
107 }
108
109 if (execv("/initrd/programs/init", argv) != 0)
110 {
111 puts(string: "bootstrapper: failed to start init");
112 return 1;
113 }
114
115 puts(string: "MOS in crisis!");
116 __builtin_unreachable();
117}
118