1use ruvix_types::{CapRights, ObjectType};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct InitialCapability {
19 pub object_id: u64,
21
22 pub object_type: ObjectType,
24
25 pub rights: CapRights,
27
28 pub badge: u64,
30
31 pub description: &'static str,
33}
34
35impl InitialCapability {
36 #[inline]
38 #[must_use]
39 pub const fn new(
40 object_id: u64,
41 object_type: ObjectType,
42 rights: CapRights,
43 badge: u64,
44 description: &'static str,
45 ) -> Self {
46 Self {
47 object_id,
48 object_type,
49 rights,
50 badge,
51 description,
52 }
53 }
54
55 #[inline]
57 #[must_use]
58 pub const fn memory(object_id: u64, start_addr: u64) -> Self {
59 Self {
60 object_id,
61 object_type: ObjectType::Region,
62 rights: CapRights::ALL,
63 badge: start_addr,
64 description: "Physical memory region",
65 }
66 }
67
68 #[inline]
70 #[must_use]
71 pub const fn memory_readonly(object_id: u64, start_addr: u64) -> Self {
72 Self {
73 object_id,
74 object_type: ObjectType::Region,
75 rights: CapRights::READ.union(CapRights::GRANT),
77 badge: start_addr,
78 description: "Read-only memory region (ROM)",
79 }
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn rvf_package(object_id: u64, package_hash_lo: u64) -> Self {
86 Self {
87 object_id,
88 object_type: ObjectType::RvfMount,
89 rights: CapRights::READ.union(CapRights::EXECUTE).union(CapRights::PROVE),
90 badge: package_hash_lo,
91 description: "Boot RVF package",
92 }
93 }
94
95 #[inline]
97 #[must_use]
98 pub const fn witness_log(object_id: u64) -> Self {
99 Self {
100 object_id,
101 object_type: ObjectType::WitnessLog,
102 rights: CapRights::ALL,
103 badge: 0,
104 description: "Kernel witness log",
105 }
106 }
107
108 #[inline]
110 #[must_use]
111 pub const fn interrupt_queue(object_id: u64, irq_mask: u64) -> Self {
112 Self {
113 object_id,
114 object_type: ObjectType::Queue,
115 rights: CapRights::ALL,
116 badge: irq_mask,
117 description: "Root interrupt queue",
118 }
119 }
120
121 #[inline]
123 #[must_use]
124 pub const fn timer(object_id: u64) -> Self {
125 Self {
126 object_id,
127 object_type: ObjectType::Timer,
128 rights: CapRights::ALL,
129 badge: 0,
130 description: "System timer",
131 }
132 }
133
134 #[inline]
136 #[must_use]
137 pub const fn root_task(object_id: u64) -> Self {
138 Self {
139 object_id,
140 object_type: ObjectType::Task,
141 rights: CapRights::ALL,
142 badge: 0,
143 description: "Root task (self)",
144 }
145 }
146
147 #[inline]
149 #[must_use]
150 pub const fn vector_store(object_id: u64, dimension: u64) -> Self {
151 Self {
152 object_id,
153 object_type: ObjectType::VectorStore,
154 rights: CapRights::ALL,
155 badge: dimension,
156 description: "Neural vector store",
157 }
158 }
159
160 #[inline]
162 #[must_use]
163 pub const fn proof_graph(object_id: u64) -> Self {
164 Self {
165 object_id,
166 object_type: ObjectType::GraphStore,
167 rights: CapRights::ALL,
168 badge: 0,
169 description: "Proof verification graph",
170 }
171 }
172}
173
174#[derive(Debug, Clone)]
179pub struct BootCapabilitySet {
180 memory_regions: [Option<InitialCapability>; 16],
182 memory_count: usize,
183
184 rvf_package: Option<InitialCapability>,
186
187 witness_log: Option<InitialCapability>,
189
190 interrupt_queue: Option<InitialCapability>,
192
193 timer: Option<InitialCapability>,
195
196 root_task: Option<InitialCapability>,
198
199 vector_store: Option<InitialCapability>,
201
202 proof_graph: Option<InitialCapability>,
204}
205
206impl BootCapabilitySet {
207 #[inline]
209 #[must_use]
210 pub const fn new() -> Self {
211 Self {
212 memory_regions: [None; 16],
213 memory_count: 0,
214 rvf_package: None,
215 witness_log: None,
216 interrupt_queue: None,
217 timer: None,
218 root_task: None,
219 vector_store: None,
220 proof_graph: None,
221 }
222 }
223
224 pub fn minimal(root_task_id: u64) -> Self {
226 let mut set = Self::new();
227 set.root_task = Some(InitialCapability::root_task(root_task_id));
228 set
229 }
230
231 pub fn full(
233 root_task_id: u64,
234 memory_start: u64,
235 memory_size: u64,
236 rvf_object_id: u64,
237 rvf_hash: u64,
238 ) -> Self {
239 let mut set = Self::new();
240
241 set.root_task = Some(InitialCapability::root_task(root_task_id));
243
244 set.memory_regions[0] = Some(InitialCapability::memory(memory_start, memory_size));
246 set.memory_count = 1;
247
248 set.rvf_package = Some(InitialCapability::rvf_package(rvf_object_id, rvf_hash));
250
251 set.witness_log = Some(InitialCapability::witness_log(root_task_id + 1));
253
254 set.interrupt_queue = Some(InitialCapability::interrupt_queue(
256 root_task_id + 2,
257 u64::MAX,
258 ));
259
260 set.timer = Some(InitialCapability::timer(root_task_id + 3));
262
263 set
264 }
265
266 pub fn add_memory_region(&mut self, object_id: u64, start_addr: u64) -> bool {
268 if self.memory_count >= 16 {
269 return false;
270 }
271
272 self.memory_regions[self.memory_count] = Some(InitialCapability::memory(object_id, start_addr));
273 self.memory_count += 1;
274 true
275 }
276
277 pub fn add_readonly_region(&mut self, object_id: u64, start_addr: u64) -> bool {
279 if self.memory_count >= 16 {
280 return false;
281 }
282
283 self.memory_regions[self.memory_count] = Some(InitialCapability::memory_readonly(object_id, start_addr));
284 self.memory_count += 1;
285 true
286 }
287
288 #[inline]
290 pub fn set_rvf_package(&mut self, object_id: u64, package_hash: u64) {
291 self.rvf_package = Some(InitialCapability::rvf_package(object_id, package_hash));
292 }
293
294 #[inline]
296 pub fn set_witness_log(&mut self, object_id: u64) {
297 self.witness_log = Some(InitialCapability::witness_log(object_id));
298 }
299
300 #[inline]
302 pub fn set_interrupt_queue(&mut self, object_id: u64, irq_mask: u64) {
303 self.interrupt_queue = Some(InitialCapability::interrupt_queue(object_id, irq_mask));
304 }
305
306 #[inline]
308 pub fn set_timer(&mut self, object_id: u64) {
309 self.timer = Some(InitialCapability::timer(object_id));
310 }
311
312 #[inline]
314 pub fn set_root_task(&mut self, object_id: u64) {
315 self.root_task = Some(InitialCapability::root_task(object_id));
316 }
317
318 #[inline]
320 pub fn set_vector_store(&mut self, object_id: u64, dimension: u64) {
321 self.vector_store = Some(InitialCapability::vector_store(object_id, dimension));
322 }
323
324 #[inline]
326 pub fn set_proof_graph(&mut self, object_id: u64) {
327 self.proof_graph = Some(InitialCapability::proof_graph(object_id));
328 }
329
330 #[inline]
332 #[must_use]
333 pub const fn memory_region_count(&self) -> usize {
334 self.memory_count
335 }
336
337 #[inline]
339 #[must_use]
340 pub fn total_count(&self) -> usize {
341 let mut count = self.memory_count;
342
343 if self.rvf_package.is_some() { count += 1; }
344 if self.witness_log.is_some() { count += 1; }
345 if self.interrupt_queue.is_some() { count += 1; }
346 if self.timer.is_some() { count += 1; }
347 if self.root_task.is_some() { count += 1; }
348 if self.vector_store.is_some() { count += 1; }
349 if self.proof_graph.is_some() { count += 1; }
350
351 count
352 }
353
354 pub fn iter(&self) -> impl Iterator<Item = &InitialCapability> {
356 self.memory_regions[..self.memory_count]
357 .iter()
358 .filter_map(|c| c.as_ref())
359 .chain(self.rvf_package.iter())
360 .chain(self.witness_log.iter())
361 .chain(self.interrupt_queue.iter())
362 .chain(self.timer.iter())
363 .chain(self.root_task.iter())
364 .chain(self.vector_store.iter())
365 .chain(self.proof_graph.iter())
366 }
367}
368
369impl Default for BootCapabilitySet {
370 fn default() -> Self {
371 Self::new()
372 }
373}
374
375#[cfg(test)]
376mod tests {
377 use super::*;
378
379 #[test]
380 fn test_initial_capability_memory() {
381 let cap = InitialCapability::memory(0x1000, 0x8000_0000);
382
383 assert_eq!(cap.object_id, 0x1000);
384 assert_eq!(cap.object_type, ObjectType::Region);
385 assert_eq!(cap.rights, CapRights::ALL);
386 assert_eq!(cap.badge, 0x8000_0000);
387 }
388
389 #[test]
390 fn test_initial_capability_rvf() {
391 let cap = InitialCapability::rvf_package(0x2000, 0xDEADBEEF);
392
393 assert_eq!(cap.object_type, ObjectType::RvfMount);
394 assert!(cap.rights.contains(CapRights::READ));
395 assert!(cap.rights.contains(CapRights::EXECUTE));
396 assert!(cap.rights.contains(CapRights::PROVE));
397 assert!(!cap.rights.contains(CapRights::WRITE));
398 }
399
400 #[test]
401 fn test_boot_capability_set_minimal() {
402 let set = BootCapabilitySet::minimal(1);
403
404 assert_eq!(set.total_count(), 1);
405 assert!(set.root_task.is_some());
406 }
407
408 #[test]
409 fn test_boot_capability_set_full() {
410 let set = BootCapabilitySet::full(
411 1, 0x1000, 0x10000, 0x2000, 0xCAFE, );
417
418 assert_eq!(set.memory_region_count(), 1);
419 assert!(set.rvf_package.is_some());
420 assert!(set.witness_log.is_some());
421 assert!(set.interrupt_queue.is_some());
422 assert!(set.timer.is_some());
423 assert!(set.root_task.is_some());
424
425 assert_eq!(set.total_count(), 6);
427 }
428
429 #[test]
430 fn test_boot_capability_set_add_memory() {
431 let mut set = BootCapabilitySet::new();
432
433 assert!(set.add_memory_region(0x1000, 0x8000_0000));
434 assert!(set.add_memory_region(0x1001, 0x9000_0000));
435
436 assert_eq!(set.memory_region_count(), 2);
437 }
438
439 #[test]
440 fn test_boot_capability_set_memory_limit() {
441 let mut set = BootCapabilitySet::new();
442
443 for i in 0..16 {
445 assert!(set.add_memory_region(i as u64, i as u64 * 0x1000_0000));
446 }
447
448 assert!(!set.add_memory_region(16, 0));
450 }
451
452 #[test]
453 fn test_boot_capability_set_iter() {
454 let set = BootCapabilitySet::full(1, 0x1000, 0x10000, 0x2000, 0xCAFE);
455
456 let mut count = 0;
457 let mut first_type = None;
458 for cap in set.iter() {
459 if first_type.is_none() {
460 first_type = Some(cap.object_type);
461 }
462 count += 1;
463 }
464
465 assert_eq!(count, 6);
466 assert_eq!(first_type, Some(ObjectType::Region));
468 }
469
470 #[test]
471 fn test_readonly_memory_region() {
472 let cap = InitialCapability::memory_readonly(0x1000, 0x0000_0000);
473
474 assert!(cap.rights.contains(CapRights::READ));
475 assert!(cap.rights.contains(CapRights::GRANT));
476 assert!(!cap.rights.contains(CapRights::WRITE));
477 assert!(!cap.rights.contains(CapRights::EXECUTE));
478 }
479}