//! Board file for Shodan's "Matcha" RISC-V development platform.

#![no_std]
#![no_main]
#![feature(llvm_asm)]
#![feature(const_fn)]
#![feature(naked_functions)]

use capsules::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
use core::fmt::Write;
use core::panic::PanicInfo;
use kernel::capabilities;
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
use kernel::component::Component;
use kernel::hil;
use kernel::hil::flash::HasClient;
use kernel::hil::time::Alarm;
use kernel::Chip;
use kernel::Platform;
use kernel::{create_capability, debug, static_init};
use kernel::debug::IoWrite;
use matcha_capsules::dprintf_capsule::DprintfCapsule;
use matcha_capsules::elfloader_capsule::ElfLoaderCapsule;
use matcha_capsules::mailbox_capsule::MailboxCapsule;
use matcha_capsules::storage_capsule::StorageCapsule;
use matcha_config::*;
use matcha_hal::spi_host_hal;
use matcha_hal::timer_hal;
use matcha_hal::uart_hal;
use matcha_hal::smc_ctrl_hal;
use matcha_hal::rv_core_ibex_hal;
use rv32i::csr;

pub mod chip;

// Writer struct for panic handler.
struct Writer {}
static mut WRITER: Writer = Writer {};
impl Write for Writer {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        self.write(s.as_bytes());
        Ok(())
    }
}
impl IoWrite for Writer {
    fn write(&mut self, buf: &[u8]) {
        unsafe {
            uart_hal::UART0.transmit_sync(buf);
        }
    }
}

// Stubbed LED for panic handler.
pub struct MatchaLed {
}
impl MatchaLed {
    pub fn new() -> Self {
        Self {}
    }
}
impl kernel::hil::led::Led for MatchaLed {
    fn init(&mut self) { }
    fn on(&mut self) { }
    fn off(&mut self) { }
    fn toggle(&mut self) { }
    fn read(&self) -> bool { true }
}

/// Panic handler.
#[cfg(not(test))]
#[no_mangle]
#[panic_handler]
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
    let first_led = &mut MatchaLed::new();
    let writer = &mut WRITER;
    debug::panic(
        &mut [first_led],
        writer,
        pi,
        &rv32i::support::nop,
        &PROCESSES,
        &CHIP,
    )
}

/// These symbols are defined in the linker script.
extern "C" {
    /// Beginning of the ROM region containing app images.
    static _sapps: u8;
    /// End of the ROM region containing app images.
    static _eapps: u8;
    /// Beginning of the RAM region for app memory.
    static mut _sappmem: u8;
    /// End of the RAM region for app memory.
    static _eappmem: u8;
}

// Actual memory for holding the active process structures. Need an empty list
// at least.
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; 4] =
    [None, None, None, None];

static mut CHIP: Option<
    &'static crate::chip::Matcha<VirtualMuxAlarm<'static, timer_hal::RvTimer>>,
> = None;

/// Dummy buffer that causes the linker to reserve enough space for the stack.
/// Must be at least 16k in debug builds (@aappleby - not sure why, what's so large?)
#[no_mangle]
#[link_section = ".stack_buffer"]
pub static mut STACK_MEMORY: [u8; 0x4000] = [0; 0x4000];

/// A structure representing this platform that holds references to all
/// capsules for this platform. We've included an alarm and console.
struct MatchaPlatform {
    console_capsule: &'static capsules::console::Console<'static>,
    alarm_capsule: &'static capsules::alarm::AlarmDriver<
        'static,
        VirtualMuxAlarm<'static, timer_hal::RvTimer<'static>>,
    >,
    dprintf_capsule: &'static DprintfCapsule,
    storage_capsule: &'static StorageCapsule,
    elfloader_capsule: &'static ElfLoaderCapsule<
        'static,
        matcha_capsules::nexus_spiflash::NexusSpiflash<
            'static,
            capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
        >,
    >,
    mailbox_capsule: &'static MailboxCapsule,
    lldb_capsule: &'static capsules::low_level_debug::LowLevelDebug<
        'static,
        capsules::virtual_uart::UartDevice<'static>,
    >,
}

