need to figure out a better way for memory mapping

This commit is contained in:
fekhesk 2022-10-27 01:00:01 -07:00
parent be015d1967
commit 50970fa2cc
No known key found for this signature in database
GPG Key ID: 6B3D8CB511646891
13 changed files with 457 additions and 113 deletions

View File

@ -11,12 +11,14 @@ spin = "0.9.1"
x86_64 = "0.14.10"
rlibc = "1.0"
multiboot2 = { version = "0.14.0", optional = true }
acpi = { version = "4.1.1", optional = true }
linked_list_allocator = { version = "0.9.0", optional = true }
[dependencies.lazy_static]
version = "1.4.0"
features = ["spin_no_std"]
[features]
default = ["f_multiboot2", "f_ll_alloc"]
f_multiboot2 = ["dep:multiboot2"]
default = ["f_multiboot2", "f_ll_alloc", "f_debug_verbose"]
f_debug_verbose = []
f_multiboot2 = ["dep:multiboot2", "dep:acpi"]
f_ll_alloc = ["dep:linked_list_allocator"]

View File

@ -7,6 +7,12 @@ BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1
WARNING: no console will be available to OS
error: no suitable video mode found.
using serial port 0 as console
debug: setup GDT
debug: GDT loaded
debug: CS set
debug: SS set
debug: TSS loaded
debug: IDT loaded
@ -16,3 +22,29 @@ initialising mapper...[OK]
initialising frame allocator...[OK]
initialising heap...[OK]
testing heap...[OK]
checking for apic compatibility...[OK]
disabling PIC...[OK]
initialising apic...[debug] read_phys_memory32: addr fee000f0 not mapped
[debug] allocated frame: PhysFrame[4KiB](0x1c000)
[debug] mapped page: Page[4KiB](0xfee00000)
[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfee00000)))
[OK]
setting up apic interrupts...[debug] write_phys_memory32: addr fec00000 not mapped
[debug] allocated frame: PhysFrame[4KiB](0x1f000)
[debug] mapped page: Page[4KiB](0xfec00000)
[debug] map_to_result: Ok(MapperFlush(Page[4KiB](0xfec00000)))
[OK]
[debug] keyboard interrupt
---KERNEL FUCKY WUKKY UWU---
double fault!
stack frame: InterruptStackFrame {
instruction_pointer: VirtAddr(
0x120ef1,
),
code_segment: 8,
cpu_flags: 0x200002,
stack_pointer: VirtAddr(
0x140c00,
),
stack_segment: 16,
}

View File

@ -1,8 +1,12 @@
use alloc::sync::Arc;
use core::marker::PhantomData;
use crate::KernelArgs;
use acpi::{AcpiHandler, PhysicalMapping};
use crate::{debug, KernelArgs};
#[cfg(feature = "f_multiboot2")]
use multiboot2::{load, MemoryMapTag, BootInformation};
use x86_64::structures::paging::{FrameAllocator, OffsetPageTable};
use crate::memory::BootInfoFrameAllocator;
pub struct KernelInfo {
kernel_start: u64,
@ -51,4 +55,65 @@ impl KernelInfo {
pub fn safe_memory_start(&self) -> u64 {
self.safe_mem_start
}
pub fn acpi_get_ioapic_addr(&self, mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator) -> u64 {
#[cfg(feature = "f_multiboot2")]
{
let acpi_tag = self.boot_info.rsdp_v1_tag().expect("no acpi tag");
let rsdp = acpi_tag;
let rsdp = unsafe { &*rsdp };
let rsdt = rsdp.rsdt_address();
#[derive(Clone)]
struct Handler<'a> {
mem_mapper: Arc<&'a mut OffsetPageTable<'a>>,
frame_allocator: Arc<&'a mut BootInfoFrameAllocator>,
}
impl<'a> AcpiHandler for Handler<'a> {
unsafe fn map_physical_region<T>(&self, physical_address: usize, size: usize) -> PhysicalMapping<Self, T> {
let frame_allocator = self.frame_allocator.clone();
debug!("read_phys_memory32: addr {:x} not mapped", physical_address);
// map the page
let frame = frame_allocator.allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) };
debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() {
panic!("Failed to map page");
}
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32;
unsafe { *addr }
} else {
panic!("Failed to map page");
}
}
fn unmap_physical_region<T>(region: &PhysicalMapping<Self, T>) {
todo!()
}
}
let rsdt = acpi::AcpiTables::from_rsdt(rsdt).expect("failed to get acpi tables");
let mut ioapic_addr = 0;
for entry in rsdt.entries() {
let entry = unsafe { &*entry };
if entry.signature() == *b"APIC" {
let apic = entry.as_apic();
let apic = unsafe { &*apic };
for entry in apic.entries() {
let entry = unsafe { &*entry };
if entry.signature() == *b"IOAP" {
let ioapic = entry.as_ioapic();
let ioapic = unsafe { &*ioapic };
ioapic_addr = ioapic.address();
}
}
}
}
ioapic_addr
}
}
}

