source: mainline/uspace/app/init/init.c@ 9905da7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9905da7 was 75701004, checked in by Martin Decky <martin@…>, 7 years ago

use a TAR as the archive format for populating TMPFS root file system

Also remove the logic of populating a TMPFS file system from the TMPFS
file system driver. A more elegant separation of concerns is to populate
the file system from the client. This is now done by the init task (if
required) and should work universally for any file system.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup init Init
30 * @brief Init process for user space environment configuration.
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 <config.h>
49#include <io/logctl.h>
50#include "untar.h"
51#include "init.h"
52
53#define ROOT_DEVICE "bd/initrd"
54#define ROOT_MOUNT_POINT "/"
55
56#define LOCFS_FS_TYPE "locfs"
57#define LOCFS_MOUNT_POINT "/loc"
58
59#define TMPFS_FS_TYPE "tmpfs"
60#define TMPFS_MOUNT_POINT "/tmp"
61
62#define SRV_CONSOLE "/srv/console"
63#define APP_GETTERM "/app/getterm"
64
65#define SRV_COMPOSITOR "/srv/compositor"
66
67#define HID_INPUT "hid/input"
68#define HID_OUTPUT "hid/output"
69#define HID_COMPOSITOR_SERVER ":0"
70
71#define srv_start(path, ...) \
72 srv_startl(path, path, ##__VA_ARGS__, NULL)
73
74/** Print banner */
75static void info_print(void)
76{
77 printf("%s: HelenOS init\n", NAME);
78}
79
80/** Report mount operation success */
81static bool mount_report(const char *desc, const char *mntpt,
82 const char *fstype, const char *dev, errno_t rc)
83{
84 switch (rc) {
85 case EOK:
86 if ((dev != NULL) && (str_cmp(dev, "") != 0))
87 printf("%s: %s mounted on %s (%s at %s)\n", NAME, desc, mntpt,
88 fstype, dev);
89 else
90 printf("%s: %s mounted on %s (%s)\n", NAME, desc, mntpt, fstype);
91 break;
92 case EBUSY:
93 printf("%s: %s already mounted on %s\n", NAME, desc, mntpt);
94 return false;
95 case ELIMIT:
96 printf("%s: %s limit exceeded\n", NAME, desc);
97 return false;
98 case ENOENT:
99 printf("%s: %s unknown type (%s)\n", NAME, desc, fstype);
100 return false;
101 default:
102 printf("%s: %s not mounted on %s (%s)\n", NAME, desc, mntpt,
103 str_error(rc));
104 return false;
105 }
106
107 return true;
108}
109
110/** Mount root file system
111 *
112 * The operation blocks until the root file system
113 * server is ready for mounting.
114 *
115 * @param[in] fstype Root file system type.
116 *
117 * @return True on success.
118 * @return False on failure.
119 *
120 */
121static bool mount_root(const char *fstype)
122{
123 const char *root_device = "";
124
125 if (str_cmp(fstype, "tmpfs") != 0)
126 root_device = ROOT_DEVICE;
127
128 errno_t rc = vfs_mount_path(ROOT_MOUNT_POINT, fstype, root_device, "",
129 IPC_FLAG_BLOCKING, 0);
130 if (rc == EOK)
131 logctl_set_root();
132
133 bool ret = mount_report("Root file system", ROOT_MOUNT_POINT, fstype,
134 root_device, rc);
135
136 rc = vfs_cwd_set(ROOT_MOUNT_POINT);
137 if (rc != EOK) {
138 printf("%s: Unable to set current directory to %s (%s)\n",
139 NAME, ROOT_MOUNT_POINT, str_error(ret));
140 return false;
141 }
142
143 if ((ret) && (str_cmp(fstype, "tmpfs") == 0)) {
144 printf("%s: Extracting root file system archive\n", NAME);
145 ret = bd_untar(ROOT_DEVICE);
146 }
147
148 return ret;
149}
150
151/** Mount locfs file system
152 *
153 * The operation blocks until the locfs file system
154 * server is ready for mounting.
155 *
156 * @return True on success.
157 * @return False on failure.
158 *
159 */
160static bool mount_locfs(void)
161{
162 errno_t rc = vfs_mount_path(LOCFS_MOUNT_POINT, LOCFS_FS_TYPE, "", "",
163 IPC_FLAG_BLOCKING, 0);
164 return mount_report("Location service file system", LOCFS_MOUNT_POINT,
165 LOCFS_FS_TYPE, NULL, rc);
166}
167
168static errno_t srv_startl(const char *path, ...)
169{
170 vfs_stat_t s;
171 if (vfs_stat_path(path, &s) != EOK) {
172 printf("%s: Unable to stat %s\n", NAME, path);
173 return ENOENT;
174 }
175
176 printf("%s: Starting %s\n", NAME, path);
177
178 va_list ap;
179 const char *arg;
180 int cnt = 0;
181
182 va_start(ap, path);
183 do {
184 arg = va_arg(ap, const char *);
185 cnt++;
186 } while (arg != NULL);
187 va_end(ap);
188
189 va_start(ap, path);
190 task_id_t id;
191 task_wait_t wait;
192 errno_t rc = task_spawn(&id, &wait, path, cnt, ap);
193 va_end(ap);
194
195 if (rc != EOK) {
196 printf("%s: Error spawning %s (%s)\n", NAME, path,
197 str_error(rc));
198 return rc;
199 }
200
201 if (!id) {
202 printf("%s: Error spawning %s (invalid task id)\n", NAME,
203 path);
204 return EINVAL;
205 }
206
207 task_exit_t texit;
208 int retval;
209 rc = task_wait(&wait, &texit, &retval);
210 if (rc != EOK) {
211 printf("%s: Error waiting for %s (%s)\n", NAME, path,
212 str_error(rc));
213 return rc;
214 }
215
216 if (texit != TASK_EXIT_NORMAL) {
217 printf("%s: Server %s failed to start (unexpectedly "
218 "terminated)\n", NAME, path);
219 return EINVAL;
220 }
221
222 if (retval != 0)
223 printf("%s: Server %s failed to start (exit code %d)\n", NAME,
224 path, retval);
225
226 return retval == 0 ? EOK : EPARTY;
227}
228
229static errno_t console(const char *isvc, const char *osvc)
230{
231 /* Wait for the input service to be ready */
232 service_id_t service_id;
233 errno_t rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
234 if (rc != EOK) {
235 printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
236 str_error(rc));
237 return rc;
238 }
239
240 /* Wait for the output service to be ready */
241 rc = loc_service_get_id(osvc, &service_id, IPC_FLAG_BLOCKING);
242 if (rc != EOK) {
243 printf("%s: Error waiting on %s (%s)\n", NAME, osvc,
244 str_error(rc));
245 return rc;
246 }
247
248 return srv_start(SRV_CONSOLE, isvc, osvc);
249}
250
251static errno_t compositor(const char *isvc, const char *name)
252{
253 /* Wait for the input service to be ready */
254 service_id_t service_id;
255 errno_t rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
256 if (rc != EOK) {
257 printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
258 str_error(rc));
259 return rc;
260 }
261
262 return srv_start(SRV_COMPOSITOR, isvc, name);
263}
264
265static int gui_start(const char *app, const char *srv_name)
266{
267 char winreg[50];
268 snprintf(winreg, sizeof(winreg), "%s%s%s", "comp", srv_name, "/winreg");
269
270 printf("%s: Spawning %s %s\n", NAME, app, winreg);
271
272 task_id_t id;
273 task_wait_t wait;
274 errno_t rc = task_spawnl(&id, &wait, app, app, winreg, NULL);
275 if (rc != EOK) {
276 printf("%s: Error spawning %s %s (%s)\n", NAME, app,
277 winreg, str_error(rc));
278 return -1;
279 }
280
281 task_exit_t texit;
282 int retval;
283 rc = task_wait(&wait, &texit, &retval);
284 if ((rc != EOK) || (texit != TASK_EXIT_NORMAL)) {
285 printf("%s: Error retrieving retval from %s (%s)\n", NAME,
286 app, str_error(rc));
287 return -1;
288 }
289
290 return retval;
291}
292
293static void getterm(const char *svc, const char *app, bool msg)
294{
295 if (msg) {
296 printf("%s: Spawning %s %s %s --msg --wait -- %s\n", NAME,
297 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
298
299 errno_t rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
300 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL);
301 if (rc != EOK)
302 printf("%s: Error spawning %s %s %s --msg --wait -- %s\n",
303 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
304 } else {
305 printf("%s: Spawning %s %s %s --wait -- %s\n", NAME,
306 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
307
308 errno_t rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
309 LOCFS_MOUNT_POINT, "--wait", "--", app, NULL);
310 if (rc != EOK)
311 printf("%s: Error spawning %s %s %s --wait -- %s\n",
312 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
313 }
314}
315
316static bool mount_tmpfs(void)
317{
318 errno_t rc = vfs_mount_path(TMPFS_MOUNT_POINT, TMPFS_FS_TYPE, "", "", 0, 0);
319 return mount_report("Temporary file system", TMPFS_MOUNT_POINT,
320 TMPFS_FS_TYPE, NULL, rc);
321}
322
323int main(int argc, char *argv[])
324{
325 errno_t rc;
326
327 info_print();
328
329 if (!mount_root(STRING(RDFMT))) {
330 printf("%s: Exiting\n", NAME);
331 return 1;
332 }
333
334 /* Make sure file systems are running. */
335 if (str_cmp(STRING(RDFMT), "tmpfs") != 0)
336 srv_start("/srv/tmpfs");
337 if (str_cmp(STRING(RDFMT), "exfat") != 0)
338 srv_start("/srv/exfat");
339 if (str_cmp(STRING(RDFMT), "fat") != 0)
340 srv_start("/srv/fat");
341 srv_start("/srv/cdfs");
342 srv_start("/srv/mfs");
343
344 srv_start("/srv/klog");
345 srv_start("/srv/locfs");
346 srv_start("/srv/taskmon");
347
348 if (!mount_locfs()) {
349 printf("%s: Exiting\n", NAME);
350 return 2;
351 }
352
353 mount_tmpfs();
354
355 srv_start("/srv/devman");
356 srv_start("/srv/s3c24xx_uart");
357 srv_start("/srv/s3c24xx_ts");
358
359 srv_start("/srv/vbd");
360 srv_start("/srv/volsrv");
361
362 srv_start("/srv/loopip");
363 srv_start("/srv/ethip");
364 srv_start("/srv/inetsrv");
365 srv_start("/srv/tcp");
366 srv_start("/srv/udp");
367 srv_start("/srv/dnsrsrv");
368 srv_start("/srv/dhcp");
369 srv_start("/srv/nconfsrv");
370
371 srv_start("/srv/clipboard");
372 srv_start("/srv/remcons");
373
374 srv_start("/srv/input", HID_INPUT);
375 srv_start("/srv/output", HID_OUTPUT);
376 srv_start("/srv/hound");
377
378 if (!config_key_exists("console")) {
379 rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER);
380 if (rc == EOK) {
381 gui_start("/app/barber", HID_COMPOSITOR_SERVER);
382 gui_start("/app/vlaunch", HID_COMPOSITOR_SERVER);
383 gui_start("/app/vterm", HID_COMPOSITOR_SERVER);
384 }
385 }
386
387 rc = console(HID_INPUT, HID_OUTPUT);
388 if (rc == EOK) {
389 getterm("term/vc0", "/app/bdsh", true);
390 getterm("term/vc1", "/app/bdsh", false);
391 getterm("term/vc2", "/app/bdsh", false);
392 getterm("term/vc3", "/app/bdsh", false);
393 getterm("term/vc4", "/app/bdsh", false);
394 getterm("term/vc5", "/app/bdsh", false);
395 }
396
397 return 0;
398}
399
400/** @}
401 */
Note: See TracBrowser for help on using the repository browser.