/// Mapping of integer syscalls to objects that implement syscalls.
impl Platform for MatchaPlatform {
    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
    where
        F: FnOnce(Option<&dyn kernel::Driver>) -> R,
    {
        match driver_num {
            CAPSULE_CONSOLE => f(Some(self.console_capsule)),
            CAPSULE_ALARM => f(Some(self.alarm_capsule)),
            CAPSULE_DPRINTF => f(Some(self.dprintf_capsule)),
            CAPSULE_STORAGE => f(Some(self.storage_capsule)),
            CAPSULE_ELFLOADER => f(Some(self.elfloader_capsule)),
            CAPSULE_MAILBOX => f(Some(self.mailbox_capsule)),
            CAPSULE_LLDB => f(Some(self.lldb_capsule)),
            _ => f(None),
        }
    }
}

/// Reset Handler.
///
/// This function is called from the arch crate after some very basic RISC-V
/// setup.
#[no_mangle]
pub unsafe fn reset_handler() {
    // Basic setup of the platform.
    rv32i::init_memory();
    // Ibex-specific handler
    crate::chip::configure_trap_handler();

    // initialize capabilities
    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);

    let main_loop_cap = create_capability!(capabilities::MainLoopCapability);

    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));

    let dynamic_deferred_call_clients =
        static_init!([DynamicDeferredCallClientState; 1], Default::default());
    let dynamic_deferred_caller = static_init!(
        DynamicDeferredCall,
        DynamicDeferredCall::new(dynamic_deferred_call_clients)
    );
    DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);

    // Create a shared UART channel for the console and for kernel debug.
    let uart_mux = components::console::UartMuxComponent::new(
        &uart_hal::UART0,
        matcha_config::UART0_BAUDRATE,
        dynamic_deferred_caller,
    )
    .finalize(());

    let alarm = &timer_hal::TIMER;
    alarm.setup();

    // Create a shared virtualization mux layer on top of a single hardware
    // alarm.
    let mux_alarm = static_init!(MuxAlarm<'static, timer_hal::RvTimer>, MuxAlarm::new(alarm));
    hil::time::Alarm::set_alarm_client(&timer_hal::TIMER, mux_alarm);

    // Alarm
    let virtual_alarm_user = static_init!(
        VirtualMuxAlarm<'static, timer_hal::RvTimer>,
        VirtualMuxAlarm::new(mux_alarm)
    );
    let scheduler_timer_virtual_alarm = static_init!(
        VirtualMuxAlarm<'static, timer_hal::RvTimer>,
        VirtualMuxAlarm::new(mux_alarm)
    );
    let alarm_capsule = static_init!(
        capsules::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, timer_hal::RvTimer>>,
        capsules::alarm::AlarmDriver::new(
            virtual_alarm_user,
            board_kernel.create_grant(&memory_allocation_cap)
        )
    );
    hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm_capsule);

    let chip = static_init!(
        crate::chip::Matcha<VirtualMuxAlarm<'static, timer_hal::RvTimer>>,
        crate::chip::Matcha::new(scheduler_timer_virtual_alarm)
    );
    scheduler_timer_virtual_alarm.set_alarm_client(chip.scheduler_timer());
    CHIP = Some(chip);

    // Need to enable all interrupts for Tock Kernel
    chip.enable_plic_interrupts();
    // enable interrupts globally
    csr::CSR
        .mie
        .modify(csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET + csr::mie::mie::mext::SET);
    csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);

    // Setup the console.
    let console_capsule =
        components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
    // Create the debugger object that handles calls to `debug!()`.
    components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());

    let lldb_capsule =
        components::lldb::LowLevelDebugComponent::new(board_kernel, uart_mux).finalize(());

    let dprintf_capsule = static_init!(
        DprintfCapsule,
        DprintfCapsule {
            app_data_grant: board_kernel.create_grant(&memory_allocation_cap)
        }
    );

    let storage_capsule = static_init!(
        matcha_capsules::storage_capsule::StorageCapsule,
        matcha_capsules::storage_capsule::StorageCapsule::new(
            board_kernel.create_grant(&memory_allocation_cap)
        )
    );

    // Construct a mailbox that points to the platform-specific base address and
    // PLIC lines
    let mailbox_hal: &'static mut matcha_hal::mailbox_hal::MailboxImpl = static_init!(
        matcha_hal::mailbox_hal::MailboxImpl,
        matcha_hal::mailbox_hal::MailboxImpl::new(
            MAILBOX_BASE,
            MAILBOX_WTIRQ,
            MAILBOX_RTIRQ,
            MAILBOX_EIRQ,
        )
    );

    let fpga_version = rv_core_ibex_hal::RV_CORE_IBEX_SEC.fpga_version();
    let elfloader_capsule = static_init!(
             matcha_capsules::elfloader_capsule::ElfLoaderCapsule<
                 'static,
             matcha_capsules::nexus_spiflash::NexusSpiflash<
                 'static,
                 capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
             >>,
             matcha_capsules::elfloader_capsule::ElfLoaderCapsule::new(fpga_version != 0)
    );

    let mailbox_capsule = static_init!(
        matcha_capsules::mailbox_capsule::MailboxCapsule,
        matcha_capsules::mailbox_capsule::MailboxCapsule::new(
            board_kernel.create_grant(&memory_allocation_cap),
        )
    );

    // Mailbox interrupts are delegated to the capsule, except for the
    // bottom-level bit twiddling.
    mailbox_hal.set_client_isr(mailbox_capsule);

    // Our other capsules and our "chip" hold references to the mailbox.
    mailbox_capsule.set_mailbox(mailbox_hal);
    elfloader_capsule.set_mailbox(mailbox_hal);
    chip.set_mailbox_isr(mailbox_hal);

    let mux_spi = components::spi::SpiMuxComponent::new(
        &spi_host_hal::SPI_HOST0
    ).finalize(components::spi_mux_component_helper!(spi_host_hal::SpiHw));
    let nexus_spiflash_spi = static_init!(
        capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
        capsules::virtual_spi::VirtualSpiMasterDevice::new(mux_spi, 0)
    );
    let nexus_spiflash_virtual_alarm = static_init!(
        VirtualMuxAlarm<'static, timer_hal::RvTimer>,
        VirtualMuxAlarm::new(mux_alarm)
    );
    let nexus_spiflash = static_init!(
        matcha_capsules::nexus_spiflash::NexusSpiflash<
            'static,
            capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
        >,
        matcha_capsules::nexus_spiflash::NexusSpiflash::new(
            nexus_spiflash_spi,
            &mut matcha_capsules::nexus_spiflash::TXBUFFER,
            &mut matcha_capsules::nexus_spiflash::RXBUFFER,
        )
    );
    nexus_spiflash_spi.set_client(nexus_spiflash);
    nexus_spiflash_virtual_alarm.set_alarm_client(nexus_spiflash);


    let mux_flash = static_init!(
        capsules::virtual_flash::MuxFlash<'static, matcha_capsules::nexus_spiflash::NexusSpiflash<
            'static,
            capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
        >>,
        capsules::virtual_flash::MuxFlash::new(nexus_spiflash)
    );
    hil::flash::HasClient::set_client(nexus_spiflash, mux_flash);
    let virtual_flash = static_init!(
        capsules::virtual_flash::FlashUser<'static, matcha_capsules::nexus_spiflash::NexusSpiflash<
            'static,
            capsules::virtual_spi::VirtualSpiMasterDevice<'static, spi_host_hal::SpiHw>,
        >>,
        capsules::virtual_flash::FlashUser::new(mux_flash)
    );
    let flash_read_page: &'static mut matcha_capsules::nexus_spiflash::NexusSpiflashPage = static_init!(
        matcha_capsules::nexus_spiflash::NexusSpiflashPage,
        matcha_capsules::nexus_spiflash::NexusSpiflashPage::default()
    );

    elfloader_capsule.set_flash(virtual_flash, flash_read_page);
    elfloader_capsule.set_smc_ctrl(&smc_ctrl_hal::SMC_CTRL);
    virtual_flash.set_client(elfloader_capsule);
    // elfloader_capsule.load_sel4();

    let platform = MatchaPlatform {
        console_capsule: console_capsule,
        alarm_capsule: alarm_capsule,
        dprintf_capsule: dprintf_capsule,
        storage_capsule: storage_capsule,
        elfloader_capsule: elfloader_capsule,
        mailbox_capsule: mailbox_capsule,
        lldb_capsule: lldb_capsule,
    };

    kernel::procs::load_processes(
        board_kernel,
        chip,
        core::slice::from_raw_parts(
            &_sapps as *const u8,
            &_eapps as *const u8 as usize - &_sapps as *const u8 as usize,
        ),
        core::slice::from_raw_parts_mut(
            &mut _sappmem as *mut u8,
            &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
        ),
        &mut PROCESSES,
        kernel::procs::FaultResponse::Panic,
        &process_mgmt_cap,
    )
    .unwrap_or_else(|err| {
        debug!("Error loading processes!");
        debug!("{:?}", err);
    });
    debug!("MatchaPlatform initialisation complete. Entering main loop");

    let scheduler = components::sched::priority::PriorityComponent::new(board_kernel).finalize(());
    board_kernel.kernel_loop(&platform, chip, None, scheduler, &main_loop_cap);
}
