use vm_fdt::Error as VmFdtError;
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryError};
pub mod layout;
pub mod fdt;
pub const PAGE_SIZE: usize = 4096;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("create fdt fail: {0}")]
CreateFdt(#[from] VmFdtError),
#[error("write fdt to memory fail: {0}")]
WriteFDTToMemory(#[from] GuestMemoryError),
#[error("Failed to compute the initrd address.")]
InitrdAddress,
#[error("invalid arguments")]
InvalidArguments,
}
pub fn get_kernel_start() -> u64 {
layout::DRAM_MEM_START
}
pub fn get_fdt_addr<M: GuestMemory>(mem: &M) -> u64 {
if let Some(offset) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) {
if mem.address_in_range(offset) {
return offset.raw_value();
}
}
layout::DRAM_MEM_START
}
pub fn initrd_load_addr<M: GuestMemory>(guest_mem: &M, initrd_size: u64) -> super::Result<u64> {
let round_to_pagesize = |size| (size + (PAGE_SIZE as u64 - 1)) & !(PAGE_SIZE as u64 - 1);
match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) {
Some(offset) => {
if guest_mem.address_in_range(offset) {
Ok(offset.raw_value())
} else {
Err(Error::InitrdAddress)
}
}
None => Err(Error::InitrdAddress),
}
}