// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Shodan ELF loader capsule

use core::cell::Cell;
use core::marker::PhantomData;
use kernel::common::cells::{OptionalCell, TakeCell};
use kernel::hil;
use kernel::hil::flash::Flash;
use kernel::{AppId, AppSlice, Callback, Driver, ReturnCode, Shared};
use matcha_hal::dprintf;
use matcha_hal::mailbox_hal::MailboxHAL;
use matcha_hal::smc_ctrl_hal;
use matcha_utils::elf_loader::{Elf32Header, Elf32Phdr};
use matcha_utils::smc_ram_memcpy;
use matcha_utils::tar_loader::TarHeader;

const PT_LOAD: u32 = 1;  // Loadable segment
const INVALID_LOAD_OFFSET: u32 = 0;

pub struct ElfLoaderCapsule<'a, F: hil::flash::Flash + 'static> {
    mailbox_hal: Option<&'static dyn MailboxHAL>,
    smc_ctrl_hal: Option<&'static dyn smc_ctrl_hal::SmcCtrlHal>,
    flash: Option<&'static capsules::virtual_flash::FlashUser<'static, F>>,
    flash_busy: Cell<bool>,
    read_page: TakeCell<'static, F::Page>,
    page_len: u32,
    state: Cell<ElfLoaderState>,
    phantom: PhantomData<&'a ()>,
    tasks: Cell<[(LoadTasks, bool); 3]>,
    current_task: OptionalCell<LoadTasks>,
    sel4_state: Cell<SEL4State>,
}

#[derive(Clone, Copy, PartialEq)]
enum LoadTasks {
    Noop,
    LoadElf(&'static str /* name */),
    StartSmc,
}

#[derive(Clone, Copy, Default)]
struct SEL4State {
    // State for current file being loaded.
    load_offset: u32, // File offset
    phdrs: [Option<Elf32Phdr>; 20], // ELF phdrs

    // Saved state for the "kernel" image.
    kernel_entry_point: u32,
    kernel_phys_max: u32,

    // Saved state for the "capdl-loader" image.
    capdl_loader_entry_point: u32,
    capdl_phys_min: u32,
    capdl_phys_max: u32,
}

#[derive(Clone, Copy, PartialEq)]
enum ElfLoaderState {
    Idle,
    FindingFile(&'static str /* name */, u32 /* cursor */),
    LoadElfHeader(u32 /* cursor */),
    LoadProgramHeaderTable(
        u32, /* cursor */
        u32, /* offset */
        u16, /* num */
        u16, /* index */
    ),
    LoadSegmentsNew(
        Elf32Phdr,    /* phdr */
        usize,        /* index */
        u32,          /* cursor */
        u32,          /* dst offset */
        u32,          /* offset_in_page */
        u32,          /* already loaded */
    ),
}

fn print_segment(index: usize, cursor: u32, offset: u32, phdr: &Elf32Phdr) {
    if phdr.p_filesz > 0 {
        dprintf!(
            "seg {:2}:{:X} -> {:X}:{:X} ({} bytes)\r\n",
            index,
            cursor,
            phdr.p_paddr + offset,
            phdr.p_paddr + offset + phdr.p_filesz,
            { phdr.p_filesz },
        );
    }
    let bss_size = phdr.p_memsz - phdr.p_filesz;
    if bss_size > 0 {
        let bss_start = phdr.p_paddr + offset + phdr.p_filesz;
        let bss_end = bss_start + bss_size;

        dprintf!(
            "bss {:2}:{:X} -> {:X}:{:X} ({} bytes)\r\n",
            index,
            cursor,
            bss_start,
            bss_end,
            bss_size
        );
    }
}

impl<'a, F: hil::flash::Flash> ElfLoaderCapsule<'a, F> {
    pub fn new() -> Self {
        Self {
            mailbox_hal: None,
            smc_ctrl_hal: None,
            flash: None,
            flash_busy: Cell::new(false),
            read_page: TakeCell::empty(),
            page_len: 0,
            state: Cell::new(ElfLoaderState::Idle),
            phantom: PhantomData,
            tasks: Cell::new([(LoadTasks::Noop, true); 3]),
            current_task: OptionalCell::empty(),
            sel4_state: Cell::new(SEL4State::default()),
        }
    }

