1#[cfg(feature = "alloc")]
7extern crate alloc;
8
9use core::sync::atomic::{AtomicU64, Ordering};
10
11use crate::error::KernelError;
12
13static CAPABILITY_COUNTER: AtomicU64 = AtomicU64::new(1);
15
16pub use crate::process::ProcessId;
18
19pub type EndpointId = u64;
21
22#[repr(C)]
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub struct IpcCapability {
31 value: u64,
33 target: EndpointId,
35 permissions: IpcPermissions,
37 limits: IpcLimits,
39}
40
41impl IpcCapability {
42 pub fn new(target: EndpointId, permissions: IpcPermissions) -> Self {
44 let id = CAPABILITY_COUNTER.fetch_add(1, Ordering::Relaxed);
45 let generation = 0u64; let cap_type = CapabilityType::Endpoint as u64;
47
48 let value = (generation << 48) | (cap_type << 32) | (id & 0xFFFFFFFF);
49
50 Self {
51 value,
52 target,
53 permissions,
54 limits: IpcLimits::default(),
55 }
56 }
57
58 pub fn id(&self) -> u64 {
60 self.value & 0xFFFFFFFF
61 }
62
63 pub fn generation(&self) -> u16 {
65 ((self.value >> 48) & 0xFFFF) as u16
66 }
67
68 pub fn cap_type(&self) -> CapabilityType {
70 let type_val = ((self.value >> 32) & 0xFFFF) as u16;
71 CapabilityType::from_u16(type_val).unwrap_or(CapabilityType::Invalid)
72 }
73
74 pub fn target(&self) -> EndpointId {
76 self.target
77 }
78
79 pub fn owner(&self) -> ProcessId {
81 ProcessId(self.target)
82 }
83
84 pub fn has_permission(&self, perm: Permission) -> bool {
86 match perm {
87 Permission::Send => self.permissions.can_send,
88 Permission::Receive => self.permissions.can_receive,
89 Permission::Share => self.permissions.can_share,
90 }
91 }
92
93 pub fn derive(&self, new_perms: IpcPermissions) -> Option<Self> {
95 if new_perms.can_send && !self.permissions.can_send {
97 return None;
98 }
99 if new_perms.can_receive && !self.permissions.can_receive {
100 return None;
101 }
102 if new_perms.can_share && !self.permissions.can_share {
103 return None;
104 }
105 if new_perms.max_message_size > self.permissions.max_message_size {
106 return None;
107 }
108
109 let mut derived = *self;
110 derived.permissions = new_perms;
111 Some(derived)
112 }
113
114 pub fn revoke(&mut self) {
116 let generation = self.generation().wrapping_add(1);
117 let cap_type = self.cap_type() as u64;
118 let id = self.id();
119 self.value = ((generation as u64) << 48) | (cap_type << 32) | id;
120 }
121}
122
123#[repr(u16)]
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum CapabilityType {
127 Invalid = 0,
129 Endpoint = 1,
131 Memory = 2,
133 Process = 3,
135 Interrupt = 4,
137 Channel = 5,
139}
140
141impl CapabilityType {
142 fn from_u16(val: u16) -> Option<Self> {
143 match val {
144 0 => Some(Self::Invalid),
145 1 => Some(Self::Endpoint),
146 2 => Some(Self::Memory),
147 3 => Some(Self::Process),
148 4 => Some(Self::Interrupt),
149 5 => Some(Self::Channel),
150 _ => None,
151 }
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum Permission {
158 Send,
160 Receive,
162 Share,
164}
165
166#[repr(C)]
168#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169pub struct IpcPermissions {
170 pub can_send: bool,
172 pub can_receive: bool,
174 pub can_share: bool,
176 pub max_message_size: usize,
178}
179
180impl IpcPermissions {
181 pub const fn all() -> Self {
183 Self {
184 can_send: true,
185 can_receive: true,
186 can_share: true,
187 max_message_size: 0, }
189 }
190
191 pub const fn send_only() -> Self {
193 Self {
194 can_send: true,
195 can_receive: false,
196 can_share: false,
197 max_message_size: 0,
198 }
199 }
200
201 pub const fn receive_only() -> Self {
203 Self {
204 can_send: false,
205 can_receive: true,
206 can_share: false,
207 max_message_size: 0,
208 }
209 }
210}
211
212#[repr(C)]
214#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
215pub struct IpcLimits {
216 pub rate_limit: u32,
218 pub bandwidth_limit: u64,
220 pub expiration: u64,
222}
223
224impl IpcLimits {
225 pub const fn unlimited() -> Self {
227 Self {
228 rate_limit: 0,
229 bandwidth_limit: 0,
230 expiration: 0,
231 }
232 }
233
234 pub const fn with_rate_limit(messages_per_sec: u32) -> Self {
236 Self {
237 rate_limit: messages_per_sec,
238 bandwidth_limit: 0,
239 expiration: 0,
240 }
241 }
242}
243
244pub struct CapabilityTable {
249 #[cfg(feature = "alloc")]
251 capabilities: alloc::collections::BTreeMap<u64, IpcCapability>,
252}
253
254impl CapabilityTable {
255 pub fn new() -> Self {
257 Self {
258 #[cfg(feature = "alloc")]
259 capabilities: alloc::collections::BTreeMap::new(),
260 }
261 }
262
263 #[cfg(feature = "alloc")]
265 pub fn insert(&mut self, cap: IpcCapability) -> Result<(), KernelError> {
266 let id = cap.id();
267 if self.capabilities.contains_key(&id) {
268 return Err(KernelError::AlreadyExists {
269 resource: "ipc_capability",
270 id,
271 });
272 }
273 self.capabilities.insert(id, cap);
274 Ok(())
275 }
276
277 #[cfg(not(feature = "alloc"))]
279 pub fn insert(&mut self, _cap: IpcCapability) -> Result<(), KernelError> {
280 Ok(())
281 }
282
283 #[cfg(feature = "alloc")]
285 pub fn lookup(&self, id: u64) -> Option<&IpcCapability> {
286 self.capabilities.get(&id)
287 }
288
289 #[cfg(not(feature = "alloc"))]
291 pub fn lookup(&self, _id: u64) -> Option<&IpcCapability> {
292 None
293 }
294
295 #[cfg(feature = "alloc")]
297 pub fn remove(&mut self, id: u64) -> Option<IpcCapability> {
298 self.capabilities.remove(&id)
299 }
300
301 #[cfg(not(feature = "alloc"))]
303 pub fn remove(&mut self, _id: u64) -> Option<IpcCapability> {
304 None
305 }
306
307 #[cfg(feature = "alloc")]
309 pub fn validate_permission(&self, cap_id: u64, perm: Permission) -> bool {
310 self.capabilities
311 .get(&cap_id)
312 .map(|cap| cap.has_permission(perm))
313 .unwrap_or(false)
314 }
315
316 #[cfg(not(feature = "alloc"))]
318 pub fn validate_permission(&self, _cap_id: u64, _perm: Permission) -> bool {
319 false
320 }
321
322 #[cfg(feature = "alloc")]
324 pub fn len(&self) -> usize {
325 self.capabilities.len()
326 }
327
328 #[cfg(not(feature = "alloc"))]
330 pub fn len(&self) -> usize {
331 0
332 }
333
334 pub fn is_empty(&self) -> bool {
336 self.len() == 0
337 }
338}
339
340impl Default for CapabilityTable {
341 fn default() -> Self {
342 Self::new()
343 }
344}
345
346#[cfg(all(test, not(target_os = "none")))]
347mod tests {
348 use super::*;
349
350 #[test]
351 fn test_capability_creation() {
352 let cap = IpcCapability::new(42, IpcPermissions::all());
353 assert_eq!(cap.target(), 42);
354 assert_eq!(cap.generation(), 0);
355 assert_eq!(cap.cap_type(), CapabilityType::Endpoint);
356 }
357
358 #[test]
359 fn test_capability_permissions() {
360 let cap = IpcCapability::new(1, IpcPermissions::send_only());
361 assert!(cap.has_permission(Permission::Send));
362 assert!(!cap.has_permission(Permission::Receive));
363 assert!(!cap.has_permission(Permission::Share));
364 }
365
366 #[test]
367 fn test_capability_derive() {
368 let cap = IpcCapability::new(1, IpcPermissions::all());
369 let derived = cap.derive(IpcPermissions::send_only());
370 assert!(derived.is_some());
371
372 let restricted = IpcCapability::new(1, IpcPermissions::send_only());
373 let invalid_derive = restricted.derive(IpcPermissions::all());
374 assert!(invalid_derive.is_none());
375 }
376}