WIP: VESA driver. Make initfs generated by code

This commit is contained in:
Jeremy Soller 2016-09-20 21:52:45 -06:00
parent a4ede1d23d
commit e110ab81b8
21 changed files with 430 additions and 306 deletions

View file

@ -3,7 +3,8 @@ use collections::VecDeque;
use spin::Mutex;
use arch::externs::memset;
use arch::paging::{ActivePageTable, InactivePageTable, Page, PageIter, VirtualAddress};
use arch::memory::Frame;
use arch::paging::{ActivePageTable, InactivePageTable, Page, PageIter, PhysicalAddress, VirtualAddress};
use arch::paging::entry::{self, EntryFlags};
use arch::paging::temporary_page::TemporaryPage;
@ -55,6 +56,47 @@ impl Grant {
});
}
pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant {
let mut active_table = unsafe { ActivePageTable::new() };
let mut flush_all = false;
let start_page = Page::containing_address(to);
let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1));
for page in Page::range_inclusive(start_page, end_page) {
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - to.get() + from.get()));
active_table.map_to(page, frame, flags);
flush_all = true;
}
if flush_all {
active_table.flush_all();
}
Grant {
start: to,
size: size,
flags: flags
}
}
pub fn physunmap(self) {
let mut active_table = unsafe { ActivePageTable::new() };
let mut flush_all = false;
let start_page = Page::containing_address(self.start);
let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
for page in Page::range_inclusive(start_page, end_page) {
active_table.unmap_return(page);
flush_all = true;
}
if flush_all {
active_table.flush_all();
}
}
pub fn start_address(&self) -> VirtualAddress {
self.start
}

View file

@ -7,6 +7,9 @@ use syscall::error::*;
use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END};
use syscall::scheme::Scheme;
#[path="../../build/userspace/initfs.rs"]
mod gen;
struct Handle {
data: &'static [u8],
seek: usize
@ -20,18 +23,9 @@ pub struct InitFsScheme {
impl InitFsScheme {
pub fn new() -> InitFsScheme {
let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new();
files.insert(b"bin/init", include_bytes!("../../build/userspace/init"));
files.insert(b"bin/ion", include_bytes!("../../build/userspace/ion"));
files.insert(b"bin/pcid", include_bytes!("../../build/userspace/pcid"));
files.insert(b"bin/ps2d", include_bytes!("../../build/userspace/ps2d"));
files.insert(b"bin/example", include_bytes!("../../build/userspace/example"));
files.insert(b"etc/init.rc", b"initfs:bin/pcid\ninitfs:bin/ps2d\ninitfs:bin/example\ninitfs:bin/ion");
InitFsScheme {
next_id: AtomicUsize::new(0),
files: files,
files: gen::gen(),
handles: RwLock::new(BTreeMap::new())
}
}

View file

@ -44,6 +44,8 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
SYS_CLONE => clone(b, stack),
SYS_YIELD => sched_yield(),
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
SYS_PHYSMAP => physmap(b, c, d),
SYS_PHYSUNMAP => physunmap(b),
_ => {
println!("Unknown syscall {}", a);
Err(Error::new(ENOSYS))

View file

@ -9,14 +9,16 @@ use spin::Mutex;
use arch;
use arch::externs::memcpy;
use arch::memory::allocate_frame;
use arch::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, entry};
use arch::paging::{ActivePageTable, InactivePageTable, Page, PhysicalAddress, VirtualAddress, entry};
use arch::paging::temporary_page::TemporaryPage;
use arch::start::usermode;
use context;
use context::memory::Grant;
use elf::{self, program_header};
use scheme;
use syscall;
use syscall::error::*;
use syscall::flag::{CLONE_VM, CLONE_FS, CLONE_FILES, MAP_WRITE, MAP_WRITE_COMBINE};
use syscall::validate::{validate_slice, validate_slice_mut};
pub fn brk(address: usize) -> Result<usize> {
@ -51,16 +53,7 @@ pub fn brk(address: usize) -> Result<usize> {
}
}
pub const CLONE_VM: usize = 0x100;
pub const CLONE_FS: usize = 0x200;
pub const CLONE_FILES: usize = 0x400;
pub const CLONE_VFORK: usize = 0x4000;
pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
//TODO: Copy on write?
// vfork not supported
assert!(flags & CLONE_VFORK == 0);
let ppid;
let pid;
{
@ -500,6 +493,83 @@ pub fn iopl(_level: usize) -> Result<usize> {
Ok(0)
}
//TODO: verify exlusive access to physical memory
pub fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
if size == 0 {
Ok(0)
} else {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut grants = context.grants.lock();
let from_address = (physical_address/4096) * 4096;
let offset = physical_address - from_address;
let full_size = ((offset + size + 4095)/4096) * 4096;
let mut to_address = arch::USER_GRANT_OFFSET;
let mut entry_flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE;
if flags & MAP_WRITE == MAP_WRITE {
entry_flags |= entry::WRITABLE;
}
if flags & MAP_WRITE_COMBINE == MAP_WRITE_COMBINE {
entry_flags |= entry::HUGE_PAGE;
}
for i in 0 .. grants.len() {
let start = grants[i].start_address().get();
if to_address + full_size < start {
grants.insert(i, Grant::physmap(
PhysicalAddress::new(from_address),
VirtualAddress::new(to_address),
full_size,
entry_flags
));
return Ok(to_address + offset);
} else {
let pages = (grants[i].size() + 4095) / 4096;
let end = start + pages * 4096;
to_address = end;
}
}
grants.push(Grant::physmap(
PhysicalAddress::new(from_address),
VirtualAddress::new(to_address),
full_size,
entry_flags
));
Ok(to_address + offset)
}
}
pub fn physunmap(virtual_address: usize) -> Result<usize> {
if virtual_address == 0 {
Ok(0)
} else {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut grants = context.grants.lock();
for i in 0 .. grants.len() {
let start = grants[i].start_address().get();
let end = start + grants[i].size();
if virtual_address >= start && virtual_address < end {
grants.remove(i).physunmap();
return Ok(0);
}
}
Err(Error::new(EFAULT))
}
}
pub fn sched_yield() -> Result<usize> {
unsafe { context::switch(); }
Ok(0)