blob: 25f0f1f0500894d9a7fbe250fc0198e790d37793 [file] [log] [blame]
#![no_std]
// Support for loading sel4 & co directly from the tarball. This is only
// used when running in simulation where there is no SPI Flash support
// (the elfloader capsule calls out to load_sel4 based on whether it
// detects fpga hardware or not).
use matcha_hal::dprintf;
use matcha_hal::mailbox_hal::MailboxHAL;
pub mod elf_loader;
pub mod tar_loader;
pub const SMC_CONTROL_BLOCK: *mut u32 = 0x54020000 as *mut u32;
pub const SMC_PAGE_SIZE: usize = 4096; // SMC page size
pub const SMC_BEGIN: usize = 0x50000000; // Start of SMC memory in SEC map
pub const SMC_END: usize = SMC_BEGIN + (4*1024*1024); // NB: 4MiB of SMC memory
// Returns true if the specified page address fits in SMC memory
pub fn smc_is_page(addr: usize) -> bool {
SMC_BEGIN <= addr && (addr + SMC_PAGE_SIZE) < SMC_END
}
pub fn round_up_to_page(addr: u32) -> u32 {
return (addr + 4095) & !4095;
}
// TODO(aappleby): Break this down into smaller pieces and move into app/main
pub fn load_sel4(mailbox: &'static dyn MailboxHAL) {
unsafe {
// Look in our tar file for the ELFs we need to boot Shodan.
let sel4_elf = elf_loader::find_elf("kernel");
let capdl_elf = elf_loader::find_elf("capdl-loader");
if sel4_elf.is_null() {
dprintf!("Boot failure, seL4 kernel ELF missing in FLASH.\n");
return;
}
if capdl_elf.is_null() {
dprintf!("Boot failure capdl-loader ELF missing in FLASH.\n");
return;
}
// If we found all of them, boot in Shodan mode.
dprintf!("Loading seL4 kernel elf\n");
elf_loader::load_elf_segments(sel4_elf.as_ref().unwrap(), 0);
let sel4_segments = elf_loader::elf_get_segments(sel4_elf);
let capdl_segments = elf_loader::elf_get_segments(capdl_elf);
let ui_p_reg_start = round_up_to_page(elf_loader::elf_phys_max(sel4_segments));
dprintf!("Loading capdl-loader to the page after seL4\n");
elf_loader::load_elf_segments(
capdl_elf.as_ref().unwrap(),
ui_p_reg_start - elf_loader::elf_phys_min(capdl_segments),
);
// NB: Renode loads the cantrip-builtins cpioarchive to the SMC memory
// carve-out so there's nothing to do here.
dprintf!("Starting management core\n");
let entry_point: u32 = (*sel4_elf).e_entry
- (elf_loader::elf_virt_min(sel4_segments) - elf_loader::elf_phys_min(sel4_segments));
smc_send_bootmsg(mailbox, [
ui_p_reg_start,
ui_p_reg_start
+ round_up_to_page(
elf_loader::elf_phys_max(capdl_segments)
- elf_loader::elf_phys_min(capdl_segments),
),
ui_p_reg_start - elf_loader::elf_phys_min(capdl_segments),
(*capdl_elf).e_entry,
]);
SMC_CONTROL_BLOCK.write_volatile(entry_point);
}
}
pub fn smc_send_bootmsg(mailbox: &'static dyn MailboxHAL, message: [u32; 4]) {
unsafe {
let _ = mailbox.send_message_sync(16, core::mem::transmute(message.as_ref()));
}
}
pub fn smc_ram_memcpy(src: &mut [u8], dst: u32, count: usize) {
unsafe {
core::ptr::copy_nonoverlapping::<u8>(
core::mem::transmute(src.as_ptr()),
core::mem::transmute(dst),
count,
);
}
}
pub fn smc_ram_zero(dst: u32, count: usize) {
unsafe {
core::ptr::write_bytes::<u8>(core::mem::transmute(dst), 0, count);
}
}