1#define _USE_XOPEN /* for strdup() */ 2#include <stdio.h> 3#include <string.h> 4 5#include <barrelfish/barrelfish.h> 6#include <barrelfish/cpu_arch.h> // for CURRENT_CPU_TYPE 7#include <barrelfish/spawn_client.h> 8 9#include <spawndomain/spawndomain.h> 10#include <vfs/vfs.h> 11 12#include "kaluga.h" 13#include "debug.h" 14 15#define MAX_DRIVER_MODULES 128 16 17static struct module_info modules[MAX_DRIVER_MODULES]; 18 19inline bool is_auto_driver(struct module_info* mi) { 20 return mi->argc > 1 && strcmp(mi->argv[1], "auto") == 0; 21} 22 23inline bool is_started(struct module_info* mi) 24{ 25 return (mi->num_started); 26} 27 28inline bool can_start(struct module_info* mi) 29{ 30 return (mi->allow_multi || (mi->num_started == 0)); 31} 32 33void set_start_function(char* binary, module_start_fn start_fn) 34{ 35 struct module_info* mi = find_module(binary); 36 if (mi != NULL) { 37 mi->start_function = start_fn; 38 } 39} 40 41void set_started(struct module_info* mi) 42{ 43 mi->num_started += 1; 44 assert(mi->allow_multi || (mi->num_started == 1)); 45} 46 47void set_multi_instance(struct module_info* mi, uint8_t is_multi) 48{ 49 mi->allow_multi = (is_multi != 0); 50} 51 52void set_core_id_offset(struct module_info* mi, coreid_t offset) 53{ 54 mi->coreoffset = offset; 55} 56 57struct capref *get_did_ptr(struct module_info *mi) 58{ 59 return (mi->did + mi->num_started); 60} 61 62coreid_t get_core_id_offset(struct module_info* mi) 63{ 64 return mi->coreoffset * mi->num_started; 65} 66 67struct module_info* find_module(char *binary) 68{ 69 assert(binary != NULL); 70 bool found = false; 71 struct module_info* si = NULL; 72 73 for (size_t i=0; i< MAX_DRIVER_MODULES; i++) { 74 si = &modules[i]; 75 if (si->binary != NULL && strcmp(si->binary, binary) == 0) { 76 found = true; 77 break; 78 } 79 } 80 81 return (found) ? si : NULL; 82} 83 84/** 85 * @brief finds corectrl driver module for a given CPU type. 86 * 87 * @param cpu_type the CPU type 88 * 89 * @return pointer to the corectrl module, or NULL if not existing 90 */ 91struct module_info* find_corectrl_for_cpu_type(enum cpu_type cpu_type) 92{ 93 switch(cpu_type) { 94 case CPU_K1OM: 95 case CPU_X86_64: 96 case CPU_X86_32: 97 case CPU_ARM7: 98 case CPU_ARM8: 99 return find_module("corectrl"); 100 break; 101 default: 102 return NULL; 103 break; 104 } 105} 106 107static void parse_module(char* line, struct module_info* si) 108{ 109 si->complete_line = strdup(line); 110 111 char* path_end = strchr(line, ' '); 112 if (path_end == NULL) { 113 path_end = line + strlen(line); 114 } 115 size_t path_size = path_end-line; 116 si->path = malloc(path_size+1); 117 strncpy(si->path, line, path_size); 118 si->path[path_size] = '\0'; 119 120 char* binary_start = strrchr(si->path, '/'); 121 si->binary = strdup(binary_start+1); // exclude / 122 memset(si->did, 0, sizeof(si->did)); 123 si->start_function = default_start_function; 124 si->num_started = 0; 125 char* cmdstart = line + path_size - strlen(si->binary); 126 si->args = strdup(line + path_size); 127 128 // cmdargs will be tagged with \0 129 si->cmdargs = strdup(cmdstart); 130 si->argc = spawn_tokenize_cmdargs(si->cmdargs, si->argv, 131 ARRAY_LENGTH(si->argv)); 132} 133 134/** 135 * \brief Parses bootmodules and stores info in 136 * boot_modules. 137 */ 138static errval_t parse_modules(char* bootmodules) 139{ 140 assert(bootmodules != NULL); 141 142 size_t entry = 0; 143 char* bm = strdup(bootmodules); 144 145 static const char* delim = "\n"; 146 char* line = strtok(bm, delim); 147 148 while (line != NULL && entry < MAX_DRIVER_MODULES) { 149 struct module_info* si = &modules[entry++]; 150 parse_module(line, si); 151 KALUGA_DEBUG("found boot module:\n%s\n%s\n%s (%d)\n", si->binary, si->path, si->cmdargs, si->argc); 152 153 line = strtok(NULL, delim); 154 } 155 free(bm); 156 157 if (line == NULL) { 158 return SYS_ERR_OK; 159 } 160 else { 161 return KALUGA_ERR_PARSE_MODULES; 162 } 163} 164 165/** 166 * \brief Open bootmodules file and read it in 167 */ 168static char* get_bootmodules(void) 169{ 170 errval_t err; 171 172 // open bootmodules file and read it in 173 vfs_handle_t vh; 174 err = vfs_open("/bootmodules", &vh); 175 if (err_is_fail(err)) { 176 USER_PANIC_ERR(err, "unable to open /bootmodules"); 177 } 178 179 struct vfs_fileinfo info; 180 err = vfs_stat(vh, &info); 181 if (err_is_fail(err)) { 182 USER_PANIC_ERR(err, "unable to stat /bootmodules"); 183 } 184 185 char *bootmodules = malloc(info.size + 1); 186 if (bootmodules == NULL) { 187 USER_PANIC_ERR(LIB_ERR_MALLOC_FAIL, 188 "failed to allocate memory for bootmodules"); 189 } 190 size_t bootmodules_len; 191 err = vfs_read(vh, bootmodules, info.size, &bootmodules_len); 192 if (err_is_fail(err)) { 193 USER_PANIC_ERR(err, "unable to read /bootmodules"); 194 } else if (bootmodules_len == 0) { 195 USER_PANIC_ERR(err, "/bootmodules is empty"); 196 } else if (bootmodules_len != info.size) { 197 USER_PANIC_ERR(err, "unexpected short read of /bootmodules"); 198 } 199 200 err = vfs_close(vh); 201 if (err_is_fail(err)) { 202 DEBUG_ERR(err, "could not close bottmodules file"); 203 } 204 205 // terminate as a string 206 bootmodules[bootmodules_len] = '\0'; 207 return bootmodules; 208} 209 210/** 211 * \brief Set an initial default environment for our boot-time children 212 */ 213void init_environ(void) 214{ 215 int r; 216 217 /* PATH=/build-arch/sbin */ 218 char pathstr[64]; 219 snprintf(pathstr, sizeof(pathstr), "/" BF_BINARY_PREFIX "%s/sbin", 220 cpu_type_to_archstr(CURRENT_CPU_TYPE)); 221 pathstr[sizeof(pathstr) - 1] = '\0'; 222 r = setenv("PATH", pathstr, 0); 223 if (r != 0) { 224 USER_PANIC("failed to set PATH"); 225 } 226 227 /* HOME=/ */ 228 r = setenv("HOME", "/", 0); 229 if (r != 0) { 230 USER_PANIC("failed to set HOME"); 231 } 232} 233 234errval_t init_boot_modules(void) 235{ 236 char* bootmodules = get_bootmodules(); 237 errval_t err = parse_modules(bootmodules); 238 free(bootmodules); 239 240 return err; 241} 242 243errval_t init_driver_argument(struct driver_argument *arg){ 244 int_startup_argument_init(&arg->int_arg); 245 errval_t err = cnode_create_l2(&arg->arg_caps, &arg->argnode_ref); 246 if(err_is_fail(err)){ 247 DEBUG_ERR(err, "Could not cnode_create_l2"); 248 return err; 249 } 250 return SYS_ERR_OK; 251} 252 253