    pub fn set_smc_ctrl(&mut self, smc_ctrl: &'static dyn smc_ctrl_hal::SmcCtrlHal) {
        self.smc_ctrl_hal = Some(smc_ctrl);
    }

    pub fn set_mailbox(&mut self, mailbox: &'static dyn MailboxHAL) {
        self.mailbox_hal = Some(mailbox);
    }

    pub fn set_flash(
        &mut self,
        flash: &'static capsules::virtual_flash::FlashUser<'static, F>,
        read_page: &'static mut F::Page,
    ) {
        self.flash = Some(flash);
        self.read_page.replace(read_page);
        let mut page_len = 0;
        self.read_page.map(|page| {
            let mut_page = page.as_mut();
            page_len = mut_page.len() as u32;
        });
        self.page_len = page_len;
    }

    pub fn run_next_task(&self) {
        self.current_task.clear();
        let mut tasks = self.tasks.get();
        for i in 0..tasks.len() {
            let (task, done) = tasks[i];
            if !done {
                tasks[i] = (task, true);
                self.current_task.replace(task);
                break;
            }
        }
        self.tasks.replace(tasks);

        self.current_task.map_or_else(
            || {
                dprintf!("No current task\r\n");
                loop {}
            },
            |task| match task {
                LoadTasks::LoadElf(file) => {
                    self.find_file(file);
                }
                LoadTasks::StartSmc => {
                    let sel4_state = self.sel4_state.get();
                    if sel4_state.capdl_phys_max > 0 {
                        // If capdl-loader was loaded we are running seL4 and
                        // it will expect a boot message to be waiting in the
                        // mailbox FIFO telling it how to setup the kernel and
                        // the rootserver.

                        // NB: ui_p_reg_start & co. come from the code in seL4
                        //   that processes these values.
                        let ui_p_reg_start =
                            matcha_utils::round_up_to_page(sel4_state.kernel_phys_max);
                        let ui_p_reg_end = ui_p_reg_start
                            + matcha_utils::round_up_to_page(
                                sel4_state.capdl_phys_max - sel4_state.capdl_phys_min
                            );
                        let pv_offset = ui_p_reg_start - sel4_state.capdl_phys_min;
                        let v_entry = sel4_state.capdl_loader_entry_point;
    /*
                        dprintf!(
                            "StartSmc: ui_p_reg {:X}:{:X} pv_offset {:X} v_entry {:X}\r\n",
                            ui_p_reg_start,
                            ui_p_reg_end,
                            pv_offset,
                            v_entry
                        );
    */
                        // XXX suppress if not seL4?
                        self.mailbox_hal.map(|mb| {
                            matcha_utils::smc_send_bootmsg(mb, [
                                  ui_p_reg_start,
                                  ui_p_reg_end,
                                  pv_offset,
                                  v_entry,
                            ])
                        });
                    }

                    assert!(self.smc_ctrl_hal.is_some());
                    self.smc_ctrl_hal.unwrap().smc_ctrl_start();
                }
                _ => unreachable!(),
            },
        );
    }

    // Load seL4 state machine.
    pub fn load_sel4(&self) {
        self.tasks.replace([
            (LoadTasks::LoadElf("kernel"), false),
            (LoadTasks::LoadElf("capdl-loader"), false),
            (LoadTasks::StartSmc, false),
        ]);
        self.run_next_task();
    }

    // Reads the data at flash address |page|. |read_complete| (below)
    // dispatchs the callback depending on the current ElfLoaderState.
    fn read_page(&self, page: u32) {
        self.flash.map(|flash| {
            self.read_page.take().map(|read_page| {
                self.flash_busy.set(true);
                if let Err((_, buf)) = flash.read_page((page / self.page_len) as usize, read_page) {
                    self.read_page.replace(buf);
                }
            });
        });
    }

    // Initiates a file lookup.
    fn find_file(&self, name: &'static str) {
        self.state.set(ElfLoaderState::FindingFile(name, 0));
        self.read_page(0);
    }