142
src/internals/cpu.rs Normal file
View File

@ -0,0 +1,142 @@
use core::arch::asm;
use x86_64::{PhysAddr, VirtAddr};
use x86_64::structures::idt::InterruptStackFrame;
use x86_64::structures::paging::OffsetPageTable;
use crate::{debug, print, println};
use crate::memory::{BootInfoFrameAllocator, read_phys_memory32, write_phys_memory32};
use crate::serial::{command, read};
// todo! maybe abstract this into different sections for different parts of cpu func?
pub fn check_apic_compat() -> bool {
unsafe {
let mut eax: u32;
let mut edx: u32;
asm!("cpuid",
in("eax") 1,
lateout("eax") eax,
lateout("edx") edx,
);
edx & (1 << 9) != 0
}
}
pub fn set_apic_base(apic: usize) {
const IA32_APIC_BASE_MSR_ENABLE: u32 = 0x800;
let mut edx = 0u32;
let mut eax = (apic & 0xfffff0000) as u32 | IA32_APIC_BASE_MSR_ENABLE;
unsafe {
asm!("wrmsr",
in("ecx") 0x1b,
in("eax") eax,
in("edx") edx,
);
}
}
pub fn get_apic_base() -> usize {
let mut edx = 0u32;
let mut eax = 0u32;
unsafe {
asm!("rdmsr",
in("ecx") 0x1b,
lateout("eax") eax,
lateout("edx") edx,
);
}
((edx as usize) << 32) | (eax as usize)
}
pub fn enable_apic(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator) {
// PIC should be disabled by now
// now enable local apic
// 1. set bit 8 of spurious interrupt vector register
let sivr_addr = 0xfee000f0;
let sivr = read_phys_memory32(mem_mapper, frame_alloc, sivr_addr);
write_phys_memory32(mem_mapper, frame_alloc, sivr_addr, sivr | (1 << 8));
}
pub fn apic_read_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32) -> u32 {
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg);
read_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10)
}
pub fn apic_write_io(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, reg: u32, val: u32) {
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32, reg);
write_phys_memory32(mem_mapper, frame_alloc, ioapicaddr as u32 + 0x10, val);
}
pub fn disable_pic() {
command(0x20, 0x11);
command(0xa0, 0x11);
command(0x21, 0xe0);
command(0xa1, 0xe8);
command(0x21, 0x04);
command(0xa1, 0x02);
command(0x21, 0x01);
command(0xa1, 0x01);
command(0x21, 0xff);
command(0xa1, 0xff);
}
pub fn ioapic_set_irq(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize, irq: u8, apic_id: u64, vector:u8) {
let lo_index: u32 = (0x10 + irq*2 ) as u32;
let hi_index: u32 = (0x10 + irq*2 + 1) as u32;
let mut high = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, hi_index);
// set apic id
high &= !(0xff000000);
high |= (apic_id as u32) << 24;
apic_write_io(mem_mapper, frame_alloc, ioapicaddr, hi_index, high);
let mut low = apic_read_io(mem_mapper, frame_alloc, ioapicaddr, lo_index);
// unmask
low &= !(1 << 16);
// set to physical delivery
low &= !(1 << 11);
// set to fixed delivery
low &= !(0x700);
// set vector
low &= !(0xff);
low |= vector as u32;
apic_write_io(mem_mapper, frame_alloc, ioapicaddr, lo_index, low);
}
pub fn apic_eoi() {
unsafe {
asm!("mov eax, 0",
"mov ecx, 0xb0",
"wrmsr",
in("ecx") 0x80b,
in("eax") 0,
);
}
}
// todo! in the future this will be removed, it is only for testing basic apic functionality
pub extern "x86-interrupt" fn keyboard_irq(stack_frame: InterruptStackFrame) {
debug!("keyboard interrupt");
unsafe { asm!("iretq"); }
let scancode = read(0x60);
print!("ksc: {},", scancode);
// reset keyboard controller
let mut a = read(0x61);
a |= 0x82;
command(0x61, a);
a &= 0x7f;
command(0x61, a);
}
// todo! we should abstract this away
pub fn setup_apic_interrupts(mem_mapper: &mut OffsetPageTable, frame_alloc: &mut BootInfoFrameAllocator, ioapicaddr: usize) {
// set keyboard irq to interrupt 40
ioapic_set_irq(mem_mapper, frame_alloc, ioapicaddr, 1, 0, 40);
}

