1 
2 #pragma once
3 
4 #include <l4/sys/consts.h>
5 #include <l4/sys/types.h>
6 #include <l4/sys/task.h>
7 
8 namespace L4 {
9 
10 class Task;
11 class Kobject;
12 
13 template< typename T > class L4_EXPORT Cap;
14 
15 /**
16  * Base class for all kinds of capabilities.
17  * \attention This class is not for direct use, use L4::Cap instead.
18  * \headerfile l4/sys/capability
19  *
20  * This class contains all the things that are independent of the type
21  * of the object referred by the capability.
22  *
23  * \see L4::Cap for typed capabilities.
24  */
25 class L4_EXPORT Cap_base
26 {
27 private:
28   struct Invalid_conversion;
29 
30 public:
31   /// Special value for uninitialized capability objects.
32   enum No_init_type
33   {
34      /**
35       * \brief Special value for constructing uninitialized Cap objects.
36       */
37      No_init
38   };
39 
40   /**
41    * \brief Invalid capability type.
42    */
43   enum Cap_type
44   {
45     Invalid = L4_INVALID_CAP ///< Invalid capability selector
46   };
47 
48   /**
49    * \brief Return capability selector.
50    * \return Capability selector.
51    */
cap()52   l4_cap_idx_t cap() const noexcept { return _c; }
53 
54   /**
55    * Test whether the capability is a valid capability index (i.e.,
56    * not L4_INVALID_CAP).
57    *
58    * \return True if capability is not invalid, false if invalid
59    */
is_valid()60   bool is_valid() const noexcept { return !(_c & L4_INVALID_CAP_BIT); }
61 
62   operator Invalid_conversion * () const noexcept
63   { return (Invalid_conversion*)(!(_c & L4_INVALID_CAP_BIT)); }
64 
65   /**
66    * Return flex-page for the capability.
67    *
68    * \param rights   Rights, defaults to 'rws'
69    *
70    * \return flex-page
71    */
72   l4_fpage_t fpage(unsigned rights = L4_CAP_FPAGE_RWS) const noexcept
73   { return l4_obj_fpage(_c, 0, rights); }
74 
75   /**
76    * Return send base.
77    *
78    * \param grant  True object should be granted.
79    * \param base   Base capability (first in a bundle of aligned capabilities)
80    *
81    * \return Map object.
82    */
83   l4_umword_t snd_base(unsigned grant = 0,
84                        l4_cap_idx_t base = L4_INVALID_CAP) const noexcept
85   {
86     if (base == L4_INVALID_CAP)
87       base = _c;
88     return l4_map_obj_control(base, grant);
89   }
90 
91 
92   /**
93    * Test if two capabilities are equal.
94    */
95   bool operator == (Cap_base const &o) const noexcept
96   { return _c == o._c; }
97 
98   /**
99    * Test if two capabilities are not equal.
100    */
101   bool operator != (Cap_base const &o) const noexcept
102   { return _c != o._c; }
103 
104   /**
105    * Check whether a capability is present (refers to an object).
106    *
107    * \utcb{u}
108    *
109    * \retval tag.label() > 0   Capability is present (refers to an object).
110    * \retval tag.label() == 0  No capability present (void object or invalid
111    *                           capability slot).
112    *
113    * A capability is considered present when it refers to an existing
114    * kernel object.
115    */
116   inline l4_msgtag_t validate(l4_utcb_t *u = l4_utcb()) const noexcept;
117 
118   /**
119    * Check whether a capability is present (refers to an object).
120    *
121    * \param task  Task to check the capability in.
122    * \utcb{u}
123    *
124    * \retval tag.label() > 0   Capability is present (refers to an object).
125    * \retval tag.label() == 0  No capability present (void object or invalid
126    *                           capability slot).
127    *
128    * A capability is considered present when it refers to an existing
129    * kernel object.
130    */
131   inline l4_msgtag_t validate(Cap<Task> task,
132                               l4_utcb_t *u = l4_utcb()) const noexcept;
133 
134   /**
135    * Set this capability to invalid (L4_INVALID_CAP).
136    */
invalidate()137   void invalidate() noexcept { _c = L4_INVALID_CAP; }
138 protected:
139   /**
140    * Generate a capability from its C representation.
141    *
142    * \param c  The C capability
143    */
Cap_base(l4_cap_idx_t c)144   explicit Cap_base(l4_cap_idx_t c) noexcept : _c(c) {}
145   /**
146    * Constructor to create an invalid capability.
147    */
Cap_base(Cap_type cap)148   explicit Cap_base(Cap_type cap) noexcept : _c(cap) {}
149 
150   /**
151    * Initialize capability with one of the default capabilities.
152    *
153    * \param cap  Capability.
154    */
Cap_base(l4_default_caps_t cap)155   explicit Cap_base(l4_default_caps_t cap) noexcept : _c(cap) {}
156 
157   /**
158    * \brief Create an uninitialized instance.
159    */
Cap_base()160   explicit Cap_base() noexcept {}
161 
162   /**
163    * Replace this capability with the contents of `src`.
164    *
165    * \param src the source capability.
166    *
167    * After the operation this capability refers to the object formerly referred
168    * to by the source capability `src`, and the source capability no longer
169    * refers to an object.
170    */
move(Cap_base const & src)171   void move(Cap_base const &src) const
172   {
173     if (!is_valid() || !src.is_valid())
174       return;
175 
176     l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_CAP_FPAGE_RWSD),
177                 snd_base(L4_MAP_ITEM_GRANT) | L4_FPAGE_C_OBJ_RIGHTS);
178   }
179 
180   /**
181    * Copy a capability.
182    * \param src the source capability.
183    *
184    * After this operation this capability refers to the same object
185    * as `src`.
186    */
copy(Cap_base const & src)187   void copy(Cap_base const &src) const
188   {
189     if (!is_valid() || !src.is_valid())
190       return;
191 
192     l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_CAP_FPAGE_RWSD),
193                 snd_base() | L4_FPAGE_C_OBJ_RIGHTS);
194   }
195 
196   /**
197    * \brief The C representation of a capability selector. */
198   l4_cap_idx_t _c;
199 };
200 
201 
202 /**
203  * C++ interface for capabilities.
204  *
205  * \tparam T  Type of the object the capability points to.
206  *
207  * The C++ version of a capability is comparable to a pointer, in fact
208  * it is a kind of smart pointer for our kernel objects and the
209  * objects derived from the kernel objects (L4::Kobject).
210  *
211  * Add
212  *
213  *     #include <l4/sys/capability>
214  *
215  * to your code to use the capability interface.
216  */
217 template< typename T >
218 class L4_EXPORT Cap : public Cap_base
219 {
220 private:
221   friend class L4::Kobject;
222 
223   /**
224    * \internal
225    * \brief Internal Constructor, use to generate a capability from a `this`
226    *        pointer.
227    *
228    * \param p  The `this` pointer of the Kobject or derived object.
229    *
230    * \attention This constructor is only useful to generate a capability
231    *            from the `this` pointer of an object that is an L4::Kobject.
232    *            Do **never** use this constructor for something else!
233    */
Cap(T const * p)234   explicit Cap(T const *p) noexcept
235   : Cap_base(reinterpret_cast<l4_cap_idx_t>(p)) {}
236 
237 public:
238 
239   /**
240    * \brief Create a copy from `o`, supporting implicit type casting.
241    * \param o  The source selector that shall be copied (and casted).
242    */
243   template< typename O >
Cap(Cap<O> const & o)244   Cap(Cap<O> const &o) noexcept : Cap_base(o.cap())
245   { T* __t = ((O*)100); (void)__t; }
246 
247   /**
248    * Constructor to create an invalid capability selector.
249    * \param cap  Capability selector.
250    */
Cap(Cap_type cap)251   Cap(Cap_type cap) noexcept : Cap_base(cap) {}
252 
253   /**
254    * \brief Initialize capability with one of the default capability selectors.
255    * \param cap  Capability selector.
256    */
Cap(l4_default_caps_t cap)257   Cap(l4_default_caps_t cap) noexcept : Cap_base(cap) {}
258 
259   /**
260    * \brief Initialize capability, defaults to the invalid capability selector.
261    * \param idx  Capability selector.
262    */
Cap_base(idx)263   explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) noexcept : Cap_base(idx) {}
264 
265   /**
266    * \brief Create an uninitialized cap selector.
267    */
Cap(No_init_type)268   explicit Cap(No_init_type) noexcept {}
269 
270   /**
271    * \brief Move a capability to this cap slot.
272    * \param src the source capability slot.
273    *
274    * After this operation the source slot is no longer valid.
275    */
move(Cap const & src)276   Cap move(Cap const &src) const
277   {
278     Cap_base::move(src);
279     return *this;
280   }
281 
282   /**
283    * \brief Copy a capability to this cap slot.
284    * \param src the source capability slot.
285    */
copy(Cap const & src)286   Cap copy(Cap const &src) const
287   {
288     Cap_base::copy(src);
289     return *this;
290   }
291 
292   /**
293    * \brief Member access of a `T`.
294    */
295   T *operator -> () const noexcept { return reinterpret_cast<T*>(_c); }
296 };
297 
298 
299 /**
300  * \internal
301  * \brief Specialization for `void` capabilities.
302  *
303  * Include
304  *
305  *     #include <l4/sys/capability>
306  *
307  * to use this.
308  */
309 template<>
310 class L4_EXPORT Cap<void> : public Cap_base
311 {
312 public:
313 
Cap(void const * p)314   explicit Cap(void const *p) noexcept
315   : Cap_base(reinterpret_cast<l4_cap_idx_t>(p)) {}
316 
317   /**
318    * \brief Constructor to create an invalid capability selector.
319    */
Cap(Cap_type cap)320   Cap(Cap_type cap) noexcept : Cap_base(cap) {}
321 
322   /**
323    * \brief Initialize capability with one of the default capability selectors.
324    * \param cap  Capability selector.
325    */
Cap(l4_default_caps_t cap)326   Cap(l4_default_caps_t cap) noexcept : Cap_base(cap) {}
327 
328   /**
329    * \brief Initialize capability, defaults to the invalid capability selector.
330    * \param idx  Capability selector.
331    */
Cap_base(idx)332   explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) noexcept : Cap_base(idx) {}
Cap(No_init_type)333   explicit Cap(No_init_type) noexcept {}
334 
335   /**
336    * \brief Move a capability to this cap slot.
337    * \param src the source capability slot.
338    *
339    * After this operation the source slot is no longer valid.
340    */
move(Cap const & src)341   Cap move(Cap const &src) const
342   {
343     Cap_base::move(src);
344     return *this;
345   }
346 
347   /**
348    * \brief Copy a capability to this cap slot.
349    * \param src the source capability slot.
350    */
copy(Cap const & src)351   Cap copy(Cap const &src) const
352   {
353     Cap_base::copy(src);
354     return *this;
355   }
356 
357   template< typename T >
Cap(Cap<T> const & o)358   Cap(Cap<T> const &o) noexcept : Cap_base(o.cap()) {}
359 };
360 
361 /**
362  * \brief static_cast for capabilities.
363  * \tparam T  The target type of the capability
364  * \tparam F  The source type (and is usually implicitly set)
365  * \param c   The source capability that shall be casted
366  * \return A capability typed to the interface `T`.
367  *
368  * The use of this cast operator is similar to the `static_cast<>()` for
369  * C++ pointers.  It does the same type checking and adjustments like
370  * C++ does on pointers.
371  *
372  * Example code:
373  *
374  *     L4::Cap<L4::Kobject> obj = ... ;
375  *     L4::Cap<L4::Icu> icu = L4::cap_cast<L4::Icu>(obj);
376  */
377 template< typename T, typename F >
378 inline
cap_cast(Cap<F> const & c)379 Cap<T> cap_cast(Cap<F> const &c) noexcept
380 {
381   (void)static_cast<T const *>(reinterpret_cast<F const *>(100));
382   return Cap<T>(c.cap());
383 }
384 
385 // gracefully deal with L4::Kobject ambiguity
386 template< typename T >
387 inline
cap_cast(Cap<L4::Kobject> const & c)388 Cap<T> cap_cast(Cap<L4::Kobject> const &c) noexcept
389 {
390   return Cap<T>(c.cap());
391 }
392 
393 /**
394  * reinterpret_cast for capabilities.
395  * \tparam T  The target type of the capability
396  * \tparam F  The source type (and is usually implicitly set)
397  * \param c   The source capability that shall be casted
398  * \return A capability typed to the interface `T`.
399  *
400  * The use of this cast operator is similar to the `reinterpret_cast<>()` for
401  * C++ pointers.  It does not do any type checking or type adjustment.
402  *
403  * Example code:
404  *
405  *     L4::Cap<L4::Kobject> obj = ... ;
406  *     L4::Cap<L4::Icu> icu = L4::cap_reinterpret_cast<L4::Icu>(obj);
407  */
408 template< typename T, typename F >
409 inline
cap_reinterpret_cast(Cap<F> const & c)410 Cap<T> cap_reinterpret_cast(Cap<F> const &c) noexcept
411 {
412   return Cap<T>(c.cap());
413 }
414 
415 }
416