1/**
2 * \file
3 * \brief Architecture independent code
4 */
5/*
6 * Copyright (c) 2014, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include "coreboot.h"
15#include <if/monitor_blocking_defs.h>
16
17extern bool done;
18extern coreid_t core_count;
19extern coreid_t core_max;
20extern struct capref kcb;
21
22char* get_binary_path(char* fmt, char* binary_name)
23{
24    assert (binary_name != NULL);
25    assert (fmt != NULL);
26
27    int length = snprintf(NULL, 0, fmt, binary_name);
28    char* binary = malloc(length+1); // TODO(gz): Free this
29    snprintf(binary, length+1, fmt, binary_name);
30
31    return binary;
32}
33
34errval_t elfload_allocate(void *state, genvaddr_t base,
35                          size_t size, uint32_t flags,
36                          void **retbase)
37{
38    struct elf_allocate_state *s = state;
39
40    *retbase = (char *)s->vbase + base - s->elfbase;
41    return SYS_ERR_OK;
42}
43
44void boot_core_reply(struct monitor_binding *st, errval_t msgerr)
45{
46    if (err_is_fail(msgerr)) {
47        USER_PANIC_ERR(msgerr, "msgerr in boot_core_reply, exiting\n");
48    }
49    DEBUG("%s:%d: got boot_core_reply.\n", __FILE__, __LINE__);
50    core_count++;
51    if (core_count == core_max) {
52        done = true;
53    }
54}
55
56static errval_t add_kcb_record(uint32_t kcb_id, coreid_t core_id, char* kcb_key)
57{
58    errval_t err = oct_set("kcb.%d { kcb_id: %d, barrelfish_id: %"PRIuCOREID", cap_key: '%s' }",
59                            kcb_id, kcb_id, core_id, kcb_key);
60    if (err_is_fail(err)) {
61        DEBUG_ERR(err, "oct_set");
62        return err;
63    }
64
65    return err;
66}
67
68errval_t create_or_get_kcb_cap(coreid_t coreid, struct capref* the_kcb)
69{
70    errval_t err;
71    struct capref kcb_mem;
72
73    DEBUG("%s:%s:%d: get capability\n",
74          __FILE__, __FUNCTION__, __LINE__);
75
76    int length = snprintf(NULL, 0, "kcb_id_%d", coreid) + 1; // +1 for \0
77    char *kcb_key = (char *)malloc(length);
78    assert (kcb_key != NULL);
79    snprintf(kcb_key, length + 1, "kcb_id_%d", coreid);
80
81    DEBUG("%s:%s:%d: oct_get_capability for key = %s\n",
82          __FILE__, __FUNCTION__, __LINE__, kcb_key);
83
84    if (!new_kcb_flag) {
85        err = oct_get_capability(kcb_key, the_kcb);
86        if (err_is_ok(err)) {
87            DEBUG("%s:%s:%d: kcb cap was cached\n",
88                  __FILE__, __FUNCTION__, __LINE__);
89            return err;
90        } else if (err_no(err) != OCT_ERR_CAP_NAME_UNKNOWN) {
91            DEBUG("%s:%s:%d: did not find the kcb in cap storage\n",
92                  __FILE__, __FUNCTION__, __LINE__);
93            return err;
94        }
95    }
96    DEBUG("%s:%s:%d: Create a new kcb (new_kcb_flag = %d)\n",
97          __FILE__, __FUNCTION__, __LINE__, new_kcb_flag);
98
99    assert(1 << log2ceil(OBJSIZE_KCB) == OBJSIZE_KCB);
100    err = ram_alloc(&kcb_mem, log2ceil(OBJSIZE_KCB));
101    if (err_is_fail(err)) {
102        DEBUG_ERR(err, "frame alloc");
103        return err;
104    }
105
106    err = slot_alloc(the_kcb);
107    if (err_is_fail(err)) {
108        DEBUG_ERR(err, "Failure in slot_alloc.");
109        return err;
110    }
111
112    err = cap_retype(*the_kcb, kcb_mem, 0,
113                     ObjType_KernelControlBlock,
114                     OBJSIZE_KCB, 1);
115    if (err_is_fail(err)) {
116        DEBUG_ERR(err, "Failure in cap_retype.");
117    }
118
119    // HACK don't store KCB right now will leak with -nm flags!
120    if (!new_kcb_flag) {
121        DEBUG("%s:%s:%d: Store the kcb.\n",
122              __FILE__, __FUNCTION__, __LINE__);
123        err = oct_put_capability(kcb_key, *the_kcb);
124        if (err_is_fail(err)) {
125            DEBUG_ERR(err, "can not save the capability.");
126            return err;
127        }
128
129        err = add_kcb_record(coreid, coreid, kcb_key);
130        if (err_is_fail(err)) {
131            DEBUG_ERR(err, "add_kcb_record failed.");
132            return err;
133        }
134    }
135
136    return err;
137}
138
139errval_t give_kcb_to_new_core(coreid_t destination_id, struct capref new_kcb)
140{
141    struct monitor_blocking_binding *mc = get_monitor_blocking_binding();
142    DEBUG("%s:%s:%d: Send KCB to local monitor for forwarding to destination_id = %"PRIuCOREID"\n",
143          __FILE__, __FUNCTION__, __LINE__, destination_id);
144
145    errval_t ret_err;
146    errval_t err = mc->rpc_tx_vtbl.forward_kcb_request(mc, destination_id, new_kcb,
147                   &ret_err);
148    if (err_is_fail(err)) {
149        USER_PANIC_ERR(err, "forward_kcb_request failed.");
150    }
151    if (err_is_fail(ret_err)) {
152        USER_PANIC_ERR(ret_err, "forward_kcb_request failed.");
153    }
154
155    DEBUG("%s:%s:%d: KCB forwarded\n", __FILE__, __FUNCTION__, __LINE__);
156    return SYS_ERR_OK;
157}
158
159errval_t cap_mark_remote(struct capref cap)
160{
161    errval_t err, msgerr;
162
163    struct monitor_blocking_binding *mc = get_monitor_blocking_binding();
164    err = mc->rpc_tx_vtbl.cap_set_remote(mc, cap, true, &msgerr);
165    if (err_is_fail(err)) {
166        debug_printf("cap_set_remote RPC transmission failed\n");
167        return err;
168    }
169
170    return msgerr;
171}
172
173/**
174 * \brief Same as frame_alloc but also identify the capability.
175 */
176errval_t frame_alloc_identify(struct capref *dest, size_t bytes,
177                              size_t *retbytes, struct frame_identity *id)
178{
179    errval_t err = frame_alloc(dest, bytes, retbytes);
180    if (err_is_fail(err)) {
181        if (err_no(err) != LIB_ERR_RAM_ALLOC_MS_CONSTRAINTS){
182            DEBUG_ERR(err, "frame_alloc failed.");
183        }
184        return err;
185    }
186
187    if (id != NULL) {
188        err = invoke_frame_identify(*dest, id);
189    }
190
191    return err;
192}
193
194static errval_t cache_module(const char *module_name, struct capref binary_image_cap)
195{
196    return oct_put_capability(module_name, binary_image_cap);
197}
198
199static errval_t lookup_module_cache(const char *module_name, struct capref *binary_image_cap)
200{
201    return oct_get_capability(module_name, binary_image_cap);
202}
203
204errval_t lookup_module(const char *module_name, lvaddr_t *binary_virt,
205                       genpaddr_t *binary_phys, size_t *binary_size)
206{
207    vfs_handle_t handle;
208    struct vfs_fileinfo info;
209    struct capref binary_image_cap;
210    struct frame_identity id;
211
212    DEBUG("Trying to find binary %s in file system\n", module_name);
213    errval_t err = vfs_open(module_name, &handle);
214    if (err_is_fail(err)) {
215        DEBUG_ERR(err, "vfs_open could not open module?");
216        return err;
217    }
218
219    err = vfs_stat(handle, &info);
220    if (err_is_fail(err)) {
221        DEBUG_ERR(err, "vfs_stat for binary failed.");
222        return err;
223    }
224    *binary_size = info.size;
225
226    DEBUG("Trying to find module in cache\n");
227    err = lookup_module_cache(module_name, &binary_image_cap);
228    if (err_is_ok(err)) {
229        err = invoke_frame_identify(binary_image_cap, &id);
230        *binary_phys = id.base;
231        DEBUG("%s:%d: id.base=0x%"PRIxGENPADDR"\n", __FILE__, __LINE__, id.base);
232        err = vspace_map_one_frame((void **)binary_virt, info.size, binary_image_cap,
233                                    NULL, NULL);
234        if (err_is_fail(err)) {
235            DEBUG_ERR(err, "Could identify frame from cap storage");
236            return err;
237        }
238    }
239    else {
240        err = frame_alloc_identify(&binary_image_cap, info.size, NULL, &id);
241        if (err_is_fail(err)) {
242            DEBUG_ERR(err, "Could not allocate space for binary");
243            return err;
244        }
245        *binary_phys = id.base;
246        DEBUG("%s:%d: id.base=0x%"PRIxGENPADDR"\n", __FILE__, __LINE__, id.base);
247        err = vspace_map_one_frame((void **)binary_virt, info.size, binary_image_cap,
248                                   NULL, NULL);
249        if (err_is_fail(err)) {
250            DEBUG_ERR(err, "Could not map frame");
251            return err;
252        }
253
254        size_t bytes_read = 0;
255        err = vfs_read(handle, (void *)*binary_virt, info.size, &bytes_read);
256        if (err_is_fail(err)) {
257            DEBUG_ERR(err, "Can not read binary from vfs");
258            return err;
259        }
260        assert(bytes_read ==
261               info.size); // TODO(gz): If this fails, need to loop vfs_read
262
263        err = cache_module(module_name, binary_image_cap);
264        if (err_is_fail(err)) {
265            DEBUG_ERR(err, "Cannot cache the module.");
266            return err;
267        }
268    }
269
270    return SYS_ERR_OK;
271}
272