components/loader/
sequential.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2024.

//! Component for creating a sequential process loader.
//!
//! `ProcessLoaderSequentialComponent` uses the standard Tock assumptions about
//! where processes are stored in flash and what RAM is allocated for process
//! use.

use core::mem::MaybeUninit;
use kernel::component::Component;
use kernel::deferred_call::DeferredCallClient;
use kernel::platform::chip::Chip;
use kernel::process::ProcessLoadingAsync;
use kernel::process::ProcessStandardDebug;

#[macro_export]
macro_rules! process_loader_sequential_component_static {
    ($C:ty, $D:ty, $NUMPROCS:expr $(,)?) => {{
        let loader = kernel::static_buf!(kernel::process::SequentialProcessLoaderMachine<
            $C, $D
        >);
        let process_binary_array = kernel::static_buf!(
            [Option<kernel::process::ProcessBinary>; $NUMPROCS]
        );

       (loader, process_binary_array)
    };};
}

pub type ProcessLoaderSequentialComponentType<C, D> =
    kernel::process::SequentialProcessLoaderMachine<'static, C, D>;

pub struct ProcessLoaderSequentialComponent<
    C: Chip + 'static,
    D: ProcessStandardDebug + 'static,
    const NUM_PROCS: usize,
> {
    checker: &'static kernel::process::ProcessCheckerMachine,
    processes: &'static mut [Option<&'static dyn kernel::process::Process>],
    kernel: &'static kernel::Kernel,
    chip: &'static C,
    fault_policy: &'static dyn kernel::process::ProcessFaultPolicy,
    appid_policy: &'static dyn kernel::process_checker::AppIdPolicy,
    storage_policy: &'static dyn kernel::process::ProcessStandardStoragePermissionsPolicy<C, D>,
}

impl<C: Chip, D: ProcessStandardDebug, const NUM_PROCS: usize>
    ProcessLoaderSequentialComponent<C, D, NUM_PROCS>
{
    pub fn new(
        checker: &'static kernel::process::ProcessCheckerMachine,
        processes: &'static mut [Option<&'static dyn kernel::process::Process>],
        kernel: &'static kernel::Kernel,
        chip: &'static C,
        fault_policy: &'static dyn kernel::process::ProcessFaultPolicy,
        appid_policy: &'static dyn kernel::process_checker::AppIdPolicy,
        storage_policy: &'static dyn kernel::process::ProcessStandardStoragePermissionsPolicy<C, D>,
    ) -> Self {
        Self {
            checker,
            processes,
            kernel,
            chip,
            fault_policy,
            appid_policy,
            storage_policy,
        }
    }
}

impl<C: Chip, D: ProcessStandardDebug, const NUM_PROCS: usize> Component
    for ProcessLoaderSequentialComponent<C, D, NUM_PROCS>
{
    type StaticInput = (
        &'static mut MaybeUninit<kernel::process::SequentialProcessLoaderMachine<'static, C, D>>,
        &'static mut MaybeUninit<[Option<kernel::process::ProcessBinary>; NUM_PROCS]>,
    );

    type Output = &'static kernel::process::SequentialProcessLoaderMachine<'static, C, D>;

    fn finalize(mut self, s: Self::StaticInput) -> Self::Output {
        let proc_manage_cap =
            kernel::create_capability!(kernel::capabilities::ProcessManagementCapability);

        const ARRAY_REPEAT_VALUE: Option<kernel::process::ProcessBinary> = None;
        let process_binary_array = s.1.write([ARRAY_REPEAT_VALUE; NUM_PROCS]);

        // These symbols are defined in the standard Tock linker script.
        extern "C" {
            /// Beginning of the ROM region containing app images.
            static _sapps: u8;
            /// End of the ROM region containing app images.
            static _eapps: u8;
            /// Beginning of the RAM region for app memory.
            static mut _sappmem: u8;
            /// End of the RAM region for app memory.
            static _eappmem: u8;
        }

        let loader = unsafe {
            s.0.write(kernel::process::SequentialProcessLoaderMachine::new(
                self.checker,
                *core::ptr::addr_of_mut!(self.processes),
                process_binary_array,
                self.kernel,
                self.chip,
                core::slice::from_raw_parts(
                    core::ptr::addr_of!(_sapps),
                    core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
                ),
                core::slice::from_raw_parts_mut(
                    core::ptr::addr_of_mut!(_sappmem),
                    core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
                ),
                self.fault_policy,
                self.storage_policy,
                self.appid_policy,
                &proc_manage_cap,
            ))
        };
        self.checker.set_client(loader);
        loader.register();
        loader.start();
        loader
    }
}