Add BF_BINARY_PREFIX define to configure binary path by build system.
[barrelfish] / usr / startd / main.c
1 /**
2  * \file
3  * \brief Startup daemon for Barrelfish.
4  * At boot, after spawnd has started, startd decides which domains to spawn.
5  * There are two phases to service startup.
6  * 1) startup distributed services.  This proceeds in lockstep, with
7  *    each service being fully started before the next is started.
8  * 2) startup applications. After all distributed services are started then
9  *    the applications are started.  Here the startd does not wait for a
10  *    previous domain to be started before continuing with the next one.
11  */
12
13 /*
14  * Copyright (c) 2010-2012, ETH Zurich.
15  * All rights reserved.
16  *
17  * This file is distributed under the terms in the attached LICENSE file.
18  * If you do not find this file, copies can be found by writing to:
19  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24
25 #include <barrelfish/barrelfish.h>
26 #include <barrelfish/nameservice_client.h>
27 #include <barrelfish_kpi/cpu.h> // for cpu_type_to_archstr()
28 #include <barrelfish/cpu_arch.h> // for CURRENT_CPU_TYPE
29
30 #include <vfs/vfs.h>
31
32 #include <dist/barrier.h>
33
34 #include "internal.h"
35
36 #define ALL_SPAWNDS_UP "all_spawnds_up" // this comes from spawnd/internal.h
37
38 coreid_t my_core_id;
39 bool is_bsp_core;
40 const char *gbootmodules;
41
42 /* set an initial default environment for our boot-time children */
43 static void init_environ(void)
44 {
45     int r;
46
47     char pathstr[64];
48     snprintf(pathstr, sizeof(pathstr), "/" BF_BINARY_PREFIX "%s/sbin",
49              cpu_type_to_archstr(CURRENT_CPU_TYPE));
50     pathstr[sizeof(pathstr) - 1] = '\0';
51     r = setenv("PATH", pathstr, 0);
52     if (r != 0) {
53         USER_PANIC("failed to set PATH");
54     }
55
56     /* HOME=/ */
57     r = setenv("HOME", "/", 0);
58     if (r != 0) {
59         USER_PANIC("failed to set HOME");
60     }
61 }
62
63
64 /* open bootmodules file and read it in */
65 static void get_bootmodules(void)
66 {
67     errval_t err;
68
69     vfs_handle_t vh;
70     err = vfs_open("/bootmodules", &vh);
71     if (err_is_fail(err)) {
72         USER_PANIC_ERR(err, "unable to open /bootmodules");
73     }
74
75     struct vfs_fileinfo info;
76     err = vfs_stat(vh, &info);
77     if (err_is_fail(err)) {
78         USER_PANIC_ERR(err, "unable to stat /bootmodules");
79     }
80
81     char *bootmodules = malloc(info.size + 1);
82     if (bootmodules == NULL) {
83         USER_PANIC_ERR(LIB_ERR_MALLOC_FAIL,
84                        "failed to allocate memory for bootmodules");
85     }
86
87     size_t bootmodules_len;
88     err = vfs_read(vh, bootmodules, info.size, &bootmodules_len);
89     if (err_is_fail(err)) {
90         USER_PANIC_ERR(err, "unable to read /bootmodules");
91     } else if (bootmodules_len == 0) {
92         USER_PANIC("/bootmodules is empty");
93     } else if (bootmodules_len != info.size) {
94         USER_PANIC("unexpected short read of /bootmodules");
95     }
96
97     vfs_close(vh);
98
99     // terminate as a string
100     bootmodules[bootmodules_len] = '\0';
101     gbootmodules = bootmodules;
102 }
103
104 int main(int argc, const char *argv[])
105 {
106     vfs_init();
107     my_core_id = disp_get_core_id();
108
109     // read in the bootmodules file so that we know what to start
110     get_bootmodules();
111
112     // construct sane inital environment
113     init_environ();
114
115 #if defined(__x86_64__) || defined(__i386__)
116     // wait for spawnd boot to finish
117     errval_t err = nsb_wait(ALL_SPAWNDS_UP);
118     if (err_is_fail(err)) {
119         USER_PANIC_ERR(err, "failed ns barrier wait for %s", ALL_SPAWNDS_UP);
120     }
121 #endif
122
123     // startup distributed services
124     spawn_dist_domains();
125
126     // startup regular apps
127     spawn_app_domains();
128
129     // startup apps listed in bootscript
130     spawn_bootscript_domains();
131
132     spawn_arrakis_domains();
133
134     return EXIT_SUCCESS;
135 }