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/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]