[dice] Retrieve the DICE data range from FDT in service VM
Bug: 287233786
Test: atest rialto_test
Change-Id: I3e3c4e1c5579726d8b139ed74780acb43b6c4ce9
diff --git a/libs/libfdt/src/iterators.rs b/libs/libfdt/src/iterators.rs
index 05fdb4a..280257b 100644
--- a/libs/libfdt/src/iterators.rs
+++ b/libs/libfdt/src/iterators.rs
@@ -14,6 +14,7 @@
//! Iterators over cells, and various layers on top of them.
+use crate::FdtError;
use crate::{AddrCells, SizeCells};
use core::marker::PhantomData;
use core::{mem::size_of, ops::Range, slice::ChunksExact};
@@ -59,6 +60,21 @@
pub size: Option<T>,
}
+impl<T: TryInto<usize>> TryFrom<Reg<T>> for Range<usize> {
+ type Error = FdtError;
+
+ fn try_from(reg: Reg<T>) -> Result<Self, Self::Error> {
+ let addr = to_usize(reg.addr)?;
+ let size = to_usize(reg.size.ok_or(FdtError::NotFound)?)?;
+ let end = addr.checked_add(size).ok_or(FdtError::BadValue)?;
+ Ok(addr..end)
+ }
+}
+
+fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize, FdtError> {
+ num.try_into().map_err(|_| FdtError::BadValue)
+}
+
impl<'a> RegIterator<'a> {
pub(crate) fn new(
cells: CellIterator<'a>,
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index a305e03..1bf285e 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -341,7 +341,8 @@
self.fdt
}
- fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
+ /// Returns the compatible node of the given name that is next after this node.
+ pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
// SAFETY: Accesses (read-only) are constrained to the DT totalsize.
let ret = unsafe {
libfdt_bindgen::fdt_node_offset_by_compatible(
@@ -354,6 +355,11 @@
Ok(fdt_err_or_option(ret)?.map(|offset| Self { fdt: self.fdt, offset }))
}
+ /// Returns the first range of `reg` in this node.
+ pub fn first_reg(&self) -> Result<Reg<u64>> {
+ self.reg()?.ok_or(FdtError::NotFound)?.next().ok_or(FdtError::NotFound)
+ }
+
fn address_cells(&self) -> Result<AddrCells> {
// SAFETY: Accesses are constrained to the DT totalsize (validated by ctor).
unsafe { libfdt_bindgen::fdt_address_cells(self.fdt.as_ptr(), self.offset) }
@@ -526,7 +532,7 @@
Ok(FdtNode { fdt: &*self.fdt, offset: fdt_err(ret)? })
}
- /// Return the compatible node of the given name that is next to this node
+ /// Returns the compatible node of the given name that is next after this node
pub fn next_compatible(self, compatible: &CStr) -> Result<Option<Self>> {
// SAFETY: Accesses (read-only) are constrained to the DT totalsize.
let ret = unsafe {
diff --git a/rialto/Android.bp b/rialto/Android.bp
index d8e4536..1df18f6 100644
--- a/rialto/Android.bp
+++ b/rialto/Android.bp
@@ -11,6 +11,7 @@
"libaarch64_paging",
"libciborium_io_nostd",
"libciborium_nostd",
+ "libdiced_open_dice_nostd",
"libhyp",
"libfdtpci",
"liblibfdt",
diff --git a/rialto/src/error.rs b/rialto/src/error.rs
index 23667ed..911cb9b 100644
--- a/rialto/src/error.rs
+++ b/rialto/src/error.rs
@@ -16,6 +16,7 @@
use aarch64_paging::MapError;
use core::{fmt, result};
+use diced_open_dice::DiceError;
use fdtpci::PciError;
use hyp::Error as HypervisorError;
use libfdt::FdtError;
@@ -50,6 +51,8 @@
SerializationFailed(CiboriumSerError),
/// Failed to deserialize.
DeserializationFailed(CiboriumDeError),
+ /// Failed DICE operation.
+ DiceOperationFailed(DiceError),
}
impl fmt::Display for Error {
@@ -72,6 +75,7 @@
}
Self::SerializationFailed(e) => write!(f, "Failed to serialize: {e}"),
Self::DeserializationFailed(e) => write!(f, "Failed to deserialize: {e}"),
+ Self::DiceOperationFailed(e) => write!(f, "Failed DICE operation: {e}"),
}
}
}
@@ -123,3 +127,9 @@
Self::DeserializationFailed(e)
}
}
+
+impl From<DiceError> for Error {
+ fn from(e: DiceError) -> Self {
+ Self::DiceOperationFailed(e)
+ }
+}
diff --git a/rialto/src/fdt.rs b/rialto/src/fdt.rs
new file mode 100644
index 0000000..8bb40c3
--- /dev/null
+++ b/rialto/src/fdt.rs
@@ -0,0 +1,26 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! High-level FDT functions.
+
+use core::ops::Range;
+use libfdt::{Fdt, FdtError};
+use vmbase::cstr;
+
+/// Reads the DICE data range from the given `fdt`.
+pub fn read_dice_range_from(fdt: &Fdt) -> libfdt::Result<Range<usize>> {
+ let node = fdt.node(cstr!("/reserved-memory"))?.ok_or(FdtError::NotFound)?;
+ let node = node.next_compatible(cstr!("google,open-dice"))?.ok_or(FdtError::NotFound)?;
+ node.first_reg()?.try_into()
+}
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 4e91574..f8f6d51 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -20,12 +20,14 @@
mod communication;
mod error;
mod exceptions;
+mod fdt;
mod requests;
extern crate alloc;
use crate::communication::VsockStream;
use crate::error::{Error, Result};
+use crate::fdt::read_dice_range_from;
use ciborium_io::Write;
use core::num::NonZeroUsize;
use core::slice;
@@ -130,6 +132,17 @@
e
})?;
}
+ let _bcc_handover = match vm_type() {
+ 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)
+ }
+ // Currently, no DICE data is retrieved for non-protected VMs, as these VMs are solely
+ // intended for debugging purposes.
+ VmType::NonProtectedVm => None,
+ };
let pci_info = PciInfo::from_fdt(fdt)?;
debug!("PCI: {pci_info:#x?}");
@@ -140,6 +153,7 @@
debug!("Found socket device: guest cid = {:?}", socket_device.guest_cid());
let mut vsock_stream = VsockStream::new(socket_device, host_addr())?;
+ // TODO(b/287233786): Pass the bcc_handover to process_request.
while let ServiceVmRequest::Process(req) = vsock_stream.read_request()? {
let response = requests::process_request(req)?;
vsock_stream.write_response(&response)?;