1/** 2 * \file 3 * \brief 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <inttypes.h> 18#include <barrelfish/barrelfish.h> 19#include <spawndomain/spawndomain.h> 20#include "spawn.h" 21 22#ifndef min 23#define min(a,b) ((a) < (b) ? (a) : (b)) 24#endif 25#ifndef max 26#define max(a,b) ((a) > (b) ? (a) : (b)) 27#endif 28 29const char *multiboot_strings = NULL; 30 31const char *getopt_module(struct mem_region *module) 32{ 33 assert(module != NULL); 34 assert(module->mr_type == RegionType_Module); 35 36 const char *optstring = multiboot_strings + module->mrmod_data; 37 38 // find the first space (or end of string if there is none) 39 const char *args = strchr(optstring, ' '); 40 if (args == NULL) { 41 args = optstring + strlen(optstring); 42 } 43 44 // search backward for last '/' before the first ' ' 45 for (const char *c = args; c > optstring; c--) { 46 if (*c == '/') { 47 return c + 1; 48 } 49 } 50 51 return optstring; 52} 53 54/// Map in the frame caps for a module into our vspace, return their location 55errval_t spawn_map_module(struct mem_region *module, size_t *retsize, 56 lvaddr_t *retaddr, genpaddr_t *retpaddr) 57{ 58 assert(module != NULL); 59 assert(module->mr_type == RegionType_Module); 60 61 errval_t err; 62 63 size_t size = module->mrmod_size; 64 65 void *base; 66 struct memobj *memobj; 67 struct vregion *vregion; 68 69 err = vspace_map_anon_attr(&base, &memobj, &vregion, size, &size, 70 VREGION_FLAGS_READ); 71 if (err_is_fail(err)) { 72 return err_push(err, LIB_ERR_VSPACE_MAP); 73 } 74 struct capref frame = { 75 .cnode = cnode_module, 76 .slot = module->mrmod_slot, 77 }; 78 79 if (retpaddr != NULL) { 80 *retpaddr = module->mr_base; 81 } 82 83 if (retsize != NULL) { 84 *retsize = size; 85 } 86 87 if (retaddr != NULL) { 88 *retaddr = (lvaddr_t)base; 89 } 90 91 assert((size & BASE_PAGE_MASK) == 0); 92 93 struct frame_identity id; 94 err = frame_identify(frame, &id); 95 assert(err_is_ok(err)); 96 // all multiboot modules backed with a single cap 97 assert(size <= id.bytes); 98 99 err = memobj->f.fill(memobj, 0, frame, id.bytes); 100 if (err_is_fail(err)) { 101 return err_push(err, LIB_ERR_MEMOBJ_FILL); 102 } 103 104 err = memobj->f.pagefault(memobj, vregion, 0, 0); 105 if (err_is_fail(err)) { 106 return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); 107 } 108 109 return SYS_ERR_OK; 110} 111 112errval_t spawn_unmap_module(lvaddr_t mapped_addr) 113{ 114 return vspace_unmap((void *)mapped_addr); 115} 116 117/// Returns a raw pointer to the modules string area string 118const char *multiboot_module_rawstring(struct mem_region *region) 119{ 120 if (multiboot_strings == NULL) { 121 errval_t err; 122 /* Map in multiboot module strings area */ 123 struct capref mmstrings_cap = { 124 .cnode = cnode_module, 125 .slot = 0 126 }; 127 err = vspace_map_one_frame_attr((void**)&multiboot_strings, 128 BASE_PAGE_SIZE, mmstrings_cap, 129 VREGION_FLAGS_READ, 130 NULL, NULL); 131 if (err_is_fail(err)) { 132 DEBUG_ERR(err, "vspace_map failed"); 133 return NULL; 134 } 135#if 0 136 printf("Mapped multiboot_strings at %p\n", multiboot_strings); 137 for (int i = 0; i < 256; i++) { 138 if ((i & 15) == 0) printf("%04x ", i); 139 printf ("%02x ", multiboot_strings[i]& 0xff); 140 if ((i & 15) == 15) printf("\n"); 141 } 142#endif 143 } 144 145 if (region == NULL || region->mr_type != RegionType_Module) { 146 return NULL; 147 } 148 return multiboot_strings + region->mrmod_data; 149} 150 151errval_t multiboot_cleanup_mapping(void) 152{ 153 errval_t err = vspace_unmap(multiboot_strings); 154 if (err_is_fail(err)) { 155 DEBUG_ERR(err, "multiboot_cleanup_mapping: vspace_unmap() failed\n"); 156 return err_push(err, LIB_ERR_VSPACE_REMOVE_REGION); 157 } 158 multiboot_strings = NULL; 159 return SYS_ERR_OK; 160} 161 162 163/// returns the basename without arguments of a multiboot module 164// XXX: returns pointer to static buffer. NOT THREAD SAFE 165const char *multiboot_module_name(struct mem_region *region) 166{ 167 const char *str = multiboot_module_rawstring(region); 168 if (str == NULL) { 169 return NULL; 170 } 171 172 // copy module data to local buffer so we can mess with it 173 static char buf[128]; 174 strncpy(buf, str, sizeof(buf)); 175 buf[sizeof(buf) - 1] = '\0'; // ensure termination 176 177 // ignore arguments for name comparison 178 char *args = strchr(buf, ' '); 179 if (args != NULL) { 180 *args = '\0'; 181 } 182 183 return buf; 184} 185 186struct mem_region *multiboot_find_module(struct bootinfo *bi, const char *name) 187{ 188 189 for(size_t i = 0; i < bi->regions_length; i++) { 190 struct mem_region *region = &bi->regions[i]; 191 const char *modname = multiboot_module_name(region); 192 if (modname != NULL && 193 strncmp(modname + strlen(modname) - strlen(name), 194 name, strlen(name)) == 0) { 195 return region; 196 } 197 } 198 199 return NULL; 200} 201 202struct mem_region *multiboot_find_module_containing(struct bootinfo *bi, 203 const char *name, 204 const char *containing) 205{ 206 assert(bi != NULL); 207 assert(name != NULL); 208 assert(containing != NULL); 209 210 size_t namelen = strlen(name); 211 212 for(size_t i = 0; i < bi->regions_length; i++) { 213 struct mem_region *region = &bi->regions[i]; 214 if (region->mr_type != RegionType_Module) 215 continue; 216 const char *raw = multiboot_module_rawstring(region); 217 if (raw == NULL) 218 continue; 219 220 const char *space = strchr(raw, ' '); 221 if (space == NULL || (space - raw < namelen)) 222 continue; 223 224 if (strncmp(space - namelen, name, namelen)) 225 continue; 226 227 if ((strstr(raw, containing)) != NULL) 228 return region; 229 } 230 231 return NULL; 232} 233 234