Merge "vmbase: Trivial changes to prepare for smccc::trng" into main
diff --git a/vmbase/src/hvc.rs b/vmbase/src/hvc.rs
index 4d489d5..ebd1625 100644
--- a/vmbase/src/hvc.rs
+++ b/vmbase/src/hvc.rs
@@ -30,11 +30,11 @@
 pub const ARM_SMCCC_TRNG_RND64: u32 = 0xc400_0053;
 
 /// Returns the (major, minor) version tuple, as defined by the SMCCC TRNG.
-pub fn trng_version() -> trng::Result<(u16, u16)> {
+pub fn trng_version() -> trng::Result<trng::Version> {
     let args = [0u64; 17];
 
     let version = positive_or_error_64::<Error>(hvc64(ARM_SMCCC_TRNG_VERSION, args)[0])?;
-    Ok(((version >> 16) as u16, version as u16))
+    (version as u32 as i32).try_into()
 }
 
 pub type TrngRng64Entropy = (u64, u64, u64);
diff --git a/vmbase/src/hvc/trng.rs b/vmbase/src/hvc/trng.rs
index 1a27d64..efb86f6 100644
--- a/vmbase/src/hvc/trng.rs
+++ b/vmbase/src/hvc/trng.rs
@@ -55,3 +55,40 @@
 }
 
 pub type Result<T> = result::Result<T, Error>;
+
+/// A version of the SMCCC TRNG interface.
+#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
+pub struct Version {
+    pub major: u16,
+    pub minor: u16,
+}
+
+impl fmt::Display for Version {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}.{}", self.major, self.minor)
+    }
+}
+
+impl fmt::Debug for Version {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl TryFrom<i32> for Version {
+    type Error = Error;
+
+    fn try_from(value: i32) -> core::result::Result<Self, Error> {
+        if value < 0 {
+            Err((value as i64).into())
+        } else {
+            Ok(Self { major: (value >> 16) as u16, minor: value as u16 })
+        }
+    }
+}
+
+impl From<Version> for u32 {
+    fn from(version: Version) -> Self {
+        (u32::from(version.major) << 16) | u32::from(version.minor)
+    }
+}
diff --git a/vmbase/src/rand.rs b/vmbase/src/rand.rs
index a5a5f5f..6b8d7e0 100644
--- a/vmbase/src/rand.rs
+++ b/vmbase/src/rand.rs
@@ -14,7 +14,7 @@
 
 //! Functions and drivers for obtaining true entropy.
 
-use crate::hvc;
+use crate::hvc::{self, TrngRng64Entropy};
 use core::fmt;
 use core::mem::size_of;
 use smccc::{self, Hvc};
@@ -30,7 +30,7 @@
     /// Unsupported SMCCC version.
     UnsupportedSmcccVersion(smccc::arch::Version),
     /// Unsupported SMCCC TRNG version.
-    UnsupportedVersion((u16, u16)),
+    UnsupportedTrngVersion(hvc::trng::Version),
 }
 
 impl From<smccc::arch::Error> for Error {
@@ -55,9 +55,7 @@
             Self::Smccc(e) => write!(f, "Architectural SMCCC error: {e}"),
             Self::Trng(e) => write!(f, "SMCCC TRNG error: {e}"),
             Self::UnsupportedSmcccVersion(v) => write!(f, "Unsupported SMCCC version {v}"),
-            Self::UnsupportedVersion((x, y)) => {
-                write!(f, "Unsupported SMCCC TRNG version v{x}.{y}")
-            }
+            Self::UnsupportedTrngVersion(v) => write!(f, "Unsupported SMCCC TRNG version {v}"),
         }
     }
 }
@@ -78,8 +76,8 @@
 
     // TRNG_RND requires SMCCC TRNG v1.0.
     match hvc::trng_version()? {
-        (1, _) => (),
-        version => return Err(Error::UnsupportedVersion(version)),
+        hvc::trng::Version { major: 1, minor: _ } => (),
+        version => return Err(Error::UnsupportedTrngVersion(version)),
     }
 
     // TRNG_RND64 doesn't define any special capabilities so ignore the successful result.
@@ -97,7 +95,7 @@
 
 /// Fills a slice of bytes with true entropy.
 pub fn fill_with_entropy(s: &mut [u8]) -> Result<()> {
-    const MAX_BYTES_PER_CALL: usize = size_of::<hvc::TrngRng64Entropy>();
+    const MAX_BYTES_PER_CALL: usize = size_of::<TrngRng64Entropy>();
 
     let (aligned, remainder) = s.split_at_mut(s.len() - s.len() % MAX_BYTES_PER_CALL);
 
@@ -125,13 +123,14 @@
     Ok(())
 }
 
-fn repeat_trng_rnd(n_bytes: usize) -> hvc::trng::Result<hvc::TrngRng64Entropy> {
+fn repeat_trng_rnd(n_bytes: usize) -> Result<TrngRng64Entropy> {
     let bits = usize::try_from(u8::BITS).unwrap();
     let n_bits = (n_bytes * bits).try_into().unwrap();
     loop {
         match hvc::trng_rnd64(n_bits) {
-            Err(hvc::trng::Error::NoEntropy) => continue,
-            res => return res,
+            Ok(entropy) => return Ok(entropy),
+            Err(hvc::trng::Error::NoEntropy) => (),
+            Err(e) => return Err(e.into()),
         }
     }
 }