pvmfw: Expect an appended BCC
In Android T, the BCC was passed by the platform to pvmfw by appending it to its binary at load time. Expect this behavior and make use of the BCC in main() by logging the slice, for now. Add the 'legacy' feature to control support for legacy interfaces; it is intended to be disabled in the future. Bug: 256827715 Test: atest MicrodroidTestApp Change-Id: I4d0cfb028e42f2f7f5d343a941124f64d4d93f9a
This commit is contained in:
parent
619f9585cf
commit
e8726e47df
|
@ -8,6 +8,9 @@ rust_ffi_static {
|
|||
defaults: ["vmbase_ffi_defaults"],
|
||||
srcs: ["src/main.rs"],
|
||||
edition: "2021",
|
||||
features: [
|
||||
"legacy",
|
||||
],
|
||||
rustlibs: [
|
||||
"libbuddy_system_allocator",
|
||||
"liblog_rust_nostd",
|
||||
|
|
|
@ -19,11 +19,15 @@ use crate::helpers;
|
|||
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 @@ fn main_wrapper(fdt: usize, payload: usize, payload_size: usize) -> Result<(), R
|
|||
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 @@ fn jump_to_payload(fdt_address: u64, payload_start: u64) -> ! {
|
|||
);
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ mod smccc;
|
|||
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 @@ fn main(fdt: &mut [u8], payload: &[u8]) {
|
|||
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...");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue