Skip to content

VESA video mode - 800x600x16bit #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target/
**/*.rs.bk
*.swp
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ llvm-tools = "0.1"
[features]
default = []
vga_320x200 = []
vesa_800x600 = []
recursive_page_table = []
map_physical_memory = []

Expand Down
7 changes: 6 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ global_asm!(include_str!("stage_2.s"));
global_asm!(include_str!("e820.s"));
global_asm!(include_str!("stage_3.s"));

#[cfg(feature = "vesa_800x600")]
global_asm!(include_str!("video_mode/vesa_800x600.s"));
#[cfg(feature = "vga_320x200")]
global_asm!(include_str!("video_mode/vga_320x200.s"));
#[cfg(not(feature = "vga_320x200"))]
#[cfg(not(any(feature = "vesa_800x600", feature = "vga_320x200")))]
global_asm!(include_str!("video_mode/vga_text_80x25.s"));

unsafe fn context_switch(boot_info: VirtAddr, entry_point: VirtAddr, stack_pointer: VirtAddr) -> ! {
Expand Down Expand Up @@ -91,6 +93,7 @@ pub unsafe extern "C" fn stage_4() -> ! {
let bootloader_start = &__bootloader_start as *const _ as u64;
let bootloader_end = &__bootloader_end as *const _ as u64;


load_elf(
IdentityMappedAddr(PhysAddr::new(kernel_start)),
kernel_size,
Expand Down Expand Up @@ -290,6 +293,8 @@ fn load_elf(

let entry_point = VirtAddr::new(entry_point);

panic!("Test");

unsafe { context_switch(boot_info_addr, entry_point, stack_end) };
}

Expand Down
12 changes: 8 additions & 4 deletions src/printer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#[cfg(not(feature = "vga_320x200"))]
pub use self::vga_text_80x25::*;

#[cfg(feature = "vga_320x200")]
pub use self::vga_320x200::*;

mod vga_320x200;
#[cfg(feature = "vesa_800x600")]
pub use self::vesa_800x600::*;

#[cfg(not(any(feature = "vesa_800x600", feature = "vga_320x200")))]
pub use self::vga_text_80x25::*;

mod vga_text_80x25;
mod vga_320x200;
mod vesa_800x600;
81 changes: 81 additions & 0 deletions src/printer/vesa_800x600.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use core::fmt::{Result, Write};
use core::slice;
use core::sync::atomic::{AtomicUsize, Ordering};

const VGA_BUFFER: *mut u16 = (500 * 512 * 4096) as *mut _;
const SCREEN_WIDTH: usize = 800;
const SCREEN_HEIGHT: usize = 600;

pub static X_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section
pub static Y_POS: AtomicUsize = AtomicUsize::new(1); // must not be 0 so that we don't have a .bss section

pub struct Printer;

impl Printer {
pub fn clear_screen(&mut self) {
let vga_buffer = Self::vga_buffer();
for pixel in vga_buffer {
*pixel = 0x66;
}
X_POS.store(0, Ordering::SeqCst);
Y_POS.store(0, Ordering::SeqCst);
}

fn vga_buffer() -> &'static mut [u16] {
unsafe { slice::from_raw_parts_mut(VGA_BUFFER, SCREEN_WIDTH * SCREEN_HEIGHT) }
}

fn newline(&mut self) {
let y_pos = Y_POS.fetch_add(8, Ordering::SeqCst);
X_POS.store(0, Ordering::SeqCst);
if y_pos >= SCREEN_HEIGHT {
self.clear_screen();
}
}

fn write_char(&mut self, c: char) {
use font8x8::UnicodeFonts;

if c == '\n' {
self.newline();
return;
}

let vga_buffer = Self::vga_buffer();

let x_pos = X_POS.fetch_add(8, Ordering::SeqCst);
let y_pos = Y_POS.load(Ordering::SeqCst);

match c {
' '..='~' => {
let rendered = font8x8::BASIC_FONTS
.get(c)
.expect("character not found in basic font");
for (y, byte) in rendered.iter().enumerate() {
for (x, bit) in (0..8).enumerate() {
if *byte & (1 << bit) == 0 {
continue;
}
let color = 0xff;
vga_buffer[(y_pos + y) * SCREEN_WIDTH + x_pos + x] = color;
}
}
}
_ => panic!("unprintable character"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please dont panic in this case. Maybe print ? or something like that.

Copy link

@adeadman adeadman Aug 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.
I realise this code doesn't actually contain a Mutex lock on the writer, so my previous comment is misguided, but generally yes - a substitute character is probably the way to go.

}

if x_pos + 8 >= SCREEN_WIDTH {
self.newline();
}
}
}

impl Write for Printer {
fn write_str(&mut self, s: &str) -> Result {
for c in s.chars() {
self.write_char(c);
}

Ok(())
}
}
1 change: 0 additions & 1 deletion src/stage_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ enable_a20:
out 0x92, al
enable_a20_after:


enter_protected_mode:
# clear interrupts
cli
Expand Down
60 changes: 60 additions & 0 deletions src/video_mode/vesa_800x600.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.section .boot, "awx"
.intel_syntax noprefix
.code16

# This code is responsible for enabling VESA graphics while in
# real mode.
config_video_mode:
# Try VESA
mov ax, 0x9000
mov es, ax
mov di, 0
mov ax, 0x4f00
int 0x10
cmp ax, 0x004f
jne vesa_out
# Check VESA version 2 or 3
mov ax, es:[di+4]
cmp ax, 0x0300
je init_vesa
cmp ax, 0x0200
jne vesa_out
# Hard coded 800x600x16bit mode; this gets us the PHY-addr of the FB
init_vesa:
mov ax, 0x4f01
mov cx, 0x114
mov di, VESAInfo
int 0x10
mov VESAfb, [es:di+0x28]

mov ax, 0x4f02
mov bx, 0x4114
int 0x10

vesa_out:
ret

vga_println:
ret

.code32

vga_map_frame_buffer:
mov eax, 0xFD000000
or eax, (1 | 2 | (1 << 7))
mov ecx, 500
vga_map_frame_buffer_loop:
mov [_p2 + ecx * 8], eax

add eax, 4096 * 512
add ecx, 1
cmp eax, 0xFD000000 + 800 * 600
jl vga_map_frame_buffer_loop

ret

VESAfb:
.word 0

VESAInfo:
.space 256, 0