diff --git a/.gitignore b/.gitignore index 3377494..9ac3d79 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ bx_enh_dbg.ini # limine -limine/ \ No newline at end of file +limine/ + +# rewrite stuff +src.bak \ No newline at end of file diff --git a/src/arch/x86_64/interrupts/apic.rs b/src/arch/x86_64/interrupts/apic.rs new file mode 100644 index 0000000..4190a70 --- /dev/null +++ b/src/arch/x86_64/interrupts/apic.rs @@ -0,0 +1,375 @@ +use crate::{drivers::acpi::SMP_REQUEST, hcf, libs::cell::OnceCell}; + +use alloc::{sync::Arc, vec::Vec}; + +use super::super::{ + cpu_get_msr, cpu_set_msr, + io::{inb, outb}, +}; + +#[repr(C, packed)] +#[derive(Clone, Copy, Debug)] +struct MADT { + pub local_apic_address: u32, + pub flags: u32, +} + +const IA32_APIC_BASE_MSR: u32 = 0x1B; +const IA32_APIC_BASE_MSR_ENABLE: usize = 0x800; + +pub fn has_apic() -> bool { + return unsafe { core::arch::x86_64::__cpuid_count(1, 0).edx } & 1 << 9 != 0; +} + +fn set_apic_base(apic: usize) { + let edx: u32 = 0; + let eax = (apic & 0xfffff0000) | IA32_APIC_BASE_MSR_ENABLE; + + unsafe { cpu_set_msr(IA32_APIC_BASE_MSR, &(eax as u32), &edx) }; +} + +fn get_apic_base() -> u32 { + let mut eax: u32 = 0; + let mut edx: u32 = 0; + unsafe { cpu_get_msr(IA32_APIC_BASE_MSR, &mut eax, &mut edx) }; + + return eax & 0xfffff000; +} + +#[repr(C, packed)] +#[derive(Clone, Copy, Debug)] +pub struct LAPIC { + pub acpi_processor_id: u8, + pub apic_id: u8, + pub flags: u32, +} + +#[repr(C, packed)] +#[derive(Clone, Copy, Debug)] +pub struct IOAPIC { + pub ioapic_id: u8, + _reserved: u8, + pub ptr: *mut u8, + pub global_interrupt_base: u32, +} + +#[repr(C, packed)] +#[derive(Clone, Copy, Debug)] +pub struct IOAPICSourceOverride { + bus_source: u8, + irq_source: u8, + global_system_interrupt: u32, + flags: u16, +} + +#[derive(Debug)] +pub struct APIC { + pub io_apic: IOAPIC, + local_apic: *mut u8, + pub cpus: Arc<[LAPIC]>, +} + +extern "C" fn test(info: *const limine::SmpInfo) -> ! { + crate::log_ok!("hey from CPU {:<02}", unsafe { (*info).processor_id }); + + hcf(); +} + +impl APIC { + pub fn new() -> Result { + disable_pic(); + + if !has_apic() { + return Err(()); + } + + let apic_base = get_apic_base() as usize; + + set_apic_base(apic_base); + + let madt = crate::drivers::acpi::find_table::("APIC"); + + if madt.is_none() { + return Err(()); + } + + let mut cpus: Vec = Vec::new(); + + let madt = madt.unwrap(); + + crate::log_info!("MADT located at: {:p}", core::ptr::addr_of!(madt)); + + let mut lapic_ptr = madt.inner.local_apic_address as *mut u8; + let mut io_apic = None; + let mut io_apic_source_override = None; + + let mut ptr = madt.extra.unwrap().as_ptr(); + let ptr_end = unsafe { ptr.add(madt.header.length as usize - 44) }; + + while (ptr as usize) < (ptr_end as usize) { + match unsafe { *ptr } { + 0 => { + if unsafe { *(ptr.add(4)) } & 1 != 0 { + cpus.push(unsafe { *ptr.add(2).cast::() }); + } + } + 1 => unsafe { + io_apic = Some(IOAPIC { + ioapic_id: *ptr.add(2), + _reserved: *ptr.add(3), + ptr: (*ptr.add(4).cast::()) as *mut u8, + global_interrupt_base: *ptr.add(8).cast::(), + }) + }, + 2 => unsafe { + io_apic_source_override = Some(IOAPICSourceOverride { + bus_source: *ptr.add(2), + irq_source: *ptr.add(3), + global_system_interrupt: *ptr.add(4).cast::(), + flags: *ptr.add(8).cast::(), + }) + }, + 5 => lapic_ptr = unsafe { *(ptr.add(4).cast::()) } as *mut u8, + _ => {} + } + + ptr = unsafe { ptr.add((*ptr.add(1)) as usize) }; + } + + if io_apic.is_none() || io_apic_source_override.is_none() { + return Err(()); + } + + let io_apic_ptr = io_apic.unwrap().ptr; + + crate::println!( + "Found {} core{}, IOAPIC {:p}, LAPIC {lapic_ptr:p}, Processor IDs:", + cpus.len(), + if cpus.len() > 1 { "s" } else { "" }, + io_apic_ptr, + ); + + for apic in &cpus { + crate::println!(" {}", apic.acpi_processor_id); + } + + let apic = Self { + io_apic: io_apic.unwrap(), + local_apic: lapic_ptr, + cpus: cpus.into(), + }; + + // Enable APIC by setting bit 8 to 1 + apic.write_lapic(0xF0, apic.read_lapic(0xF0) | 0x100); + + let io_apic_ver = apic.read_ioapic(0x01); + + let number_of_inputs = ((io_apic_ver >> 16) & 0xFF) + 1; + + crate::println!("{number_of_inputs}"); + + // // hopefully nothing important is on that page :shrug: + // // TODO: use the page allocator we wrote maybe + // unsafe { core::ptr::copy(test as *mut u8, 0x8000 as *mut u8, 4096) } + + let smp_request = SMP_REQUEST.get_response().get_mut(); + + if smp_request.is_none() { + panic!("Failed to get smp from limine!"); + } + + let smp_request = smp_request.unwrap(); + let bsp_lapic_id = smp_request.bsp_lapic_id; + + for cpu in smp_request.cpus() { + if cpu.processor_id == bsp_lapic_id { + continue; + } + + cpu.goto_address = test; + } + + // for cpu_apic in apic.cpus.iter() { + // let lapic_id = cpu_apic.apic_id; + + // // TODO: If CPU is the BSP, do not intialize it + + // crate::log_info!("Initializing CPU {processor_id:<02}, please wait",); + + // match apic.bootstrap_processor(processor_id, 0x8000) { + // Err(_) => crate::log_error!("Failed to initialize CPU {processor_id:<02}!"), + // Ok(_) => crate::log_ok!("Successfully initialized CPU {processor_id:<02}!"), + // } + // } + + // Set and enable keyboard interrupt + apic.set_interrupt(0x01, 0x01); + + return Ok(apic); + } + + // pub fn bootstrap_processor(&self, processor_id: u8, startup_page: usize) -> Result<(), ()> { + // // Clear LAPIC errors + // self.write_lapic(0x280, 0); + // // Select Auxiliary Processor + // self.write_lapic( + // 0x310, + // (self.read_lapic(0x310) & 0x00FFFFFF) | (processor_id as u32) << 24, + // ); + // // send INIT Inter-Processor Interrupt + // self.write_lapic(0x300, (self.read_lapic(0x300) & 0x00FFFFFF) | 0x00C500); + + // // Wait for IPI delivery + // while self.read_lapic(0x300) & (1 << 12) != 0 { + // unsafe { + // core::arch::asm!("pause"); + // } + // } + + // // Select Auxiliary Processor + // self.write_lapic( + // 0x310, + // (self.read_lapic(0x310) & 0x00FFFFFF) | (processor_id as u32) << 24, + // ); + // // deassert + // self.write_lapic(0x300, (self.read_lapic(0x300) & 0x00FFFFFF) | 0x00C500); + + // // Wait for IPI delivery + // while self.read_lapic(0x300) & (1 << 12) != 0 { + // unsafe { + // core::arch::asm!("pause"); + // } + // } + + // msdelay(10); + + // for i in 0..2 { + // self.write_lapic(0x280, 0); + // self.write_lapic( + // 0x310, + // (self.read_lapic(0x310) & 0x00FFFFFF) | (processor_id as u32) << 24, + // ); + // self.write_lapic(0x300, (self.read_lapic(0x300) & 0xfff0f800) | 0x000608); + // if i == 0 { + // usdelay(200); + // } else { + // msdelay(1000); + // } + // while self.read_lapic(0x300) & (1 << 12) != 0 { + // unsafe { + // core::arch::asm!("pause"); + // } + // } + // } + + // return Ok(()); + // } + + pub fn read_ioapic(&self, reg: u32) -> u32 { + unsafe { + core::ptr::write_volatile(self.io_apic.ptr.cast::(), reg & 0xff); + return core::ptr::read_volatile(self.io_apic.ptr.cast::().add(4)); + } + } + + pub fn write_ioapic(&self, reg: u32, value: u32) { + unsafe { + core::ptr::write_volatile(self.io_apic.ptr.cast::(), reg & 0xff); + core::ptr::write_volatile(self.io_apic.ptr.cast::().add(4), value); + } + } + + pub fn read_lapic(&self, reg: u32) -> u32 { + unsafe { + return *self.local_apic.add(reg as usize).cast::(); + } + } + + pub fn write_lapic(&self, reg: u32, value: u32) { + unsafe { + *self.local_apic.add(reg as usize).cast::() = value; + } + } + + pub fn lapic_send_ipi(&self, dest_id: u32, vec: u32) { + self.write_lapic(0x310, dest_id << 24); + self.write_lapic(0x300, vec); + } + + pub fn set_interrupt(&self, int_num: u8, redirtion_num: u8) { + let retbl_offset: u32 = 0x10 + (int_num as u32 * 2); + let interrupts_vt = + ((self.read_ioapic(retbl_offset) & 0x7FFF) & 0xFF00) | (0x20 + redirtion_num as u32); + + self.write_ioapic(retbl_offset, interrupts_vt) + } + + pub fn end_of_interrupt(&self) { + self.write_lapic(0xB0, 0x00); + } +} + +const PIC_CMD_MASTER: u16 = 0x20; +const PIC_CMD_SLAVE: u16 = 0xA0; +const PIC_DATA_MASTER: u16 = 0x21; +const PIC_DATA_SLAVE: u16 = 0xA1; + +fn disable_pic() { + // Tell each PIC we're going to initialize it. + outb(PIC_CMD_MASTER, 0x11); + outb(PIC_CMD_SLAVE, 0x11); + + // Byte 1: Set up our base offsets. + outb(PIC_DATA_MASTER, 0x20); + outb(PIC_DATA_SLAVE, 0x28); + + // Byte 2: Configure chaining + outb(PIC_DATA_MASTER, 0x04); // Tell Master Pic that there is a slave Pic at IRQ2 + outb(PIC_DATA_SLAVE, 0x02); // Tell Slave PIC it's cascade identity + + // Byte 3: Set out mode to 8086. + outb(PIC_DATA_MASTER, 0x01); + outb(PIC_DATA_SLAVE, 0x01); + + // Set each PIC's mask to 0xFF, disabling PIC interrupts + outb(PIC_DATA_MASTER, 0xFF); + outb(PIC_DATA_SLAVE, 0xFF); +} + +pub fn usdelay(useconds: u16) { + let pit_count = ((useconds as u32 * 1193) / 1000) as u16; + + pit_delay(pit_count); +} + +pub fn msdelay(ms: u32) { + let mut total_count = ms * 1193; + + while total_count > 0 { + let chunk_count = if total_count > u16::MAX as u32 { + u16::MAX + } else { + total_count as u16 + }; + + pit_delay(chunk_count); + + total_count -= chunk_count as u32; + } +} + +pub fn pit_delay(count: u16) { + // Set PIT to mode 0 + outb(0x43, 0x30); + outb(0x40, (count & 0xFF) as u8); + outb(0x40, ((count & 0xFF00) >> 8) as u8); + loop { + // Tell PIT to give us a timer status + outb(0x43, 0xE2); + if ((inb(0x40) >> 7) & 0x01) != 0 { + break; + } + } +} + +pub static APIC: OnceCell = OnceCell::new(); diff --git a/src/arch/x86_64/io.rs b/src/arch/x86_64/io.rs new file mode 100644 index 0000000..de9faf3 --- /dev/null +++ b/src/arch/x86_64/io.rs @@ -0,0 +1,132 @@ +use core::arch::asm; + +#[inline(always)] +pub fn outb(port: u16, value: u8) { + unsafe { + asm!( + "out dx, al", + in("dx") port, + in("al") value, + options(preserves_flags, nomem, nostack) + ); + } +} + +#[inline(always)] +pub fn inb(port: u16) -> u8 { + let mut value: u8; + unsafe { + asm!( + "in al, dx", + out("al") value, + in("dx") port, + options(preserves_flags, nomem, nostack) + ); + } + + value +} + +#[inline(always)] +pub fn outw(port: u16, value: u16) { + unsafe { + asm!( + "out dx, ax", + in("dx") port, + in("ax") value, + options(preserves_flags, nomem, nostack) + ); + } +} + +#[inline(always)] +pub fn inw(port: u16) -> u16 { + let mut value: u16; + unsafe { + asm!( + "in ax, dx", + out("ax") value, + in("dx") port, + options(preserves_flags, nomem, nostack) + ); + } + + value +} + +/// Reads `count` 16-bit values from the specified `port` into the `buffer`. +/// +/// # Safety +/// +/// This function panics if the supplied buffer's size is smaller than `count`. +#[inline(always)] +pub unsafe fn insw(port: u16, buffer: *mut u16, count: usize) { + asm!("cld", + "rep insw", + in("dx") port, + inout("rdi") buffer => _, + inout("rcx") count => _ + ); +} + +/// Outputs `count` 8-bit values from the specified `port` into the `buffer`. +/// +/// # Safety +/// +/// This function panics if the supplied buffer's size is smaller than `count`. +#[inline(always)] +pub unsafe fn outsb(port: u16, buffer: *const u8, count: usize) { + asm!("cld", + "rep outsb", + in("dx") port, + inout("rsi") buffer => _, + inout("rcx") count => _ + ); +} + +/// Outputs `count` 16-bit values from the specified `port` into the `buffer`. +/// +/// # Safety +/// +/// This function panics if the supplied buffer's size is smaller than `count`. +#[inline(always)] +pub unsafe fn outsw(port: u16, buffer: *const u16, count: usize) { + asm!("cld", + "rep outsw", + in("dx") port, + inout("rsi") buffer => _, + inout("rcx") count => _ + ); +} + +#[inline(always)] +pub fn outl(port: u16, value: u32) { + unsafe { + asm!( + "out dx, eax", + in("dx") port, + in("eax") value, + options(preserves_flags, nomem, nostack) + ); + } +} + +#[inline(always)] +pub fn inl(port: u16) -> u32 { + let mut value: u32; + unsafe { + asm!( + "in eax, dx", + out("eax") value, + in("dx") port, + options(preserves_flags, nomem, nostack) + ); + } + + value +} + +#[inline(always)] +pub fn io_wait() { + outb(0x80, 0); +} diff --git a/src/arch/x86_64/stack_trace.rs b/src/arch/x86_64/stack_trace.rs new file mode 100644 index 0000000..9bec98a --- /dev/null +++ b/src/arch/x86_64/stack_trace.rs @@ -0,0 +1,99 @@ +use alloc::{borrow::ToOwned, string::String, vec::Vec}; + +// use crate::drivers::fs::vfs::VfsFileSystem; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +struct StackFrame { + back: *const StackFrame, + rip: u64, +} + +pub fn print_stack_trace(max_frames: usize, rbp: u64) { + let mut stackframe = rbp as *const StackFrame; + + crate::println!("Stack Trace:"); + for _frame in 0..max_frames { + if stackframe.is_null() || unsafe { (*stackframe).back.is_null() } { + break; + } + + let instruction_pointer = unsafe { (*stackframe).rip }; + + if instruction_pointer == 0x0 { + unsafe { + stackframe = (*stackframe).back; + }; + continue; + } + + crate::print!(" {:#X} ", instruction_pointer); + + let instrcution_info = get_function_name(instruction_pointer); + + if let Ok((function_name, function_offset)) = instrcution_info { + crate::println!("<{}+{:#X}>", function_name, function_offset); + } else { + crate::println!(); + } + + unsafe { + stackframe = (*stackframe).back; + }; + } +} + +fn get_function_name(function_address: u64) -> Result<(String, u64), ()> { + return Err(()); + + // let symbols_fd = (*crate::drivers::fs::initramfs::INITRAMFS).open("/symbols.table")?; + + // let symbols_table_bytes = symbols_fd.read()?; + // let symbols_table = core::str::from_utf8(&symbols_table_bytes).ok().ok_or(())?; + + // let mut previous_symbol: Option<(&str, u64)> = None; + + // let symbols_table_lines: Vec<&str> = symbols_table.lines().collect(); + + // for (i, line) in symbols_table_lines.iter().enumerate() { + // let line_parts: Vec<&str> = line.splitn(2, ' ').collect(); + + // if line_parts.len() < 2 { + // continue; + // } + + // let (address, function_name) = ( + // u64::from_str_radix(line_parts[0], 16).ok().ok_or(())?, + // line_parts[1], + // ); + + // if address == function_address { + // return Ok((function_name.to_owned(), 0)); + // } + + // if i == symbols_table_lines.len() - 1 { + // return Ok((function_name.to_owned(), function_address - address)); + // } + + // if i == 0 { + // if function_address < address { + // return Err(()); + // } + + // previous_symbol = Some((function_name, address)); + // continue; + // } + + // if function_address > previous_symbol.unwrap().1 && function_address < address { + // // function is previous symbol + // return Ok(( + // previous_symbol.unwrap().0.to_owned(), + // address - previous_symbol.unwrap().1, + // )); + // } + + // previous_symbol = Some((function_name, address)); + // } + + // unreachable!(); +} diff --git a/src/drivers/fs/devfs.rs b/src/drivers/fs/devfs.rs new file mode 100644 index 0000000..1052ead --- /dev/null +++ b/src/drivers/fs/devfs.rs @@ -0,0 +1,19 @@ +use alloc::{boxed::Box, string::String, sync::Arc}; + +#[repr(u8)] +pub enum DeviceType { + CharacterDevice = 0, + BlockDevice = 1, +} + +pub struct Device { + typ: DeviceType, + block_size: usize, + name: String, + ops: Box, +} + +pub trait DeviceOperations { + fn read(&self, sector: u64, sector_count: usize) -> Result, ()>; + fn write(&self, sector: u64, data: &[u8]) -> Result<(), ()>; +} diff --git a/src/drivers/fs/vfs.rs b/src/drivers/fs/vfs.rs index c2d4b25..e109c0b 100755 --- a/src/drivers/fs/vfs.rs +++ b/src/drivers/fs/vfs.rs @@ -62,16 +62,24 @@ use core::fmt::Debug; -use alloc::{alloc::handle_alloc_error, boxed::Box, sync::Arc, vec::Vec}; +use alloc::{ + alloc::{alloc, handle_alloc_error}, + boxed::Box, + sync::Arc, + vec::Vec, +}; -use crate::{log_info, mem::PHYSICAL_MEMORY_MANAGER}; +use crate::{ + log_info, + mem::{ALLOCATOR, PHYSICAL_MEMORY_MANAGER}, +}; static mut ROOT_VFS: Vfs = Vfs::null(); pub struct Vfs { next: Option<*mut Vfs>, ops: Option>, - vnode_covered: Option>, + vnode_covered: Option<*const VNode>, flags: u32, block_size: u32, pub data: *mut u8, @@ -259,7 +267,7 @@ pub struct VAttr { pub fn add_vfs(mount_point: &str, fs_ops: Box) -> Result<(), ()> { let layout = alloc::alloc::Layout::new::(); - let vfs = PHYSICAL_MEMORY_MANAGER.alloc(1).unwrap().cast::(); + let vfs = unsafe { alloc(layout).cast::() }; let vfs = unsafe { &mut *vfs }; diff --git a/src/drivers/storage/ide.rs b/src/drivers/storage/ide.rs index e4be190..cce6667 100755 --- a/src/drivers/storage/ide.rs +++ b/src/drivers/storage/ide.rs @@ -690,8 +690,6 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) { let fat_fs = fat_fs.unwrap(); - crate::println!("adding fat fs to / :scared:"); - add_vfs("/", Box::new(fat_fs)); // let vfs = crate::drivers::fs::vfs::Vfs::new( diff --git a/src/drivers/video.rs b/src/drivers/video.rs new file mode 100644 index 0000000..9c39624 --- /dev/null +++ b/src/drivers/video.rs @@ -0,0 +1,93 @@ +use limine::FramebufferRequest; + +use crate::libs::cell::OnceCell; + +#[derive(Clone, Copy, Debug)] +pub struct Framebuffer { + pub width: usize, + pub height: usize, + pub bpp: usize, + pub pitch: usize, + pub pointer: *mut u8, +} + +impl Framebuffer { + #[inline] + const fn new(bpp: usize, pitch: usize, ptr: *mut u8, width: usize, height: usize) -> Self { + return Self { + width, + height, + bpp, + pitch, + pointer: ptr, + }; + } + + // Returns the size of the framebuffer in bytes + pub fn len(&self) -> usize { + return self.pitch * self.height; + } + + pub fn put_pixel(&self, x: u32, y: u32, color: u32) { + let pixel_offset = (y * self.pitch as u32 + (x * (self.bpp / 8) as u32)) as isize; + + unsafe { + *(self.pointer.offset(pixel_offset) as *mut u32) = color; + } + } + + // This is slow, but significantly faster than filling the framebuffer pixel-by-pixel with for loops. + // idk, fix it later ig. + pub fn fill_screen(&self, color: u32, mirror_buffer: Option) { + let buffer_size = (self.pitch / (self.bpp / 8)) * self.height; + + unsafe { + if let Some(mirror_buffer) = mirror_buffer { + crate::mem::memset32(mirror_buffer.pointer as *mut u32, color, buffer_size); + } + + crate::mem::memset32(self.pointer as *mut u32, color, buffer_size); + } + } + + pub fn blit_screen(&self, buffer: &mut [u32], mirror_buffer: Option) { + unsafe { + core::ptr::copy_nonoverlapping(buffer.as_ptr(), self.pointer as *mut u32, buffer.len()); + + if let Some(mirror_buffer) = mirror_buffer { + core::ptr::copy_nonoverlapping( + buffer.as_ptr(), + mirror_buffer.pointer as *mut u32, + buffer.len(), + ); + } + }; + } +} + +pub static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new(0); +pub static FRAMEBUFFER: OnceCell> = OnceCell::new(); + +pub fn get_framebuffer() -> Option { + *FRAMEBUFFER.get_or_set(|| { + let framebuffer_response = crate::drivers::video::FRAMEBUFFER_REQUEST + .get_response() + .get()?; + + if framebuffer_response.framebuffer_count < 1 { + return None; + } + + let framebuffer_response = &framebuffer_response.framebuffers()[0]; + + let framebuffer = Framebuffer::new( + framebuffer_response.bpp as usize, + framebuffer_response.pitch as usize, + framebuffer_response.address.as_ptr().unwrap(), + framebuffer_response.width as usize, + framebuffer_response.height as usize, + ); + + return Some(framebuffer); + }) +} diff --git a/src/libs/cell/lazy.rs b/src/libs/cell/lazy.rs new file mode 100755 index 0000000..b0f7f9f --- /dev/null +++ b/src/libs/cell/lazy.rs @@ -0,0 +1,54 @@ +use core::ops::Deref; + +use super::Cell; + +#[derive(PartialEq)] +enum LazyState T> { + Uninitialized(F), + Initializing, + Initialized(T), +} + +pub struct LazyCell T> { + state: Cell>, +} + +impl T> LazyCell { + pub const fn new(init_func: F) -> Self { + Self { + state: Cell::new(LazyState::Uninitialized(init_func)), + } + } + + pub fn get(&self) -> Option<&T> { + match self.state.get() { + LazyState::Initialized(data) => Some(data), + _ => None, + } + } +} + +impl T> Deref for LazyCell { + type Target = T; + + fn deref(&self) -> &Self::Target { + match self.state.get() { + LazyState::Uninitialized(func) => { + self.state.set(LazyState::Initializing); + + // initialize and return value + let new_value = func(); + + self.state.set(LazyState::Initialized(new_value)); + + self.get().unwrap() + } + LazyState::Initialized(data) => data, + LazyState::Initializing => { + panic!("Attempted to initialize Lazy while initializing Lazy!") + } + } + } +} + +unsafe impl T + Send> Sync for LazyCell {} diff --git a/src/libs/cell/mod.rs b/src/libs/cell/mod.rs new file mode 100644 index 0000000..3b531b5 --- /dev/null +++ b/src/libs/cell/mod.rs @@ -0,0 +1,27 @@ +use core::cell::UnsafeCell; + +mod lazy; +mod once; + +pub use lazy::LazyCell; +pub use once::OnceCell; + +pub struct Cell { + value: UnsafeCell, +} + +impl Cell { + pub const fn new(value: T) -> Cell { + return Self { + value: UnsafeCell::new(value), + }; + } + + pub fn get(&self) -> &T { + return unsafe { &*self.value.get() }; + } + + pub fn set(&self, new_value: T) { + unsafe { *self.value.get() = new_value }; + } +} diff --git a/src/libs/cell/once.rs b/src/libs/cell/once.rs new file mode 100644 index 0000000..a08f47c --- /dev/null +++ b/src/libs/cell/once.rs @@ -0,0 +1,63 @@ +use core::ops::Deref; + +use super::Cell; + +pub struct OnceCell { + state: Cell>, +} + +unsafe impl Sync for OnceCell {} + +enum OnceCellState { + Uninitialized, + Initializing, + Initialized(T), +} + +impl OnceCell { + pub const fn new() -> Self { + return OnceCell { + state: Cell::new(OnceCellState::Uninitialized), + }; + } + + pub fn set(&self, new_data: T) { + match self.state.get() { + OnceCellState::Uninitialized => { + self.state.set(OnceCellState::Initializing); + + self.state.set(OnceCellState::Initialized(new_data)); + } + _ => panic!("Tried to initialize data that is alread initialized"), + } + } + + pub fn get_or_set(&self, func: F) -> &T + where + F: FnOnce() -> T, + { + match self.state.get() { + OnceCellState::Uninitialized => { + self.set(func()); + self.get() + } + OnceCellState::Initializing => panic!("Tried to get or set data that is initializing"), + OnceCellState::Initialized(data) => data, + } + } + + fn get(&self) -> &T { + match self.state.get() { + OnceCellState::Initialized(data) => data, + _ => panic!("Attempted to access uninitialized data!"), + } + } +} + +impl Deref for OnceCell { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.get() + } +} diff --git a/src/libs/sync/mod.rs b/src/libs/sync/mod.rs new file mode 100644 index 0000000..663c496 --- /dev/null +++ b/src/libs/sync/mod.rs @@ -0,0 +1,3 @@ +mod mutex; + +pub use mutex::Mutex; diff --git a/src/libs/sync/mutex.rs b/src/libs/sync/mutex.rs new file mode 100755 index 0000000..d725796 --- /dev/null +++ b/src/libs/sync/mutex.rs @@ -0,0 +1,72 @@ +use core::{ + cell::UnsafeCell, + ops::{Deref, DerefMut}, + sync::atomic::{AtomicBool, Ordering}, +}; + +pub struct Mutex { + locked: AtomicBool, + data: UnsafeCell, +} + +unsafe impl Sync for Mutex {} + +impl Mutex { + #[inline] + pub const fn new(data: T) -> Self { + return Self { + locked: AtomicBool::new(false), + data: UnsafeCell::new(data), + }; + } + + pub fn lock(&self) -> MutexGuard<'_, T> { + // if self.locked.load(Ordering::Acquire) == true { + // unsafe { core::arch::asm!("out dx, al", in("dx") 0x3f8, in("al") 'S' as u8) }; + // } + while self.locked.swap(true, Ordering::Acquire) { + // spin lock + } + return MutexGuard { mutex: self }; + } +} + +impl core::fmt::Debug for Mutex { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let locked = self.locked.load(Ordering::SeqCst); + write!(f, "Mutex: {{ data: ")?; + + if locked { + write!(f, " }}") + } else { + write!(f, "{:?} }}", self.data) + } + } +} + +pub struct MutexGuard<'a, T: ?Sized> { + mutex: &'a Mutex, +} + +impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + // unsafe { core::arch::asm!("out dx, al", in("dx") 0x3f8, in("al") 'D' as u8) }; + + unsafe { &*self.mutex.data.get() } + } +} + +impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> { + fn deref_mut(&mut self) -> &mut T { + // unsafe { core::arch::asm!("out dx, al", in("dx") 0x3f8, in("al") 'M' as u8) }; + unsafe { &mut *self.mutex.data.get() } + } +} + +impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { + fn drop(&mut self) { + self.mutex.locked.store(false, Ordering::Release); + } +} diff --git a/src/main.rs b/src/main.rs index 156f437..123f1b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,14 @@ pub extern "C" fn _start() -> ! { drivers::storage::ide::init(); - crate::println!("{:?}", vfs_open("/example.txt")); + let nested_file = vfs_open("/boot/limine/limine.cfg").unwrap(); + + crate::println!( + "{:X?}", + nested_file + .ops + .open(0, UserCred { uid: 0, gid: 0 }, nested_file.as_ptr()) + ); let file = vfs_open("/example.txt").unwrap(); crate::println!( @@ -102,7 +109,7 @@ macro_rules! print { #[macro_export] macro_rules! log_info { - ($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[90m? \x1B[97m]\x1B[0m () {}", &alloc::format!($($arg)*))); + ($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[90m? \x1B[97m]\x1B[0m {}", &alloc::format!($($arg)*))); } #[macro_export]