View File

@ -1,8 +1,8 @@
pub mod errors;
pub mod interrupts;
pub mod cpu;
pub mod WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood {
use core::arch::asm;
use core::marker::PhantomData;
#[derive(Clone, Copy)]
pub struct Point {

View File

@ -12,12 +12,16 @@ extern crate alloc;
use alloc::rc::Rc;
use alloc::vec;
use core::arch::asm;
use lazy_static::lazy_static;
use core::panic::PanicInfo;
use multiboot2::MemoryAreaType;
use spin::Mutex;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};
use x86_64::structures::tss::TaskStateSegment;
use x86_64::{PhysAddr, VirtAddr};
use x86_64::registers::segmentation::{CS, Segment, SS};
use x86_64::structures::paging::Translate;
use crate::boot::KernelInfo;
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
@ -32,11 +36,16 @@ mod memory;
mod macros;
lazy_static! {
static ref GDT: Mutex<GlobalDescriptorTable> = {
let mut gdt = GlobalDescriptorTable::new();
Mutex::new(gdt)
};
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(internals::errors::breakpoint_exception);
idt.double_fault.set_handler_fn(internals::errors::double_fault);
idt.page_fault.set_handler_fn(internals::errors::page_fault);
idt[40].set_handler_fn(internals::cpu::keyboard_irq);
idt
};
}
@ -93,6 +102,60 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
println!("using serial port {} as console", i);
}
// temporarily disable interrupts
x86_64::instructions::interrupts::disable();
println!("debug: setup GDT");
// load TSS
static mut tss: TaskStateSegment = TaskStateSegment::new();
{
unsafe {
tss.interrupt_stack_table[0] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
let stack_end = stack_start + STACK_SIZE;
stack_end
};
// set word at offset 102 to 0x68 and last two bytes of the tss to 0xffff
// this is a hack to make the tss valid
let tss_ptr = &tss as *const TaskStateSegment as *mut u8;
unsafe {
*tss_ptr.add(102) = 0x68;
*tss_ptr.add(104) = 0xff;
*tss_ptr.add(105) = 0xff;
}
}
let kcs = GDT.lock().add_entry(Descriptor::kernel_code_segment());
let kds = GDT.lock().add_entry(Descriptor::kernel_data_segment());
let tsss = unsafe { GDT.lock().add_entry(Descriptor::tss_segment(&tss)) };
// load GDT
unsafe {
GDT.lock().load_unsafe();
}
println!("debug: GDT loaded");
// set code segment to kernel code segment
unsafe {
CS::set_reg(kcs);
}
println!("debug: CS set");
// set data segment to kernel data segment
unsafe {
SS::set_reg(kds);
}
println!("debug: SS set");
// load TSS
unsafe {
x86_64::instructions::tables::load_tss(tsss);
}
println!("debug: TSS loaded");
// load IDT
IDT.load();
println!("debug: IDT loaded");
// enable interrupts
x86_64::instructions::interrupts::enable();
}
println!();
println!();
@ -100,28 +163,58 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
println!("welcome to wukkOS!");
println!("(c) 2022 Real Microsoft, LLC");
let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args));
print!("initialising mapper...");
let mut mapper = unsafe { memory::init(VirtAddr::new(0)) };
println!("[OK]");
print!("initialising frame allocator...");
let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(kern_info) };
println!("[OK]");
print!("initialising heap...");
memory::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap init failed");
println!("[OK]");
print!("testing heap...");
let reference_counted = Rc::new(vec![1, 2, 3]);
let cloned = reference_counted.clone();
let test_1 = Rc::strong_count(&reference_counted) == 2;
drop(cloned);
let test_2 = Rc::strong_count(&reference_counted) == 1;
if test_1 && test_2 {
// memory stuff
let mut mapper = None;
let mut frame_allocator = None;
{
print!("initialising mapper...");
mapper = Some(unsafe { memory::init(VirtAddr::new(0)) });
println!("[OK]");
print!("initialising frame allocator...");
frame_allocator = Some(unsafe { memory::BootInfoFrameAllocator::init(kern_info) });
println!("[OK]");
print!("initialising heap...");
memory::allocator::init_heap(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()).expect("heap init failed");
println!("[OK]");
} else {
println!("[FAIL]");
}
drop(reference_counted);
loop {}
print!("testing heap...");
let reference_counted = Rc::new(vec![1, 2, 3]);
let cloned = reference_counted.clone();
let test_1 = Rc::strong_count(&reference_counted) == 2;
drop(cloned);
let test_2 = Rc::strong_count(&reference_counted) == 1;
if test_1 && test_2 {
println!("[OK]");
} else {
println!("[FAIL]");
}
drop(reference_counted);
}
// apic stuff
{
print!("checking for apic compatibility...");
let apic_compatible = unsafe { internals::cpu::check_apic_compat() };
if apic_compatible {
println!("[OK]");
} else {
println!("[FAIL]");
panic!("apic required at the moment");
}
print!("disabling PIC...");
unsafe { internals::cpu::disable_pic() };
println!("[OK]");
print!("initialising apic...");
unsafe { internals::cpu::enable_apic(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) };
println!("[OK]");
print!("setting up apic interrupts...");
unsafe { internals::cpu::setup_apic_interrupts(mapper.as_mut().unwrap(), frame_allocator.as_mut().unwrap()) };
println!("[OK]");
// enable interrupts
x86_64::instructions::interrupts::enable();
}
loop {
}
}