    // Callback from |read_complete| for a file lookup. If the file was
    // found start loading the ELF headers; otherwise advance the file
    // lookup mechanism (to stride through the tar file). If the search
    // was unsuccessful log to the console and advance to the next task.
    fn find_file_callback(&self) {
        self.read_page.map(|page| {
            let mut_page = page.as_mut();
            let tar_header = TarHeader::from_bytes(mut_page);
            match self.state.get() {
                ElfLoaderState::FindingFile(name, cursor) => {
                    if tar_header.name().contains(name) {
                        let mut sel4_state = self.sel4_state.get();
                        sel4_state.load_offset = cursor + self.page_len;
                        self.sel4_state.replace(sel4_state);
                        self.state.set(ElfLoaderState::Idle);
                    } else if !tar_header.has_magic() {
                        // File not found.
                        dprintf!("{} not found!\r\n", name);
                        let mut sel4_state = self.sel4_state.get();
                        sel4_state.load_offset = INVALID_LOAD_OFFSET;
                        self.sel4_state.replace(sel4_state);
                        self.state.set(ElfLoaderState::Idle);
                    } else {
                        let new_cursor =
                            self.page_len + cursor + ((tar_header.size() + 511) & !511);
                        self.state
                            .set(ElfLoaderState::FindingFile(name, new_cursor));
                    }
                }
                _ => unreachable!(),
            };
        });

        match self.state.get() {
            ElfLoaderState::FindingFile(_, cursor) => self.read_page(cursor),
            ElfLoaderState::Idle => {
                if self.sel4_state.get().load_offset != INVALID_LOAD_OFFSET {
                    self.load_elf_headers();
                } else {
                    self.run_next_task();
                }
            }
            _ => panic!("507"),
        }
    }

    // Initiates reading ELF header data for the current file.
    // NB: this clobbers program headers so any state derived from a file's
    //   headers must be recorded below (see |load_elf_header_callback|).
    fn load_elf_headers(&self) {
        let mut sel4_state = self.sel4_state.get();
        sel4_state.phdrs = SEL4State::default().phdrs; // Reset shared phdrs
        let cursor = sel4_state.load_offset;
        assert!(cursor  != INVALID_LOAD_OFFSET);
        self.sel4_state.replace(sel4_state);
        self.state.set(ElfLoaderState::LoadElfHeader(cursor));
        self.read_page(cursor);
    }

    // Callback from |read_complete| after reading the ELF header. Saves
    // the ELF entry point and initiate reading the ELF program headers.
    fn load_elf_header_callback(&self) {
        self.read_page.map(|page| {
            let mut_page = page.as_mut();
            let elf_header = Elf32Header::from_bytes(mut_page);
            assert!(elf_header.check_magic());
            self.current_task.map(|task| {
                let mut sel4_state = self.sel4_state.get();
                match task {
                    LoadTasks::LoadElf("kernel") => {
                        sel4_state.kernel_entry_point = elf_header.e_entry;
                    }
                    LoadTasks::LoadElf("capdl-loader") => {
                        sel4_state.capdl_loader_entry_point = elf_header.e_entry;
                    }
                    _ => unreachable!(),
                };
                self.sel4_state.replace(sel4_state);
            });
            match self.state.get() {
                ElfLoaderState::LoadElfHeader(cursor) => {
                    // Kick off reading the ELF program headers.
                    self.state.set(ElfLoaderState::LoadProgramHeaderTable(
                        cursor,
                        elf_header.phoff(),
                        elf_header.phnum(),
                        0,
                    ));
                }
                _ => unreachable!(),
            }
        });
        match self.state.get() {
            ElfLoaderState::LoadProgramHeaderTable(cursor, ..) =>
                self.read_page(cursor),
            _ => unreachable!(),
        }
    }

