diff --git a/src/kernel/ata.rs b/src/kernel/ata.rs index 0ef25dac5..ba0eaa9fb 100644 --- a/src/kernel/ata.rs +++ b/src/kernel/ata.rs @@ -1,5 +1,5 @@ use bit_field::BitField; -use crate::{print, kernel}; +use crate::{print, log}; use lazy_static::lazy_static; use alloc::vec::Vec; use alloc::string::String; @@ -260,8 +260,7 @@ pub fn init() { } let sectors = (buf[61] as u32) << 16 | (buf[60] as u32); let (size, unit) = disk_size(sectors); - let uptime = kernel::clock::clock_monotonic(); - print!("[{:.6}] ATA {}:{} {} {} ({} {})\n", uptime, bus, drive, model.trim(), serial.trim(), size, unit); + log!("ATA {}:{} {} {} ({} {})\n", bus, drive, model.trim(), serial.trim(), size, unit); } /* diff --git a/src/kernel/console.rs b/src/kernel/console.rs index 3ec7ea9f3..426ded8e9 100644 --- a/src/kernel/console.rs +++ b/src/kernel/console.rs @@ -27,6 +27,29 @@ macro_rules! print { }); } +#[cfg(feature="vga")] +#[macro_export] +macro_rules! log { + ($($arg:tt)*) => ({ + let uptime = $crate::kernel::clock::clock_monotonic(); + let (fg, bg) = $crate::kernel::vga::color(); + $crate::kernel::vga::set_color($crate::kernel::vga::Color::Green, bg); + $crate::kernel::vga::print_fmt(format_args!("[{:.6}] ", uptime)); + $crate::kernel::vga::set_color(fg, bg); + $crate::kernel::vga::print_fmt(format_args!($($arg)*)); + }); +} + +#[cfg(feature="serial")] +#[macro_export] +macro_rules! log { + ($($arg:tt)*) => ({ + let uptime = $crate::kernel::clock::clock_monotonic(); + $crate::kernel::serial::print_fmt(format_args!("[{:.6}] ", uptime)); + $crate::kernel::serial::print_fmt(format_args!($($arg)*)); + }); +} + pub fn disable_echo() { let mut echo = ECHO.lock(); *echo = false; diff --git a/src/kernel/cpu.rs b/src/kernel/cpu.rs index 4dc69f973..500d1f776 100644 --- a/src/kernel/cpu.rs +++ b/src/kernel/cpu.rs @@ -1,21 +1,21 @@ use raw_cpuid::CpuId; -use crate::{print, kernel}; +use crate::log; pub fn init() { let cpuid = CpuId::new(); if let Some(vendor_info) = cpuid.get_vendor_info() { - print!("[{:.6}] CPU {}\n", kernel::clock::clock_monotonic(), vendor_info); + log!("CPU {}\n", vendor_info); } if let Some(extended_function_info) = cpuid.get_extended_function_info() { if let Some(processor_brand_string) = extended_function_info.processor_brand_string() { - print!("[{:.6}] CPU {}\n", kernel::clock::clock_monotonic(), processor_brand_string); + log!("CPU {}\n", processor_brand_string); } } if let Some(processor_frequency_info) = cpuid.get_processor_frequency_info() { let processor_base_frequency = processor_frequency_info.processor_base_frequency(); - print!("[{:.6}] CPU {} MHz\n", kernel::clock::clock_monotonic(), processor_base_frequency); + log!("CPU {} MHz\n", processor_base_frequency); } } diff --git a/src/kernel/mem.rs b/src/kernel/mem.rs index 060628387..f72300fe9 100644 --- a/src/kernel/mem.rs +++ b/src/kernel/mem.rs @@ -1,5 +1,5 @@ use bootloader::bootinfo::{BootInfo, MemoryMap, MemoryRegionType}; -use crate::{print, kernel}; +use crate::{log, kernel}; use lazy_static::lazy_static; use spin::Mutex; use x86_64::structures::paging::mapper::MapperAllSizes; @@ -16,9 +16,9 @@ pub fn init(boot_info: &'static BootInfo) { let start_addr = region.range.start_addr(); let end_addr = region.range.end_addr(); mem_total += end_addr - start_addr; - print!("[{:.6}] MEM [0x{:016X}-0x{:016X}] {:?}\n", kernel::clock::clock_monotonic(), start_addr, end_addr, region.region_type); + log!("MEM [0x{:016X}-0x{:016X}] {:?}\n", start_addr, end_addr, region.region_type); } - print!("[{:.6}] MEM {} KB\n", kernel::clock::clock_monotonic(), mem_total >> 10); + log!("MEM {} KB\n", mem_total >> 10); let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); let mut mapper = unsafe { mapper(phys_mem_offset) }; diff --git a/src/kernel/pci.rs b/src/kernel/pci.rs index 689a6001c..6eb878f41 100644 --- a/src/kernel/pci.rs +++ b/src/kernel/pci.rs @@ -1,5 +1,5 @@ use bit_field::BitField; -use crate::{print, kernel}; +use crate::log; use alloc::vec::Vec; use lazy_static::lazy_static; use spin::Mutex; @@ -110,11 +110,7 @@ fn add_device(bus: u8, device: u8, function: u8) { let config = DeviceConfig::new(bus, device, function); PCI_DEVICES.lock().push(config); - let uptime = kernel::clock::clock_monotonic(); - print!( - "[{:.6}] PCI {:04}:{:02}:{:02} [{:04X}:{:04X}]\n", - uptime, bus, device, function, config.vendor_id, config.device_id - ); + log!("PCI {:04}:{:02}:{:02} [{:04X}:{:04X}]\n", bus, device, function, config.vendor_id, config.device_id); } fn get_vendor_id(bus: u8, device: u8, function: u8) -> u16 { diff --git a/src/kernel/rtl8139.rs b/src/kernel/rtl8139.rs index e77b34485..16311e768 100644 --- a/src/kernel/rtl8139.rs +++ b/src/kernel/rtl8139.rs @@ -2,7 +2,7 @@ use alloc::boxed::Box; use alloc::collections::BTreeMap; use core::cell::RefCell; use core::convert::TryInto; -use crate::{print, kernel}; +use crate::{log, print, kernel}; use crate::user; use lazy_static::lazy_static; use smoltcp::Result; @@ -432,8 +432,7 @@ pub fn init() { rtl8139_device.init(); if let Some(eth_addr) = rtl8139_device.eth_addr { - let uptime = kernel::clock::clock_monotonic(); - print!("[{:.6}] NET RTL8139 MAC {}\n", uptime, eth_addr); + log!("NET RTL8139 MAC {}\n", eth_addr); let neighbor_cache = NeighborCache::new(BTreeMap::new()); let routes = Routes::new(BTreeMap::new()); diff --git a/src/kernel/vga.rs b/src/kernel/vga.rs index 3ba3d1a56..d60e7123e 100644 --- a/src/kernel/vga.rs +++ b/src/kernel/vga.rs @@ -1,3 +1,4 @@ +use bit_field::BitField; use core::fmt; use core::fmt::Write; use lazy_static::lazy_static; @@ -42,6 +43,25 @@ pub enum Color { White = 15, } +const COLORS: [Color; 16] = [ + Color::Black, + Color::Blue, + Color::Green, + Color::Cyan, + Color::Red, + Color::Magenta, + Color::Brown, + Color::LightGray, + Color::DarkGray, + Color::LightBlue, + Color::LightGreen, + Color::LightCyan, + Color::LightRed, + Color::Pink, + Color::Yellow, + Color::White, +]; + /// A combination of a foreground and a background color. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(transparent)] @@ -212,6 +232,17 @@ impl Writer { self.col_pos = 0; self.set_cursor_position(self.col_pos, self.row_pos); } + + pub fn set_color(&mut self, foreground: Color, background: Color) { + self.color_code = ColorCode::new(foreground, background); + } + + pub fn color(&self) -> (Color, Color) { + let cc = self.color_code.0; + let fg = COLORS[cc.get_bits(0..4) as usize]; + let bg = COLORS[cc.get_bits(4..8) as usize]; + (fg, bg) + } } impl fmt::Write for Writer { @@ -277,6 +308,22 @@ pub fn writer_position() -> (usize, usize) { }) } +pub fn color() -> (Color, Color) { + interrupts::without_interrupts(|| { + WRITER.lock().color() + }) +} + +pub fn set_color(foreground: Color, background: Color) { + interrupts::without_interrupts(|| { + WRITER.lock().set_color(foreground, background) + }) +} + +pub fn colors() -> [Color; 16] { + COLORS +} + // Printable ascii chars + backspace + newline pub fn is_printable(c: u8) -> bool { match c { @@ -284,3 +331,37 @@ pub fn is_printable(c: u8) -> bool { _ => false, } } + +// Dark Gruvbox color palette +const PALETTE: [(u8, u8, u8, u8); 16] = [ + (0x00, 0x28, 0x28, 0x28), // Black + (0x01, 0x45, 0x85, 0x88), // Blue + (0x02, 0x98, 0x97, 0x1A), // Green + (0x03, 0x68, 0x9D, 0x6A), // Cyan + (0x04, 0xCC, 0x24, 0x1D), // Red + (0x05, 0xB1, 0x62, 0x86), // Magenta + (0x07, 0xEB, 0xDB, 0xB2), // Light Gray + (0x14, 0xD7, 0x99, 0x21), // Brown (Dark Yellow) + (0x38, 0xA8, 0x99, 0x84), // Gray (Dark Gray) + (0x39, 0x83, 0xa5, 0x98), // Light Blue + (0x3A, 0xB8, 0xBB, 0x26), // Light Green + (0x3B, 0x8E, 0xC0, 0x7C), // Light Cyan + (0x3C, 0xFB, 0x49, 0x34), // Light Red + (0x3D, 0xD3, 0x86, 0x9B), // Pink (Light Magenta) + (0x3E, 0xFA, 0xBD, 0x2F), // Yellow (Light Yellow) + (0x3F, 0xFB, 0xF1, 0xF7), // White +]; + +pub fn init() { + //let mut isr: Port = Port::new(0x03DA); // Input Status Register + let mut addr: Port = Port::new(0x03C8); // Address Write Mode Register + let mut data: Port = Port::new(0x03C9); // Data Register + for (i, r, g, b) in &PALETTE { + unsafe { + addr.write(*i); + data.write(*r >> 2); + data.write(*g >> 2); + data.write(*b >> 2); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 04478076d..fcc06784c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,12 +10,13 @@ pub mod user; use bootloader::BootInfo; pub fn init(boot_info: &'static BootInfo) { + kernel::vga::init(); kernel::gdt::init(); kernel::idt::init(); unsafe { kernel::pic::PICS.lock().initialize() }; x86_64::instructions::interrupts::enable(); - print!("[{:.6}] MOROS version {}\n", kernel::clock::clock_monotonic(), env!("CARGO_PKG_VERSION")); + log!("MOROS version {}\n", env!("CARGO_PKG_VERSION")); kernel::time::init(); kernel::keyboard::init(); diff --git a/src/user/colors.rs b/src/user/colors.rs new file mode 100644 index 000000000..d8a240973 --- /dev/null +++ b/src/user/colors.rs @@ -0,0 +1,22 @@ +use crate::{print, kernel, user}; + +pub fn main(_args: &[&str]) -> user::shell::ExitCode { + let (fg, bg) = kernel::vga::color(); + + for &c in &kernel::vga::colors() { + kernel::vga::set_color(c, bg); + print!(" {:02} ", c as u8); + } + kernel::vga::set_color(fg, bg); + print!("\n"); + + for &c in &kernel::vga::colors() { + kernel::vga::set_color(bg, c); + print!(" {:02} ", c as u8); + } + kernel::vga::set_color(fg, bg); + print!("\n"); + + user::shell::ExitCode::CommandSuccessful +} + diff --git a/src/user/mod.rs b/src/user/mod.rs index 01c558f55..8f963da38 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -1,6 +1,7 @@ pub mod base64; pub mod clear; pub mod copy; +pub mod colors; pub mod date; pub mod delete; pub mod dhcp; diff --git a/src/user/shell.rs b/src/user/shell.rs index 1d34a8649..27df3e6c5 100644 --- a/src/user/shell.rs +++ b/src/user/shell.rs @@ -289,6 +289,7 @@ impl Shell { "http" => user::http::main(&args), "host" => user::host::main(&args), "ip" => user::ip::main(&args), + "colors" => user::colors::main(&args), _ => ExitCode::CommandUnknown, } }