vga_buffer code first commit
This commit is contained in:
parent
69299bda2d
commit
4c12c768dc
6 changed files with 191 additions and 36 deletions
|
|
@ -6,7 +6,7 @@ authors = ["Jack Halford <jack@crans.org>", "William Escande <wescande@student.4
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
panic = "abort"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
rlibc = "1.0"
|
||||||
|
spin = "0.4.5"
|
||||||
|
volatile = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
project := bluesnow
|
project := bluesnow
|
||||||
arch ?= x86
|
arch ?= x86
|
||||||
NASM := nasm -f elf
|
NASM := nasm -f elf
|
||||||
LD := ld -m elf_i386 -n
|
LD := ld -m elf_i386 -n --gc-sections
|
||||||
QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait
|
QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait
|
||||||
|
|
||||||
kernel := build/kernel-$(arch).bin
|
kernel := build/kernel-$(arch).bin
|
||||||
|
|
@ -9,7 +9,7 @@ iso := build/os-$(arch).iso
|
||||||
DIRISO := build/isofiles
|
DIRISO := build/isofiles
|
||||||
|
|
||||||
target ?= $(arch)-$(project)
|
target ?= $(arch)-$(project)
|
||||||
rust_os := target/$(target)/release/lib$(project).a
|
rust_os := target/$(target)/debug/lib$(project).a
|
||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
|
||||||
linker_script := src/arch/$(arch)/linker.ld
|
linker_script := src/arch/$(arch)/linker.ld
|
||||||
|
|
@ -42,9 +42,9 @@ clean:
|
||||||
@rm -r build
|
@rm -r build
|
||||||
|
|
||||||
$(rust_os): $(target).json Makefile
|
$(rust_os): $(target).json Makefile
|
||||||
@xargo build --release --target $(target)
|
@RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target)
|
||||||
|
|
||||||
kernel: $(rust_os)
|
kernel: $(rust_os)
|
||||||
iso: $(iso)
|
iso: $(iso)
|
||||||
|
|
||||||
.PHONY: run clean kernel iso
|
.PHONY: run clean kernel iso $(rust_os)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ SECTIONS {
|
||||||
|
|
||||||
.boot : {
|
.boot : {
|
||||||
/* ensure that the multiboot header is at the beginning */
|
/* ensure that the multiboot header is at the beginning */
|
||||||
*(.multiboot_header)
|
KEEP(*(.multiboot_header))
|
||||||
}
|
}
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,39 @@
|
||||||
// #![no_std]
|
|
||||||
// #[cfg(test)]
|
|
||||||
// mod tests {
|
|
||||||
// #[test]
|
|
||||||
// fn it_works() {
|
|
||||||
// assert_eq!(2 + 2, 4);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
#![feature(const_fn)]
|
||||||
|
#![feature(ptr_internals)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[lang = "eh_personality"]
|
extern crate spin;
|
||||||
extern fn eh_personality() {
|
extern crate volatile;
|
||||||
|
extern crate rlibc;
|
||||||
}
|
|
||||||
|
|
||||||
#[lang = "panic_fmt"]
|
|
||||||
extern fn rust_begin_panic() -> ! {
|
|
||||||
loop {}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod vga_buffer;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn kmain() -> ! {
|
pub extern fn kmain() -> ! {
|
||||||
unsafe {
|
vga_buffer::clear_screen();
|
||||||
let vga = 0xb8000 as *mut u32;
|
println!("Kernel startup...");
|
||||||
|
|
||||||
*vga = 0x2f592f412f;
|
loop {
|
||||||
|
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "eh_personality"] #[no_mangle]
|
||||||
|
pub extern fn eh_personality() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "panic_fmt"] #[no_mangle]
|
||||||
|
pub extern fn panic_fmt(
|
||||||
|
fmt: core::fmt::Arguments,
|
||||||
|
file: &'static str,
|
||||||
|
line: u32)
|
||||||
|
-> ! {
|
||||||
|
println!("\n\nPANIC in {} at line {}:", file, line);
|
||||||
|
println!(" {}", fmt);
|
||||||
loop {}
|
loop {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
152
kernel-rs/src/vga_buffer.rs
Normal file
152
kernel-rs/src/vga_buffer.rs
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
// Copyright 2016 Philipp Oppermann. See the README.md
|
||||||
|
// file at the top-level directory of this distribution.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use core::ptr::Unique;
|
||||||
|
use core::fmt;
|
||||||
|
use spin::Mutex;
|
||||||
|
use volatile::Volatile;
|
||||||
|
|
||||||
|
struct Buffer {
|
||||||
|
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
|
}
|
||||||
|
|
||||||
|
const BUFFER_HEIGHT: usize = 25;
|
||||||
|
const BUFFER_WIDTH: usize = 80;
|
||||||
|
|
||||||
|
static mut VGA_BUFFER: Unique<Buffer> = unsafe {
|
||||||
|
Unique::new_unchecked(0xb8000 as *mut _)
|
||||||
|
};
|
||||||
|
|
||||||
|
fn vga_buffer() -> &'static mut Buffer {
|
||||||
|
unsafe { VGA_BUFFER.as_mut() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
|
||||||
|
column_position: 0,
|
||||||
|
color_code: ColorCode::new(Color::LightGreen, Color::Black),
|
||||||
|
});
|
||||||
|
|
||||||
|
macro_rules! println {
|
||||||
|
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||||
|
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! print {
|
||||||
|
($($arg:tt)*) => ({
|
||||||
|
$crate::vga_buffer::print(format_args!($($arg)*));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(args: fmt::Arguments) {
|
||||||
|
use core::fmt::Write;
|
||||||
|
WRITER.lock().write_fmt(args).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_screen() {
|
||||||
|
for _ in 0..BUFFER_HEIGHT {
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Color {
|
||||||
|
Black = 0,
|
||||||
|
Blue = 1,
|
||||||
|
Green = 2,
|
||||||
|
Cyan = 3,
|
||||||
|
Red = 4,
|
||||||
|
Magenta = 5,
|
||||||
|
Brown = 6,
|
||||||
|
LightGray = 7,
|
||||||
|
DarkGray = 8,
|
||||||
|
LightBlue = 9,
|
||||||
|
LightGreen = 10,
|
||||||
|
LightCyan = 11,
|
||||||
|
LightRed = 12,
|
||||||
|
Pink = 13,
|
||||||
|
Yellow = 14,
|
||||||
|
White = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Writer {
|
||||||
|
column_position: usize,
|
||||||
|
color_code: ColorCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writer {
|
||||||
|
pub fn write_byte(&mut self, byte: u8) {
|
||||||
|
match byte {
|
||||||
|
b'\n' => self.new_line(),
|
||||||
|
byte => {
|
||||||
|
if self.column_position >= BUFFER_WIDTH {
|
||||||
|
self.new_line();
|
||||||
|
}
|
||||||
|
let row = BUFFER_HEIGHT - 1;
|
||||||
|
let col = self.column_position;
|
||||||
|
|
||||||
|
let color_code = self.color_code;
|
||||||
|
|
||||||
|
vga_buffer().chars[row][col].write(ScreenChar {
|
||||||
|
ascii_character: byte,
|
||||||
|
color_code: color_code,
|
||||||
|
});
|
||||||
|
self.column_position += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_line(&mut self) {
|
||||||
|
for row in 1..BUFFER_HEIGHT {
|
||||||
|
for col in 0..BUFFER_WIDTH {
|
||||||
|
let buffer = vga_buffer();
|
||||||
|
let character = buffer.chars[row][col].read();
|
||||||
|
buffer.chars[row - 1][col].write(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.clear_row(BUFFER_HEIGHT - 1);
|
||||||
|
self.column_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_row(&mut self, row: usize) {
|
||||||
|
let blank = ScreenChar {
|
||||||
|
ascii_character: b' ',
|
||||||
|
color_code: self.color_code,
|
||||||
|
};
|
||||||
|
for col in 0..BUFFER_WIDTH {
|
||||||
|
vga_buffer().chars[row][col].write(blank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for Writer {
|
||||||
|
fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
|
||||||
|
for byte in s.bytes() {
|
||||||
|
self.write_byte(byte)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct ColorCode(u8);
|
||||||
|
|
||||||
|
impl ColorCode {
|
||||||
|
const fn new(foreground: Color, background: Color) -> ColorCode {
|
||||||
|
ColorCode((background as u8) << 4 | (foreground as u8))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct ScreenChar {
|
||||||
|
ascii_character: u8,
|
||||||
|
color_code: ColorCode,
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,6 @@
|
||||||
"target-pointer-width": "32",
|
"target-pointer-width": "32",
|
||||||
"target-c-int-width": "32",
|
"target-c-int-width": "32",
|
||||||
"features": "-mmx,-fxsr,-sse,-sse2,+soft-float",
|
"features": "-mmx,-fxsr,-sse,-sse2,+soft-float",
|
||||||
"eliminate-frame-pointer": false
|
"eliminate-frame-pointer": false,
|
||||||
|
"panic-strategy": "abort"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue