WIP: VESA driver. Make initfs generated by code
This commit is contained in:
parent
a4ede1d23d
commit
e110ab81b8
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
build
|
build
|
||||||
target
|
target
|
||||||
|
initfs/bin
|
||||||
|
|
34
Makefile
34
Makefile
|
@ -28,7 +28,9 @@ clean:
|
||||||
cargo clean --manifest-path ion/Cargo.toml
|
cargo clean --manifest-path ion/Cargo.toml
|
||||||
cargo clean --manifest-path drivers/ps2d/Cargo.toml
|
cargo clean --manifest-path drivers/ps2d/Cargo.toml
|
||||||
cargo clean --manifest-path drivers/pcid/Cargo.toml
|
cargo clean --manifest-path drivers/pcid/Cargo.toml
|
||||||
|
cargo clean --manifest-path drivers/vesad/Cargo.toml
|
||||||
cargo clean --manifest-path schemes/example/Cargo.toml
|
cargo clean --manifest-path schemes/example/Cargo.toml
|
||||||
|
rm -rf initfs/bin
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
@ -123,24 +125,40 @@ $(BUILD)/libstd.rlib: libstd/Cargo.toml libstd/src/** $(BUILD)/libcore.rlib $(BU
|
||||||
$(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -o $@
|
$(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -o $@
|
||||||
cp libstd/target/$(TARGET)/debug/deps/*.rlib $(BUILD)
|
cp libstd/target/$(TARGET)/debug/deps/*.rlib $(BUILD)
|
||||||
|
|
||||||
$(BUILD)/init: init/Cargo.toml init/src/*.rs $(BUILD)/libstd.rlib
|
|
||||||
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
|
||||||
strip $@
|
|
||||||
|
|
||||||
$(BUILD)/ion: ion/Cargo.toml ion/src/*.rs $(BUILD)/libstd.rlib
|
$(BUILD)/ion: ion/Cargo.toml ion/src/*.rs $(BUILD)/libstd.rlib
|
||||||
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
||||||
strip $@
|
strip $@
|
||||||
|
|
||||||
$(BUILD)/pcid: drivers/pcid/Cargo.toml drivers/pcid/src/** $(BUILD)/libstd.rlib
|
initfs/bin/init: init/Cargo.toml init/src/*.rs $(BUILD)/libstd.rlib
|
||||||
|
mkdir -p initfs/bin
|
||||||
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
||||||
strip $@
|
strip $@
|
||||||
|
rm $@.d
|
||||||
|
|
||||||
$(BUILD)/ps2d: drivers/ps2d/Cargo.toml drivers/ps2d/src/** $(BUILD)/libstd.rlib
|
initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib
|
||||||
|
mkdir -p initfs/bin
|
||||||
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
||||||
strip $@
|
strip $@
|
||||||
|
rm $@.d
|
||||||
|
|
||||||
$(BUILD)/example: schemes/example/Cargo.toml schemes/example/src/** $(BUILD)/libstd.rlib
|
initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib
|
||||||
|
mkdir -p initfs/bin
|
||||||
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
$(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@
|
||||||
strip $@
|
strip $@
|
||||||
|
rm $@.d
|
||||||
|
|
||||||
$(BUILD)/initfs.rs: $(BUILD)/init $(BUILD)/ion $(BUILD)/pcid $(BUILD)/ps2d $(BUILD)/example
|
|
||||||
|
$(BUILD)/initfs.rs: \
|
||||||
|
initfs/bin/init \
|
||||||
|
initfs/bin/pcid \
|
||||||
|
initfs/bin/ps2d \
|
||||||
|
initfs/bin/vesad \
|
||||||
|
initfs/bin/example
|
||||||
|
echo 'use collections::BTreeMap;' > $@
|
||||||
|
echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], &'"'"'static [u8]> {' >> $@
|
||||||
|
echo ' let mut files: BTreeMap<&'"'"'static [u8], &'"'"'static [u8]> = BTreeMap::new();' >> $@
|
||||||
|
find initfs -type f -o -type l | cut -d '/' -f2- | sort \
|
||||||
|
| awk '{printf(" files.insert(b\"%s\", include_bytes!(\"../../initfs/%s\"));\n", $$0, $$0)}' \
|
||||||
|
>> $@
|
||||||
|
echo ' files' >> $@
|
||||||
|
echo '}' >> $@
|
||||||
|
|
|
@ -6,7 +6,6 @@ version = "0.1.0"
|
||||||
bitflags = "*"
|
bitflags = "*"
|
||||||
hole_list_allocator = { path = "../../alloc/hole_list_allocator" }
|
hole_list_allocator = { path = "../../alloc/hole_list_allocator" }
|
||||||
io = { path = "../../drivers/io" }
|
io = { path = "../../drivers/io" }
|
||||||
ransid = { git = "https://github.com/redox-os/ransid.git", branch = "new_api" }
|
|
||||||
spin = "*"
|
spin = "*"
|
||||||
|
|
||||||
[dependencies.x86]
|
[dependencies.x86]
|
||||||
|
|
|
@ -1,31 +1,14 @@
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
use device::display;
|
|
||||||
use device::serial::COM1;
|
use device::serial::COM1;
|
||||||
|
|
||||||
pub static CONSOLE: Mutex<Console> = Mutex::new(Console::new());
|
pub static CONSOLE: Mutex<Console> = Mutex::new(Console);
|
||||||
|
|
||||||
pub struct Console;
|
pub struct Console;
|
||||||
|
|
||||||
impl Console {
|
|
||||||
const fn new() -> Self {
|
|
||||||
Console
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Write for Console {
|
impl Write for Console {
|
||||||
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
||||||
if let Some(ref mut console) = *display::CONSOLE.lock() {
|
|
||||||
if let Some(ref mut display) = *display::DISPLAY.lock() {
|
|
||||||
console.write(s.as_bytes(), |event| {
|
|
||||||
display.event(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
COM1.lock().write_str(s)
|
COM1.lock().write_str(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,245 +0,0 @@
|
||||||
use core::{cmp, slice};
|
|
||||||
use ransid::{Console, Event};
|
|
||||||
use spin::Mutex;
|
|
||||||
|
|
||||||
use memory::Frame;
|
|
||||||
use paging::{ActivePageTable, Page, PhysicalAddress, VirtualAddress, entry};
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
#[inline(always)]
|
|
||||||
#[cold]
|
|
||||||
unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
|
|
||||||
asm!("cld
|
|
||||||
rep movsq"
|
|
||||||
:
|
|
||||||
: "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
|
|
||||||
: "cc", "memory"
|
|
||||||
: "intel", "volatile");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
#[inline(always)]
|
|
||||||
#[cold]
|
|
||||||
unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) {
|
|
||||||
asm!("cld
|
|
||||||
rep stosd"
|
|
||||||
:
|
|
||||||
: "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len)
|
|
||||||
: "cc", "memory"
|
|
||||||
: "intel", "volatile");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
#[inline(always)]
|
|
||||||
#[cold]
|
|
||||||
unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
|
|
||||||
asm!("cld
|
|
||||||
rep stosq"
|
|
||||||
:
|
|
||||||
: "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len)
|
|
||||||
: "cc", "memory"
|
|
||||||
: "intel", "volatile");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The info of the VBE mode
|
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
|
||||||
#[repr(packed)]
|
|
||||||
pub struct VBEModeInfo {
|
|
||||||
attributes: u16,
|
|
||||||
win_a: u8,
|
|
||||||
win_b: u8,
|
|
||||||
granularity: u16,
|
|
||||||
winsize: u16,
|
|
||||||
segment_a: u16,
|
|
||||||
segment_b: u16,
|
|
||||||
winfuncptr: u32,
|
|
||||||
bytesperscanline: u16,
|
|
||||||
pub xresolution: u16,
|
|
||||||
pub yresolution: u16,
|
|
||||||
xcharsize: u8,
|
|
||||||
ycharsize: u8,
|
|
||||||
numberofplanes: u8,
|
|
||||||
bitsperpixel: u8,
|
|
||||||
numberofbanks: u8,
|
|
||||||
memorymodel: u8,
|
|
||||||
banksize: u8,
|
|
||||||
numberofimagepages: u8,
|
|
||||||
unused: u8,
|
|
||||||
redmasksize: u8,
|
|
||||||
redfieldposition: u8,
|
|
||||||
greenmasksize: u8,
|
|
||||||
greenfieldposition: u8,
|
|
||||||
bluemasksize: u8,
|
|
||||||
bluefieldposition: u8,
|
|
||||||
rsvdmasksize: u8,
|
|
||||||
rsvdfieldposition: u8,
|
|
||||||
directcolormodeinfo: u8,
|
|
||||||
physbaseptr: u32,
|
|
||||||
offscreenmemoryoffset: u32,
|
|
||||||
offscreenmemsize: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static CONSOLE: Mutex<Option<Console>> = Mutex::new(None);
|
|
||||||
|
|
||||||
pub static DISPLAY: Mutex<Option<Display>> = Mutex::new(None);
|
|
||||||
|
|
||||||
static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font");
|
|
||||||
|
|
||||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
|
||||||
active_table.identity_map(Frame::containing_address(PhysicalAddress::new(0x5200)), entry::PRESENT | entry::NO_EXECUTE);
|
|
||||||
|
|
||||||
let mode_info = &*(0x5200 as *const VBEModeInfo);
|
|
||||||
if mode_info.physbaseptr > 0 {
|
|
||||||
let width = mode_info.xresolution as usize;
|
|
||||||
let height = mode_info.yresolution as usize;
|
|
||||||
let onscreen = mode_info.physbaseptr as usize + ::KERNEL_OFFSET;
|
|
||||||
let size = width * height;
|
|
||||||
|
|
||||||
{
|
|
||||||
let start_page = Page::containing_address(VirtualAddress::new(onscreen));
|
|
||||||
let end_page = Page::containing_address(VirtualAddress::new(onscreen + size * 4 - 1));
|
|
||||||
for page in Page::range_inclusive(start_page, end_page) {
|
|
||||||
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - ::KERNEL_OFFSET));
|
|
||||||
active_table.map_to(page, frame, /*actually sets PAT for write combining*/ entry::HUGE_PAGE | entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fast_set64(onscreen as *mut u64, 0, size/2);
|
|
||||||
|
|
||||||
let offscreen = ::allocator::__rust_allocate(size * 4, 4096);
|
|
||||||
fast_set64(offscreen as *mut u64, 0, size/2);
|
|
||||||
|
|
||||||
*DISPLAY.lock() = Some(Display::new(width, height,
|
|
||||||
slice::from_raw_parts_mut(onscreen as *mut u32, size),
|
|
||||||
slice::from_raw_parts_mut(offscreen as *mut u32, size)
|
|
||||||
));
|
|
||||||
*CONSOLE.lock() = Some(Console::new(width/8, height/16));
|
|
||||||
}
|
|
||||||
|
|
||||||
active_table.unmap(Page::containing_address(VirtualAddress::new(0x5200)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A display
|
|
||||||
pub struct Display {
|
|
||||||
pub width: usize,
|
|
||||||
pub height: usize,
|
|
||||||
pub onscreen: &'static mut [u32],
|
|
||||||
pub offscreen: &'static mut [u32],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display {
|
|
||||||
fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display {
|
|
||||||
Display {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
onscreen: onscreen,
|
|
||||||
offscreen: offscreen,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Draw a rectangle
|
|
||||||
fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
|
||||||
let start_y = cmp::min(self.height - 1, y);
|
|
||||||
let end_y = cmp::min(self.height, y + h);
|
|
||||||
|
|
||||||
let start_x = cmp::min(self.width - 1, x);
|
|
||||||
let len = cmp::min(self.width, x + w) - start_x;
|
|
||||||
|
|
||||||
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
|
||||||
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
|
||||||
|
|
||||||
let stride = self.width * 4;
|
|
||||||
|
|
||||||
let offset = y * stride + start_x * 4;
|
|
||||||
offscreen_ptr += offset;
|
|
||||||
onscreen_ptr += offset;
|
|
||||||
|
|
||||||
let mut rows = end_y - start_y;
|
|
||||||
while rows > 0 {
|
|
||||||
unsafe {
|
|
||||||
fast_set(offscreen_ptr as *mut u32, color, len);
|
|
||||||
fast_set(onscreen_ptr as *mut u32, color, len);
|
|
||||||
}
|
|
||||||
offscreen_ptr += stride;
|
|
||||||
onscreen_ptr += stride;
|
|
||||||
rows -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Draw a character
|
|
||||||
fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
|
|
||||||
if x + 8 <= self.width && y + 16 <= self.height {
|
|
||||||
let mut font_i = 16 * (character as usize);
|
|
||||||
let font_end = font_i + 16;
|
|
||||||
if font_end <= FONT.len() {
|
|
||||||
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
|
||||||
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
|
||||||
|
|
||||||
let stride = self.width * 4;
|
|
||||||
|
|
||||||
let offset = y * stride + x * 4;
|
|
||||||
offscreen_ptr += offset;
|
|
||||||
onscreen_ptr += offset;
|
|
||||||
|
|
||||||
while font_i < font_end {
|
|
||||||
let mut row_data = FONT[font_i];
|
|
||||||
let mut col = 8;
|
|
||||||
while col > 0 {
|
|
||||||
col -= 1;
|
|
||||||
if row_data & 1 == 1 {
|
|
||||||
unsafe {
|
|
||||||
*((offscreen_ptr + col * 4) as *mut u32) = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row_data = row_data >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
fast_copy64(onscreen_ptr as *mut u64, offscreen_ptr as *const u64, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
offscreen_ptr += stride;
|
|
||||||
onscreen_ptr += stride;
|
|
||||||
font_i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Scroll display
|
|
||||||
pub fn scroll(&mut self, rows: usize, color: u32) {
|
|
||||||
let data = (color as u64) << 32 | color as u64;
|
|
||||||
|
|
||||||
let width = self.width/2;
|
|
||||||
let height = self.height;
|
|
||||||
if rows > 0 && rows < height {
|
|
||||||
let off1 = rows * width;
|
|
||||||
let off2 = height * width - off1;
|
|
||||||
unsafe {
|
|
||||||
let data_ptr = self.offscreen.as_mut_ptr() as *mut u64;
|
|
||||||
fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2);
|
|
||||||
fast_set64(data_ptr.offset(off2 as isize), data, off1);
|
|
||||||
|
|
||||||
fast_copy64(self.onscreen.as_mut_ptr() as *mut u64, data_ptr, off1 + off2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle ransid event
|
|
||||||
pub fn event(&mut self, event: Event) {
|
|
||||||
match event {
|
|
||||||
Event::Char { x, y, c, color, .. } => {
|
|
||||||
self.char(x * 8, y * 16, c, color.data);
|
|
||||||
},
|
|
||||||
Event::Rect { x, y, w, h, color } => {
|
|
||||||
self.rect(x * 8, y * 16, w * 8, h * 16, color.data);
|
|
||||||
},
|
|
||||||
Event::Scroll { rows, color } => {
|
|
||||||
self.scroll(rows * 16, color.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,5 @@
|
||||||
use paging::ActivePageTable;
|
|
||||||
|
|
||||||
pub mod display;
|
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
|
|
||||||
pub unsafe fn init(active_table: &mut ActivePageTable){
|
pub unsafe fn init(){
|
||||||
serial::init();
|
serial::init();
|
||||||
display::init(active_table);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ extern crate hole_list_allocator as allocator;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
extern crate io;
|
extern crate io;
|
||||||
extern crate ransid;
|
|
||||||
extern crate spin;
|
extern crate spin;
|
||||||
pub extern crate x86;
|
pub extern crate x86;
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize devices
|
// Initialize devices
|
||||||
device::init(&mut active_table);
|
device::init();
|
||||||
|
|
||||||
// Send kernel page table to APs
|
// Send kernel page table to APs
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Entry to rust for an AP
|
/// Entry to rust for an AP
|
||||||
pub unsafe extern fn kstart_ap(cpu_id: usize, page_table: usize, stack_start: usize, stack_end: usize) -> ! {
|
pub unsafe extern fn kstart_ap(cpu_id: usize, _page_table: usize, stack_start: usize, stack_end: usize) -> ! {
|
||||||
{
|
{
|
||||||
assert_eq!(BSS_TEST_ZERO, 0);
|
assert_eq!(BSS_TEST_ZERO, 0);
|
||||||
assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
|
assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
|
||||||
|
|
6
drivers/vesad/Cargo.toml
Normal file
6
drivers/vesad/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "vesad"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syscall = { path = "../../syscall/" }
|
112
drivers/vesad/src/display.rs
Normal file
112
drivers/vesad/src/display.rs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
use primitive::{fast_set, fast_set64, fast_copy64};
|
||||||
|
|
||||||
|
static FONT: &'static [u8] = include_bytes!("../../../res/unifont.font");
|
||||||
|
|
||||||
|
/// A display
|
||||||
|
pub struct Display {
|
||||||
|
pub width: usize,
|
||||||
|
pub height: usize,
|
||||||
|
pub onscreen: &'static mut [u32],
|
||||||
|
pub offscreen: &'static mut [u32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display {
|
||||||
|
pub fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display {
|
||||||
|
Display {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
onscreen: onscreen,
|
||||||
|
offscreen: offscreen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw a rectangle
|
||||||
|
pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
||||||
|
let start_y = cmp::min(self.height - 1, y);
|
||||||
|
let end_y = cmp::min(self.height, y + h);
|
||||||
|
|
||||||
|
let start_x = cmp::min(self.width - 1, x);
|
||||||
|
let len = cmp::min(self.width, x + w) - start_x;
|
||||||
|
|
||||||
|
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
||||||
|
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
||||||
|
|
||||||
|
let stride = self.width * 4;
|
||||||
|
|
||||||
|
let offset = y * stride + start_x * 4;
|
||||||
|
offscreen_ptr += offset;
|
||||||
|
onscreen_ptr += offset;
|
||||||
|
|
||||||
|
let mut rows = end_y - start_y;
|
||||||
|
while rows > 0 {
|
||||||
|
unsafe {
|
||||||
|
fast_set(offscreen_ptr as *mut u32, color, len);
|
||||||
|
fast_set(onscreen_ptr as *mut u32, color, len);
|
||||||
|
}
|
||||||
|
offscreen_ptr += stride;
|
||||||
|
onscreen_ptr += stride;
|
||||||
|
rows -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw a character
|
||||||
|
fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
|
||||||
|
if x + 8 <= self.width && y + 16 <= self.height {
|
||||||
|
let mut font_i = 16 * (character as usize);
|
||||||
|
let font_end = font_i + 16;
|
||||||
|
if font_end <= FONT.len() {
|
||||||
|
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
|
||||||
|
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
|
||||||
|
|
||||||
|
let stride = self.width * 4;
|
||||||
|
|
||||||
|
let offset = y * stride + x * 4;
|
||||||
|
offscreen_ptr += offset;
|
||||||
|
onscreen_ptr += offset;
|
||||||
|
|
||||||
|
while font_i < font_end {
|
||||||
|
let mut row_data = FONT[font_i];
|
||||||
|
let mut col = 8;
|
||||||
|
while col > 0 {
|
||||||
|
col -= 1;
|
||||||
|
if row_data & 1 == 1 {
|
||||||
|
unsafe {
|
||||||
|
*((offscreen_ptr + col * 4) as *mut u32) = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row_data = row_data >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
fast_copy64(onscreen_ptr as *mut u64, offscreen_ptr as *const u64, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
offscreen_ptr += stride;
|
||||||
|
onscreen_ptr += stride;
|
||||||
|
font_i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Scroll display
|
||||||
|
pub fn scroll(&mut self, rows: usize, color: u32) {
|
||||||
|
let data = (color as u64) << 32 | color as u64;
|
||||||
|
|
||||||
|
let width = self.width/2;
|
||||||
|
let height = self.height;
|
||||||
|
if rows > 0 && rows < height {
|
||||||
|
let off1 = rows * width;
|
||||||
|
let off2 = height * width - off1;
|
||||||
|
unsafe {
|
||||||
|
let data_ptr = self.offscreen.as_mut_ptr() as *mut u64;
|
||||||
|
fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2);
|
||||||
|
fast_set64(data_ptr.offset(off2 as isize), data, off1);
|
||||||
|
|
||||||
|
fast_copy64(self.onscreen.as_mut_ptr() as *mut u64, data_ptr, off1 + off2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
drivers/vesad/src/main.rs
Normal file
54
drivers/vesad/src/main.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#![feature(alloc)]
|
||||||
|
#![feature(asm)]
|
||||||
|
#![feature(heap_api)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
extern crate syscall;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::{slice, thread};
|
||||||
|
use syscall::{physmap, physunmap, MAP_WRITE, MAP_WRITE_COMBINE};
|
||||||
|
|
||||||
|
use display::Display;
|
||||||
|
use mode_info::VBEModeInfo;
|
||||||
|
use primitive::fast_set64;
|
||||||
|
|
||||||
|
pub mod display;
|
||||||
|
pub mod mode_info;
|
||||||
|
pub mod primitive;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let width;
|
||||||
|
let height;
|
||||||
|
let physbaseptr;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) };
|
||||||
|
|
||||||
|
width = mode_info.xresolution as usize;
|
||||||
|
height = mode_info.yresolution as usize;
|
||||||
|
physbaseptr = mode_info.physbaseptr as usize;
|
||||||
|
|
||||||
|
unsafe { let _ = physunmap(mode_info as *const _ as usize); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if physbaseptr > 0 {
|
||||||
|
let mut socket = File::create(":display").expect("vesad: failed to create display scheme");
|
||||||
|
thread::spawn(move || {
|
||||||
|
let size = width * height;
|
||||||
|
|
||||||
|
let onscreen = unsafe { physmap(physbaseptr as usize, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
|
||||||
|
unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };
|
||||||
|
|
||||||
|
let offscreen = unsafe { alloc::heap::allocate(size * 4, 4096) };
|
||||||
|
unsafe { fast_set64(offscreen as *mut u64, 0, size/2) };
|
||||||
|
|
||||||
|
let mut display = Display::new(width, height,
|
||||||
|
unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) },
|
||||||
|
unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }
|
||||||
|
);
|
||||||
|
|
||||||
|
display.rect(100, 100, 100, 100, 0xFF0000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
37
drivers/vesad/src/mode_info.rs
Normal file
37
drivers/vesad/src/mode_info.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/// The info of the VBE mode
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct VBEModeInfo {
|
||||||
|
attributes: u16,
|
||||||
|
win_a: u8,
|
||||||
|
win_b: u8,
|
||||||
|
granularity: u16,
|
||||||
|
winsize: u16,
|
||||||
|
segment_a: u16,
|
||||||
|
segment_b: u16,
|
||||||
|
winfuncptr: u32,
|
||||||
|
bytesperscanline: u16,
|
||||||
|
pub xresolution: u16,
|
||||||
|
pub yresolution: u16,
|
||||||
|
xcharsize: u8,
|
||||||
|
ycharsize: u8,
|
||||||
|
numberofplanes: u8,
|
||||||
|
bitsperpixel: u8,
|
||||||
|
numberofbanks: u8,
|
||||||
|
memorymodel: u8,
|
||||||
|
banksize: u8,
|
||||||
|
numberofimagepages: u8,
|
||||||
|
unused: u8,
|
||||||
|
redmasksize: u8,
|
||||||
|
redfieldposition: u8,
|
||||||
|
greenmasksize: u8,
|
||||||
|
greenfieldposition: u8,
|
||||||
|
bluemasksize: u8,
|
||||||
|
bluefieldposition: u8,
|
||||||
|
rsvdmasksize: u8,
|
||||||
|
rsvdfieldposition: u8,
|
||||||
|
directcolormodeinfo: u8,
|
||||||
|
pub physbaseptr: u32,
|
||||||
|
offscreenmemoryoffset: u32,
|
||||||
|
offscreenmemsize: u16,
|
||||||
|
}
|
38
drivers/vesad/src/primitive.rs
Normal file
38
drivers/vesad/src/primitive.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cold]
|
||||||
|
pub unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
|
||||||
|
asm!("cld
|
||||||
|
rep movsq"
|
||||||
|
:
|
||||||
|
: "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
|
||||||
|
: "cc", "memory"
|
||||||
|
: "intel", "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cold]
|
||||||
|
pub unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) {
|
||||||
|
asm!("cld
|
||||||
|
rep stosd"
|
||||||
|
:
|
||||||
|
: "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len)
|
||||||
|
: "cc", "memory"
|
||||||
|
: "intel", "volatile");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cold]
|
||||||
|
pub unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
|
||||||
|
asm!("cld
|
||||||
|
rep stosq"
|
||||||
|
:
|
||||||
|
: "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len)
|
||||||
|
: "cc", "memory"
|
||||||
|
: "intel", "volatile");
|
||||||
|
}
|
5
initfs/etc/init.rc
Normal file
5
initfs/etc/init.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
initfs:bin/vesad
|
||||||
|
initfs:bin/ps2d
|
||||||
|
initfs:bin/pcid
|
||||||
|
initfs:bin/example
|
||||||
|
initfs:bin/ion
|
|
@ -3,7 +3,8 @@ use collections::VecDeque;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
use arch::externs::memset;
|
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::entry::{self, EntryFlags};
|
||||||
use arch::paging::temporary_page::TemporaryPage;
|
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 {
|
pub fn start_address(&self) -> VirtualAddress {
|
||||||
self.start
|
self.start
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ use syscall::error::*;
|
||||||
use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END};
|
use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END};
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
|
|
||||||
|
#[path="../../build/userspace/initfs.rs"]
|
||||||
|
mod gen;
|
||||||
|
|
||||||
struct Handle {
|
struct Handle {
|
||||||
data: &'static [u8],
|
data: &'static [u8],
|
||||||
seek: usize
|
seek: usize
|
||||||
|
@ -20,18 +23,9 @@ pub struct InitFsScheme {
|
||||||
|
|
||||||
impl InitFsScheme {
|
impl InitFsScheme {
|
||||||
pub fn new() -> 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 {
|
InitFsScheme {
|
||||||
next_id: AtomicUsize::new(0),
|
next_id: AtomicUsize::new(0),
|
||||||
files: files,
|
files: gen::gen(),
|
||||||
handles: RwLock::new(BTreeMap::new())
|
handles: RwLock::new(BTreeMap::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_CLONE => clone(b, stack),
|
||||||
SYS_YIELD => sched_yield(),
|
SYS_YIELD => sched_yield(),
|
||||||
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
|
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);
|
println!("Unknown syscall {}", a);
|
||||||
Err(Error::new(ENOSYS))
|
Err(Error::new(ENOSYS))
|
||||||
|
|
|
@ -9,14 +9,16 @@ use spin::Mutex;
|
||||||
use arch;
|
use arch;
|
||||||
use arch::externs::memcpy;
|
use arch::externs::memcpy;
|
||||||
use arch::memory::allocate_frame;
|
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::paging::temporary_page::TemporaryPage;
|
||||||
use arch::start::usermode;
|
use arch::start::usermode;
|
||||||
use context;
|
use context;
|
||||||
|
use context::memory::Grant;
|
||||||
use elf::{self, program_header};
|
use elf::{self, program_header};
|
||||||
use scheme;
|
use scheme;
|
||||||
use syscall;
|
use syscall;
|
||||||
use syscall::error::*;
|
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};
|
use syscall::validate::{validate_slice, validate_slice_mut};
|
||||||
|
|
||||||
pub fn brk(address: usize) -> Result<usize> {
|
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> {
|
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 ppid;
|
||||||
let pid;
|
let pid;
|
||||||
{
|
{
|
||||||
|
@ -500,6 +493,83 @@ pub fn iopl(_level: usize) -> Result<usize> {
|
||||||
Ok(0)
|
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> {
|
pub fn sched_yield() -> Result<usize> {
|
||||||
unsafe { context::switch(); }
|
unsafe { context::switch(); }
|
||||||
Ok(0)
|
Ok(0)
|
||||||
|
|
|
@ -14,14 +14,17 @@ pub const CLONE_SUPERVISE: usize = 0x400000;
|
||||||
pub const CLOCK_REALTIME: usize = 1;
|
pub const CLOCK_REALTIME: usize = 1;
|
||||||
pub const CLOCK_MONOTONIC: usize = 4;
|
pub const CLOCK_MONOTONIC: usize = 4;
|
||||||
|
|
||||||
pub const MODE_DIR: u16 = 0x4000;
|
|
||||||
pub const MODE_FILE: u16 = 0x8000;
|
|
||||||
pub const MODE_ALL: u16 = MODE_DIR | MODE_FILE;
|
|
||||||
|
|
||||||
pub const FUTEX_WAIT: usize = 0;
|
pub const FUTEX_WAIT: usize = 0;
|
||||||
pub const FUTEX_WAKE: usize = 1;
|
pub const FUTEX_WAKE: usize = 1;
|
||||||
pub const FUTEX_REQUEUE: usize = 2;
|
pub const FUTEX_REQUEUE: usize = 2;
|
||||||
|
|
||||||
|
pub const MAP_WRITE: usize = 1;
|
||||||
|
pub const MAP_WRITE_COMBINE: usize = 2;
|
||||||
|
|
||||||
|
pub const MODE_DIR: u16 = 0x4000;
|
||||||
|
pub const MODE_FILE: u16 = 0x8000;
|
||||||
|
pub const MODE_ALL: u16 = MODE_DIR | MODE_FILE;
|
||||||
|
|
||||||
pub const SEEK_SET: usize = 0;
|
pub const SEEK_SET: usize = 0;
|
||||||
pub const SEEK_CUR: usize = 1;
|
pub const SEEK_CUR: usize = 1;
|
||||||
pub const SEEK_END: usize = 2;
|
pub const SEEK_END: usize = 2;
|
||||||
|
|
|
@ -110,6 +110,14 @@ pub fn open(path: &str, flags: usize) -> Result<usize> {
|
||||||
unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) }
|
unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
|
||||||
|
syscall3(SYS_PHYSMAP, physical_address, size, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
|
||||||
|
syscall1(SYS_PHYSUNMAP, virtual_address)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
|
pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
|
||||||
unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
|
unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ pub const SYS_LSEEK: usize = 19;
|
||||||
pub const SYS_MKDIR: usize = 39;
|
pub const SYS_MKDIR: usize = 39;
|
||||||
pub const SYS_NANOSLEEP: usize = 162;
|
pub const SYS_NANOSLEEP: usize = 162;
|
||||||
pub const SYS_OPEN: usize = 5;
|
pub const SYS_OPEN: usize = 5;
|
||||||
|
pub const SYS_PHYSMAP: usize = 945;
|
||||||
|
pub const SYS_PHYSUNMAP: usize = 946;
|
||||||
pub const SYS_PIPE2: usize = 331;
|
pub const SYS_PIPE2: usize = 331;
|
||||||
pub const SYS_READ: usize = 3;
|
pub const SYS_READ: usize = 3;
|
||||||
pub const SYS_RMDIR: usize = 84;
|
pub const SYS_RMDIR: usize = 84;
|
||||||
|
|
Loading…
Reference in a new issue