1// vi:set ft=cpp: -*- Mode: C++ -*- 2/* 3 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 4 * Alexander Warg <warg@os.inf.tu-dresden.de> 5 * economic rights: Technische Universität Dresden (Germany) 6 * 7 * This file is part of TUD:OS and distributed under the terms of the 8 * GNU General Public License 2. 9 * Please see the COPYING-GPL-2 file for details. 10 * 11 * As a special exception, you may use this file as part of a free software 12 * library without restriction. Specifically, if other files instantiate 13 * templates or use macros or inline functions from this file, or you compile 14 * this file and link it with other files to produce an executable, this 15 * file does not by itself cause the resulting executable to be covered by 16 * the GNU General Public License. This exception does not however 17 * invalidate any other reasons why the executable file might be covered by 18 * the GNU General Public License. 19 */ 20#pragma once 21 22#include <l4/cxx/avl_tree> 23#include <l4/cxx/std_ops> 24#include <l4/sys/cxx/ipc_epiface> 25#include <l4/cxx/string> 26 27#include <l4/sys/capability> 28#include <l4/re/namespace> 29 30#include <cstddef> 31 32namespace L4Re { namespace Util { 33 34class Dbg; 35class Err; 36 37namespace Names { 38 39/** 40 * \brief Name class. 41 */ 42class Name : public cxx::String 43{ 44public: 45 46 Name(const char *name = "") : String(name, __builtin_strlen(name)) {} 47 Name(const char *name, unsigned long len) : String(name, len) {} 48 Name(cxx::String const &n) : String(n) {} 49 char const *name() const { return start(); } 50 bool operator < (Name const &r) const; 51}; 52 53 54/** 55 * \internal 56 */ 57class Obj 58{ 59protected: 60 unsigned _f; 61 union 62 { 63 l4_cap_idx_t _cap; 64 L4::Epiface *_obj; 65 }; 66 67 68public: 69 enum Flags 70 { 71 F_rw = L4Re::Namespace::Rw, 72 F_strong = L4Re::Namespace::Strong, 73 74 F_trusted = L4Re::Namespace::Trusted, 75 76 F_rights_mask = F_rw | F_strong | F_trusted, 77 78 F_cap = 0x100, 79 F_local = 0x200, 80 F_replacable = 0x400, 81 F_base_mask = 0xf00, 82 }; 83 84 85 unsigned flags() const { return _f; } 86 void restrict_flags(unsigned max_rights) 87 { _f &= (~F_rights_mask | (max_rights & F_rights_mask)); } 88 89 bool is_rw() const { return (_f & F_rw) == F_rw; } 90 bool is_strong() const { return _f & F_strong; } 91 92 bool is_valid() const { return _f & F_cap; } 93 bool is_complete() const { return is_valid(); } 94 bool is_local() const { return _f & F_local; } 95 bool is_replacable() const { return _f & F_replacable; } 96 bool is_trusted() const { return _f & F_trusted; } 97 98 L4::Epiface *obj() const { if (is_local()) return _obj; return 0; } 99 L4::Cap<void> cap() const 100 { 101 if (!is_local()) 102 return L4::Cap<void>(_cap); 103 if (!_obj) 104 return L4::Cap<void>::Invalid; 105 return _obj->obj_cap(); 106 } 107 108 109 void set(Obj const &o, unsigned flags) 110 { 111 *this = o; 112 restrict_flags(flags); 113 } 114 115 explicit Obj(unsigned flags = 0) 116 : _f(flags), _cap(L4_INVALID_CAP) 117 {} 118 119 Obj(unsigned f, L4::Cap<void> const &cap) 120 : _f((f & ~F_base_mask) | F_cap), _cap(cap.cap()) 121 {} 122 123 Obj(unsigned f, L4::Epiface *o) 124 : _f((f & ~F_base_mask) | F_cap | F_local), _obj(o) 125 {} 126 127 void reset(unsigned flags) 128 { 129 _f = (_f & F_replacable) | (flags & ~(F_cap | F_local)); 130 _cap = L4_INVALID_CAP; 131 } 132 133 134}; 135 136 137/** 138 * \internal 139 */ 140class Entry : public cxx::Avl_tree_node 141{ 142private: 143 friend class Name_space; 144 Name _n; 145 Obj _o; 146 147 bool _dynamic; 148 149public: 150 Entry(Name const &n, Obj const &o, bool dynamic = false) 151 : _n(n), _o(o), _dynamic(dynamic) {} 152 153 Name const &name() const { return _n; } 154 Obj const *obj() const { return &_o; } 155 Obj *obj() { return &_o; } 156 void obj(Obj const &o) { _o = o; } 157 158 bool is_placeholder() const 159 { return !obj()->is_complete(); } 160 161 bool is_dynamic() const { return _dynamic; } 162 163 void set(Obj const &o); 164 165private: 166 void * operator new (size_t s); 167 void operator delete(void *b); 168 169}; 170 171struct Names_get_key 172{ 173 typedef Name Key_type; 174 static Key_type const &key_of(Entry const *e) 175 { return e->name(); } 176}; 177 178 179/** 180 * Abstract server-side implementation of the L4::Namespace interface. 181 * 182 * \internal 183 */ 184class Name_space 185{ 186 friend class Entry; 187 188private: 189 typedef cxx::Avl_tree<Entry, Names_get_key> Tree; 190 Tree _tree; 191 192protected: 193 L4Re::Util::Dbg const &_dbg; 194 L4Re::Util::Err const &_err; 195 196public: 197 198 typedef Tree::Const_iterator Const_iterator; 199 200 Const_iterator begin() const { return _tree.begin(); } 201 Const_iterator end() const { return _tree.end(); } 202 203 Name_space(L4Re::Util::Dbg const &dbg, L4Re::Util::Err const &err) 204 : _dbg(dbg), _err(err) 205 {} 206 207 virtual ~Name_space() {} 208 209 Entry *find(Name const &name) const { return _tree.find_node(name); } 210 Entry *remove(Name const &name) { return _tree.remove(name); } 211 Entry *find_iter(Name const &name) const; 212 bool insert(Entry *e) { return _tree.insert(e).second; } 213 214 void dump(bool rec = false, int indent = 0) const; 215 216protected: 217 // server support -------------------------------------------- 218 /** 219 * Allocate a new entry for the given name. 220 * 221 * \param n Name of the entry, must be copied. 222 * \param flags Entry flags, see Obj::Flags. 223 * 224 * \return A pointer to the newly allocated entry or NULL on error. 225 * 226 * This method is called when a new entry was received. It must 227 * allocate memory, copy `n` out of the receive buffer and wrap 228 * everything in an Entry. 229 */ 230 virtual Entry *alloc_dynamic_entry(Name const &n, unsigned flags) = 0; 231 232 /** 233 * Free an entry previously allocated with alloc_dynamic_entry(). 234 * 235 * \param e Entry to free. 236 */ 237 virtual void free_dynamic_entry(Entry *e) = 0; 238 239 /** 240 * Return a pointer to the epiface assigned to a given label. 241 * 242 * \param[in] data Label or in the local case the capability slot of 243 * the receiving capability. 244 * \param[in] is_local If true, a local capability slot was supplied, if 245 * false the label of a locally bound IPC gate. 246 * \param[out] lo Pointer to epiface responsible for the capability. 247 * 248 * \return #L4_EOK if a valid interface could be found or an error message 249 * otherwise. 250 * 251 * This method is called when a new entry is registered and some 252 * local ID was received for the capability. In this case, the 253 * generic implementation needs to get the epiface in order to get 254 * the capability. 255 * 256 * The callee must make sure that the epiface remains valid until 257 * free_epiface is called. In particular, the capability slot must 258 * not be reallocated as long as the namespace server holds a 259 * reference to the epiface. 260 */ 261 virtual int get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo) = 0; 262 263 /** 264 * Return the receive capability for permanent use. 265 * 266 * \param[out] cap Capability slot with the received capability. Must 267 * be permanently available until free_capability() is called. 268 * 269 * This method is called when a new entry is registered together 270 * with a capability mapping. It must decide whether and where to 271 * store the capability and return the final capability slot. 272 * Typical implementations return the capability slot in the receive 273 * window and allocate a new receive window. 274 */ 275 virtual int copy_receive_cap(L4::Cap<void> *cap) = 0; 276 277 /** 278 * Free a capability previously acquired with copy_receive_cap(). 279 * 280 * \param[in] cap Capability to free. 281 * 282 * Counterpart of #copy_receive_cap. Free the capability slot when 283 * the entry is deleted or changed. 284 */ 285 virtual void free_capability(L4::Cap<void> cap) = 0; 286 287 /** 288 * Free epiface previously acquired with get_epiface(). 289 * 290 * \param[in] epiface Epiface to free. 291 * 292 * Called when an entry that points to an epiface is deleted 293 * allowing implementations that hold resources to free them. 294 */ 295 virtual void free_epiface(L4::Epiface *epiface) = 0; 296 297 int insert_entry(Name const &name, unsigned flags, Entry **e); 298 299public: 300 // server interface ------------------------------------------ 301 int op_query(L4Re::Namespace::Rights, 302 L4::Ipc::Array_in_buf<char, unsigned long> const &name, 303 L4::Ipc::Snd_fpage &snd_cap, L4::Ipc::Opt<L4::Opcode> &, 304 L4::Ipc::Opt<L4::Ipc::Array_ref<char, unsigned long> > &out_name); 305 306 int op_register_obj(L4Re::Namespace::Rights, unsigned flags, 307 L4::Ipc::Array_in_buf<char, unsigned long> const &name, 308 L4::Ipc::Snd_fpage &cap); 309 310 int op_unlink(L4Re::Namespace::Rights r, 311 L4::Ipc::Array_in_buf<char, unsigned long> const &name); 312}; 313 314}}} 315 316