1/*
2 * Copyright (c) 2016, ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <stdio.h>
11#include <string.h>
12
13#include <barrelfish/barrelfish.h>
14#include <barrelfish/spawn_client.h>
15
16#include <driverkit/driverkit.h>
17
18#include "kaluga.h"
19
20#define DRIVER_DOMAIN_NAME "driverdomain"
21
22// Add an argument to argc/argv pair. argv must be mallocd!
23static void argv_push(int * argc, char *** argv, char * new_arg){
24    int new_size = *argc + 1;
25    *argv = realloc(*argv, (new_size+1) * sizeof(char*)); // +1 for last NULL entry.
26    if(*argv == NULL){
27        USER_PANIC("Could not allocate argv memory");
28    }
29    *argc = new_size;
30    (*argv)[new_size-1] = new_arg;
31    (*argv)[new_size] = NULL;
32}
33
34static errval_t launch_driver_domain(coreid_t where, uint64_t did, struct module_info* ddomain)
35{
36    assert(ddomain != NULL);
37    errval_t err = SYS_ERR_OK;
38
39    char **argv = NULL;
40    int argc = ddomain->argc;
41    argv = malloc(sizeof(char*)*ddomain->argc); // +1 for trailing NULL
42    assert(argv != NULL);
43
44    memcpy(argv, ddomain->argv, (argc+1) * sizeof(char *));
45    assert(argv[argc] == NULL);
46
47    char* did_str = calloc(26, sizeof(char));
48    assert(did_str != NULL);
49    snprintf(did_str, 26, "%"PRIu64"", did);
50    argv_push(&argc, &argv, did_str);
51
52    err = spawn_program_with_caps(where, ddomain->path, argv,
53                                  environ, NULL_CAP, NULL_CAP,
54                                  0, get_did_ptr(ddomain));
55    if (err_is_fail(err)) {
56        DEBUG_ERR(err, "Spawning %s failed.", ddomain->path);
57    }
58
59    free(argv);
60    return err;
61}
62
63static void wait_for_id(struct domain_instance* di) {
64    while (di->b == NULL) {
65        messages_wait_and_handle_next();
66    }
67    KALUGA_DEBUG("%s:%s:%d: done with waiting for ID\n", __FILE__, __FUNCTION__, __LINE__);
68}
69
70struct domain_instance* instantiate_driver_domain(char* name, coreid_t where) {
71    static uint64_t did = 1;
72
73    errval_t err = launch_driver_domain(where, did, find_module(name));
74    if (err_is_fail(err)) {
75        USER_PANIC_ERR(err, "call failed.");
76    }
77    struct domain_instance* di = ddomain_create_domain_instance(did);
78    did++;
79
80    wait_for_id(di);
81
82    return di;
83}
84