source: mainline/uspace/app/init/init.c

Last change on this file was 514108e, checked in by Jiri Svoboda <jiri@…>, 9 months ago

Minimize /app/init, once root is mounted, go to /srv/system

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * Copyright (c) 2005 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup init
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <stdarg.h>
39#include <vfs/vfs.h>
40#include <stdbool.h>
41#include <errno.h>
42#include <task.h>
43#include <stdlib.h>
44#include <macros.h>
45#include <str.h>
46#include <loc.h>
47#include <str_error.h>
48#include <io/logctl.h>
49#include <vfs/vfs.h>
50#include "untar.h"
51#include "init.h"
52
53#define BANNER_LEFT "######> "
54#define BANNER_RIGHT " <######"
55
56#define ROOT_DEVICE "bd/initrd"
57#define ROOT_MOUNT_POINT "/"
58
59#define srv_start(path, ...) \
60 srv_startl(path, path, ##__VA_ARGS__, NULL)
61
62/** Print banner */
63static void info_print(void)
64{
65 printf("%s: HelenOS init\n", NAME);
66}
67
68static void oom_check(errno_t rc, const char *path)
69{
70 if (rc == ENOMEM) {
71 printf("%sOut-of-memory condition detected%s\n", BANNER_LEFT,
72 BANNER_RIGHT);
73 printf("%sBailing out of the boot process after %s%s\n",
74 BANNER_LEFT, path, BANNER_RIGHT);
75 printf("%sMore physical memory is required%s\n", BANNER_LEFT,
76 BANNER_RIGHT);
77 exit(ENOMEM);
78 }
79}
80
81/** Report mount operation success */
82static bool mount_report(const char *desc, const char *mntpt,
83 const char *fstype, const char *dev, errno_t rc)
84{
85 switch (rc) {
86 case EOK:
87 if ((dev != NULL) && (str_cmp(dev, "") != 0))
88 printf("%s: %s mounted on %s (%s at %s)\n", NAME, desc, mntpt,
89 fstype, dev);
90 else
91 printf("%s: %s mounted on %s (%s)\n", NAME, desc, mntpt, fstype);
92 break;
93 case EBUSY:
94 printf("%s: %s already mounted on %s\n", NAME, desc, mntpt);
95 return false;
96 case ELIMIT:
97 printf("%s: %s limit exceeded\n", NAME, desc);
98 return false;
99 case ENOENT:
100 printf("%s: %s unknown type (%s)\n", NAME, desc, fstype);
101 return false;
102 default:
103 printf("%s: %s not mounted on %s (%s)\n", NAME, desc, mntpt,
104 str_error(rc));
105 return false;
106 }
107
108 return true;
109}
110
111/** Mount root file system
112 *
113 * The operation blocks until the root file system
114 * server is ready for mounting.
115 *
116 * @param[in] fstype Root file system type.
117 *
118 * @return True on success.
119 * @return False on failure.
120 *
121 */
122static bool mount_root(const char *fstype)
123{
124 const char *root_device = "";
125
126 if (str_cmp(fstype, "tmpfs") != 0)
127 root_device = ROOT_DEVICE;
128
129 errno_t rc = vfs_mount_path(ROOT_MOUNT_POINT, fstype, root_device, "",
130 IPC_FLAG_BLOCKING, 0);
131 if (rc == EOK)
132 logctl_set_root();
133
134 bool ret = mount_report("Root file system", ROOT_MOUNT_POINT, fstype,
135 root_device, rc);
136
137 rc = vfs_cwd_set(ROOT_MOUNT_POINT);
138 if (rc != EOK) {
139 printf("%s: Unable to set current directory to %s (%s)\n",
140 NAME, ROOT_MOUNT_POINT, str_error(ret));
141 return false;
142 }
143
144 if ((ret) && (str_cmp(fstype, "tmpfs") == 0)) {
145 printf("%s: Extracting root file system archive\n", NAME);
146 ret = bd_untar(ROOT_DEVICE);
147 }
148
149 return ret;
150}
151
152static errno_t srv_startl(const char *path, ...)
153{
154 vfs_stat_t s;
155 if (vfs_stat_path(path, &s) != EOK) {
156 printf("%s: Unable to stat %s\n", NAME, path);
157 return ENOENT;
158 }
159
160 printf("%s: Starting %s\n", NAME, path);
161
162 va_list ap;
163 const char *arg;
164 int cnt = 0;
165
166 va_start(ap, path);
167 do {
168 arg = va_arg(ap, const char *);
169 cnt++;
170 } while (arg != NULL);
171 va_end(ap);
172
173 va_start(ap, path);
174 task_id_t id;
175 task_wait_t wait;
176 errno_t rc = task_spawn(&id, &wait, path, cnt, ap);
177 va_end(ap);
178
179 if (rc != EOK) {
180 oom_check(rc, path);
181 printf("%s: Error spawning %s (%s)\n", NAME, path,
182 str_error(rc));
183 return rc;
184 }
185
186 if (!id) {
187 printf("%s: Error spawning %s (invalid task id)\n", NAME,
188 path);
189 return EINVAL;
190 }
191
192 task_exit_t texit;
193 int retval;
194 rc = task_wait(&wait, &texit, &retval);
195 if (rc != EOK) {
196 printf("%s: Error waiting for %s (%s)\n", NAME, path,
197 str_error(rc));
198 return rc;
199 }
200
201 if (texit != TASK_EXIT_NORMAL) {
202 printf("%s: Server %s failed to start (unexpectedly "
203 "terminated)\n", NAME, path);
204 return EINVAL;
205 }
206
207 if (retval != 0)
208 printf("%s: Server %s failed to start (exit code %d)\n", NAME,
209 path, retval);
210
211 return retval == 0 ? EOK : EPARTY;
212}
213
214int main(int argc, char *argv[])
215{
216 info_print();
217
218 if (!mount_root(STRING(RDFMT))) {
219 printf("%s: Exiting\n", NAME);
220 return 1;
221 }
222
223 /* System server takes over once root is mounted */
224 srv_start("/srv/system");
225 return 0;
226}
227
228/** @}
229 */
Note: See TracBrowser for help on using the repository browser.