Skip to content
Snippets Groups Projects
Commit ef189114 authored by Eemeli Lehtonen's avatar Eemeli Lehtonen
Browse files

vga println

parent f6ad75b6
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,47 @@ ...@@ -2,6 +2,47 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "hyperion" name = "hyperion"
version = "0.1.0" version = "0.1.0"
dependencies = [
"spin",
"volatile",
]
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "spin"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
dependencies = [
"lock_api",
]
[[package]]
name = "volatile"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ca98349dda8a60ae74e04fd90c7fb4d6a4fbe01e6d3be095478aa0b76f6c0c"
...@@ -9,3 +9,6 @@ edition = "2021" ...@@ -9,3 +9,6 @@ edition = "2021"
crate-type = ["staticlib"] crate-type = ["staticlib"]
[dependencies] [dependencies]
spin = "0.9.4"
volatile = "0.4.5"
#tracing = { version = "0.1.37", default-features = false }
...@@ -57,17 +57,17 @@ start: ...@@ -57,17 +57,17 @@ start:
error: error:
;; print 'ERR: <err>' ;; print 'ERR: <err>'
mov dword [0xb8000], 0x4f524f45 mov dword [0xb8000], 0x4F524F45
mov dword [0xb8004], 0x4f3a4f52 mov dword [0xb8004], 0x4F3A4F52
mov dword [0xb8008], 0x4f204f20 mov dword [0xb8008], 0x4F204F20
mov byte [0xb800a], al mov byte [0xb800a], al
jmp halt jmp halt
halt: halt:
;; print ZZZ ;; print ZZZ
mov word [0xb8f00], 0x0f5a mov word [0xb8f00], 0x0F5A
mov word [0xb8f02], 0x0f5a mov word [0xb8f02], 0x0F5A
mov word [0xb8f04], 0x0f5a mov word [0xb8f04], 0x0F5A
hlt hlt
jmp halt jmp halt
...@@ -199,8 +199,9 @@ long_mode_start: ...@@ -199,8 +199,9 @@ long_mode_start:
mov gs, ax mov gs, ax
; print 'OK' ; print 'OK'
mov dword [0xb8000], 0x2f4b2f4f mov dword [0xb8000], 0x2F4B2F4F
mov rdi, 42
call kernel_main call kernel_main
.halt: .halt:
hlt hlt
......
#![no_std] #![no_std]
#![no_main] #![no_main]
pub mod vga;
#[panic_handler] #[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! { fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {} loop {}
...@@ -8,10 +10,10 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! { ...@@ -8,10 +10,10 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
#[no_mangle] #[no_mangle]
#[link_section = ".boot"] #[link_section = ".boot"]
pub extern "C" fn kernel_main() -> ! { pub extern "C" fn kernel_main(magic_num: u64) -> ! {
unsafe { // null byte clears the VGA buffer
*(0xB8000 as *mut u32) = 0x4f524f45; print!("\0");
} println!("Hello from Hyperion, magic_num = {magic_num}");
loop { loop {
unsafe { unsafe {
......
use core::{
fmt::{Arguments, Write},
ops::{Deref, DerefMut},
};
use spin::{Mutex, MutexGuard};
use volatile::Volatile;
//
#[macro_export]
macro_rules! println {
() => {
println!("");
};
($($arg:tt)*) => {
$crate::vga::_println(format_args!($($arg)*))
}
}
#[macro_export]
macro_rules! print {
() => {
print!("");
};
($($arg:tt)*) => {
$crate::vga::_print(format_args!($($arg)*))
};
}
//
pub struct Writer {
cursor: [usize; 2],
color: ColorCode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(C)]
pub enum Color {
#[default]
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGrey = 7,
DarkGrey = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct ColorCode(u8);
//
impl Writer {
pub fn lock() -> MutexGuard<'static, Self> {
WRITER.lock()
}
pub fn write_str(&mut self, s: &str) {
for byte in s.bytes() {
self.write_byte(byte);
}
}
pub fn write_char(&mut self, c: char) {
self.write_str(c.encode_utf8(&mut [0; 4]))
}
pub fn write_byte(&mut self, byte: u8) {
match byte {
// 'special' ascii chars
b'\r' => self.cursor[0] = 0,
b'\n' => self.new_line(),
b'\0' => self.clear(),
// 'normal' ascii chars
byte => {
// line wrapping
if self.cursor[0] >= WIDTH {
self.new_line();
}
// insert the byte
self.set_char(
self.cursor,
Char {
byte,
color: self.color,
},
);
// move the cursor
self.cursor[0] += 1;
}
}
}
pub fn clear(&mut self) {
self.cursor = [0, 0];
for row in 0..HEIGHT {
self.clear_row(row);
}
}
/// SAFETY: Only one [`Writer`] should ever exist
const unsafe fn new() -> Self {
Self {
cursor: [0, 0],
color: ColorCode::new(Color::White, Color::Black),
}
}
fn buffer(&self) -> &'static [[Volatile<Char>; WIDTH]; HEIGHT] {
// SAFETY: Only one [`Writer`] should ever exist
// then multiple immutable refs are allowed
unsafe { &*(0xB8000 as *const _) }
}
fn buffer_mut(&mut self) -> &'static mut [[Volatile<Char>; WIDTH]; HEIGHT] {
// SAFETY: Only one [`Writer`] should ever exist
// then one mutable ref is allowed
unsafe { &mut *(0xB8000 as *mut _) }
}
fn new_line(&mut self) {
if self.cursor[1] + 1 >= HEIGHT {
// move all rows upwards
for row in 0..HEIGHT - 1 {
for col in 0..WIDTH {
self.set_char([col, row], self.get_char([col, row + 1]));
}
}
} else {
// next row
self.cursor[1] += 1;
}
self.clear_row(HEIGHT - 1);
self.cursor[0] = 0;
}
fn clear_row(&mut self, row: usize) {
self.fill_row(
row,
Char {
byte: b' ',
color: ColorCode::default(),
},
)
}
fn fill_row(&mut self, row: usize, fill: Char) {
for col in 0..WIDTH {
self.set_char([col, row], fill);
}
}
fn get_char(&self, cursor: [usize; 2]) -> Char {
self.buffer()[cursor[1]][cursor[0]].read()
}
fn set_char(&mut self, cursor: [usize; 2], ch: Char) {
self.buffer_mut()[cursor[1]][cursor[0]].write(ch);
}
}
impl ColorCode {
pub const fn new(fg: Color, bg: Color) -> ColorCode {
ColorCode((bg as u8) << 4 | (fg as u8))
}
}
impl Default for ColorCode {
fn default() -> Self {
Self::new(Color::White, Color::Black)
}
}
//
const WIDTH: usize = 80;
const HEIGHT: usize = 25;
//
/// SAFETY: safe, because this is the only Writer
static WRITER: Mutex<Writer> = Mutex::new(unsafe { Writer::new() });
//
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
struct Char {
// ascii
byte: u8,
// foreground and background
color: ColorCode,
}
//
impl Write for Writer {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write_str(s);
Ok(())
}
}
impl Deref for Char {
type Target = Self;
fn deref(&self) -> &Self::Target {
self
}
}
impl DerefMut for Char {
fn deref_mut(&mut self) -> &mut Self::Target {
self
}
}
//
#[doc(hidden)]
pub fn _print(args: Arguments) {
let mut writer = WRITER.lock();
writer.write_fmt(args).unwrap();
}
#[doc(hidden)]
pub fn _println(args: Arguments) {
let mut writer = WRITER.lock();
writer.write_fmt(args).unwrap();
writer.write_byte(b'\n');
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment