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