Merge "[VM] Refactor VirtualMachineConfig serialization from file"
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 71bac72..77de696 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -8,6 +8,9 @@
defaults: ["vmbase_ffi_defaults"],
srcs: ["src/main.rs"],
edition: "2021",
+ features: [
+ "legacy",
+ ],
rustlibs: [
"libbuddy_system_allocator",
"liblog_rust_nostd",
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index dc2087d..c0ad878 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -19,11 +19,15 @@
use crate::mmio_guard;
use core::arch::asm;
use core::slice;
-use log::{debug, error, LevelFilter};
-use vmbase::{console, logger, main, power::reboot};
+use log::debug;
+use log::error;
+use log::LevelFilter;
+use vmbase::{console, layout, logger, main, power::reboot};
#[derive(Debug, Clone)]
enum RebootReason {
+ /// A malformed BCC was received.
+ InvalidBcc,
/// An unexpected internal error happened.
InternalError,
}
@@ -80,8 +84,17 @@
RebootReason::InternalError
})?;
+ // SAFETY - We only get the appended payload from here, once. It is mapped and the linker
+ // script prevents it from overlapping with other objects.
+ let bcc = as_bcc(unsafe { get_appended_data_slice() }).ok_or_else(|| {
+ error!("Invalid BCC");
+ RebootReason::InvalidBcc
+ })?;
+
// This wrapper allows main() to be blissfully ignorant of platform details.
- crate::main(fdt, payload);
+ crate::main(fdt, payload, bcc);
+
+ // TODO: Overwrite BCC before jumping to payload to avoid leaking our sealing key.
mmio_guard::unmap(console::BASE_ADDRESS).map_err(|e| {
error!("Failed to unshare the UART: {e}");
@@ -147,3 +160,22 @@
);
};
}
+
+unsafe fn get_appended_data_slice() -> &'static mut [u8] {
+ let base = helpers::align_up(layout::binary_end(), helpers::SIZE_4KB).unwrap();
+ // pvmfw is contained in a 2MiB region so the payload can't be larger than the 2MiB alignment.
+ let size = helpers::align_up(base, helpers::SIZE_2MB).unwrap() - base;
+
+ slice::from_raw_parts_mut(base as *mut u8, size)
+}
+
+fn as_bcc(data: &mut [u8]) -> Option<&mut [u8]> {
+ const BCC_SIZE: usize = helpers::SIZE_4KB;
+
+ if cfg!(feature = "legacy") {
+ // TODO(b/256148034): return None if BccHandoverParse(bcc) != kDiceResultOk.
+ Some(&mut data[..BCC_SIZE])
+ } else {
+ None
+ }
+}
diff --git a/pvmfw/src/helpers.rs b/pvmfw/src/helpers.rs
index adfc189..59cf9f3 100644
--- a/pvmfw/src/helpers.rs
+++ b/pvmfw/src/helpers.rs
@@ -17,12 +17,25 @@
pub const SIZE_4KB: usize = 4 << 10;
pub const SIZE_2MB: usize = 2 << 20;
-/// Computes the address of the page containing a given address.
-pub const fn page_of(addr: usize, page_size: usize) -> usize {
- addr & !(page_size - 1)
+/// Computes the largest multiple of the provided alignment smaller or equal to the address.
+///
+/// Note: the result is undefined if alignment isn't a power of two.
+pub const fn unchecked_align_down(addr: usize, alignment: usize) -> usize {
+ addr & !(alignment - 1)
+}
+
+/// Safe wrapper around unchecked_align_up() that validates its assumptions and doesn't wrap.
+pub const fn align_up(addr: usize, alignment: usize) -> Option<usize> {
+ if !alignment.is_power_of_two() {
+ None
+ } else if let Some(s) = addr.checked_add(alignment - 1) {
+ Some(unchecked_align_down(s, alignment))
+ } else {
+ None
+ }
}
/// Computes the address of the 4KiB page containing a given address.
pub const fn page_4kb_of(addr: usize) -> usize {
- page_of(addr, SIZE_4KB)
+ unchecked_align_down(addr, SIZE_4KB)
}
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index c0bb263..8178d0b 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -29,7 +29,7 @@
use avb::PUBLIC_KEY;
use log::{debug, info};
-fn main(fdt: &mut [u8], payload: &[u8]) {
+fn main(fdt: &mut [u8], payload: &[u8], bcc: &[u8]) {
info!("pVM firmware");
debug!(
"fdt_address={:#018x}, payload_start={:#018x}, payload_size={:#018x}",
@@ -37,6 +37,7 @@
payload.as_ptr() as usize,
payload.len(),
);
+ debug!("BCC: {:?} ({:#x} bytes)", bcc.as_ptr(), bcc.len());
debug!("AVB public key: addr={:?}, size={:#x} ({1})", PUBLIC_KEY.as_ptr(), PUBLIC_KEY.len());
info!("Starting payload...");
}