    // Callback from |read_complete| after reading an ELF program header.
    // Saves the header and initiates a read of the next header or, if all
    // headers have been read, initiates loading the ELF segments. If all
    // headers have been read this also records per-file data based on the
    // full set of headers (that may be clobbered if another file is read).
    fn load_program_header_table_callback(&self) {
        self.read_page.map(|page| {
            let mut_page = page.as_mut();
            match self.state.get() {
                ElfLoaderState::LoadProgramHeaderTable(_, offset, _, index) => {
                    let phdr = Elf32Phdr::from_bytes(
                        &mut mut_page[(((offset as usize)
                            + (index as usize * core::mem::size_of::<Elf32Phdr>()))
                            as usize)..],
                    );
//dprintf!("[{}] {:#08x?}\r\n", index, &phdr);
                    if phdr.p_type == PT_LOAD {
                        let mut sel4_state = self.sel4_state.get();
                        let mut next_slot: Option<usize> = None;
                        for i in 0..sel4_state.phdrs.len() {
                            if sel4_state.phdrs[i] == None {
                                next_slot = Some(i);
                                break;
                            }
                        }
                        if let Some(slot) = next_slot {
                            sel4_state.phdrs[slot] = Some(phdr);
                        } else {
                            panic!("Too many ELF program headers");
                        }
                        self.sel4_state.replace(sel4_state);
                    }
                }
                _ => unreachable!(),
            };
        });
        match self.state.get() {
            ElfLoaderState::LoadProgramHeaderTable(cursor, offset, count, index) => {
                if index + 1 < count {
                    self.state.set(ElfLoaderState::LoadProgramHeaderTable(
                        cursor,
                        offset,
                        count,
                        index + 1,
                    ));
                    self.read_page(cursor);
                } else {
                    // Record state derived from phdrs before they get clobbered.
                    let mut segment_load_offset = 0;
                    self.current_task.map(|task| {
                        let mut sel4_state = self.sel4_state.get();
                        match task {
                            LoadTasks::LoadElf("kernel") => {
                                // Stash end of kernel for loading capdl-loader
                                sel4_state.kernel_phys_max = matcha_utils::elf_loader::elf_phys_max_opt(&sel4_state.phdrs);

                                dprintf!("Loading seL4 kernel\r\n");
                                segment_load_offset = 0;
                            }
                            LoadTasks::LoadElf("capdl-loader") => {
                                sel4_state.capdl_phys_max = matcha_utils::elf_loader::elf_phys_max_opt(&sel4_state.phdrs);
                                sel4_state.capdl_phys_min = matcha_utils::elf_loader::elf_phys_min_opt(&sel4_state.phdrs);

                                dprintf!("Loading capdl-loader to the page after seL4\r\n");
                                segment_load_offset = matcha_utils::round_up_to_page(
                                    sel4_state.kernel_phys_max
                                ) - sel4_state.capdl_phys_min;
                            }
                            _ => unreachable!(),
                        };
                        self.sel4_state.replace(sel4_state);
                    });
                    self.load_elf_segments(segment_load_offset);
                }
            }
            _ => unreachable!(),
        }
    }

    // Initiates loading the ELF segments for the current file.
    fn load_elf_segments(&self, offset: u32) {
        let phdr = self.sel4_state.get().phdrs[0].unwrap();
        // XXX assumes p_filesz > 0; consolidate with code below
        let mod_offset = phdr.p_offset % self.page_len;
        let div_offset = phdr.p_offset / self.page_len;
        let load_offset = self.sel4_state.get().load_offset;
        assert!(load_offset  != INVALID_LOAD_OFFSET);
        let cursor = load_offset + (div_offset * self.page_len);
        let new_state =
            ElfLoaderState::LoadSegmentsNew(phdr, 0, cursor, offset, mod_offset, 0);
        self.state.set(new_state);
        // XXX wrong, but preserve for now
        assert!(phdr.p_type == PT_LOAD && phdr.p_filesz > 0);
        print_segment(0, cursor, offset, &phdr);
        self.read_page(cursor);
    }

