pvmfw: Loop SMCCC_TRNG_RND on NO_ENTROPY

As the firmware is allowed by the specification to return NO_ENTROPY:

    The call is non-blocking, when the available entropy is less than N,
    the call must returns `NO_ENTROPY`.
    There are system designs where FW may limit the rate at which
    entropy is requested by a caller.
    To enable this entropy request rate limitation, the call is allowed
    to return `NO_ENTROPY` even if sufficient conditioned

Loop until we receive the requested entropy instead of throwing an error
(resulting in a pvmfw panic).

Note that this could cause a pVM to become unresponsive during boot if
the firmware never returns the requested entropy (a behaviour that seems
to be compliant with the spec).

Bug: 270841564
Test: atest MicrodroidHostTests
Change-Id: If2bb3fba0dcbded3772a41c9b7e6e7fb1180f225
diff --git a/pvmfw/src/rand.rs b/pvmfw/src/rand.rs
index a53cac6..bf0edd5 100644
--- a/pvmfw/src/rand.rs
+++ b/pvmfw/src/rand.rs
@@ -52,12 +52,11 @@
 
 fn fill_with_entropy(s: &mut [u8]) -> Result<()> {
     const MAX_BYTES_PER_CALL: usize = size_of::<hvc::TrngRng64Entropy>();
-    let bits = usize::try_from(u8::BITS).unwrap();
 
     let (aligned, remainder) = s.split_at_mut(s.len() - s.len() % MAX_BYTES_PER_CALL);
 
     for chunk in aligned.chunks_exact_mut(MAX_BYTES_PER_CALL) {
-        let (r, s, t) = hvc::trng_rnd64((chunk.len() * bits).try_into().unwrap())?;
+        let (r, s, t) = repeat_trng_rnd(chunk.len())?;
 
         let mut words = chunk.chunks_exact_mut(size_of::<u64>());
         words.next().unwrap().clone_from_slice(&t.to_ne_bytes());
@@ -67,7 +66,7 @@
 
     if !remainder.is_empty() {
         let mut entropy = [0; MAX_BYTES_PER_CALL];
-        let (r, s, t) = hvc::trng_rnd64((remainder.len() * bits).try_into().unwrap())?;
+        let (r, s, t) = repeat_trng_rnd(remainder.len())?;
 
         let mut words = entropy.chunks_exact_mut(size_of::<u64>());
         words.next().unwrap().clone_from_slice(&t.to_ne_bytes());
@@ -80,6 +79,17 @@
     Ok(())
 }
 
+fn repeat_trng_rnd(n_bytes: usize) -> hvc::trng::Result<hvc::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,
+        }
+    }
+}
+
 pub fn random_array<const N: usize>() -> Result<[u8; N]> {
     let mut arr = [0; N];
     fill_with_entropy(&mut arr)?;