1use core::fmt;
9use core::hash::Hash;
10use core::marker::PhantomData;
11
12use crate::{sys, InvocationContext, IpcBuffer, NoExplicitInvocationContext, WORD_SIZE};
13
14pub type CPtrBits = sys::seL4_CPtr;
16
17#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
19pub struct CPtr {
20 bits: CPtrBits,
21}
22
23impl CPtr {
24 pub const fn bits(self) -> CPtrBits {
25 self.bits
26 }
27
28 pub const fn from_bits(bits: CPtrBits) -> Self {
29 Self { bits }
30 }
31
32 pub const fn cast<T: CapType>(self) -> Cap<T> {
33 Cap::from_cptr(self)
34 }
35}
36
37#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
39pub struct CPtrWithDepth {
40 bits: CPtrBits,
41 depth: usize,
42}
43
44impl CPtrWithDepth {
45 pub const fn from_bits_with_depth(bits: CPtrBits, depth: usize) -> Self {
46 Self { bits, depth }
47 }
48
49 pub const fn bits(&self) -> CPtrBits {
50 self.bits
51 }
52
53 pub const fn depth(&self) -> usize {
54 self.depth
55 }
56
57 pub const fn empty() -> Self {
59 Self::from_bits_with_depth(0, 0)
60 }
61
62 pub(crate) fn depth_for_kernel(&self) -> u8 {
64 self.depth().try_into().unwrap()
65 }
66}
67
68impl From<CPtr> for CPtrWithDepth {
69 fn from(cptr: CPtr) -> Self {
70 Self::from_bits_with_depth(cptr.bits(), WORD_SIZE)
71 }
72}
73
74#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
90pub struct Cap<T: CapType, C = NoExplicitInvocationContext> {
91 cptr: CPtr,
92 invocation_context: C,
93 _phantom: PhantomData<T>,
94}
95
96impl<T: CapType, C> Cap<T, C> {
97 pub const fn cptr(&self) -> CPtr {
98 self.cptr
99 }
100
101 pub const fn bits(&self) -> CPtrBits {
102 self.cptr().bits()
103 }
104
105 pub fn cast<T1: CapType>(self) -> Cap<T1, C> {
106 Cap {
107 cptr: self.cptr,
108 invocation_context: self.invocation_context,
109 _phantom: PhantomData,
110 }
111 }
112
113 pub fn with<C1>(self, context: C1) -> Cap<T, C1> {
114 Cap {
115 cptr: self.cptr,
116 invocation_context: context,
117 _phantom: PhantomData,
118 }
119 }
120
121 pub fn without_context(self) -> Cap<T> {
122 self.with(NoExplicitInvocationContext::new())
123 }
124
125 pub fn into_invocation_context(self) -> C {
126 self.invocation_context
127 }
128}
129
130impl<T: CapType> Cap<T> {
131 pub const fn from_cptr(cptr: CPtr) -> Self {
132 Self {
133 cptr,
134 invocation_context: NoExplicitInvocationContext::new(),
135 _phantom: PhantomData,
136 }
137 }
138
139 pub const fn from_bits(bits: CPtrBits) -> Self {
140 CPtr::from_bits(bits).cast()
141 }
142}
143
144impl<T: CapType, C: InvocationContext> Cap<T, C> {
145 pub(crate) fn invoke<R>(self, f: impl FnOnce(CPtr, &mut IpcBuffer) -> R) -> R {
149 let cptr = self.cptr();
150 self.into_invocation_context()
151 .with_context(|ipc_buffer| f(cptr, ipc_buffer))
152 }
153}
154
155impl<T: CapType, C> fmt::Debug for Cap<T, C> {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 f.debug_tuple(T::NAME).field(&self.cptr().bits()).finish()
158 }
159}
160
161pub trait CapType: Copy + Clone + Eq + PartialEq + Ord + PartialOrd + Hash {
167 const NAME: &'static str;
168}
169
170pub mod cap_type {
171 use sel4_config::sel4_cfg_if;
176
177 use crate::{
178 declare_cap_type, declare_cap_type_for_object_of_fixed_size,
179 declare_cap_type_for_object_of_variable_size,
180 };
181
182 pub use crate::arch::cap_type_arch::*;
183
184 declare_cap_type_for_object_of_variable_size! {
185 Untyped { ObjectType, ObjectBlueprint }
187 }
188
189 declare_cap_type_for_object_of_fixed_size! {
190 Endpoint { ObjectType, ObjectBlueprint }
192 }
193
194 declare_cap_type_for_object_of_fixed_size! {
195 Notification { ObjectType, ObjectBlueprint }
197 }
198
199 declare_cap_type_for_object_of_fixed_size! {
200 Tcb { ObjectType, ObjectBlueprint }
202 }
203
204 declare_cap_type_for_object_of_variable_size! {
205 CNode { ObjectType, ObjectBlueprint }
207 }
208
209 declare_cap_type! {
210 IrqControl
212 }
213
214 declare_cap_type! {
215 IrqHandler
217 }
218
219 declare_cap_type! {
220 AsidControl
222 }
223
224 declare_cap_type! {
225 AsidPool
227 }
228
229 declare_cap_type! {
230 Null
232 }
233
234 declare_cap_type! {
235 Unspecified
237 }
238
239 declare_cap_type! {
240 UnspecifiedPage
242 }
243
244 declare_cap_type! {
245 UnspecifiedIntermediateTranslationTable
247 }
248
249 sel4_cfg_if! {
250 if #[sel4_cfg(KERNEL_MCS)] {
251 declare_cap_type! {
252 Reply
254 }
255
256 declare_cap_type_for_object_of_variable_size! {
257 SchedContext { ObjectType, ObjectBlueprint }
259 }
260
261 declare_cap_type! {
262 SchedControl
264 }
265 }
266 }
267}
268
269use cap::*;
270
271pub mod cap {
272 use sel4_config::sel4_cfg_if;
277
278 use crate::declare_cap_alias;
279
280 pub use crate::arch::cap_arch::*;
281
282 declare_cap_alias!(Untyped);
283 declare_cap_alias!(Endpoint);
284 declare_cap_alias!(Notification);
285 declare_cap_alias!(Tcb);
286 declare_cap_alias!(CNode);
287 declare_cap_alias!(IrqControl);
288 declare_cap_alias!(IrqHandler);
289 declare_cap_alias!(AsidControl);
290 declare_cap_alias!(AsidPool);
291
292 declare_cap_alias!(Null);
293 declare_cap_alias!(Unspecified);
294 declare_cap_alias!(UnspecifiedPage);
295 declare_cap_alias!(UnspecifiedIntermediateTranslationTable);
296
297 declare_cap_alias!(VSpace);
298 declare_cap_alias!(Granule);
299
300 sel4_cfg_if! {
301 if #[sel4_cfg(KERNEL_MCS)] {
302 declare_cap_alias!(Reply);
303 declare_cap_alias!(SchedContext);
304 declare_cap_alias!(SchedControl);
305 }
306 }
307}
308
309impl<T: CapType, C> Cap<T, C> {
310 pub fn upcast(self) -> Unspecified<C> {
311 self.cast()
312 }
313}
314
315impl<C> Unspecified<C> {
316 pub fn downcast<T: CapType>(self) -> Cap<T, C> {
317 self.cast()
318 }
319}
320
321#[derive(Copy, Clone, Debug, Eq, PartialEq)]
337pub struct AbsoluteCPtr<C = NoExplicitInvocationContext> {
338 root: CNode<C>,
339 path: CPtrWithDepth,
340}
341
342impl<C> AbsoluteCPtr<C> {
343 pub const fn new(root: CNode<C>, path: CPtrWithDepth) -> Self {
344 Self { root, path }
345 }
346
347 pub const fn root(&self) -> &CNode<C> {
348 &self.root
349 }
350
351 pub fn into_root(self) -> CNode<C> {
352 self.root
353 }
354
355 pub const fn path(&self) -> &CPtrWithDepth {
356 &self.path
357 }
358
359 pub fn with<C1>(self, context: C1) -> AbsoluteCPtr<C1> {
360 AbsoluteCPtr {
361 root: self.root.with(context),
362 path: self.path,
363 }
364 }
365
366 pub fn without_context(self) -> AbsoluteCPtr {
367 self.with(NoExplicitInvocationContext::new())
368 }
369}
370
371impl<C: InvocationContext> AbsoluteCPtr<C> {
372 pub(crate) fn invoke<R>(self, f: impl FnOnce(CPtr, CPtrWithDepth, &mut IpcBuffer) -> R) -> R {
373 let path = *self.path();
374 self.into_root()
375 .invoke(|cptr, ipc_buffer| f(cptr, path, ipc_buffer))
376 }
377}
378
379pub trait HasCPtrWithDepth {
383 fn cptr_with_depth(self) -> CPtrWithDepth;
385}
386
387impl HasCPtrWithDepth for CPtr {
388 fn cptr_with_depth(self) -> CPtrWithDepth {
389 self.into()
390 }
391}
392
393impl<T: CapType, C> HasCPtrWithDepth for Cap<T, C> {
394 fn cptr_with_depth(self) -> CPtrWithDepth {
395 self.cptr().into()
396 }
397}
398
399impl HasCPtrWithDepth for CPtrWithDepth {
400 fn cptr_with_depth(self) -> CPtrWithDepth {
401 self
402 }
403}
404
405impl<C> CNode<C> {
406 pub fn absolute_cptr<T: HasCPtrWithDepth>(self, path: T) -> AbsoluteCPtr<C> {
408 AbsoluteCPtr {
409 root: self,
410 path: path.cptr_with_depth(),
411 }
412 }
413
414 pub fn absolute_cptr_from_bits_with_depth(
418 self,
419 bits: CPtrBits,
420 depth: usize,
421 ) -> AbsoluteCPtr<C> {
422 self.absolute_cptr(CPtrWithDepth::from_bits_with_depth(bits, depth))
423 }
424
425 pub fn absolute_cptr_for_self(self) -> AbsoluteCPtr<C> {
432 self.absolute_cptr(CPtrWithDepth::empty())
433 }
434}