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, Universitaetstrasse 6, 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 38coreid_t my_core_id; 39bool is_bsp_core; 40const char *gbootmodules; 41 42/* set an initial default environment for our boot-time children */ 43static 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 */ 65static 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 104int 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 // wait for spawnd boot to finish 116 errval_t err = nsb_wait(ALL_SPAWNDS_UP); 117 if (err_is_fail(err)) { 118 USER_PANIC_ERR(err, "failed ns barrier wait for %s", ALL_SPAWNDS_UP); 119 } 120 121 // startup distributed services 122 spawn_dist_domains(); 123 124 // startup regular apps 125 spawn_app_domains(); 126 127 // startup apps listed in bootscript 128 spawn_bootscript_domains(); 129 130 spawn_arrakis_domains(); 131 132 return EXIT_SUCCESS; 133} 134