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 | |
18 | static constexpr auto MOS_ASCII_ART = R"( |
19 | ,---. ,---. ,-----. .-'''-. |
20 | | \ / | .' .-, '. / _ \ |
21 | | , \/ , | / ,-.| \ _ \ (`' )/`--' |
22 | | |\_ /| | ; \ '_ / | : (_ o _). |
23 | | _( )_/ | | | _`,/ \ _/ | (_,_). '. |
24 | | (_ o _) | | : ( '\_/ \ ; .---. \ : |
25 | | (_,_) | | \ `"/ \ ) / \ `-' | |
26 | | | | | '. \_/``".' \ / |
27 | '--' '--' '-----' `-...-' |
28 | )" ; |
29 | |
30 | s64 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 | |
60 | int 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 | |