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