Skip to main content

kernel/utilities/
helpers.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Helper functions and macros.
6//!
7//! These are various utility functions and macros that are useful throughout
8//! the Tock kernel and are provided here for convenience.
9//!
10//! The macros are exported through the top level of the `kernel` crate.
11
12/// Create an object with the given capabilities.
13///
14/// ```
15/// # use kernel::capabilities::{ProcessManagementCapability, MemoryAllocationCapability};
16/// # use kernel::create_capability;
17/// let process_mgmt_cap = create_capability!(ProcessManagementCapability);
18/// let unified_cap = create_capability!(ProcessManagementCapability, MemoryAllocationCapability);
19/// ```
20///
21/// This helper macro cannot be called from `#![forbid(unsafe_code)]` crates,
22/// and is used by trusted code to generate a capability that it can either use
23/// or pass to another module.
24///
25/// # Safety
26///
27/// This macro can only be used in a context that is allowed to use
28/// `unsafe`. Specifically, an internal `allow(unsafe_code)` directive
29/// will conflict with any `forbid(unsafe_code)` at the crate or block
30/// level.
31///
32/// ```compile_fail
33/// # use kernel::capabilities::ProcessManagementCapability;
34/// # use kernel::create_capability;
35/// #[forbid(unsafe_code)]
36/// fn untrusted_fn() {
37///     let process_mgmt_cap = create_capability!(ProcessManagementCapability);
38/// }
39/// ```
40#[macro_export]
41macro_rules! create_capability {
42    ($($T:ty),+) => {{
43        #[allow(unsafe_code)]
44        struct Cap(());
45        $(
46            // SAFETY: `$T`'s safety contract only requires that capabilities
47            // be created in a context permitted to use `unsafe`. The
48            // `#[allow(unsafe_code)]` above discharges that: it conflicts
49            // with any `forbid(unsafe_code)` at the crate or block level, so
50            // this expansion only compiles where `unsafe` is permitted.
51            unsafe impl $T for Cap {}
52        )*
53        Cap(())
54    }};
55}
56
57/// Create a struct that implements the given capability traits.
58///
59/// Unlike [`create_capability!`], this macro creates an instance of a struct
60/// with a visibly named type. Use this when you need to name the capability
61/// type, such as when passing it to a component's static buffer macro.
62///
63/// # Usage Example
64///
65/// ```ignore
66/// # use kernel::capabilities::ProcessManagementCapability;
67/// # use kernel::create_typed_capability;
68///
69/// create_typed_capability!(proc_cap, ProcCapForManager: ProcessManagementCapability);
70///
71/// let manager = components::manager::ManagerComponent::new(
72///     board_kernel,
73///     mux_alarm,
74///     proc_cap,
75/// )
76/// .finalize(components::manager_component_static!(
77///     AlarmHw,
78///     ProcCapForManager,
79/// ));
80/// ```
81///
82/// # Difference from `create_capability!()`
83///
84/// `create_typed_capability!()` creates a visibly named type, whereas
85/// [`create_capability!`] does not. If possible, use [`create_capability!`].
86/// However, for components that need to name the type for static constructors,
87/// use `create_typed_capability!()` to create the struct that is used in that
88/// macro expansion and in the component `finalize()` method.
89///
90/// # Supporting Multiple Capabilities
91///
92/// Some type signatures require multiple capabilities. This macro supports
93/// declaring multiple capabilities. For example:
94///
95/// ```
96/// kernel::create_typed_capability!(process_console_cap, ProcessConsoleCap:
97///     kernel::capabilities::ProcessManagementCapability,
98///     kernel::capabilities::ProcessStartCapability
99/// );
100/// ```
101///
102/// # Restrictions
103///
104/// This helper macro cannot be called from `#![forbid(unsafe_code)]` crates,
105/// and is used by trusted code to generate a capability type.
106///
107/// # Safety
108///
109/// This macro can only be used in a context that is allowed to use `unsafe`.
110/// Specifically, an internal `allow(unsafe_code)` directive will conflict with
111/// any `forbid(unsafe_code)` at the crate or block level.
112#[macro_export]
113macro_rules! create_typed_capability {
114    ($var:ident, $type:ident: $($T:path),+ $(,)?) => {
115        // In plain macros, there's not an ergonomic way to construct a new
116        // identifier for the module name, but we do need unique module name.
117        // Modules and structs share the same namespace, so we can't use
118        // `mod $type` here, but _variables_ exist in a separate namespace,
119        // so we can use the variable name as a module name.
120        //
121        // The implication of this design is that something in the same scope
122        // of this macro _could_ write
123        //     unsafe { $type::__new_only_for_use_in_macro() }
124        // to mint another capability, but doing so requires both an unsafe
125        // block and use of an obviously wrong method name.
126        mod $var {
127            // Bring the invocation site's surrounding module into scope, so
128            // `$T` arguments can be given as bare names brought in by a
129            // local `use`, not just fully-qualified paths. This is often
130            // unused (most call sites already use fully-qualified paths),
131            // hence the `allow`.
132            #[allow(unused_imports)]
133            use super::*;
134
135            // Prevent creation by anything external.
136            pub struct $type(());
137
138            // Implement specified capabilities.
139            $(
140                // SAFETY: `$T`'s safety contract only requires that
141                // capabilities be created in a context permitted to use
142                // `unsafe`. The `allow(unsafe_code)` below discharges that:
143                // it conflicts with any `forbid(unsafe_code)` at the crate
144                // or block level.
145                #[allow(unsafe_code)]
146                unsafe impl $T for $type {}
147            )*
148
149            impl $type {
150                // Mark the constructor unsafe to prevent non-obvious use.
151                #[doc(hidden)]
152                pub unsafe fn __new_only_for_use_in_macro() -> Self {
153                    $type(())
154                }
155            }
156        }
157        // Import the type name to the current scope
158        use $var::$type;
159
160        // Create one instance of the capability.
161        //
162        // SAFETY: this is the macro's own single, controlled call to the
163        // gated constructor above.
164        let $var = unsafe { $type::__new_only_for_use_in_macro() };
165    };
166}
167
168/// Define a struct type that implements the given capability traits.
169///
170/// Unlike [`create_capability!`] or [`create_typed_capability!`], this macro
171/// only defines a visibly named type, it does not create any instances.
172/// Use this when you need to name the capability type across scope boundaries.
173///
174/// Use `mint_defined_capability!` to create an instance. Note: You can only
175/// mint capabilities in the module that defines this type, or in a descendant
176/// of that module.
177///
178/// This macro is intended to be used at module level scope (i.e. not in a
179/// code block), since minting requires naming the type across a scope
180/// boundary.
181///
182/// # Usage Example
183///
184/// ```
185/// # use kernel::capabilities::ProcessManagementCapability;
186/// # use kernel::define_capability_type;
187///
188/// define_capability_type!(ProcCapForManager: ProcessManagementCapability);
189/// ```
190///
191/// # Restrictions
192///
193/// This helper macro cannot be called from `#![forbid(unsafe_code)]` crates,
194/// and is used by trusted code to define a capability type.
195///
196/// # Safety
197///
198/// This macro can only be used in a context that is allowed to use `unsafe`.
199/// Specifically, an internal `allow(unsafe_code)` directive will conflict with
200/// any `forbid(unsafe_code)` at the crate or block level.
201#[macro_export]
202macro_rules! define_capability_type {
203    ($type:ident: $($T:path),+ $(,)?) => {
204        /// Publicly nameable type for capabilities.
205        pub struct $type {
206            // Make it obvious that this should not be directly constructed.
207            _not_for_public_construction: (),
208        }
209
210        // Implement specified capabilities.
211        $(
212            // SAFETY: `$T`'s safety contract only requires that capabilities
213            // be created in a context permitted to use `unsafe`. The
214            // `allow(unsafe_code)` below discharges that: it conflicts with
215            // any `forbid(unsafe_code)` at the crate or block level.
216            #[allow(unsafe_code)]
217            unsafe impl $T for $type {}
218        )*
219
220        impl $type {
221            // Mark the constructor unsafe to prevent non-obvious use.
222            //
223            // Must not be `pub` to prevent external users. Note this is not
224            // airtight: anything in the same module (or a descendant module)
225            // as this type definition _could_ write
226            //     unsafe { $type::__macro_only_capability_creator() }
227            // to mint another capability, but doing so requires both an
228            // unsafe block and use of an obviously-not-public method name.
229            #[doc(hidden)]
230            unsafe fn __macro_only_capability_creator() -> Self {
231                Self { _not_for_public_construction: () }
232            }
233        }
234    };
235}
236
237/// Create an instance of a capability type defined by [`define_capability_type!`].
238///
239/// Use this to create one instance of a capability previously declared via
240/// [`define_capability_type`]. Note: You can only mint capabilities in the
241/// module that defines this type, or in a descendant of that module.
242///
243/// # Usage Example
244///
245/// ```ignore
246/// # use kernel::mint_defined_capability;
247///
248/// let proc_cap = unsafe { mint_defined_capability!(ProcCapForManager) };
249/// ```
250///
251/// # Restrictions
252///
253/// This macro invokes an `unsafe` function. Callers must wrap use of this
254/// macro in `unsafe` to assert they are trusted to mint a capability.
255// Note: Ultimately, this is just a wrapper around a function call, and does
256// not _need_ to be in a macro per se. However, minting capabilities is a
257// highly sensitive operation, and encapsulating this in a macro helps code
258// review spot this directly as the creation of a capability, which may be less
259// apparent when just constructing an arbitrarily named struct.
260#[macro_export]
261macro_rules! mint_defined_capability {
262    ($type:ident) => {
263        $type::__macro_only_capability_creator()
264    };
265}
266
267/// Count the number of passed expressions.
268///
269/// Useful for constructing variable sized arrays in other macros.
270/// Taken from the Little Book of Rust Macros.
271///
272/// ```ignore
273/// use kernel:count_expressions;
274///
275/// let count: usize = count_expressions!(1+2, 3+4);
276/// ```
277#[macro_export]
278macro_rules! count_expressions {
279    () => (0usize);
280    ($head:expr $(,)?) => (1usize);
281    ($head:expr, $($tail:expr),* $(,)?) => (1usize + count_expressions!($($tail),*));
282}
283
284/// Executables must specify their stack size by using the `stack_size!` macro.
285///
286/// It takes a single argument, the desired stack size in bytes. Example:
287/// ```
288/// kernel::stack_size!{0x1000}
289/// ```
290// stack_size works by putting a symbol equal to the size of the stack in the
291// .stack_buffer section. The linker script uses the .stack_buffer section to
292// size the stack.
293#[macro_export]
294macro_rules! stack_size {
295    {$size:expr} => {
296        /// Size to allocate for the stack.
297        ///
298        /// This creates a static buffer inserted into the `.stack_buffer`
299        /// section that the linker script picks up and places at the correct
300        /// location in RAM.
301        ///
302        /// This section attribute is only applied when targeting bare-metal
303        /// (`target_os = "none"`). Host builds (e.g. tests, clippy, doc) use
304        /// object formats (Mach-O, PE, ...) that reject a bare section name
305        /// like this, yielding errors such as: `mach-o section specifier
306        /// requires a segment and section separated by a comma`.
307        #[cfg_attr(target_os = "none", unsafe(link_section = ".stack_buffer"))]
308        #[unsafe(no_mangle)]
309        static mut STACK_MEMORY: [u8; $size] = [0; $size];
310    }
311}
312
313/// Initialize all fields of a `MaybeUninit<T>` struct.
314///
315/// Use this macro to guarantee that all fields in `T` are initialized.
316///
317/// Instead of the normal code, which would look like this:
318///
319/// ```rust,ignore
320/// let process_uninit: &mut MaybeUninit<ProcessStandard<C, D>> =
321///     unsafe { &mut *process_struct_memory_location };
322///
323/// let process_uptr = process_uninit.as_mut_ptr();
324///
325/// unsafe {
326///     (&raw mut (*process_uptr).kernel).write(kernel);
327///     (&raw mut (*process_uptr).chip).write(chip);
328///     ...
329/// }
330/// ```
331///
332/// which has the limitation that if not every field is set, then this code is
333/// unsafe. With this macro, the code looks like this:
334///
335/// ```rust,ignore
336/// let process_uninit: &mut MaybeUninit<ProcessStandard<C, D>> =
337///     unsafe { &mut *process_struct_memory_location };
338///
339/// unsafe {
340///     init_uninit_struct!(process_uninit => ProcessStandard<C, D> {
341///         kernel: kernel,
342///         chip: chip,
343///         ...
344///     });
345/// }
346/// ```
347///
348/// If not every field is set then there will be a compiler error.
349///
350/// # Implementation
351///
352/// This macro creates a fake implementation of the struct `T` and then
353/// populates all of the provided fields. This allows the normal Rust compiler
354/// to check that all fields are actually set.
355///
356/// The generated code looks something like this:
357///
358/// ```rust,ignore
359/// #[allow(unreachable_code)]
360/// if false {
361///     let _: ProcessStandard<C, D> = ProcessStandard {
362///         kernel: ::core::panicking::panic("not yet implemented"),
363///         chip: ::core::panicking::panic("not yet implemented"),
364///         ...
365///     };
366/// }
367/// ```
368///
369/// Using `todo!()` avoids any issues with the borrow checker. However, using
370/// `todo!()` causes the `diverging_sub_expression` clippy lint to trigger.
371/// Since we are doing this intentionally, we manually ignore the
372/// `diverging_sub_expression` lint.
373///
374/// # Safety
375///
376/// The struct to be initialized needs to be correctly allocated and all fields
377/// need to be correctly aligned.
378#[macro_export]
379macro_rules! init_uninit_struct {
380    (@field $field:ident : $value:expr) => {
381        $value
382    };
383
384    (@field $field:ident) => {
385        $field
386    };
387
388    ( $s: expr => $t: ident < $($gen:tt),* > { $( $field:ident : $value:expr ),* $(,)? } ) => {
389        #[allow(unreachable_code)]
390        #[allow(clippy::diverging_sub_expression)]
391        if false {
392            let _: $t<$($gen),*> = $t {
393                $( $field: todo!() ),*
394            };
395        }
396
397        let s = $s.as_mut_ptr();
398        $(
399            (&raw mut (*s).$field).write(init_uninit_struct!(@field $field : $value));
400        )*
401    };
402}
403
404/// Reinterpret a `&mut usize` as a `&mut u32` (32-bit targets) or `&mut u64`
405/// (64-bit targets).
406///
407/// This is useful for architectures (e.g. RISC-V) that store syscall/upcall
408/// register arguments as `usize` so that a single struct definition can serve
409/// both 32-bit and 64-bit targets, but need to pass register-width-specific
410/// (`u32`/`u64`) references into TRD-defined encode/decode functions.
411///
412/// This is a plain function, not a macro, on purpose: the conversion is only
413/// sound behind a real function-call boundary.
414#[cfg(target_pointer_width = "32")]
415pub fn usize_as_native_mut(val: &mut usize) -> &mut u32 {
416    let ptr = core::ptr::from_mut::<usize>(val);
417    // SAFETY: We are guaranteed to be on a 32-bit platform, so a `usize` is
418    // the same size and alignment as a `u32`, and `val` is guaranteed to be
419    // initialized to some value.
420    unsafe { &mut *ptr.cast::<u32>() }
421}
422
423/// Reinterpret a `&mut usize` as a `&mut u32` (32-bit targets) or `&mut u64`
424/// (64-bit targets).
425///
426/// This is a plain function, not a macro, on purpose: the conversion is only
427/// sound behind a real function-call boundary.
428#[cfg(target_pointer_width = "64")]
429pub fn usize_as_native_mut(val: &mut usize) -> &mut u64 {
430    let ptr = core::ptr::from_mut::<usize>(val);
431    // SAFETY: We are guaranteed to be on a 64-bit platform, so a `usize` is
432    // the same size and alignment as a `u64`, and `val` is guaranteed to be
433    // initialized to some value.
434    unsafe { &mut *ptr.cast::<u64>() }
435}
436
437/// Compute a POSIX-style CRC32 checksum of a slice.
438///
439/// Online calculator: <https://crccalc.com/>
440pub fn crc32_posix(b: &[u8]) -> u32 {
441    let mut crc: u32 = 0;
442
443    for c in b {
444        crc ^= (*c as u32) << 24;
445
446        for _i in 0..8 {
447            if crc & (0b1 << 31) > 0 {
448                crc = (crc << 1) ^ 0x04c11db7;
449            } else {
450                crc <<= 1;
451            }
452        }
453    }
454    !crc
455}