View File

@ -12,8 +12,24 @@ macro_rules! println {
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
#[macro_export]
macro_rules! debug {
($($arg:tt)*) => ($crate::macros::_debug(format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
use core::fmt::Write;
ST.writer.lock().write_fmt(args).unwrap();
}
#[doc(hidden)]
pub fn _debug(args: fmt::Arguments) {
use core::fmt::Write;
#[cfg(feature = "f_debug_verbose")]
{
ST.log("[debug] ");
ST.writer.lock().write_fmt(args).unwrap();
ST.logln("");
}
}

View File

@ -1,6 +1,8 @@
pub mod allocator;
use x86_64::structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB};
use alloc::boxed::Box;
use alloc::sync::Arc;
use x86_64::structures::paging::{FrameAllocator, Mapper, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate};
use x86_64::{PhysAddr, VirtAddr};
pub struct Locked<A> {
@ -40,6 +42,7 @@ unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTa
use multiboot2::{MemoryMapTag, BootInformation};
use spin::Mutex;
use crate::boot::KernelInfo;
use crate::{debug, print, println};
pub struct BootInfoFrameAllocator {
kern_info: Mutex<KernelInfo>,
@ -81,4 +84,62 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
frame
}
}
}
pub fn read_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32) -> u32 {
let initaladdr = VirtAddr::new(addr as u64);
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32;
unsafe { *addr }
} else {
debug!("read_phys_memory32: addr {:x} not mapped", initaladdr.as_u64());
// map the page
let frame = frame_allocator.allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) };
debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() {
panic!("Failed to map page");
}
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *const u32;
unsafe { *addr }
} else {
panic!("Failed to map page");
}
}
}
pub fn write_phys_memory32(mem_mapper: &mut OffsetPageTable, frame_allocator: &mut BootInfoFrameAllocator, addr: u32, value: u32) {
let initaladdr = VirtAddr::new(addr as u64);
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *mut u32;
unsafe { *addr = value };
} else {
debug!("write_phys_memory32: addr {:x} not mapped", initaladdr.as_u64());
// map the page
let frame = frame_allocator.allocate_frame().unwrap();
debug!("allocated frame: {:?}", frame);
let flags = x86_64::structures::paging::PageTableFlags::PRESENT | x86_64::structures::paging::PageTableFlags::WRITABLE;
let page = x86_64::structures::paging::Page::containing_address(initaladdr);
debug!("mapped page: {:?}", page);
let map_to_result = unsafe { mem_mapper.map_to(page, frame, flags, frame_allocator) };
debug!("map_to_result: {:?}", map_to_result);
if map_to_result.is_err() {
panic!("Failed to map page");
}
let addr = unsafe { mem_mapper.translate_addr(initaladdr) };
if let Some(addr) = addr {
let addr = addr.as_u64() as *mut u32;
unsafe { *addr = value };
} else {
panic!("Failed to map page");
}
}
}

