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}