fix VGA color on x86_64

master
WangRunji 6 years ago
parent e70cac58c8
commit a3edd38046

35
kernel/Cargo.lock generated

@ -137,6 +137,14 @@ name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "getopts"
version = "0.2.18"
@ -145,6 +153,23 @@ dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hash32"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "heapless"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hash32 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.3.0"
@ -266,6 +291,7 @@ dependencies = [
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
"console-traits 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"device_tree 1.0.3 (git+https://github.com/jiegec/device_tree-rs)",
"heapless 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -423,6 +449,11 @@ name = "tock-registers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uart_16550"
version = "0.1.0"
@ -549,7 +580,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0"
"checksum font8x8 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b81d84c3c978af7d05d31a2198af4b9ba956d819d15d8f6d58fc150e33f8dc1f"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum generic-array 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8107dafa78c80c848b71b60133954b4a58609a3a1a5f9af037ecc7f67280f369"
"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
"checksum hash32 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12d790435639c06a7b798af9e1e331ae245b7ef915b92f70a39b4cf8c00686af"
"checksum heapless 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "56b960caff1a46f1fb3c1eb05f0575ac21c6248364ebebde11b11116e099881c"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
"checksum linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "655d57c71827fe0891ce72231b6aa5e14033dae3f604609e6a6f807267c1678d"
@ -581,6 +615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5"

@ -45,6 +45,7 @@ xmas-elf = "0.6"
bitflags = "1.0"
bit_field = "0.9"
volatile = "0.2"
heapless = "0.4"
console-traits = "0.3"
linked_list_allocator = "0.6"
device_tree = { git = "https://github.com/jiegec/device_tree-rs" }

@ -207,7 +207,7 @@ debug: $(kernel) $(bin)
build: $(bin)
asm:
@$(objdump) -dS $(kernel) | less
@$(objdump) -d $(kernel) | less
header:
@$(objdump) -h $(kernel)

@ -1,7 +1,9 @@
//! Frambuffer color
use crate::util::color::ConsoleColor;
pub trait FramebufferColor {
/// pack as 32-bit integer
/// pack as 16-bit integer
fn pack16(&self) -> u16;
/// pack as 32-bit integer
@ -12,34 +14,12 @@ pub trait FramebufferColor {
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RgbColor(u8, u8, u8);
#[repr(u8)]
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ConsoleColor {
Black = 0,
Red = 1,
Green = 2,
Yellow = 3,
Blue = 4,
Magenta = 5,
Cyan = 6,
White = 7,
BrightBlack = 60,
BrightRed = 61,
BrightGreen = 62,
BrightYellow = 63,
BrightBlue = 64,
BrightMagenta = 65,
BrightCyan = 66,
BrightWhite = 67,
}
use self::ConsoleColor::*;
impl From<ConsoleColor> for RgbColor {
/// Convert `ConsoleColor` to `RgbColor`.
/// use `CMD` color scheme.
/// (ref: https://en.wikipedia.org/wiki/ANSI_escape_code)
fn from(color: ConsoleColor) -> Self {
use self::ConsoleColor::*;
match color {
Black => RgbColor(0, 0, 0),
Red => RgbColor(128, 0, 0),

@ -1,21 +1,23 @@
//! Framebuffer console display driver for ARM64
mod color;
mod escape_parser;
mod fonts;
use self::color::FramebufferColor;
use self::escape_parser::{CharacterAttribute, EscapeParser};
use self::fonts::{Font, Font8x16};
use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER};
use alloc::vec::Vec;
use core::fmt;
use core::marker::PhantomData;
use lazy_static::lazy_static;
use log::*;
use spin::Mutex;
use crate::util::escape_parser::{CharacterAttribute, EscapeParser};
use super::fb::{ColorDepth::*, FRAME_BUFFER, FramebufferInfo};
use self::color::FramebufferColor;
use self::fonts::{Font, Font8x16};
mod color;
mod fonts;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ConsoleChar {

@ -8,6 +8,7 @@ pub mod consts;
pub mod cpu;
pub mod driver;
pub mod timer;
pub mod syscall;
#[cfg(feature = "board_raspi3")]
#[path = "board/raspi3/mod.rs"]

@ -0,0 +1,4 @@
pub fn translate(id: usize) -> usize {
// FIXME: translate syscall id on aarch64
id
}

@ -1,18 +1,45 @@
use core::fmt;
use console_traits::*;
use lazy_static::lazy_static;
use spin::Mutex;
use volatile::Volatile;
use lazy_static::lazy_static;
use x86_64::instructions::port::Port;
use crate::logging::Color;
use crate::consts::KERNEL_OFFSET;
use console_traits::*;
use crate::util::color::ConsoleColor;
use crate::util::escape_parser::EscapeParser;
#[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))
fn new(foreground: ConsoleColor, background: ConsoleColor) -> ColorCode {
ColorCode(background.to_code() << 4 | foreground.to_code())
}
}
impl ConsoleColor {
fn to_code(&self) -> u8 {
use self::ConsoleColor::*;
match self {
Black => 0,
Blue => 1,
Green => 2,
Cyan => 3,
Red => 4,
Magenta => 5,
Yellow => 6,
White => 7,
BrightBlack => 8,
BrightBlue => 9,
BrightGreen => 10,
BrightCyan => 11,
BrightRed => 12,
BrightMagenta => 13,
BrightYellow => 14,
BrightWhite => 15,
}
}
}
@ -24,7 +51,7 @@ pub struct ScreenChar {
}
impl ScreenChar {
pub const fn new(ascii_char: u8, foreground_color: Color, background_color: Color) -> Self {
pub fn new(ascii_char: u8, foreground_color: ConsoleColor, background_color: ConsoleColor) -> Self {
ScreenChar {
ascii_char,
color_code: ColorCode::new(foreground_color, background_color)
@ -41,7 +68,7 @@ pub struct VgaBuffer {
impl VgaBuffer {
pub fn clear(&mut self) {
let blank = ScreenChar::new(b' ', Color::LightGray, Color::Black);
let blank = ScreenChar::new(b' ', ConsoleColor::White, ConsoleColor::Black);
for row in 0 .. BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
self.chars[row][col].write(blank);
@ -76,9 +103,10 @@ lazy_static! {
pub struct VgaWriter {
pos: Position,
color: Color,
color_code: ColorCode,
ctrl_char_mode: ControlCharMode,
esc_char_mode: EscapeCharMode,
escape_parser: EscapeParser,
buffer: &'static mut VgaBuffer,
}
@ -105,6 +133,7 @@ impl BaseConsole for VgaWriter {
fn set_pos(&mut self, pos: Position) -> Result<(), Self::Error> {
self.pos = pos;
self.buffer.set_cursor_at(pos.row.0 as usize, pos.col.0 as usize);
Ok(())
}
@ -135,24 +164,35 @@ impl BaseConsole for VgaWriter {
self.buffer.write(row - 1, col, screen_char);
}
}
let blank = ScreenChar::new(b' ', self.color, Color::Black);
let blank = ScreenChar::new(b' ', ConsoleColor::White, ConsoleColor::Black);
for col in 0..BUFFER_WIDTH {
self.buffer.write(BUFFER_HEIGHT - 1, col, blank);
}
self.buffer.set_cursor_at(BUFFER_HEIGHT - 1, 0);
Ok(())
}
}
impl AsciiConsole for VgaWriter {
fn write_char_at(&mut self, ch: u8, pos: Position) -> Result<(), Self::Error> {
self.buffer.write(pos.row.0 as usize, pos.col.0 as usize, ScreenChar::new(ch, self.color, Color::Black));
self.buffer.set_cursor_at(pos.row.0 as usize, pos.col.0 as usize);
let screen_char = ScreenChar {
ascii_char: ch,
color_code: self.color_code,
};
self.buffer.write(pos.row.0 as usize, pos.col.0 as usize, screen_char);
Ok(())
}
fn handle_escape(&mut self, escaped_char: u8) -> bool {
true
if escaped_char == b'[' {
self.escape_parser.start_parse();
}
self.escape_parser.parse(escaped_char);
let end = escaped_char == b'm';
if end {
let attr = self.escape_parser.char_attribute();
self.color_code = ColorCode::new(attr.foreground, attr.background);
}
end
}
}
@ -161,16 +201,13 @@ impl VgaWriter {
buffer.clear();
VgaWriter {
pos: Position::origin(),
color: Color::LightGray,
color_code: ColorCode::new(ConsoleColor::White, ConsoleColor::Black),
ctrl_char_mode: ControlCharMode::Interpret,
esc_char_mode: EscapeCharMode::Waiting,
escape_parser: EscapeParser::new(),
buffer,
}
}
pub fn set_color(&mut self, color: Color) {
self.color = color;
}
}
impl fmt::Write for VgaWriter {

@ -1,10 +1,13 @@
use core::fmt;
use lazy_static::lazy_static;
use log::{self, Level, LevelFilter, Log, Metadata, Record};
use crate::sync::SpinNoIrqLock as Mutex;
use lazy_static::lazy_static;
use crate::util::color::ConsoleColor;
lazy_static! {
static ref log_mutex: Mutex<()> = Mutex::new(());
static ref LOG_LOCK: Mutex<()> = Mutex::new(());
}
pub fn init() {
@ -37,20 +40,20 @@ macro_rules! println {
/// Add escape sequence to print with color in Linux console
macro_rules! with_color {
($args: ident, $color: ident) => {{
let (show, code) = color_to_console_code($color);
format_args!("\u{1B}[{};{}m{}\u{1B}[0m", show.clone(), code + 30, $args)
let code = $color.to_console_code();
format_args!("\u{1B}[{}m{}\u{1B}[0m", code as u8, $args)
}};
}
fn print_in_color(args: fmt::Arguments, color: Color) {
fn print_in_color(args: fmt::Arguments, color: ConsoleColor) {
use crate::arch::io;
let _guard = log_mutex.lock();
let _guard = LOG_LOCK.lock();
io::putfmt(with_color!(args, color));
}
pub fn print(args: fmt::Arguments) {
use crate::arch::io;
let _guard = log_mutex.lock();
let _guard = LOG_LOCK.lock();
io::putfmt(args);
}
@ -66,63 +69,20 @@ impl Log for SimpleLogger {
if self.enabled(record.metadata()) && !DISABLED_TARGET.contains(&record.target()) {
// let target = record.target();
// let begin = target.as_bytes().iter().rposition(|&c| c == b':').map(|i| i + 1).unwrap_or(0);
print_in_color(format_args!("[{:>5}] {}\n", record.level(), record.args()), Color::from(record.level()));
print_in_color(format_args!("[{:>5}] {}\n", record.level(), record.args()), ConsoleColor::from(record.level()));
}
}
fn flush(&self) {}
}
impl From<Level> for Color {
impl From<Level> for ConsoleColor {
fn from(level: Level) -> Self {
match level {
Level::Error => Color::Red,
Level::Warn => Color::Yellow,
Level::Info => Color::Blue,
Level::Debug => Color::Green,
Level::Trace => Color::DarkGray,
Level::Error => ConsoleColor::Red,
Level::Warn => ConsoleColor::Yellow,
Level::Info => ConsoleColor::Blue,
Level::Debug => ConsoleColor::Green,
Level::Trace => ConsoleColor::BrightBlack,
}
}
}
fn color_to_console_code(color: Color) -> (u8, u8) {
match color {
Color::Black => (0, 0),
Color::Blue => (0, 4),
Color::Green => (0, 2),
Color::Cyan => (0, 6),
Color::Red => (0, 1),
Color::Magenta => (0, 5),
Color::Brown => (0, 3),
Color::LightGray => (1, 7),
Color::DarkGray => (0, 7),
Color::LightBlue => (1, 4),
Color::LightGreen => (1, 2),
Color::LightCyan => (1, 6),
Color::LightRed => (1, 1),
Color::Pink => (1, 5),
Color::Yellow => (1, 3),
Color::White => (1, 0),
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[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,
}

@ -301,6 +301,7 @@ pub enum SysError {
#[allow(non_snake_case)]
impl fmt::Display for SysError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::SysError::*;
write!(f, "{}",
match self {
EPERM => "Operation not permitted",

@ -0,0 +1,65 @@
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ConsoleColor {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BrightBlack,
BrightRed,
BrightGreen,
BrightYellow,
BrightBlue,
BrightMagenta,
BrightCyan,
BrightWhite,
}
impl ConsoleColor {
pub fn to_console_code(&self) -> u8 {
use self::ConsoleColor::*;
match self {
Black => 30,
Red => 31,
Green => 32,
Yellow => 33,
Blue => 34,
Magenta => 35,
Cyan => 36,
White => 37,
BrightBlack => 90,
BrightRed => 91,
BrightGreen => 92,
BrightYellow => 93,
BrightBlue => 94,
BrightMagenta => 95,
BrightCyan => 96,
BrightWhite => 97,
}
}
pub fn from_console_code(code: u8) -> Option<ConsoleColor> {
use self::ConsoleColor::*;
match code {
30 => Some(Black),
31 => Some(Red),
32 => Some(Green),
33 => Some(Yellow),
34 => Some(Blue),
35 => Some(Magenta),
36 => Some(Cyan),
37 => Some(White),
90 => Some(BrightBlack),
91 => Some(BrightRed),
92 => Some(BrightGreen),
93 => Some(BrightYellow),
94 => Some(BrightBlue),
95 => Some(BrightMagenta),
96 => Some(BrightCyan),
97 => Some(BrightWhite),
_ => None,
}
}
}

@ -1,16 +1,17 @@
//! ANSI escape sequences parser
//! (ref: https://en.wikipedia.org/wiki/ANSI_escape_code)
use super::color::{ConsoleColor, ConsoleColor::*, FramebufferColor};
use alloc::vec::Vec;
use heapless::Vec;
use heapless::consts::U8;
use super::color::ConsoleColor;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CharacterAttribute<C: FramebufferColor = ConsoleColor> {
pub struct CharacterAttribute {
/// foreground color
pub foreground: C,
pub foreground: ConsoleColor,
/// background color
pub background: C,
pub background: ConsoleColor,
/// show underline
pub underline: bool,
/// swap foreground and background colors
@ -22,8 +23,8 @@ pub struct CharacterAttribute<C: FramebufferColor = ConsoleColor> {
impl Default for CharacterAttribute {
fn default() -> Self {
CharacterAttribute {
foreground: White,
background: Black,
foreground: ConsoleColor::White,
background: ConsoleColor::Black,
underline: false,
reverse: false,
strikethrough: false,
@ -50,7 +51,7 @@ pub struct EscapeParser {
status: ParseStatus,
char_attr: CharacterAttribute,
current_param: Option<u8>,
params: Vec<u8>,
params: Vec<u8, U8>,
}
impl EscapeParser {
@ -69,14 +70,13 @@ impl EscapeParser {
/// See an `ECS` character, start parsing escape sequence.
pub fn start_parse(&mut self) {
assert!(self.status == ParseStatus::Text);
assert_eq!(self.status, ParseStatus::Text);
self.status = ParseStatus::BeginEscapeSequence;
self.current_param = None;
}
//// Parse SGR (Select Graphic Rendition) parameters.
fn parse_sgr_params(&mut self) {
use core::mem::transmute;
for param in &self.params {
match param {
0 => self.char_attr = CharacterAttribute::default(),
@ -86,8 +86,8 @@ impl EscapeParser {
24 => self.char_attr.underline = false,
27 => self.char_attr.reverse = false,
29 => self.char_attr.strikethrough = false,
30...37 | 90...97 => self.char_attr.foreground = unsafe { transmute(param - 30) },
40...47 | 100...107 => self.char_attr.background = unsafe { transmute(param - 40) },
30...37 | 90...97 => self.char_attr.foreground = ConsoleColor::from_console_code(*param).unwrap(),
40...47 | 100...107 => self.char_attr.background = ConsoleColor::from_console_code(*param - 10).unwrap(),
_ => { /* unimplemented!() */ }
}
}
@ -95,7 +95,7 @@ impl EscapeParser {
/// See a character during parsing.
pub fn parse(&mut self, byte: u8) -> bool {
assert!(self.status != ParseStatus::Text);
assert_ne!(self.status, ParseStatus::Text);
match self.status {
ParseStatus::BeginEscapeSequence => match byte {
b'[' => {
@ -117,7 +117,7 @@ impl EscapeParser {
}
b';' => {
if let Some(param) = self.current_param {
self.params.push(param);
self.params.push(param).unwrap();
}
self.current_param = Some(0);
return true;
@ -125,7 +125,7 @@ impl EscapeParser {
// @AZ[\]^_`az{|}~
0x40...0x7E => {
if let Some(param) = self.current_param {
self.params.push(param);
self.params.push(param).unwrap();
}
match byte {
b'm' => self.parse_sgr_params(),

@ -1,3 +1,6 @@
pub mod color;
pub mod escape_parser;
/// Convert C string to Rust string
pub unsafe fn from_cstr(s: *const u8) -> &'static str {
use core::{str, slice};
Loading…
Cancel
Save