Implement conversions between ErrorCode and u32/u64
Implement TryFrom and From traits for ErrorCode to support conversions
between ErrorCode and u32/u64 types. According to the PSCI
specification, error code values are represented as 32-bit or 64-bit
signed integers. These new trait implementations allow ErrorCode to be
converted to and from u32/u64, making it possible to use the values
directly in registers.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: If4b4151760d8d7600d65d1c3d83d317547223457
diff --git a/Cargo.lock b/Cargo.lock
index 20d418c..7d8e56b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,7 +4,7 @@
[[package]]
name = "arm-psci"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"bitflags",
"num_enum",
diff --git a/Cargo.toml b/Cargo.toml
index c2ee1a4..6960b7d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@
[package]
name = "arm-psci"
-version = "0.1.1"
+version = "0.1.2"
authors = [
"Balint Dobszay <balint.dobszay@arm.com>",
"Imre Kis <imre.kis@arm.com>",
diff --git a/src/lib.rs b/src/lib.rs
index 087872b..1daec01 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -26,6 +26,8 @@
UnrecognisedFunctionId(u32),
#[error("unrecognised PSCI error code {0}")]
UnrecognisedErrorCode(i32),
+ #[error("overflowing PSCI error code {0}")]
+ OverflowingErrorCode(i64),
#[error("invalid PSCI version {0}")]
InvalidVersion(u32),
#[error("invalid power state value {0}")]
@@ -162,6 +164,41 @@
InvalidAddress = -9,
}
+impl TryFrom<u32> for ErrorCode {
+ type Error = Error;
+
+ fn try_from(value: u32) -> Result<Self, Self::Error> {
+ Self::try_from_primitive(value as i32)
+ }
+}
+
+impl TryFrom<u64> for ErrorCode {
+ type Error = Error;
+
+ fn try_from(value: u64) -> Result<Self, Self::Error> {
+ let signed_value =
+ i32::try_from(value as i64).map_err(|_| Error::OverflowingErrorCode(value as i64))?;
+ Self::try_from_primitive(signed_value)
+ }
+}
+
+impl From<ErrorCode> for u32 {
+ /// Converts `ErrorCode` to be suitable for returning it in a 32-bit register.
+ /// See 5.2.2 Return error codes
+ fn from(value: ErrorCode) -> Self {
+ i32::from(value) as u32
+ }
+}
+
+impl From<ErrorCode> for u64 {
+ /// Converts `ErrorCode` to be suitable for returning it in a 64-bit register, i.e. it does
+ /// sign extension to 64 bits.
+ /// See 5.2.2 Return error codes
+ fn from(value: ErrorCode) -> Self {
+ i32::from(value) as u64
+ }
+}
+
/// Structure for describing PSCI major and minor version.
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct Version {
@@ -1107,6 +1144,37 @@
assert_eq!(-7, i32::from(ErrorCode::NotPresent));
assert_eq!(-8, i32::from(ErrorCode::Disabled));
assert_eq!(-9, i32::from(ErrorCode::InvalidAddress));
+
+ assert_eq!(
+ Err(Error::UnrecognisedErrorCode(0)),
+ ErrorCode::try_from(0u32)
+ );
+
+ assert_eq!(
+ Ok(ErrorCode::NotSupported),
+ ErrorCode::try_from(0xffff_ffffu32)
+ );
+
+ assert_eq!(
+ Err(Error::UnrecognisedErrorCode(0)),
+ ErrorCode::try_from(0u64)
+ );
+
+ assert_eq!(
+ Err(Error::OverflowingErrorCode(0x7fff_ffff_ffff_ffff)),
+ ErrorCode::try_from(0x7fff_ffff_ffff_ffffu64)
+ );
+
+ assert_eq!(
+ Ok(ErrorCode::NotSupported),
+ ErrorCode::try_from(0xffff_ffff_ffff_ffffu64)
+ );
+
+ assert_eq!(0xffff_fffe, u32::from(ErrorCode::InvalidParameters));
+ assert_eq!(
+ 0xffff_ffff_ffff_fffe,
+ u64::from(ErrorCode::InvalidParameters)
+ );
}
#[test]