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, Universitaetstrasse 6, 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 = 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 = 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