diff --git a/os/src/gui/graphic.rs b/os/src/gui/graphic.rs index d13ad61..4c18a26 100644 --- a/os/src/gui/graphic.rs +++ b/os/src/gui/graphic.rs @@ -27,6 +27,10 @@ impl Graphics { let fb = self.drv.get_framebuffer(); fb.fill(0u8); } + + pub fn get_framebuffer(&self)-> &mut [u8] { + self.drv.get_framebuffer() + } } impl OriginDimensions for Graphics { diff --git a/os/src/mm/address.rs b/os/src/mm/address.rs index cf147a0..8792f62 100644 --- a/os/src/mm/address.rs +++ b/os/src/mm/address.rs @@ -260,3 +260,4 @@ where } } pub type VPNRange = SimpleRange; +pub type PPNRange = SimpleRange; diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 1ecfe99..a280379 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -18,6 +18,9 @@ impl FrameTracker { } Self { ppn } } + pub fn new_nowrite(ppn: PhysPageNum) -> Self { + Self { ppn } + } } impl Debug for FrameTracker { diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 663b68d..8875617 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -1,7 +1,7 @@ use super::{frame_alloc, FrameTracker}; use super::{PTEFlags, PageTable, PageTableEntry}; use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; -use super::{StepByOne, VPNRange}; +use super::{StepByOne, VPNRange, PPNRange}; use crate::config::{MEMORY_END, MMIO, PAGE_SIZE, TRAMPOLINE}; use crate::sync::UPIntrFreeCell; use alloc::collections::BTreeMap; @@ -78,6 +78,10 @@ impl MemorySet { } self.areas.push(map_area); } + pub fn push_noalloc(&mut self, mut map_area: MapArea, ppn_range: PPNRange) { + map_area.map_noalloc(&mut self.page_table, ppn_range); + self.areas.push(map_area); + } /// Mention that trampoline is not collected by areas. fn map_trampoline(&mut self) { self.page_table.map( @@ -301,6 +305,14 @@ impl MapArea { self.map_one(page_table, vpn); } } + pub fn map_noalloc(&mut self, page_table: &mut PageTable,ppn_range:PPNRange) { + for (vpn,ppn) in core::iter::zip(self.vpn_range,ppn_range) { + self.data_frames.insert(vpn, FrameTracker::new_nowrite(ppn)); + let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap(); + page_table.map(vpn, ppn, pte_flags); + } + } + pub fn unmap(&mut self, page_table: &mut PageTable) { for vpn in self.vpn_range { self.unmap_one(page_table, vpn); diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 34220c4..9482a30 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -4,11 +4,11 @@ mod heap_allocator; mod memory_set; mod page_table; -use address::VPNRange; +pub use address::{VPNRange, PPNRange}; pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum}; pub use frame_allocator::{frame_alloc, frame_dealloc, FrameTracker}; pub use memory_set::remap_test; -pub use memory_set::{kernel_token, MapPermission, MemorySet, KERNEL_SPACE}; +pub use memory_set::{kernel_token, MapPermission, MemorySet, MapArea, MapType, KERNEL_SPACE}; use page_table::PTEFlags; pub use page_table::{ translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable, diff --git a/os/src/syscall/gui.rs b/os/src/syscall/gui.rs new file mode 100644 index 0000000..0018604 --- /dev/null +++ b/os/src/syscall/gui.rs @@ -0,0 +1,37 @@ +use crate::mm::{MapArea, MapPermission, MapType, PPNRange, PhysAddr}; +use crate::task::current_process; + +//use crate::gui::*; +use crate::drivers::GPU_DEVICE; + +const FB_VADDR: usize = 0x10000000; + +pub fn sys_framebuffer() -> isize { + let gpu = GPU_DEVICE.clone(); + let fb = gpu.get_framebuffer(); + let len = fb.len(); + println!("[kernel] FrameBuffer: addr 0x{:X}, len {}", fb.as_ptr() as usize , len); + let fb_ppn = PhysAddr::from(fb.as_ptr() as usize).floor(); + let fb_end_ppn = PhysAddr::from(fb.as_ptr() as usize + len).ceil(); + + let current_process = current_process(); + let mut inner = current_process.inner_exclusive_access(); + let mem_set = &mut inner.memory_set; + + mem_set.push_noalloc( + MapArea::new( + (FB_VADDR as usize).into(), + (FB_VADDR + len as usize).into(), + MapType::Framed, + MapPermission::R | MapPermission::W | MapPermission::U, + ), + PPNRange::new(fb_ppn, fb_end_ppn), + ); + FB_VADDR as isize +} + +pub fn sys_framebuffer_flush() -> isize { + let gpu = GPU_DEVICE.clone(); + gpu.flush(); + 0 +} \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index fa4a4cf..3f95b94 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -25,16 +25,20 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022; const SYSCALL_CONDVAR_CREATE: usize = 1030; const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; +const SYSCALL_FRAMEBUFFER: usize = 2000; +const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; mod fs; mod process; mod sync; mod thread; +mod gui; use fs::*; use process::*; use sync::*; use thread::*; +use gui::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { @@ -65,6 +69,8 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]), SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]), SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), + SYSCALL_FRAMEBUFFER => sys_framebuffer(), + SYSCALL_FRAMEBUFFER_FLUSH => sys_framebuffer_flush(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/user/Cargo.toml b/user/Cargo.toml index a609f4d..d8d10cc 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } +embedded-graphics = "0.7.1" [profile.release] debug = true diff --git a/user/src/bin/gui_simple.rs b/user/src/bin/gui_simple.rs new file mode 100644 index 0000000..df4cfbb --- /dev/null +++ b/user/src/bin/gui_simple.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +use user_lib::{framebuffer, framebuffer_flush}; + +#[macro_use] +extern crate user_lib; + +// use embedded_graphics::pixelcolor::Rgb888; +// use embedded_graphics::prelude::{Drawable, Point, RgbColor, Size}; +// use embedded_graphics::primitives::Primitive; +// use embedded_graphics::primitives::{PrimitiveStyle, Rectangle}; +// use embedded_graphics::{ +// draw_target::DrawTarget, +// prelude::{OriginDimensions}, +// }; +pub const VIRTGPU_XRES: usize = 1280; +pub const VIRTGPU_YRES: usize = 800; + +#[no_mangle] +pub fn main() -> i32 { + let fb_ptr =framebuffer() as *mut u8; + println!("Hello world from user mode program! 0x{:X} , len {}", fb_ptr as usize, VIRTGPU_XRES*VIRTGPU_YRES*4); + let fb= unsafe {core::slice::from_raw_parts_mut(fb_ptr as *mut u8, VIRTGPU_XRES*VIRTGPU_YRES*4 as usize)}; + for y in 0..800 { + for x in 0..1280 { + let idx = (y * 1280 + x) * 4; + fb[idx] = x as u8; + fb[idx + 1] = y as u8; + fb[idx + 2] = (x + y) as u8; + } + } + framebuffer_flush(); + 0 +} diff --git a/user/src/lib.rs b/user/src/lib.rs index 729eaef..16d4abd 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -198,6 +198,12 @@ pub fn condvar_signal(condvar_id: usize) { pub fn condvar_wait(condvar_id: usize, mutex_id: usize) { sys_condvar_wait(condvar_id, mutex_id); } +pub fn framebuffer() -> isize { + sys_framebuffer() +} +pub fn framebuffer_flush() -> isize { + sys_framebuffer_flush() +} #[macro_export] macro_rules! vstore { diff --git a/user/src/syscall.rs b/user/src/syscall.rs index b4bb67a..330388c 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -25,6 +25,8 @@ const SYSCALL_SEMAPHORE_DOWN: usize = 1022; const SYSCALL_CONDVAR_CREATE: usize = 1030; const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; +const SYSCALL_FRAMEBUFFER: usize = 2000; +const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -154,3 +156,12 @@ pub fn sys_condvar_signal(condvar_id: usize) -> isize { pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize { syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0]) } + + +pub fn sys_framebuffer() -> isize { + syscall(SYSCALL_FRAMEBUFFER, [0, 0, 0]) +} + +pub fn sys_framebuffer_flush() -> isize { + syscall(SYSCALL_FRAMEBUFFER_FLUSH, [0, 0, 0]) +} \ No newline at end of file