source: mainline/uspace/app/init/init.c@ 02f45748

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 02f45748 was 02f45748, checked in by Jiri Svoboda <jiri@…>, 6 years ago

Source display server events from input server

  • Property mode set to 100644
File size: 11.1 KB
RevLine 
[3eddaff]1/*
[df4ed85]2 * Copyright (c) 2005 Martin Decky
[3eddaff]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
[a63966d]29/** @addtogroup init
[b2951e2]30 * @{
[c91c9fb]31 */
[b2951e2]32/**
33 * @file
34 */
35
[0b63dc2]36#include <fibril.h>
[00c4994]37#include <stdio.h>
[6d5e378]38#include <stdarg.h>
[860271d4]39#include <vfs/vfs.h>
[3e6a98c5]40#include <stdbool.h>
[860271d4]41#include <errno.h>
42#include <task.h>
[38d150e]43#include <stdlib.h>
[c91c9fb]44#include <macros.h>
[19f857a]45#include <str.h>
[15f3c3f]46#include <loc.h>
[d9fae235]47#include <str_error.h>
[73d8600]48#include <config.h>
[8e9b2534]49#include <io/logctl.h>
[0b63dc2]50#include <vfs/vfs.h>
[63c1dd5]51#include <vol.h>
[75701004]52#include "untar.h"
[860271d4]53#include "init.h"
54
[d9fae235]55#define ROOT_DEVICE "bd/initrd"
56#define ROOT_MOUNT_POINT "/"
57
[15f3c3f]58#define LOCFS_FS_TYPE "locfs"
59#define LOCFS_MOUNT_POINT "/loc"
[47a350f]60
[1ab0852]61#define TMPFS_FS_TYPE "tmpfs"
62#define TMPFS_MOUNT_POINT "/tmp"
[d9fae235]63
[8fefd8b]64#define SRV_CONSOLE "/srv/hid/console"
[df747bd8]65#define APP_GETTERM "/app/getterm"
[47a350f]66
[0b63dc2]67#define SRV_DISPLAY "/srv/hid/display"
[6d5e378]68
69#define HID_INPUT "hid/input"
70#define HID_OUTPUT "hid/output"
71#define HID_COMPOSITOR_SERVER ":0"
72
73#define srv_start(path, ...) \
74 srv_startl(path, path, ##__VA_ARGS__, NULL)
75
[63c1dd5]76static const char *sys_dirs[] = {
77 "/w/cfg",
78 "/w/data"
79};
80
[53d6ac3d]81/** Print banner */
[36b8100a]82static void info_print(void)
83{
[d9fae235]84 printf("%s: HelenOS init\n", NAME);
[36b8100a]85}
86
[53d6ac3d]87/** Report mount operation success */
[d9fae235]88static bool mount_report(const char *desc, const char *mntpt,
[b7fd2a0]89 const char *fstype, const char *dev, errno_t rc)
[860271d4]90{
[f49cf64]91 switch (rc) {
92 case EOK:
[75701004]93 if ((dev != NULL) && (str_cmp(dev, "") != 0))
[d9fae235]94 printf("%s: %s mounted on %s (%s at %s)\n", NAME, desc, mntpt,
95 fstype, dev);
96 else
97 printf("%s: %s mounted on %s (%s)\n", NAME, desc, mntpt, fstype);
[f49cf64]98 break;
99 case EBUSY:
[d9fae235]100 printf("%s: %s already mounted on %s\n", NAME, desc, mntpt);
[f49cf64]101 return false;
102 case ELIMIT:
[d9fae235]103 printf("%s: %s limit exceeded\n", NAME, desc);
[f49cf64]104 return false;
105 case ENOENT:
[d9fae235]106 printf("%s: %s unknown type (%s)\n", NAME, desc, fstype);
[f49cf64]107 return false;
108 default:
[d9fae235]109 printf("%s: %s not mounted on %s (%s)\n", NAME, desc, mntpt,
110 str_error(rc));
[f49cf64]111 return false;
[860271d4]112 }
[a35b458]113
[860271d4]114 return true;
115}
116
[75701004]117/** Mount root file system
[53d6ac3d]118 *
[75701004]119 * The operation blocks until the root file system
[53d6ac3d]120 * server is ready for mounting.
121 *
[75701004]122 * @param[in] fstype Root file system type.
[53d6ac3d]123 *
124 * @return True on success.
125 * @return False on failure.
126 *
127 */
[d9fae235]128static bool mount_root(const char *fstype)
[a095d20]129{
[75701004]130 const char *root_device = "";
[a35b458]131
[75701004]132 if (str_cmp(fstype, "tmpfs") != 0)
133 root_device = ROOT_DEVICE;
[a35b458]134
[75701004]135 errno_t rc = vfs_mount_path(ROOT_MOUNT_POINT, fstype, root_device, "",
[4979403]136 IPC_FLAG_BLOCKING, 0);
[8e9b2534]137 if (rc == EOK)
138 logctl_set_root();
[75701004]139
140 bool ret = mount_report("Root file system", ROOT_MOUNT_POINT, fstype,
141 root_device, rc);
142
143 rc = vfs_cwd_set(ROOT_MOUNT_POINT);
144 if (rc != EOK) {
145 printf("%s: Unable to set current directory to %s (%s)\n",
146 NAME, ROOT_MOUNT_POINT, str_error(ret));
147 return false;
148 }
149
150 if ((ret) && (str_cmp(fstype, "tmpfs") == 0)) {
151 printf("%s: Extracting root file system archive\n", NAME);
152 ret = bd_untar(ROOT_DEVICE);
153 }
154
155 return ret;
[d9fae235]156}
157
[75701004]158/** Mount locfs file system
[53d6ac3d]159 *
[75701004]160 * The operation blocks until the locfs file system
[53d6ac3d]161 * server is ready for mounting.
162 *
163 * @return True on success.
164 * @return False on failure.
165 *
166 */
[15f3c3f]167static bool mount_locfs(void)
[d9fae235]168{
[b7fd2a0]169 errno_t rc = vfs_mount_path(LOCFS_MOUNT_POINT, LOCFS_FS_TYPE, "", "",
[4979403]170 IPC_FLAG_BLOCKING, 0);
[75701004]171 return mount_report("Location service file system", LOCFS_MOUNT_POINT,
[15f3c3f]172 LOCFS_FS_TYPE, NULL, rc);
[a095d20]173}
174
[b7fd2a0]175static errno_t srv_startl(const char *path, ...)
[860271d4]176{
[39330200]177 vfs_stat_t s;
[23a0368]178 if (vfs_stat_path(path, &s) != EOK) {
[6d5e378]179 printf("%s: Unable to stat %s\n", NAME, path);
180 return ENOENT;
181 }
[a35b458]182
[6d5e378]183 printf("%s: Starting %s\n", NAME, path);
[a35b458]184
[6d5e378]185 va_list ap;
186 const char *arg;
187 int cnt = 0;
[a35b458]188
[6d5e378]189 va_start(ap, path);
190 do {
191 arg = va_arg(ap, const char *);
192 cnt++;
193 } while (arg != NULL);
194 va_end(ap);
[a35b458]195
[6d5e378]196 va_start(ap, path);
197 task_id_t id;
[1c635d6]198 task_wait_t wait;
[b7fd2a0]199 errno_t rc = task_spawn(&id, &wait, path, cnt, ap);
[6d5e378]200 va_end(ap);
[a35b458]201
[0485135]202 if (rc != EOK) {
[6d5e378]203 printf("%s: Error spawning %s (%s)\n", NAME, path,
[0485135]204 str_error(rc));
[6d5e378]205 return rc;
[0485135]206 }
[a35b458]207
[95bc57c]208 if (!id) {
[6d5e378]209 printf("%s: Error spawning %s (invalid task id)\n", NAME,
210 path);
211 return EINVAL;
[95bc57c]212 }
[a35b458]213
[6d5e378]214 task_exit_t texit;
215 int retval;
[1c635d6]216 rc = task_wait(&wait, &texit, &retval);
[95bc57c]217 if (rc != EOK) {
[6d5e378]218 printf("%s: Error waiting for %s (%s)\n", NAME, path,
[0485135]219 str_error(rc));
[6d5e378]220 return rc;
[95bc57c]221 }
[a35b458]222
[0485135]223 if (texit != TASK_EXIT_NORMAL) {
224 printf("%s: Server %s failed to start (unexpectedly "
[6d5e378]225 "terminated)\n", NAME, path);
226 return EINVAL;
[0485135]227 }
[a35b458]228
[6d5e378]229 if (retval != 0)
[0485135]230 printf("%s: Server %s failed to start (exit code %d)\n", NAME,
[6d5e378]231 path, retval);
[a35b458]232
[1569a9b]233 return retval == 0 ? EOK : EPARTY;
[95bc57c]234}
235
[b7fd2a0]236static errno_t console(const char *isvc, const char *osvc)
[47a350f]237{
[15f3c3f]238 /* Wait for the input service to be ready */
239 service_id_t service_id;
[b7fd2a0]240 errno_t rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
[0485135]241 if (rc != EOK) {
[7c014d1]242 printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
[d9fae235]243 str_error(rc));
[6d5e378]244 return rc;
[0485135]245 }
[a35b458]246
[6d5e378]247 /* Wait for the output service to be ready */
248 rc = loc_service_get_id(osvc, &service_id, IPC_FLAG_BLOCKING);
[0485135]249 if (rc != EOK) {
[6d5e378]250 printf("%s: Error waiting on %s (%s)\n", NAME, osvc,
[7c014d1]251 str_error(rc));
[6d5e378]252 return rc;
253 }
[a35b458]254
[6d5e378]255 return srv_start(SRV_CONSOLE, isvc, osvc);
256}
257
[0b63dc2]258static errno_t display_server(void)
[6d5e378]259{
[0b63dc2]260 return srv_start(SRV_DISPLAY);
[6d5e378]261}
262
[0b63dc2]263static int gui_start(const char *app)
[6d5e378]264{
[0b63dc2]265 printf("%s: Spawning %s\n", NAME, app);
[a35b458]266
[6d5e378]267 task_id_t id;
[1c635d6]268 task_wait_t wait;
[0b63dc2]269 errno_t rc = task_spawnl(&id, &wait, app, app, NULL);
[7c014d1]270 if (rc != EOK) {
[0b63dc2]271 printf("%s: Error spawning %s (%s)\n", NAME, app,
272 str_error(rc));
[6d5e378]273 return -1;
[0485135]274 }
[a35b458]275
[6d5e378]276 task_exit_t texit;
277 int retval;
[1c635d6]278 rc = task_wait(&wait, &texit, &retval);
[6d5e378]279 if ((rc != EOK) || (texit != TASK_EXIT_NORMAL)) {
280 printf("%s: Error retrieving retval from %s (%s)\n", NAME,
281 app, str_error(rc));
282 return -1;
[0485135]283 }
[a35b458]284
[6d5e378]285 return retval;
[47a350f]286}
287
[593e023]288static void getterm(const char *svc, const char *app, bool msg)
[36b8100a]289{
[593e023]290 if (msg) {
291 printf("%s: Spawning %s %s %s --msg --wait -- %s\n", NAME,
292 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
[a35b458]293
[b7fd2a0]294 errno_t rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
[593e023]295 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL);
296 if (rc != EOK)
297 printf("%s: Error spawning %s %s %s --msg --wait -- %s\n",
298 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
[4deb8b5]299 } else {
[593e023]300 printf("%s: Spawning %s %s %s --wait -- %s\n", NAME,
301 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
[a35b458]302
[b7fd2a0]303 errno_t rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
[593e023]304 LOCFS_MOUNT_POINT, "--wait", "--", app, NULL);
305 if (rc != EOK)
306 printf("%s: Error spawning %s %s %s --wait -- %s\n",
307 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
[0485135]308 }
[36b8100a]309}
310
[1ab0852]311static bool mount_tmpfs(void)
[03333bc]312{
[b7fd2a0]313 errno_t rc = vfs_mount_path(TMPFS_MOUNT_POINT, TMPFS_FS_TYPE, "", "", 0, 0);
[75701004]314 return mount_report("Temporary file system", TMPFS_MOUNT_POINT,
[1ab0852]315 TMPFS_FS_TYPE, NULL, rc);
[03333bc]316}
317
[63c1dd5]318/** Init system volume.
319 *
320 * See if system volume is configured. If so, try to wait for it to become
321 * available. If not, create basic directories for live image omde.
322 */
323static errno_t init_sysvol(void)
324{
325 vol_t *vol = NULL;
326 vol_info_t vinfo;
327 volume_id_t *volume_ids = NULL;
328 size_t nvols;
329 size_t i;
330 errno_t rc;
331 bool found_cfg;
332 const char **cp;
333
334 rc = vol_create(&vol);
335 if (rc != EOK) {
336 printf("Error contacting volume service.\n");
337 goto error;
338 }
339
340 rc = vol_get_volumes(vol, &volume_ids, &nvols);
341 if (rc != EOK) {
342 printf("Error getting list of volumes.\n");
343 goto error;
344 }
345
346 /* XXX This could be handled more efficiently by volsrv itself */
347 found_cfg = false;
348 for (i = 0; i < nvols; i++) {
349 rc = vol_info(vol, volume_ids[i], &vinfo);
350 if (rc != EOK) {
351 printf("Error getting volume information.\n");
352 rc = EIO;
353 goto error;
354 }
355
356 if (str_cmp(vinfo.path, "/w") == 0) {
357 found_cfg = true;
358 break;
359 }
360 }
361
362 vol_destroy(vol);
363 free(volume_ids);
364
365 if (!found_cfg) {
366 /* Prepare directory structure for live image mode */
367 printf("%s: Creating live image directory structure.\n", NAME);
368 cp = sys_dirs;
369 while (*cp != NULL) {
370 rc = vfs_link_path(*cp, KIND_DIRECTORY, NULL);
371 if (rc != EOK) {
372 printf("%s: Error creating directory '%s'.\n",
373 NAME, *cp);
374 return rc;
375 }
376
377 ++cp;
378 }
379 } else {
380 printf("%s: System volume is configured.\n", NAME);
381 }
382
383 return EOK;
384error:
385 vol_destroy(vol);
386 if (volume_ids != NULL)
387 free(volume_ids);
388
389 return rc;
390}
391
[5106e98]392int main(int argc, char *argv[])
393{
[b7fd2a0]394 errno_t rc;
[73d8600]395
[860271d4]396 info_print();
[a35b458]397
[36b8100a]398 if (!mount_root(STRING(RDFMT))) {
[d9fae235]399 printf("%s: Exiting\n", NAME);
[6d5e378]400 return 1;
[860271d4]401 }
[a35b458]402
[395df52]403 /* Make sure file systems are running. */
[6d5e378]404 if (str_cmp(STRING(RDFMT), "tmpfs") != 0)
[8fefd8b]405 srv_start("/srv/fs/tmpfs");
[395df52]406 if (str_cmp(STRING(RDFMT), "exfat") != 0)
[8fefd8b]407 srv_start("/srv/fs/exfat");
[395df52]408 if (str_cmp(STRING(RDFMT), "fat") != 0)
[8fefd8b]409 srv_start("/srv/fs/fat");
410 srv_start("/srv/fs/cdfs");
411 srv_start("/srv/fs/mfs");
[a35b458]412
[ca05e9b]413 srv_start("/srv/klog");
[8fefd8b]414 srv_start("/srv/fs/locfs");
[5cd1eb9a]415 srv_start("/srv/taskmon");
[a35b458]416
[15f3c3f]417 if (!mount_locfs()) {
[d9fae235]418 printf("%s: Exiting\n", NAME);
[6d5e378]419 return 2;
[a095d20]420 }
[a35b458]421
[1ab0852]422 mount_tmpfs();
[a35b458]423
[6d5e378]424 srv_start("/srv/devman");
[8fefd8b]425 srv_start("/srv/hid/s3c24xx_uart");
426 srv_start("/srv/hid/s3c24xx_ts");
[a35b458]427
[8fefd8b]428 srv_start("/srv/bd/vbd");
[dc2d582]429 srv_start("/srv/volsrv");
[a35b458]430
[8fefd8b]431 srv_start("/srv/net/loopip");
432 srv_start("/srv/net/ethip");
433 srv_start("/srv/net/inetsrv");
434 srv_start("/srv/net/tcp");
435 srv_start("/srv/net/udp");
436 srv_start("/srv/net/dnsrsrv");
437 srv_start("/srv/net/dhcp");
438 srv_start("/srv/net/nconfsrv");
[a35b458]439
[6d5e378]440 srv_start("/srv/clipboard");
[8fefd8b]441 srv_start("/srv/hid/remcons");
[a35b458]442
[8fefd8b]443 srv_start("/srv/hid/input", HID_INPUT);
444 srv_start("/srv/hid/output", HID_OUTPUT);
445 srv_start("/srv/audio/hound");
[a35b458]446
[63c1dd5]447 init_sysvol();
448
[73d8600]449 if (!config_key_exists("console")) {
[0b63dc2]450 rc = display_server();
[73d8600]451 if (rc == EOK) {
[0b63dc2]452 fibril_sleep(1);
[02f45748]453 gui_start("/app/terminal");
[73d8600]454 }
[593e023]455 }
[a35b458]456
[593e023]457 rc = console(HID_INPUT, HID_OUTPUT);
458 if (rc == EOK) {
459 getterm("term/vc0", "/app/bdsh", true);
460 getterm("term/vc1", "/app/bdsh", false);
461 getterm("term/vc2", "/app/bdsh", false);
462 getterm("term/vc3", "/app/bdsh", false);
463 getterm("term/vc4", "/app/bdsh", false);
464 getterm("term/vc5", "/app/bdsh", false);
[6d5e378]465 }
[a35b458]466
[3eddaff]467 return 0;
468}
[b2951e2]469
470/** @}
471 */
Note: See TracBrowser for help on using the repository browser.