[dice] Map and read the DICE data in service VM

This cl first maps the DICE range as read-only data and then
parses it as BccHandover data.

The whole process is checked in rialto_test.

Test: atest rialto_test
Bug: 287233786
Change-Id: Icebd60b0a858373dd6ba1efa02d2a31bb0066a7b
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index f8f6d51..7b5cf81 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -31,6 +31,7 @@
 use ciborium_io::Write;
 use core::num::NonZeroUsize;
 use core::slice;
+use diced_open_dice::bcc_handover_parse;
 use fdtpci::PciInfo;
 use hyp::{get_mem_sharer, get_mmio_guard};
 use libfdt::FdtError;
@@ -136,8 +137,21 @@
         VmType::ProtectedVm => {
             let dice_range = read_dice_range_from(fdt)?;
             info!("DICE range: {dice_range:#x?}");
-            // TODO(b/287233786): Read the bcc_handover from the given range.
-            Some(dice_range)
+            // SAFETY: This region was written by pvmfw in its writable_data region. The region
+            // has no overlap with the main memory region and is safe to be mapped as read-only
+            // data.
+            let res = unsafe {
+                MEMORY.lock().as_mut().unwrap().alloc_range_outside_main_memory(&dice_range)
+            };
+            res.map_err(|e| {
+                error!("Failed to use DICE range from DT: {dice_range:#x?}");
+                e
+            })?;
+            let dice_start = dice_range.start as *const u8;
+            // SAFETY: There's no memory overlap and the region is mapped as read-only data.
+            let bcc_handover = unsafe { slice::from_raw_parts(dice_start, dice_range.len()) };
+            let bcc_handover = bcc_handover_parse(bcc_handover)?;
+            Some(bcc_handover)
         }
         // Currently, no DICE data is retrieved for non-protected VMs, as these VMs are solely
         // intended for debugging purposes.
diff --git a/vmbase/src/memory/shared.rs b/vmbase/src/memory/shared.rs
index dfa29e4..6c8a844 100644
--- a/vmbase/src/memory/shared.rs
+++ b/vmbase/src/memory/shared.rs
@@ -135,7 +135,26 @@
     /// Allocate the address range for a const slice; returns None if failed.
     pub fn alloc_range(&mut self, range: &MemoryRange) -> Result<MemoryRange> {
         let region = MemoryRegion { range: range.clone(), mem_type: MemoryType::ReadOnly };
-        self.check(&region)?;
+        self.check_allocatable(&region)?;
+        self.page_table.map_rodata(&get_va_range(range)).map_err(|e| {
+            error!("Error during range allocation: {e}");
+            MemoryTrackerError::FailedToMap
+        })?;
+        self.add(region)
+    }
+
+    /// Allocates the address range for a const slice.
+    ///
+    /// # Safety
+    ///
+    /// Callers of this method need to ensure that the `range` is valid for mapping as read-only
+    /// data.
+    pub unsafe fn alloc_range_outside_main_memory(
+        &mut self,
+        range: &MemoryRange,
+    ) -> Result<MemoryRange> {
+        let region = MemoryRegion { range: range.clone(), mem_type: MemoryType::ReadOnly };
+        self.check_no_overlap(&region)?;
         self.page_table.map_rodata(&get_va_range(range)).map_err(|e| {
             error!("Error during range allocation: {e}");
             MemoryTrackerError::FailedToMap
@@ -146,7 +165,7 @@
     /// Allocate the address range for a mutable slice; returns None if failed.
     pub fn alloc_range_mut(&mut self, range: &MemoryRange) -> Result<MemoryRange> {
         let region = MemoryRegion { range: range.clone(), mem_type: MemoryType::ReadWrite };
-        self.check(&region)?;
+        self.check_allocatable(&region)?;
         self.page_table.map_data_dbm(&get_va_range(range)).map_err(|e| {
             error!("Error during mutable range allocation: {e}");
             MemoryTrackerError::FailedToMap
@@ -196,13 +215,20 @@
         Ok(())
     }
 
-    /// Checks that the given region is within the range of the `MemoryTracker` and doesn't overlap
-    /// with any other previously allocated regions, and that the regions ArrayVec has capacity to
-    /// add it.
-    fn check(&self, region: &MemoryRegion) -> Result<()> {
+    /// Checks that the memory region meets the following criteria:
+    /// - It is within the range of the `MemoryTracker`.
+    /// - It does not overlap with any previously allocated regions.
+    /// - The `regions` ArrayVec has sufficient capacity to add it.
+    fn check_allocatable(&self, region: &MemoryRegion) -> Result<()> {
         if !region.range.is_within(&self.total) {
             return Err(MemoryTrackerError::OutOfRange);
         }
+        self.check_no_overlap(region)
+    }
+
+    /// Checks that the given region doesn't overlap with any other previously allocated regions,
+    /// and that the regions ArrayVec has capacity to add it.
+    fn check_no_overlap(&self, region: &MemoryRegion) -> Result<()> {
         if self.regions.iter().any(|r| region.range.overlaps(&r.range)) {
             return Err(MemoryTrackerError::Overlaps);
         }