1 // Copyright 2023 the authors.
2 // This project is dual-licensed under Apache 2.0 and MIT terms.
3 // See LICENSE-APACHE and LICENSE-MIT for details.
4 
5 //! Utility functions for error handling.
6 //!
7 //! These functions can be combined with the appropriate HVC or SMC functions to wrap calls which
8 //! return a single value where negative values indicate an error.
9 //!
10 //! For example, the [`system_off`](crate::psci::system_off) function is implemented approximately
11 //! as:
12 //!
13 //! ```
14 //! # #[cfg(target_arch = "aarch64")]
15 //! use smccc::{
16 //!     error::success_or_error_32,
17 //!     psci::{error::Error, PSCI_SYSTEM_OFF},
18 //!     smc32,
19 //! };
20 //!
21 //! # #[cfg(target_arch = "aarch64")]
22 //! pub fn system_off() -> Result<(), Error> {
23 //!     success_or_error_32(smc32(PSCI_SYSTEM_OFF, [0; 7])[0])
24 //! }
25 //! ```
26 
27 /// A value commonly returned to indicate a successful SMCCC call.
28 pub const SUCCESS: i32 = 0;
29 
30 /// Converts the given value (returned from an HVC32 or SMC32 call) either to `Ok(())` if it is
31 /// equal to [`SUCCESS`], or else an error of the given type.
success_or_error_32<E: From<i32>>(value: u32) -> Result<(), E>32 pub fn success_or_error_32<E: From<i32>>(value: u32) -> Result<(), E> {
33     let value = value as i32;
34     if value == SUCCESS {
35         Ok(())
36     } else {
37         Err(value.into())
38     }
39 }
40 
41 /// Converts the given value (returned from an HVC64 or SMC64 call) either to `Ok(())` if it is
42 /// equal to [`SUCCESS`], or else an error of the given type.
success_or_error_64<E: From<i64>>(value: u64) -> Result<(), E>43 pub fn success_or_error_64<E: From<i64>>(value: u64) -> Result<(), E> {
44     let value = value as i64;
45     if value == SUCCESS.into() {
46         Ok(())
47     } else {
48         Err(value.into())
49     }
50 }
51 
52 /// Returns `Ok(value)` if the given value has its high bit unset (i.e. would be positive when
53 /// treated as a signed value), or an error of the given type if the high bit is set.
54 ///
55 /// This is intended to be used with the return value of [`hvc32`](super::hvc32) or
56 /// [`smc32`](super::smc32).
positive_or_error_32<E: From<i32>>(value: u32) -> Result<u32, E>57 pub fn positive_or_error_32<E: From<i32>>(value: u32) -> Result<u32, E> {
58     let signed = value as i32;
59     if signed < 0 {
60         Err(signed.into())
61     } else {
62         Ok(value)
63     }
64 }
65 
66 /// Returns `Ok(value)` if the given value has its high bit unset (i.e. would be positive when
67 /// treated as a signed value), or an error of the given type if the high bit is set.
68 ///
69 /// This is intended to be used with the return value of [`hvc64`](super::hvc64) or
70 /// [`smc64`](super::smc64).
positive_or_error_64<E: From<i64>>(value: u64) -> Result<u64, E>71 pub fn positive_or_error_64<E: From<i64>>(value: u64) -> Result<u64, E> {
72     let signed = value as i64;
73     if signed < 0 {
74         Err(signed.into())
75     } else {
76         Ok(value)
77     }
78 }
79