diff --git a/elf.rs b/elf.rs new file mode 100644 index 0000000..c223bb1 --- /dev/null +++ b/elf.rs @@ -0,0 +1,120 @@ +//! ELF executables + +use collections::{String, Vec}; + +use core::{mem, ptr, str, slice}; + +pub use arch::elf::*; + +/// An ELF executable +pub struct Elf<'a> { + pub data: &'a [u8], +} + +impl<'a> Elf<'a> { + /// Create a ELF executable from data + pub fn from(data: &'a [u8]) -> Result, String> { + if data.len() < mem::size_of::() { + Err(format!("Elf: Not enough data: {} < {}", data.len(), mem::size_of::())) + } else if &data[..4] != b"\x7FELF" { + Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], b"\x7FELF")) + } else if data.get(4) != Some(&ELF_CLASS) { + Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(4), Some(&ELF_CLASS))) + } else { + Ok(Elf { data: data }) + } + } + + pub unsafe fn load_segments(&self) -> Vec { + let mut segments = Vec::new(); + + let header = &*(self.data.as_ptr() as usize as *const ElfHeader); + + for i in 0..header.ph_len { + let segment = ptr::read((self.data.as_ptr() as usize + header.ph_off as usize + i as usize * header.ph_ent_len as usize) as *const ElfSegment); + + if segment._type == 1 || segment._type == 7 { + segments.push(segment); + } + } + + segments + } + + /// Get the entry field of the header + pub unsafe fn entry(&self) -> usize { + let header = &*(self.data.as_ptr() as usize as *const ElfHeader); + header.entry as usize + } + + /// ELF symbol + pub unsafe fn symbol(&self, name: &str) -> usize { + let header = &*(self.data.as_ptr() as usize as *const ElfHeader); + + let sh_str_section = + &*((self.data.as_ptr() as usize + header.sh_off as usize + + header.sh_str_index as usize * + header.sh_ent_len as usize) as *const ElfSection); + + let mut sym_section = &*((self.data.as_ptr() as usize + header.sh_off as usize) as *const ElfSection); + + let mut str_section = &*((self.data.as_ptr() as usize + header.sh_off as usize) as *const ElfSection); + + for i in 0..header.sh_len { + let section = + &*((self.data.as_ptr() as usize + header.sh_off as usize + + i as usize * + header.sh_ent_len as usize) as *const ElfSection); + + let section_name_ptr = + (self.data.as_ptr() as usize + sh_str_section.off as usize + section.name as usize) as *const u8; + let mut section_name_len = 0; + for j in 0..4096 { + section_name_len = j; + if ptr::read(section_name_ptr.offset(j)) == 0 { + break; + } + } + let section_name = + str::from_utf8_unchecked(slice::from_raw_parts(section_name_ptr, + section_name_len as usize)); + + if section_name == ".symtab" { + sym_section = section; + } else if section_name == ".strtab" { + str_section = section; + } + } + + if sym_section.off > 0 && str_section.off > 0 { + if sym_section.ent_len > 0 { + let len = sym_section.len / sym_section.ent_len; + for i in 0..len { + let symbol = &*((self.data.as_ptr() as usize + sym_section.off as usize + i as usize * sym_section.ent_len as usize) as *const ElfSymbol); + + let symbol_name_ptr = + (self.data.as_ptr() as usize + str_section.off as usize + + symbol.name as usize) as *const u8; + let mut symbol_name_len = 0; + for j in 0..4096 { + symbol_name_len = j; + if ptr::read(symbol_name_ptr.offset(j)) == 0 { + break; + } + } + let symbol_name = str::from_utf8_unchecked(slice::from_raw_parts(symbol_name_ptr, symbol_name_len as usize)); + + if name == symbol_name { + return symbol.value as usize; + } + } + } else { + print!("No sym_section ent len\n"); + } + } else { + print!("No sym_section or str_section\n"); + } + + 0 + } +} diff --git a/lib.rs b/lib.rs index 5b8d135..474c30e 100644 --- a/lib.rs +++ b/lib.rs @@ -65,6 +65,7 @@ //! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry. #![feature(alloc)] +#![feature(asm)] #![feature(collections)] #![feature(const_fn)] #![feature(drop_types_in_const)] @@ -94,6 +95,9 @@ extern crate spin; /// Context management pub mod context; +/// ELF file parsing +pub mod elf; + /// Schemes, filesystem handlers pub mod scheme; @@ -106,16 +110,18 @@ pub mod tests; #[no_mangle] pub extern fn kmain() { + print!("{}", format!("BSP\n")); + loop { unsafe { interrupt::enable_and_halt(); } - print!("INT BSP\n"); } } #[no_mangle] -pub extern fn kmain_ap() { +pub extern fn kmain_ap(id: usize) { + print!("{}", format!("ASP {}\n", id)); + loop { unsafe { interrupt::enable_and_halt() } - print!("INT AP\n"); } } diff --git a/syscall/mod.rs b/syscall/mod.rs index df9b6d3..8512f52 100644 --- a/syscall/mod.rs +++ b/syscall/mod.rs @@ -106,3 +106,11 @@ pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> :: Call::Unknown => Err(Error::NoCall) }.map_err(|err| err.into()) } + +#[no_mangle] +pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize { + match handle(a, b, c, d, e, f) { + Ok(value) => value, + Err(value) => !value + } +}