// Trivial elf segment loader, just copies segments straight from the in-memory
// blob to the physical addresses specified in the program header.

use core::cmp;
use core::mem::transmute;
use core::ptr;
use core::slice;

use crate::tar_loader;
use matcha_hal::dprintf;

pub const ELF_MAGIC: u32 = 0x464c457f;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct Elf32Header {
    pub e_ident: [u8; 16],
    pub e_type: u16,      /* Relocatable=1, Executable=2 (+ some more ..) */
    pub e_machine: u16,   /* Target architecture: MIPS=8 */
    pub e_version: u32,   /* Elf version (should be 1) */
    pub e_entry: u32,     /* Code entry point */
    pub e_phoff: u32,     /* Program header table */
    pub e_shoff: u32,     /* Section header table */
    pub e_flags: u32,     /* Flags */
    pub e_ehsize: u16,    /* ELF header size */
    pub e_phentsize: u16, /* Size of one program segment header */
    pub e_phnum: u16,     /* Number of program segment headers */
    pub e_shentsize: u16, /* Size of one section header */
    pub e_shnum: u16,     /* Number of section headers */
    pub e_shstrndx: u16,  /* Section header index of the string table for section
                          header names */
}

#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct Elf32Phdr {
    pub p_type: u32,   /* Segment type: Loadable segment = 1 */
    pub p_offset: u32, /* Offset of segment in file */
    pub p_vaddr: u32,  /* Reqd virtual address of segment when loading */
    pub p_paddr: u32,  /* Reqd physical address of segment (ignore) */
    pub p_filesz: u32, /* How many bytes this segment occupies in file */
    pub p_memsz: u32,  /* How many bytes this segment should occupy in memory */
    pub p_flags: u32,  /* Flags: logical "or" of PF_ constants below */
    pub p_align: u32,  /* Reqd alignment of segment in memory */
}

pub fn elf_phys_min(segments: &[Elf32Phdr]) -> u32 {
    return segments.iter().fold(0xFFFFFFFF, |acc, seg| {
        if seg.p_type != 1 {
            return acc;
        } else {
            return cmp::min(acc, seg.p_paddr);
        }
    });
}

pub fn elf_phys_max(segments: &[Elf32Phdr]) -> u32 {
    return segments.iter().fold(0, |acc, seg| {
        if seg.p_type != 1 {
            return acc;
        } else {
            return cmp::max(acc, seg.p_paddr + seg.p_memsz);
        }
    });
}

pub fn elf_virt_min(segments: &[Elf32Phdr]) -> u32 {
    return segments.iter().fold(0xFFFFFFFF, |acc, seg| {
        if seg.p_type != 1 {
            return acc;
        } else {
            return cmp::min(acc, seg.p_vaddr);
        }
    });
}

pub fn elf_virt_max(segments: &[Elf32Phdr]) -> u32 {
    return segments.iter().fold(0, |acc, seg| {
        if seg.p_type != 1 {
            return acc;
        } else {
            return cmp::max(acc, seg.p_vaddr + seg.p_memsz);
        }
    });
}

pub unsafe fn elf_get_segments(elf: *const Elf32Header) -> &'static [Elf32Phdr] {
    let base: *const u8 = transmute(elf);
    let seg_count = (*elf).e_phnum as usize;
    let segments: &[Elf32Phdr] =
        slice::from_raw_parts(transmute(base.offset((*elf).e_phoff as isize)), seg_count);
    return segments;
}

pub unsafe fn find_elf(name: &str) -> *const Elf32Header {
    let (tar_offset, tar_size) = tar_loader::find_file(name);

    if tar_size > 0 {
        let pmagic: *const u32 = transmute(tar_offset);
        if pmagic.read_volatile() == ELF_MAGIC {
            let elf_header: *const Elf32Header = transmute(tar_offset);
            return elf_header;
        }
    }

    dprintf!("Could not find elf for '{}'\n", name);
    return transmute(0);
}

pub unsafe fn load_elf_segments(elf: &Elf32Header, dst_offset: u32) {
    let base: *const u8 = transmute(elf);
    let seg_count = elf.e_phnum as usize;
    let segments: &[Elf32Phdr] =
        slice::from_raw_parts(transmute(base.offset(elf.e_phoff as isize)), seg_count);

    for i in 0..segments.len() {
        let seg = &segments[i];

        // Loadable segment type.
        const PT_LOAD: u32 = 1;
        if seg.p_type != PT_LOAD {
            continue;
        }
        if seg.p_filesz == 0 {
            continue;
        }

        let src: *const u8 = transmute(base.offset(seg.p_offset as isize));

        let txt_size = seg.p_filesz as usize;
        let txt_start: *mut u8 = transmute(seg.p_paddr + dst_offset);
        let txt_end = txt_start.offset(txt_size as isize);

        dprintf!(
            "seg {}: {:?} -> {:?}:{:?} ({} bytes)\n",
            i,
            src,
            txt_start,
            txt_end,
            txt_size
        );
        ptr::copy_nonoverlapping(src, txt_start, txt_size);

        let bss_size = (seg.p_memsz - seg.p_filesz) as usize;
        let bss_start = txt_end;
        let bss_end = bss_start.offset(bss_size as isize);

        dprintf!(
            "bss {}: {:?} -> {:?}:{:?} ({} bytes)\n",
            i,
            src,
            bss_start,
            bss_end,
            bss_size
        );
        ptr::write_bytes(bss_start, 0, bss_size as usize);
    }
}