    // Callback from |read_complete| after reading a page for the current
    // loadable program segment. Data may be copied to the SMC memory or
    // SMC memory may be zero'd (e.g. for bss). If the segment is completed
    // advamce to the next load segment. If all segments have been processed
    // advance to the next task.
    fn load_segment_callback(&self) {
        match self.state.get() {
            ElfLoaderState::LoadSegmentsNew(
                phdr,
                index,
                cursor,
                offset,
                mod_offset,
                loaded,
            ) => {
                // Copy read data to SMC ram.
                let bytes_in_this_page = self.page_len - mod_offset;
                self.read_page.map(|page| {
                    let mut_page = page.as_mut();
                    // NB: read_page always reads a full page from flash, maybe copy less
                    let bytes_to_copy =
                        if loaded + bytes_in_this_page >= phdr.p_filesz {
                            phdr.p_filesz - loaded
                        } else { bytes_in_this_page };
                    smc_ram_memcpy(
                        &mut mut_page[(mod_offset as usize)..],
                        phdr.p_paddr + offset + loaded,
                        bytes_to_copy as usize,
                    );
                });
                let progress = loaded + bytes_in_this_page;
                if progress < phdr.p_filesz {
                    // Same program header, more file data; issue a new read.
                    let next_cursor = cursor + self.page_len;
                    let new_state = ElfLoaderState::LoadSegmentsNew(
                        phdr, index, next_cursor, offset, /*mod_offset=*/ 0, progress,
                    );
                    self.state.set(new_state);
                    self.read_page(next_cursor);
                } else {
                    // No more file data to read for this program header.
                    if phdr.p_filesz < phdr.p_memsz {
                        // Zero-pad remainder of segment.
                        let zero_bytes = phdr.p_memsz - phdr.p_filesz;
                        matcha_utils::smc_ram_zero(
                            phdr.p_paddr + offset + phdr.p_filesz,
                            zero_bytes as usize
                        );
                    }
                    // Current segment is complete, advance to the next segment.
                    let next_index = index + 1;
                    if next_index >= self.sel4_state.get().phdrs.len() ||
                       self.sel4_state.get().phdrs[next_index] == None {
                        // Last load segment, advance to the next task.
                        self.state.set(ElfLoaderState::Idle);
                        self.run_next_task();
                    } else {
                        // Setup reading the next load segment.
                        let next_phdr = self.sel4_state.get().phdrs[next_index].unwrap();
                        let (mod_offset, div_offset) = if next_phdr.p_filesz > 0 {
                            (next_phdr.p_offset % self.page_len, next_phdr.p_offset / self.page_len)
                        } else {
                            (self.page_len, 0)
                        };
                        let next_cursor = self.sel4_state.get().load_offset + (div_offset * self.page_len);

                        print_segment(next_index, next_cursor, offset, &next_phdr);

                        let new_state =
                            ElfLoaderState::LoadSegmentsNew(next_phdr, next_index, next_cursor, offset, mod_offset, 0);
                        self.state.set(new_state);
                        self.read_page(next_cursor);
                    }
                }
            }
            _ => unreachable!(),
        }
    }
}

impl<'a, F: hil::flash::Flash> Driver for ElfLoaderCapsule<'a, F> {
    fn subscribe(&self, _: usize, _: Option<Callback>, _: AppId) -> ReturnCode {
        return ReturnCode::EINVAL;
    }

    fn command(&self, minor_num: usize, _r2: usize, _r3: usize, _app_id: AppId) -> ReturnCode {
        if minor_num == matcha_config::CMD_ELFLOADER_BOOT_SEL4 {
            match self.flash {
                Some(_) => {
                    #[cfg(debug_assertions)]
                    let debug = true;

                    #[cfg(not(debug_assertions))]
                    let debug = false;
                    if !debug {
                        self.load_sel4();
                    } else {
                        dprintf!("Debug; bypass loading from SPI flash\r\n");
                        self.mailbox_hal.map(|mb| {
                            matcha_utils::load_sel4(mb);
                        });
                    }
                    return ReturnCode::SUCCESS;
                }
                None => {
                    dprintf!("No flash available\r\n");
                    return ReturnCode::EINVAL;
                }
            }
        }

        return ReturnCode::EINVAL;
    }

    fn allow(&self, _: AppId, _: usize, _: Option<AppSlice<Shared, u8>>) -> ReturnCode {
        return ReturnCode::EINVAL;
    }
}

impl<'a, F: hil::flash::Flash> hil::flash::Client<capsules::virtual_flash::FlashUser<'a, F>>
    for ElfLoaderCapsule<'a, F>
{
    fn read_complete(&self, read_page: &'static mut F::Page, _err: kernel::hil::flash::Error) {
        self.read_page.replace(read_page);
        self.flash_busy.set(false);
        match self.state.get() {
            ElfLoaderState::FindingFile(..) => self.find_file_callback(),
            ElfLoaderState::LoadElfHeader(..) =>
                self.load_elf_header_callback(),
            ElfLoaderState::LoadProgramHeaderTable(..) =>
                self.load_program_header_table_callback(),
            ElfLoaderState::LoadSegmentsNew(..) =>
                self.load_segment_callback(),
            _ => panic!("583"),
        }
    }
    fn write_complete(
        &self,
        _: &'static mut <F as kernel::hil::flash::Flash>::Page,
        _: kernel::hil::flash::Error,
    ) {
        todo!()
    }
    fn erase_complete(&self, _: kernel::hil::flash::Error) {
        todo!()
    }
}
