Major log rework
This commit is contained in:
parent
0399650788
commit
8a87fa80b1
@ -176,4 +176,4 @@ command = "gdb"
|
||||
args = ["${ARTIFACTDIR}/kernel", "--eval-command=target remote localhost:1234"]
|
||||
|
||||
[tasks.debug]
|
||||
run_task = { name = ["debug-run", "debug-view"], fork = true, parallel = true }
|
||||
run_task = { name = ["debug_run", "debug_view"], fork = true, parallel = true }
|
||||
|
@ -1,13 +1,342 @@
|
||||
// Copyright (c) 2025 shibedrill
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use crate::log::LogSubscriber;
|
||||
use x86_64::instructions::port::Port;
|
||||
#![allow(dead_code)]
|
||||
|
||||
impl LogSubscriber for Port<u8> {
|
||||
fn log_write(&mut self, msg: &str) {
|
||||
for c in msg.chars() {
|
||||
unsafe { self.write(c as u8) };
|
||||
use enumflags2::{BitFlag, BitFlags};
|
||||
use intbits::Bits;
|
||||
use x86_64::instructions::port::Port;
|
||||
use num_traits::FromPrimitive;
|
||||
use num_derive::FromPrimitive;
|
||||
|
||||
/// Represents an x86 port-mapped serial port.
|
||||
pub struct SerialPort {
|
||||
base_port: Port<u8>,
|
||||
interrupt_enable: Port<u8>,
|
||||
interrupt_id_fifo_control: Port<u8>,
|
||||
line_control: Port<u8>,
|
||||
modem_control: Port<u8>,
|
||||
line_status: Port<u8>,
|
||||
modem_status: Port<u8>,
|
||||
scratch: Port<u8>,
|
||||
fifo_register: u8,
|
||||
pub crlf: Crlf,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum Crlf {
|
||||
Lf,
|
||||
Crlf,
|
||||
}
|
||||
|
||||
#[derive(FromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum DataBits {
|
||||
Five = 0,
|
||||
Six = 1,
|
||||
Seven = 2,
|
||||
Eight = 3,
|
||||
}
|
||||
|
||||
#[derive(FromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum ParityBits {
|
||||
None = 0b000,
|
||||
Odd = 0b001,
|
||||
Even = 0b011,
|
||||
Mark = 0b101,
|
||||
Space = 0b111,
|
||||
}
|
||||
|
||||
#[enumflags2::bitflags]
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum InterruptEnable {
|
||||
ModemStatus = 0b1000,
|
||||
ReceiverLineStatus = 0b100,
|
||||
TransmitterHoldingRegisterEmpty = 0b10,
|
||||
ReceivedDataAvail = 0b1,
|
||||
}
|
||||
|
||||
#[enumflags2::bitflags]
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ModemControl {
|
||||
DataTerminalReady = 0b00000001,
|
||||
RequestToSend = 0b00000010,
|
||||
Out1 = 0b00000100,
|
||||
Out2 = 0b00001000,
|
||||
Loop = 0b00010000,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(FromPrimitive)]
|
||||
pub enum TriggerLevel {
|
||||
OneByte = 0b00,
|
||||
FourBytes = 0b01,
|
||||
EightBytes = 0b10,
|
||||
FourteenBytes = 0b11,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(FromPrimitive)]
|
||||
pub enum InterruptState {
|
||||
ModemStatus = 0b00,
|
||||
TransmitterEmpty = 0b01,
|
||||
ReceivedDataAvail = 0b10,
|
||||
ReceiverLineStatus = 0b11,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(FromPrimitive)]
|
||||
pub enum FifoState {
|
||||
NoFifo = 0b00,
|
||||
FifoEnabledUnusable = 0b01,
|
||||
FifoEnabled = 0b10,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[enumflags2::bitflags]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum LineStatus {
|
||||
DataReady = 0b00000001,
|
||||
OverrunError = 0b00000010,
|
||||
ParityError = 0b00000100,
|
||||
FramingError = 0b00001000,
|
||||
BreakIndicator = 0b00010000,
|
||||
TransmitterHoldingRegisterEmpty = 0b00100000,
|
||||
TransmitterEmpty = 0b01000000,
|
||||
ImpendingError = 0b10000000,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[enumflags2::bitflags]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ModemStatus {
|
||||
DeltaClearToSend = 0b00000001,
|
||||
DeltaDataSetReady = 0b00000010,
|
||||
TrailingEdgeRingIndicator = 0b00000100,
|
||||
DeltaDataCarrierDetect = 0b00001000,
|
||||
ClearToSend = 0b00010000,
|
||||
DataSetReady = 0b00100000,
|
||||
RingIndicator = 0b01000000,
|
||||
DataCarrierDetect = 0b10000000,
|
||||
}
|
||||
|
||||
impl SerialPort {
|
||||
|
||||
pub fn log_write(&mut self, msg: &str) {
|
||||
if self.crlf == Crlf::Crlf {
|
||||
for c in msg.chars() {
|
||||
if c == '\n' {
|
||||
self.write_char('\r');
|
||||
}
|
||||
self.write_char(c);
|
||||
}
|
||||
} else {
|
||||
for c in msg.chars() {
|
||||
self.write_char(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_writeln(&mut self, msg: &str) {
|
||||
self.log_write(msg);
|
||||
self.log_write("\n");
|
||||
}
|
||||
|
||||
/// Create a new port-mapped serial port with the base address `port_addr`.
|
||||
pub fn new(port_addr: u16) -> Self {
|
||||
let mut port = SerialPort {
|
||||
base_port: Port::new(port_addr),
|
||||
interrupt_enable: Port::new(port_addr + 1),
|
||||
interrupt_id_fifo_control: Port::new(port_addr + 2),
|
||||
line_control: Port::new(port_addr + 3),
|
||||
modem_control: Port::new(port_addr + 4),
|
||||
line_status: Port::new(port_addr + 5),
|
||||
modem_status: Port::new(port_addr + 6),
|
||||
scratch: Port::new(port_addr + 7),
|
||||
fifo_register: 0,
|
||||
crlf: Crlf::Crlf,
|
||||
};
|
||||
// ensure this is false
|
||||
port.set_dlab(false);
|
||||
port
|
||||
}
|
||||
|
||||
fn get_line_control(&mut self) -> u8 {
|
||||
unsafe { self.line_control.read() }
|
||||
}
|
||||
fn set_line_control(&mut self, value: u8) {
|
||||
unsafe { self.line_control.write(value) };
|
||||
}
|
||||
|
||||
fn get_dlab(&mut self) -> bool {
|
||||
self.get_line_control().bit(7)
|
||||
}
|
||||
fn set_dlab(&mut self, dlab: bool) {
|
||||
let mut new_lcr = unsafe {self.line_control.read()};
|
||||
new_lcr.set_bit(7, dlab);
|
||||
unsafe { self.line_control.write(new_lcr) };
|
||||
}
|
||||
|
||||
/// Read a single character from the RX buffer.
|
||||
pub fn read_char(&mut self) -> u8 {
|
||||
unsafe { self.base_port.read() }
|
||||
}
|
||||
/// Write a single character to the TX buffer.
|
||||
pub fn write_char(&mut self, c: char) {
|
||||
unsafe { self.base_port.write(c as u8) };
|
||||
}
|
||||
|
||||
/// Get the baud rate divisor.
|
||||
pub fn get_divisor(&mut self) -> u16 {
|
||||
self.set_dlab(true);
|
||||
let result: u16 = unsafe { self.base_port.read() as u16 | ((self.interrupt_enable.read() as u16) << 8) as u16};
|
||||
self.set_dlab(false);
|
||||
result
|
||||
}
|
||||
/// Set the baud rate divisor.
|
||||
pub fn set_divisor(&mut self, divisor: u16) {
|
||||
self.set_dlab(true);
|
||||
unsafe {
|
||||
self.base_port.write((divisor & 0b11111111) as u8);
|
||||
self.interrupt_enable.write(((divisor & 0b1111111100000000) >> 8) as u8);
|
||||
}
|
||||
self.set_dlab(false);
|
||||
}
|
||||
|
||||
/// Get the number of bits in a character.
|
||||
pub fn get_data_bits(&mut self) -> DataBits {
|
||||
DataBits::from_u8(self.get_line_control().bits(0..=1)).unwrap()
|
||||
}
|
||||
/// Set the number of bits in a character.
|
||||
pub fn set_data_bits(&mut self, bits: DataBits) {
|
||||
let new_value = self.get_line_control().bits(2..=7) | bits as u8;
|
||||
self.set_line_control(new_value);
|
||||
}
|
||||
|
||||
/// Get the number of bits sent after each character.
|
||||
/// A value of False means only 1 bit will be sent.
|
||||
/// A value of True means 2 bits will be sent.
|
||||
/// If the character length is 5 bits, a value of True means 1.5 bits will be sent.
|
||||
pub fn get_stop_bits(&mut self) -> bool {
|
||||
self.get_line_control().bit(2)
|
||||
}
|
||||
/// Set the number of bits sent after each character.
|
||||
/// A value of False means only 1 bit will be sent.
|
||||
/// A value of True means 2 bits will be sent.
|
||||
/// If the character length is 5 bits, a value of True means 1.5 bits will be sent.
|
||||
pub fn set_stop_bits(&mut self, bit: bool) {
|
||||
let mut new_value = self.get_line_control();
|
||||
new_value.set_bit(2, bit);
|
||||
self.set_line_control(new_value);
|
||||
}
|
||||
|
||||
/// Get the parity strategy.
|
||||
pub fn get_parity_bits(&mut self) -> ParityBits {
|
||||
ParityBits::from_u8(self.get_line_control().bits(3..=5) >> 3).unwrap()
|
||||
}
|
||||
/// Set the parity strategy.
|
||||
pub fn set_parity_bits(&mut self, parity: ParityBits) {
|
||||
let mut new_value = self.get_line_control();
|
||||
new_value.set_bits(3..=5, parity as u8);
|
||||
self.set_line_control(new_value);
|
||||
}
|
||||
|
||||
/// Get the Interrupt Enable control register.
|
||||
pub fn get_interrupt_enable(&mut self) -> BitFlags<InterruptEnable> {
|
||||
InterruptEnable::from_bits(unsafe {self.interrupt_enable.read().bits(0..=3)}).unwrap()
|
||||
}
|
||||
/// Set the Interrupt Enable control register.
|
||||
pub fn set_interrupt_enable(&mut self, interrupt: InterruptEnable) {
|
||||
unsafe { self.interrupt_enable.write(interrupt as u8) };
|
||||
}
|
||||
|
||||
/// Set the FIFO control register.
|
||||
pub fn set_fifo_control(&mut self, value: u8) {
|
||||
unsafe { self.interrupt_id_fifo_control.write(value) };
|
||||
}
|
||||
/// Clear the transmitter FIFO.
|
||||
pub fn clear_tx_fifo(&mut self) {
|
||||
let mut new_value = self.fifo_register;
|
||||
new_value.set_bit(2, true);
|
||||
self.set_fifo_control(new_value);
|
||||
}
|
||||
/// Clear the receiver FIFO.
|
||||
pub fn clear_rx_fifo(&mut self) {
|
||||
let mut new_value = self.fifo_register;
|
||||
new_value.set_bit(1, true);
|
||||
self.set_fifo_control(new_value);
|
||||
}
|
||||
/// Enable or disable FIFOs.
|
||||
pub fn set_fifo_enable(&mut self, enable: bool) {
|
||||
self.fifo_register.set_bit(0, enable);
|
||||
self.set_fifo_control(self.fifo_register);
|
||||
}
|
||||
/// Get whether FIFOs were enabled using this API.
|
||||
pub fn get_fifo_enable(&mut self) -> bool {
|
||||
self.fifo_register.bit(0)
|
||||
}
|
||||
/// Set the DMA mode of the serial controller.
|
||||
pub fn set_dma_mode(&mut self, enable: bool) {
|
||||
self.fifo_register.set_bit(3, enable);
|
||||
self.set_fifo_control(self.fifo_register);
|
||||
}
|
||||
/// Get whether DMA mode was enabled using this API.
|
||||
pub fn get_dma_mode(&mut self) -> bool {
|
||||
self.fifo_register.bit(3)
|
||||
}
|
||||
/// Get the Interrupt Trigger Level.
|
||||
pub fn get_interrupt_trigger_level(&mut self) -> TriggerLevel {
|
||||
TriggerLevel::from_u8(self.fifo_register.bits(6..=7) >> 6).unwrap()
|
||||
}
|
||||
/// Set the Interrupt Trigger Level.
|
||||
pub fn set_interrupt_trigger_level(&mut self, level: TriggerLevel) {
|
||||
self.fifo_register.set_bits(6..=7, level as u8);
|
||||
self.set_fifo_control(self.fifo_register);
|
||||
}
|
||||
|
||||
/// Get the Interrupt ID status register.
|
||||
pub fn get_interrupt_id(&mut self) -> u8 {
|
||||
unsafe { self.interrupt_id_fifo_control.read() }
|
||||
}
|
||||
/// Get the state of the FIFO buffers.
|
||||
pub fn get_fifo_buffer_state(&mut self) -> FifoState {
|
||||
FifoState::from_u8(self.get_interrupt_id().bits(6..=7) >> 6).unwrap()
|
||||
}
|
||||
/// Get whether a timeout interrupt is pending. Only used on UART 16550 chips, otherwise reserved.
|
||||
pub fn get_timeout_pending(&mut self) -> bool {
|
||||
self.get_interrupt_id().bit(3)
|
||||
}
|
||||
/// Get the Interrupt State of the controller.
|
||||
pub fn get_interrupt_state(&mut self) -> InterruptState {
|
||||
InterruptState::from_u8(self.get_interrupt_id().bits(1..=2) >> 1).unwrap()
|
||||
}
|
||||
/// Get whether an interrupt is pending.
|
||||
pub fn get_interrupt_pending(&mut self) -> bool {
|
||||
!self.get_interrupt_id().bit(0)
|
||||
}
|
||||
|
||||
/// Set the Modem Control register flags.
|
||||
/// This OVERWRITES all held flags. To set specific flags, first store the current
|
||||
/// value using `get_modem_control()`, then modify the flags you want to change.
|
||||
pub fn set_modem_control(&mut self, control: BitFlags<ModemControl>) {
|
||||
unsafe { self.modem_control.write(control.bits() as u8) };
|
||||
}
|
||||
/// Get the Modem Control register flags.
|
||||
pub fn get_modem_control(&mut self) -> BitFlags<ModemControl> {
|
||||
ModemControl::from_bits(unsafe { self.modem_control.read() & 0b0001111 }).unwrap()
|
||||
}
|
||||
|
||||
/// Get the Line Status Register flags.
|
||||
pub fn get_line_status(&mut self) -> BitFlags<LineStatus> {
|
||||
LineStatus::from_bits(unsafe {self.line_status.read()}).unwrap()
|
||||
}
|
||||
|
||||
/// Get the Modem Status Register flags.
|
||||
pub fn get_modem_status(&mut self) -> BitFlags<ModemStatus> {
|
||||
ModemStatus::from_bits(unsafe {self.modem_status.read()}).unwrap()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,123 +1,78 @@
|
||||
// Copyright (c) 2025 shibedrill
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use crate::constants::{LOG_DEFAULT_LEVEL, NEWLINE};
|
||||
use crate::memory::alloc;
|
||||
use alloc::boxed::*;
|
||||
use alloc::string::*;
|
||||
use alloc::vec::*;
|
||||
use crate::memory::alloc::vec::Vec;
|
||||
use crate::memory::alloc::boxed::Box;
|
||||
use crate::constants::LOG_DEFAULT_LEVEL;
|
||||
use crate::memory::alloc::string::String;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
use crate::format;
|
||||
|
||||
pub struct Logger {
|
||||
pub level: LogLevel,
|
||||
devices: Vec<Box<dyn Fn(&str) + Send + Sync>>
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref LOGGER: Mutex<Logger> = Mutex::new(Logger::new());
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_info {
|
||||
($($arg:tt)*) => {
|
||||
LOGGER.log(LogLevel::Info, &format!($($arg)*), file!(), line!(), column!())
|
||||
LOGGER.lock().log(LogLevel::Info, &format!($($arg)*), file!(), line!(), column!())
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_trace {
|
||||
($($arg:tt)*) => {
|
||||
LOGGER.log(LogLevel::Trace, &format!($($arg)*), file!(), line!(), column!())
|
||||
LOGGER.lock().log(LogLevel::Trace, &format!($($arg)*), file!(), line!(), column!())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! log_warning {
|
||||
($($arg:tt)*) => {
|
||||
LOGGER.log(LogLevel::Warning, &format!($($arg)*), file!(), line!(), column!())
|
||||
LOGGER.lock().log(LogLevel::Warning, &format!($($arg)*), file!(), line!(), column!())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! log_error {
|
||||
($($arg:tt)*) => {
|
||||
LOGGER.log(LogLevel::Error, &format!($($arg)*), file!(), line!(), column!())
|
||||
LOGGER.lock().log(LogLevel::Error, &format!($($arg)*), file!(), line!(), column!())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! log_critical {
|
||||
($($arg:tt)*) => {
|
||||
LOGGER.log(LogLevel::Critical, &format!($($arg)*), file!(), line!(), column!())
|
||||
LOGGER.lock().log(LogLevel::Critical, &format!($($arg)*), file!(), line!(), column!())
|
||||
};
|
||||
}
|
||||
|
||||
pub struct Logger {
|
||||
pub inner: Mutex<LoggerInner>,
|
||||
}
|
||||
|
||||
impl Logger {
|
||||
pub fn log(&self, level: LogLevel, msg: &str, file: &'static str, line: u32, column: u32) {
|
||||
self.inner.lock().log(level, msg, file, line, column);
|
||||
pub fn new() -> Self {
|
||||
Logger { level: LOG_DEFAULT_LEVEL, devices: Vec::new() }
|
||||
}
|
||||
pub fn add_subscriber<T: LogSubscriber + Send + Sync + 'static>(&self, sub: T) {
|
||||
self.inner
|
||||
.lock()
|
||||
.subscriber
|
||||
.push(Mutex::new(alloc::boxed::Box::new(sub)));
|
||||
pub fn log(&mut self, level: LogLevel, message: &str, file: &'static str, line: u32, column: u32) {
|
||||
for dev in &self.devices {
|
||||
let message = format!("{} {}:{},{}- {}", level.normalized_string(), file, line, column, message);
|
||||
dev(&message)
|
||||
}
|
||||
}
|
||||
pub fn set_level(&self, level: LogLevel) {
|
||||
self.inner.lock().level = level;
|
||||
pub fn add_device(&mut self, device: Box<dyn Fn(&str) + Send + Sync>) {
|
||||
self.devices.push(device);
|
||||
}
|
||||
}
|
||||
|
||||
// The logger exists for the entire lifetime of the kernel.
|
||||
pub static LOGGER: Logger = Logger {
|
||||
inner: Mutex::new(LoggerInner::new()),
|
||||
};
|
||||
|
||||
pub struct EnumParseError {}
|
||||
|
||||
pub struct LoggerInner {
|
||||
pub level: LogLevel,
|
||||
pub subscriber: Vec<Mutex<Box<dyn LogSubscriber>>>,
|
||||
}
|
||||
|
||||
pub trait LogSubscriber: Send + Sync {
|
||||
fn log_write(&mut self, msg: &str);
|
||||
}
|
||||
|
||||
impl Default for LoggerInner {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl LoggerInner {
|
||||
pub const fn new() -> Self {
|
||||
LoggerInner {
|
||||
level: LOG_DEFAULT_LEVEL,
|
||||
subscriber: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// Calling log will sequentially acquire lock on all logging subscribers
|
||||
// to write to them with a formatted log message.
|
||||
pub fn log(&self, level: LogLevel, msg: &str, file: &'static str, line: u32, column: u32) {
|
||||
// Nobody is EVER allowed to call log with the Disabled log level. It is a placeholder.
|
||||
if level == LogLevel::Disabled {
|
||||
// Nothing
|
||||
} else if level <= self.level {
|
||||
let level_string = String::from(level);
|
||||
for sub in &self.subscriber {
|
||||
let mut message = String::new();
|
||||
write!(
|
||||
&mut message,
|
||||
"[{level_string}] {file}:{line},{column} - {msg}{NEWLINE}"
|
||||
)
|
||||
.unwrap();
|
||||
sub.lock().log_write(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
||||
pub enum LogLevel {
|
||||
Disabled = 0,
|
||||
@ -171,3 +126,16 @@ impl From<LogLevel> for String {
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl LogLevel {
|
||||
fn normalized_string(&self) -> &str {
|
||||
match self {
|
||||
LogLevel::Critical => "[CRIT ]",
|
||||
LogLevel::Error => "[ERROR]",
|
||||
LogLevel::Info => "[INFO ]",
|
||||
LogLevel::Trace => "[TRACE]",
|
||||
LogLevel::Warning => "[WARN ]",
|
||||
LogLevel::Disabled => "[DSBLD]",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,17 +21,20 @@ mod process;
|
||||
mod util;
|
||||
|
||||
use boot::{BASE_REVISION, params, *};
|
||||
use constants::*;
|
||||
use limine::firmware_type::FirmwareType;
|
||||
use log::*;
|
||||
use memory::alloc::{format, string::*, vec};
|
||||
|
||||
use memory::alloc::{format, vec, boxed::Box, string::{String, ToString}};
|
||||
use arch::x86_64::interrupts::IDT;
|
||||
use params::*;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use lzma_rs::lzma_decompress;
|
||||
use lazy_static::lazy_static;
|
||||
use limine::firmware_type::FirmwareType;
|
||||
use spin::{mutex::Mutex};
|
||||
use crate::arch::x86_64::serial::SerialPort;
|
||||
use crate::constants::*;
|
||||
|
||||
use crate::arch::x86_64::interrupts::IDT;
|
||||
lazy_static! {
|
||||
pub static ref SERIAL_3F8: Mutex<SerialPort> = Mutex::new(arch::x86_64::serial::SerialPort::new(0x3f8));
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn main() -> ! {
|
||||
@ -41,15 +44,12 @@ unsafe extern "C" fn main() -> ! {
|
||||
// Ensure IDT exists
|
||||
IDT.load();
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let serial: x86_64::instructions::port::Port<u8> = x86_64::instructions::port::Port::new(0x3f8);
|
||||
|
||||
// Set up logging level from params
|
||||
// Nothing we can do here if this fails since no log subscribers are initialized yet
|
||||
if let Some(level) = PARAMS.get("-loglevel")
|
||||
&& let Ok(parsed_level) = LogLevel::try_from(level.as_str())
|
||||
{
|
||||
LOGGER.set_level(parsed_level);
|
||||
LOGGER.lock().level = parsed_level;
|
||||
}
|
||||
// Add subscribers to logger
|
||||
if let Some(device) = PARAMS.get("-logdev") {
|
||||
@ -59,8 +59,8 @@ unsafe extern "C" fn main() -> ! {
|
||||
}
|
||||
if log_device_list.contains(&"serial") {
|
||||
// TODO: Set up device discovery
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
LOGGER.add_subscriber(serial);
|
||||
let serial_logger = |msg: &str| {SERIAL_3F8.lock().log_writeln(msg)};
|
||||
LOGGER.lock().add_device(Box::new(serial_logger));
|
||||
}
|
||||
log_trace!("Configured kernel logging devices");
|
||||
}
|
||||
@ -135,14 +135,9 @@ unsafe extern "C" fn main() -> ! {
|
||||
log_info!("Hypervisor: {:?}", string.identify());
|
||||
}
|
||||
|
||||
panic!("Bailing");
|
||||
SERIAL_3F8.lock().log_write("hi");
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
loop {
|
||||
for _i in 0..50000000u64 {
|
||||
crate::arch::asm::nop();
|
||||
}
|
||||
core::hint::black_box(());
|
||||
log_trace!("Heartbeat");
|
||||
arch::asm::nop();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ pub enum Syscall {
|
||||
Resolve,
|
||||
Spawn,
|
||||
Version,
|
||||
Yield,
|
||||
}
|
||||
|
||||
#[derive(FromPrimitive, Debug)]
|
||||
@ -20,22 +21,17 @@ pub enum SyscallStatus {
|
||||
Success,
|
||||
NoSuchCall,
|
||||
NoSuchProcess,
|
||||
NoSuchServer,
|
||||
NoSuchService,
|
||||
NoPermission,
|
||||
OutOfMemory,
|
||||
Aborted,
|
||||
Unspecified,
|
||||
Unknown,
|
||||
Unimplemented,
|
||||
}
|
||||
|
||||
pub struct UnknownStatus {}
|
||||
|
||||
impl From<u64> for SyscallStatus {
|
||||
fn from(value: u64) -> Self {
|
||||
SyscallStatus::from_u64(value).unwrap_or(Self::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
//pub fn exit(code: u64) -> SyscallStatus {
|
||||
// arch::syscall_impl::caller_syscall_1(Syscall::Exit as u64, code).into()
|
||||
//}
|
||||
|
Loading…
Reference in New Issue
Block a user