blob: 03c45c6b9806af29c8b65072fac48e3f171a2dd8 [file] [log] [blame]
#![no_std]
use core::mem::transmute;
use matcha_hal::dprintf;
pub mod elf_loader;
pub mod tar_loader;
pub const SMC_CONTROL_BLOCK: *mut u32 = 0x50020000 as *mut u32;
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() {
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.\n");
return;
}
if capdl_elf.is_null() {
dprintf!("Boot failure seL4 CapDL ELF missing.\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 sel4_pend = 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(),
sel4_pend - elf_loader::elf_phys_min(capdl_segments),
);
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));
let message = [
transmute(sel4_pend),
transmute(
sel4_pend
+ round_up_to_page(
elf_loader::elf_phys_max(capdl_segments)
- elf_loader::elf_phys_min(capdl_segments),
),
),
transmute(sel4_pend - elf_loader::elf_phys_min(capdl_segments)),
transmute((*capdl_elf).e_entry),
];
matcha_hal::mailbox_hal::MAILBOX.send_message_sync(&message);
dprintf!("seL4 boot message posted\n");
SMC_CONTROL_BLOCK.write_volatile(entry_point);
dprintf!("SMC started, waiting on ACK\n");
let mut reply : [u32;1] = [0];
matcha_hal::mailbox_hal::MAILBOX.recv_message_sync(&mut reply);
dprintf!("ACK = 0x{:08X} received.\n", reply[0]);
// This message is checked in shodan_boot.robot - keep in sync.
dprintf!("load_sel4() completed successfully\n");
}
}