Skip to main content

ruvix_cap/
boot.rs

1//! Initial capability set creation at boot.
2//!
3//! At kernel boot, the root task is created with a set of initial
4//! capabilities granting access to all physical resources. These
5//! capabilities form the basis of all subsequent derivation.
6//!
7//! # Initial Capabilities (from ADR-087 Section 6.3)
8//!
9//! 1. **Physical memory regions** - Full access to all physical RAM
10//! 2. **Boot RVF package** - The verified firmware/kernel image
11//! 3. **Kernel witness log** - For proof attestation
12//! 4. **Root interrupt queue** - For interrupt handling
13
14use ruvix_types::{CapRights, ObjectType};
15
16/// Initial capability descriptor for boot-time creation.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct InitialCapability {
19    /// Object identifier.
20    pub object_id: u64,
21
22    /// Object type.
23    pub object_type: ObjectType,
24
25    /// Rights granted.
26    pub rights: CapRights,
27
28    /// Badge for identification.
29    pub badge: u64,
30
31    /// Description for debugging.
32    pub description: &'static str,
33}
34
35impl InitialCapability {
36    /// Creates a new initial capability descriptor.
37    #[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    /// Creates a physical memory capability.
56    #[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    /// Creates a read-only physical memory capability (e.g., ROM).
69    #[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            // Read + Grant (can share) but no Write, Execute, or Revoke
76            rights: CapRights::READ.union(CapRights::GRANT),
77            badge: start_addr,
78            description: "Read-only memory region (ROM)",
79        }
80    }
81
82    /// Creates a boot RVF package capability.
83    #[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    /// Creates a kernel witness log capability.
96    #[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    /// Creates a root interrupt queue capability.
109    #[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    /// Creates a root timer capability.
122    #[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    /// Creates a root task capability (self-reference).
135    #[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    /// Creates a vector store capability for neural memory.
148    #[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    /// Creates a proof graph capability (uses GraphStore for proof-related data).
161    #[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/// The complete set of initial capabilities for the root task.
175///
176/// This struct describes all capabilities that should be created
177/// during kernel boot and granted to the root task.
178#[derive(Debug, Clone)]
179pub struct BootCapabilitySet {
180    /// Memory region capabilities.
181    memory_regions: [Option<InitialCapability>; 16],
182    memory_count: usize,
183
184    /// RVF package capability.
185    rvf_package: Option<InitialCapability>,
186
187    /// Witness log capability.
188    witness_log: Option<InitialCapability>,
189
190    /// Interrupt queue capability.
191    interrupt_queue: Option<InitialCapability>,
192
193    /// Timer capability.
194    timer: Option<InitialCapability>,
195
196    /// Root task self-reference.
197    root_task: Option<InitialCapability>,
198
199    /// Vector store capability.
200    vector_store: Option<InitialCapability>,
201
202    /// Proof graph capability.
203    proof_graph: Option<InitialCapability>,
204}
205
206impl BootCapabilitySet {
207    /// Creates an empty boot capability set.
208    #[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    /// Creates a minimal boot set with essential capabilities.
225    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    /// Creates a full boot set with all standard capabilities.
232    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        // Root task self-reference
242        set.root_task = Some(InitialCapability::root_task(root_task_id));
243
244        // Single memory region covering all physical RAM
245        set.memory_regions[0] = Some(InitialCapability::memory(memory_start, memory_size));
246        set.memory_count = 1;
247
248        // Boot RVF package
249        set.rvf_package = Some(InitialCapability::rvf_package(rvf_object_id, rvf_hash));
250
251        // Witness log
252        set.witness_log = Some(InitialCapability::witness_log(root_task_id + 1));
253
254        // Interrupt queue (all IRQs enabled)
255        set.interrupt_queue = Some(InitialCapability::interrupt_queue(
256            root_task_id + 2,
257            u64::MAX,
258        ));
259
260        // Timer
261        set.timer = Some(InitialCapability::timer(root_task_id + 3));
262
263        set
264    }
265
266    /// Adds a memory region capability.
267    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    /// Adds a read-only memory region (e.g., ROM).
278    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    /// Sets the RVF package capability.
289    #[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    /// Sets the witness log capability.
295    #[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    /// Sets the interrupt queue capability.
301    #[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    /// Sets the timer capability.
307    #[inline]
308    pub fn set_timer(&mut self, object_id: u64) {
309        self.timer = Some(InitialCapability::timer(object_id));
310    }
311
312    /// Sets the root task capability.
313    #[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    /// Sets the vector store capability.
319    #[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    /// Sets the proof graph capability.
325    #[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    /// Returns the number of memory regions.
331    #[inline]
332    #[must_use]
333    pub const fn memory_region_count(&self) -> usize {
334        self.memory_count
335    }
336
337    /// Returns the total number of capabilities in the set.
338    #[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    /// Returns an iterator over all capabilities in the set.
355    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,          // root_task_id
412            0x1000,     // memory_start
413            0x10000,    // memory_size
414            0x2000,     // rvf_object_id
415            0xCAFE,     // rvf_hash
416        );
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        // Should have 6 capabilities total
426        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        // Fill up all 16 slots
444        for i in 0..16 {
445            assert!(set.add_memory_region(i as u64, i as u64 * 0x1000_0000));
446        }
447
448        // 17th should fail
449        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        // First should be memory
467        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}