Add syscall handler, still work in progress
Add elf files
This commit is contained in:
parent
71a17070b1
commit
5588c38178
|
@ -85,7 +85,7 @@ pub enum MadtEntry {
|
||||||
InvalidIoApic(usize),
|
InvalidIoApic(usize),
|
||||||
IntSrcOverride(&'static MadtIntSrcOverride),
|
IntSrcOverride(&'static MadtIntSrcOverride),
|
||||||
InvalidIntSrcOverride(usize),
|
InvalidIntSrcOverride(usize),
|
||||||
Unknown
|
Unknown(u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MadtIter {
|
pub struct MadtIter {
|
||||||
|
@ -117,7 +117,7 @@ impl Iterator for MadtIter {
|
||||||
} else {
|
} else {
|
||||||
MadtEntry::InvalidIntSrcOverride(entry_len)
|
MadtEntry::InvalidIntSrcOverride(entry_len)
|
||||||
},
|
},
|
||||||
_ => MadtEntry::Unknown
|
_ => MadtEntry::Unknown(entry_type)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.i += entry_len;
|
self.i += entry_len;
|
||||||
|
|
92
arch/x86_64/src/elf.rs
Normal file
92
arch/x86_64/src/elf.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
pub const ELF_CLASS: u8 = 2;
|
||||||
|
pub type ElfAddr = u64;
|
||||||
|
pub type ElfOff = u64;
|
||||||
|
pub type ElfHalf = u16;
|
||||||
|
pub type ElfWord = u32;
|
||||||
|
pub type ElfXword = u64;
|
||||||
|
|
||||||
|
/// An ELF header
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ElfHeader {
|
||||||
|
/// The "magic number" (4 bytes)
|
||||||
|
pub magic: [u8; 4],
|
||||||
|
/// 64 or 32 bit?
|
||||||
|
pub class: u8,
|
||||||
|
/// Little (1) or big endianness (2)?
|
||||||
|
pub endian: u8,
|
||||||
|
/// The ELF version (set to 1 for default)
|
||||||
|
pub ver: u8,
|
||||||
|
/// Operating system ABI (0x03 for Linux)
|
||||||
|
pub abi: [u8; 2],
|
||||||
|
/// Unused
|
||||||
|
pub pad: [u8; 7],
|
||||||
|
/// Specify whether the object is relocatable, executable, shared, or core (in order).
|
||||||
|
pub _type: ElfHalf,
|
||||||
|
/// Instruction set archcitecture
|
||||||
|
pub machine: ElfHalf,
|
||||||
|
/// Second version
|
||||||
|
pub ver_2: ElfWord,
|
||||||
|
/// The ELF entry
|
||||||
|
pub entry: ElfAddr,
|
||||||
|
/// The program header table offset
|
||||||
|
pub ph_off: ElfOff,
|
||||||
|
/// The section header table offset
|
||||||
|
pub sh_off: ElfOff,
|
||||||
|
/// The flags set
|
||||||
|
pub flags: ElfWord,
|
||||||
|
/// The header table length
|
||||||
|
pub h_len: ElfHalf,
|
||||||
|
/// The program header table entry length
|
||||||
|
pub ph_ent_len: ElfHalf,
|
||||||
|
/// The program head table length
|
||||||
|
pub ph_len: ElfHalf,
|
||||||
|
/// The section header table entry length
|
||||||
|
pub sh_ent_len: ElfHalf,
|
||||||
|
/// The section header table length
|
||||||
|
pub sh_len: ElfHalf,
|
||||||
|
/// The section header table string index
|
||||||
|
pub sh_str_index: ElfHalf,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ELF segment
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ElfSegment {
|
||||||
|
pub _type: ElfWord,
|
||||||
|
pub flags: ElfWord,
|
||||||
|
pub off: ElfOff,
|
||||||
|
pub vaddr: ElfAddr,
|
||||||
|
pub paddr: ElfAddr,
|
||||||
|
pub file_len: ElfXword,
|
||||||
|
pub mem_len: ElfXword,
|
||||||
|
pub align: ElfXword,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ELF section
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ElfSection {
|
||||||
|
pub name: ElfWord,
|
||||||
|
pub _type: ElfWord,
|
||||||
|
pub flags: ElfXword,
|
||||||
|
pub addr: ElfAddr,
|
||||||
|
pub off: ElfOff,
|
||||||
|
pub len: ElfXword,
|
||||||
|
pub link: ElfWord,
|
||||||
|
pub info: ElfWord,
|
||||||
|
pub addr_align: ElfXword,
|
||||||
|
pub ent_len: ElfXword,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ELF symbol
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ElfSymbol {
|
||||||
|
pub name: ElfWord,
|
||||||
|
pub info: u8,
|
||||||
|
pub other: u8,
|
||||||
|
pub sh_index: ElfHalf,
|
||||||
|
pub value: ElfAddr,
|
||||||
|
pub size: ElfXword,
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ pub unsafe fn init() {
|
||||||
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
||||||
entry.set_offset(8, blank as usize);
|
entry.set_offset(8, blank as usize);
|
||||||
}
|
}
|
||||||
|
IDT[0x80].set_offset(8, syscall as usize);
|
||||||
IDTR.set_slice(&IDT);
|
IDTR.set_slice(&IDT);
|
||||||
|
|
||||||
init_ap();
|
init_ap();
|
||||||
|
@ -54,6 +55,29 @@ interrupt_error!(page_fault, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern fn syscall() {
|
||||||
|
extern {
|
||||||
|
fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
let a;
|
||||||
|
let b;
|
||||||
|
let c;
|
||||||
|
let d;
|
||||||
|
let e;
|
||||||
|
let f;
|
||||||
|
asm!("" : "={rax}"(a), "={rbx}"(b), "={rcx}"(c), "={rdx}"(d), "={rsi}"(e), "={rdi}"(f)
|
||||||
|
: : : "intel", "volatile");
|
||||||
|
|
||||||
|
let a = syscall(a, b, c, d, e, f);
|
||||||
|
|
||||||
|
asm!("" : : "{rax}"(a) : : "intel", "volatile");
|
||||||
|
|
||||||
|
// Pop scratch registers, error code, and return
|
||||||
|
asm!("iretq" : : : : "intel", "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub flags IdtFlags: u8 {
|
pub flags IdtFlags: u8 {
|
||||||
const IDT_PRESENT = 1 << 7,
|
const IDT_PRESENT = 1 << 7,
|
||||||
|
|
|
@ -119,6 +119,9 @@ macro_rules! interrupt_error {
|
||||||
/// ACPI table parsing
|
/// ACPI table parsing
|
||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
|
|
||||||
|
/// ELF file handling
|
||||||
|
pub mod elf;
|
||||||
|
|
||||||
/// Memcpy, memmove, etc.
|
/// Memcpy, memmove, etc.
|
||||||
pub mod externs;
|
pub mod externs;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern {
|
||||||
/// Kernel main function
|
/// Kernel main function
|
||||||
fn kmain() -> !;
|
fn kmain() -> !;
|
||||||
/// Kernel main for APs
|
/// Kernel main for APs
|
||||||
fn kmain_ap() -> !;
|
fn kmain_ap(id: usize) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The entry to Rust, all things must be initialized
|
/// The entry to Rust, all things must be initialized
|
||||||
|
@ -88,8 +88,6 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
BSP_READY.store(true, Ordering::SeqCst);
|
BSP_READY.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
print!("BSP\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kmain();
|
kmain();
|
||||||
|
@ -115,7 +113,5 @@ pub unsafe extern fn kstart_ap(stack_start: usize, stack_end: usize) -> ! {
|
||||||
asm!("pause" : : : : "intel", "volatile");
|
asm!("pause" : : : : "intel", "volatile");
|
||||||
}
|
}
|
||||||
|
|
||||||
print!("{}", ::core::str::from_utf8_unchecked(&[b'A', b'P', b' ', ap_number as u8 + b'0', b'\n']));
|
kmain_ap(ap_number);
|
||||||
|
|
||||||
kmain_ap();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,3 @@ kernel_file:
|
||||||
.end:
|
.end:
|
||||||
.length equ kernel_file.end - kernel_file
|
.length equ kernel_file.end - kernel_file
|
||||||
.length_sectors equ .length / 512
|
.length_sectors equ .length / 512
|
||||||
|
|
||||||
times 1024*1024-($-$$) db 0
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
ENTRY(kstart)
|
ENTRY(kstart)
|
||||||
OUTPUT_FORMAT(elf64-x86-64)
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
|
||||||
KERNEL_OFFSET = 0;
|
KERNEL_OFFSET = 0x100000;
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0x100000;
|
. = KERNEL_OFFSET;
|
||||||
|
|
||||||
. += SIZEOF_HEADERS;
|
. += SIZEOF_HEADERS;
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
|
|
||||||
. += KERNEL_OFFSET;
|
|
||||||
|
|
||||||
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
|
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
|
||||||
__text_start = .;
|
__text_start = .;
|
||||||
*(.text*)
|
*(.text*)
|
||||||
|
|
120
kernel/elf.rs
Normal file
120
kernel/elf.rs
Normal file
|
@ -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<Elf<'a>, String> {
|
||||||
|
if data.len() < mem::size_of::<ElfHeader>() {
|
||||||
|
Err(format!("Elf: Not enough data: {} < {}", data.len(), mem::size_of::<ElfHeader>()))
|
||||||
|
} 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<ElfSegment> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,6 +65,7 @@
|
||||||
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
||||||
|
|
||||||
#![feature(alloc)]
|
#![feature(alloc)]
|
||||||
|
#![feature(asm)]
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(drop_types_in_const)]
|
#![feature(drop_types_in_const)]
|
||||||
|
@ -94,6 +95,9 @@ extern crate spin;
|
||||||
/// Context management
|
/// Context management
|
||||||
pub mod context;
|
pub mod context;
|
||||||
|
|
||||||
|
/// ELF file parsing
|
||||||
|
pub mod elf;
|
||||||
|
|
||||||
/// Schemes, filesystem handlers
|
/// Schemes, filesystem handlers
|
||||||
pub mod scheme;
|
pub mod scheme;
|
||||||
|
|
||||||
|
@ -106,16 +110,18 @@ pub mod tests;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn kmain() {
|
pub extern fn kmain() {
|
||||||
|
print!("{}", format!("BSP\n"));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe { interrupt::enable_and_halt(); }
|
unsafe { interrupt::enable_and_halt(); }
|
||||||
print!("INT BSP\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn kmain_ap() {
|
pub extern fn kmain_ap(id: usize) {
|
||||||
|
print!("{}", format!("ASP {}\n", id));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe { interrupt::enable_and_halt() }
|
unsafe { interrupt::enable_and_halt() }
|
||||||
print!("INT AP\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,3 +106,11 @@ pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> ::
|
||||||
Call::Unknown => Err(Error::NoCall)
|
Call::Unknown => Err(Error::NoCall)
|
||||||
}.map_err(|err| err.into())
|
}.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"code-model": "kernel",
|
"code-model": "kernel",
|
||||||
"disable-redzone": true,
|
"disable-redzone": true,
|
||||||
"eliminate-frame-pointer": false,
|
"eliminate-frame-pointer": false,
|
||||||
"exe-suffix": ".bin",
|
"exe-suffix": "",
|
||||||
"has-rpath": false,
|
"has-rpath": false,
|
||||||
"no-compiler-rt": true,
|
"no-compiler-rt": true,
|
||||||
"no-default-libraries": true,
|
"no-default-libraries": true,
|
||||||
|
|
Loading…
Reference in a new issue