View File

@ -4,7 +4,6 @@ use core::arch::asm;
use core::borrow::{Borrow, BorrowMut};
use core::ops::Deref;
pub mod ps2;
pub mod terminal_helpers;
pub mod terminal;
@ -60,14 +59,14 @@ pub struct SerialPorts {
}
#[cfg(any(target_arch="x86", target_arch="x86_64"))]
fn command(port: u16, data: u8) {
pub fn command(port: u16, data: u8) {
unsafe {
asm!("out dx, al", in("al") data, in("dx") port);
}
}
#[cfg(any(target_arch="x86", target_arch="x86_64"))]
fn read(port: u16) -> u8 {
pub fn read(port: u16) -> u8 {
let mut data: u8;
unsafe {
asm!("in al, dx", out("al") data, in("dx") port);

View File

@ -1,70 +0,0 @@
use super::*;
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::{KernelError, ErrorKind, ErrorLevel};
pub enum PS2Type {
AncientKeyboard,
Keyboard,
Mouse,
FiveButtonMouse,
ScrollWheelMouse,
Unknown,
}
enum Messages {
MSGDisableScanning = 0xF5,
MSGIdentify = 0xF2,
MSGACK = 0xFA,
}
pub fn probePort(port : Port) -> Result<PS2Type, KernelError> {
let mut response : u8;
response = port.transrecv(Messages::MSGDisableScanning as u8);
// check for ACK
if response != Messages::MSGACK as u8 {
return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::Warning, "Did not receive ACK", port.base.to_string()));
}
response = port.transrecv(Messages::MSGIdentify as u8);
// check for ACK
if response != Messages::MSGACK as u8 {
return Err(KernelError::new(ErrorKind::HardwareFuckUp, ErrorLevel::MinorFuckUp, "Did not receive ACK after asking port to identify", port.base.to_string()));
}
// read the response with a timeout of x cpu cycles, this can be quite low as it will only matter on slow machines
response = port.receive(0xFFFF);
// if there's no response, it's a really old keyboard (IBM or whoever, why did you have to do this??)\
if response == 0 {
return Ok(PS2Type::AncientKeyboard);
} else {
// switch on the response
match response {
0x00 => { // standard mouse
return Ok(PS2Type::Mouse);
},
0x03 => { // mouse with scroll wheel
return Ok(PS2Type::ScrollWheelMouse);
},
0x04 => { // 5 button mouse
return Ok(PS2Type::FiveButtonMouse);
},
0xAB => { // some type of keyboard, we'll need to read another byte to be sure
response = port.receive(0xFFFF);
match response {
0x41 => { // some keyboard idfk
return Ok(PS2Type::Keyboard);
},
0xC1 => { // same as above
return Ok(PS2Type::Keyboard);
},
0x83 => { // keyboard after taking normal pills
return Ok(PS2Type::Keyboard);
},
_ => { // what?
return Ok(PS2Type::Unknown);
}
}
},
_ => { // some other device idk
return Ok(PS2Type::Unknown);
}
}
}
}

View File

@ -1,3 +0,0 @@
static DATA_PORT: u16 = 0x60;
static COMMAND_PORT: u16 = 0x64;

View File

@ -2,6 +2,7 @@ use core::fmt;
use core::ops::Deref;
use lazy_static::lazy_static;
use spin::Mutex;
use x86_64::instructions::interrupts::without_interrupts;
use crate::serial::Port;
pub struct SerialTerminal {
@ -32,24 +33,30 @@ impl SerialTerminal {
}
pub fn log(&self, message: &str) {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(message);
}
without_interrupts(|| {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(message);
}
});
}
pub fn logln(&self, message: &str) {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(message);
port.transmit_string("\r\n");
}
without_interrupts(|| {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(message);
port.transmit_string("\r\n");
}
});
}
}
impl fmt::Write for SerialTerminalWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(s);
}
without_interrupts(|| {
if let Some(port) = self.port.lock().deref() {
port.transmit_string(s);
}
});
Ok(())
}
}