diff --git a/.cargo/config.toml b/.cargo/config.toml index 5bbb07d..01664bc 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,4 +6,5 @@ build-std = [ ] [build] -target = "./src/arch/x86_64/x86_64-unknown-none.json" \ No newline at end of file +target = "./src/arch/x86_64/x86_64-unknown-none.json" +rustflags = ["-Cforce-frame-pointers=yes"] \ No newline at end of file diff --git a/Makefile b/Makefile index cc875cb..ce50651 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,9 @@ else endif build-iso: partition-iso + nm target/${ARCH}-unknown-none/${MODE}/CappuccinOS.elf > scripts/symbols.table + python scripts/demangle-symbols.py + mv scripts/symbols.table ${ISO_PATH}/boot # Install the Limine bootloader on the ISO ./limine/limine bios-install ${IMAGE_PATH} diff --git a/README.md b/README.md index b86f2e4..c32748b 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ CappuccinOS is a small x86-64 operating system written from scratch in rust. Thi Before building CappuccinOS, make sure you have the following installed on your machine: - rust +- python - binutils - sgdisk - mtools @@ -64,22 +65,19 @@ curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none Install the dependencies:
Arch - - ```BASH - sudo pacman -S binutils gptfdisk mtools squashfs-tools + + sudo pacman -S binutils gptfdisk mtools squashfs-tools python # Optionally sudo pacman -S qemu-system-x86 - ```
Ubuntu - - ```BASH + Python should be installed by default, and if it's not, make an issue or a PR and I'll fix it + sudo apt install binutils gdisk mtools squashfs-tools # Optionally sudo apt install qemu - ```
## Usage diff --git a/scripts/README.md b/scripts/README.md index b425a37..e23ab35 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,4 +1,2 @@ # CappuccinOS/scripts -This folder is responsible for holding all the scripts that are necessary for building CappuccinOS, the list currently includes: - -- [initramfs.py](initramfs.py): This file is used for generating an initramfs file that holds critical drivers that the kernel needs to access other drivers that may be located on block storage. \ No newline at end of file +This folder is responsible for holding all the scripts that are necessary for building CappuccinOS diff --git a/scripts/demangle-symbols.py b/scripts/demangle-symbols.py new file mode 100644 index 0000000..6664482 --- /dev/null +++ b/scripts/demangle-symbols.py @@ -0,0 +1,20 @@ +import rustc_demangle.rustc_demangle as rustc_demangle + +def demangle_function_name(mangled_name): + return rustc_demangle.demangle(mangled_name).get_fn_name(False) + +if __name__ == "__main__": + with open("scripts/symbols.table", 'r') as infile: + lines = infile.readlines() + + sorted_lines = sorted(lines, key=lambda line: int(line.split()[0], 16) if len(line.split()) >= 1 else 0) + + with open("scripts/symbols.table", 'w') as outfile: + for line in sorted_lines: + parts = line.split() + if len(parts) >= 3: + address = parts[0] + mangled_name = parts[2] + demangled_name = demangle_function_name(mangled_name) + new_line = f"{address} {demangled_name}\n" + outfile.write(new_line) diff --git a/scripts/initramfs.py b/scripts/initramfs.py deleted file mode 100644 index 799b10a..0000000 --- a/scripts/initramfs.py +++ /dev/null @@ -1,25 +0,0 @@ -import os -import gzip -import shutil -import sys - -if __name__ == "__main__": - if len(sys.argv) != 3: - print(f"Usage: python scripts/initramfs.py /path/to/source/directory /path/to/output/directory/initramfs.gz") - sys.exit(1) - - source_dir, output_file = sys.argv[1], sys.argv[2] - - try: - with gzip.open(output_file, 'wb') as gz_file: - for foldername, subfolders, filenames in os.walk(source_dir): - for filename in filenames: - file_path = os.path.join(foldername, filename) - rel_path = os.path.relpath(file_path, source_dir) - gz_file.write(os.path.join(rel_path).encode()) - with open(file_path, 'rb') as source_file: - shutil.copyfileobj(source_file, gz_file) - print(f"Compression completed. Output file: {output_file}") - except Exception as e: - print(f"Error compressing directory: {str(e)}") - sys.exit(1) diff --git a/src/arch/x86_64/interrupts/exceptions.rs b/src/arch/x86_64/interrupts/exceptions.rs index 22bec45..3b00e43 100644 --- a/src/arch/x86_64/interrupts/exceptions.rs +++ b/src/arch/x86_64/interrupts/exceptions.rs @@ -30,6 +30,7 @@ pub extern "C" fn exception_handler(int: u64, eip: u64, cs: u64, eflags: u64) -> log_error!("EXCEPTION!"); } } + log_info!( "INT: {:x} EIP: {:X}, CS: {:X}, EFLAGS: {:b}", int, @@ -38,6 +39,12 @@ pub extern "C" fn exception_handler(int: u64, eip: u64, cs: u64, eflags: u64) -> eflags ); + // unsafe { + // core::arch::asm!("cli"); + // }; + + crate::arch::stack_trace::print_stack_trace(6); + hcf(); } diff --git a/src/arch/x86_64/interrupts/mod.rs b/src/arch/x86_64/interrupts/mod.rs old mode 100644 new mode 100755 diff --git a/src/arch/x86_common/mod.rs b/src/arch/x86_common/mod.rs index b8ef87e..f4e351c 100644 --- a/src/arch/x86_common/mod.rs +++ b/src/arch/x86_common/mod.rs @@ -1,5 +1,6 @@ pub mod io; pub mod pic; +pub mod stack_trace; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[inline(always)] diff --git a/src/arch/x86_common/stack_trace.rs b/src/arch/x86_common/stack_trace.rs new file mode 100644 index 0000000..6a6adbf --- /dev/null +++ b/src/arch/x86_common/stack_trace.rs @@ -0,0 +1,26 @@ +#[repr(C)] +#[derive(Clone, Copy, Debug)] +struct StackFrame { + back: *const StackFrame, + rip: u64, +} + +pub fn print_stack_trace(max_frames: usize) { + let mut stackframe: *const StackFrame; + + unsafe { + core::arch::asm!("mov {0:r}, rbp", out(reg) stackframe); + }; + + crate::println!("Stack Trace:"); + for _frame in 0..max_frames { + if stackframe.is_null() || unsafe { (*stackframe).back.is_null() } { + break; + } + + unsafe { + crate::println!(" {:#X}", (*stackframe).rip); + stackframe = (*stackframe).back; + }; + } +} diff --git a/src/drivers/fs/fat.rs b/src/drivers/fs/fat.rs old mode 100644 new mode 100755 index ca7f7a1..c61626f --- a/src/drivers/fs/fat.rs +++ b/src/drivers/fs/fat.rs @@ -2,7 +2,7 @@ use alloc::{ boxed::Box, string::{String, ToString}, sync::Arc, - vec::{self, Vec}, + vec::Vec, }; use crate::drivers::storage::drive::{BlockDevice, GPTPartitionEntry}; @@ -23,6 +23,7 @@ use super::vfs::{VFSDirectory, VFSFile, VFSFileSystem}; // End Of Chain const EOC: u32 = 0x0FFFFFF8; +#[derive(Debug)] enum FatType { Fat12, Fat16, @@ -154,6 +155,7 @@ pub struct FATFS<'a> { fat_start: u64, fat_type: FatType, cluster_size: usize, + sectors_per_fat: usize, } impl<'a> FATFS<'a> { @@ -219,6 +221,7 @@ impl<'a> FATFS<'a> { } else { (bpb.total_sectors as u32, bpb.sectors_per_fat as u32) }; + let root_dir_sectors = ((bpb.root_directory_count * 32) + (bpb.bytes_per_sector - 1)) / bpb.bytes_per_sector; let total_data_sectors = total_sectors @@ -236,6 +239,13 @@ impl<'a> FATFS<'a> { FatType::Fat32 }; + crate::println!("Found {fat_type:?} FS"); + + let sectors_per_fat = match fat_type { + FatType::Fat32 => bpb.sectors_per_fat_ext as usize, + _ => bpb.sectors_per_fat as usize, + }; + let cluster_size = bpb.sectors_per_cluster as usize * 512; return Ok(Self { @@ -247,6 +257,7 @@ impl<'a> FATFS<'a> { fat_start, fat_type, cluster_size, + sectors_per_fat, }); } @@ -364,17 +375,17 @@ impl<'a> FATFS<'a> { } fn cluster_to_sector(&self, cluster: usize) -> usize { - let fat_size = self.bpb.sectors_per_fat_ext; + let fat_size = self.sectors_per_fat; let root_dir_sectors = ((self.bpb.root_directory_count * 32) + (self.bpb.bytes_per_sector - 1)) / self.bpb.bytes_per_sector; - let first_data_sector = self.bpb.reserved_sectors as u32 - + (self.bpb.fat_count as u32 * fat_size) - + root_dir_sectors as u32; + let first_data_sector = self.bpb.reserved_sectors as usize + + (self.bpb.fat_count as usize * fat_size) + + root_dir_sectors as usize; return ((cluster - 2) as isize * self.bpb.sectors_per_cluster as isize) as usize - + first_data_sector as usize; + + first_data_sector; } fn get_next_cluster(&self, cluster: usize) -> u32 { diff --git a/src/drivers/fs/initramfs/mod.rs b/src/drivers/fs/initramfs/mod.rs old mode 100644 new mode 100755 index 3d31c85..e0bd5cf --- a/src/drivers/fs/initramfs/mod.rs +++ b/src/drivers/fs/initramfs/mod.rs @@ -1,11 +1,15 @@ pub mod compressors; +use alloc::vec::Vec; use limine::ModuleRequest; pub static MODULE_REQUEST: ModuleRequest = ModuleRequest::new(0); +const SQUASHFS_INODE_OFFSET: fn(a: u32) -> u32 = |a| a & 0xFFF; +const SQUASHFS_INODE_BLK: fn(a: u32) -> u32 = |a| a >> 16; + pub fn init() { - // TODO: Put this stuff in another file? + // TODO: Put the module request stuff in another file? if MODULE_REQUEST.get_response().get().is_none() { crate::log_error!("Module request in none!"); return; @@ -28,6 +32,7 @@ pub fn init() { initramfs = Some(module); } + // End TODO if initramfs.is_none() { crate::log_error!("Initramfs was not found!"); @@ -44,11 +49,291 @@ pub fn init() { .add(initramfs.length as usize) }); - init_fs(initramfs.base.as_ptr().unwrap()); + let squashfs = Squashfs::new(initramfs.base.as_ptr().unwrap()); + + if squashfs.is_err() { + crate::log_error!("Initramfs in corrupt!"); + return; + } + + let squashfs = squashfs.unwrap(); + + crate::println!("{:X?}", squashfs); + crate::println!("{:?}", squashfs.superblock.features()); + + squashfs.test(); +} + +#[derive(Debug)] +struct Squashfs<'a> { + ptr: *mut u8, + superblock: SquashfsSuperblock, + data_table: &'a [u8], + inode_table: &'a [u8], + directory_table: &'a [u8], + fragment_table: Option<&'a [u8]>, + export_table: Option<&'a [u8]>, + id_table: &'a [u8], + xattr_table: Option<&'a [u8]>, +} + +impl Squashfs<'_> { + fn new(ptr: *mut u8) -> Result, ()> { + crate::println!("Parsing initramfs fs at {:p}", ptr); + + // bytes used from superblock + let length = unsafe { u64::from_le(*(ptr.add(40) as *const u64)) as usize }; + + let squashfs_data: &[u8] = unsafe { core::slice::from_raw_parts(ptr, length) }; + + let superblock = SquashfsSuperblock::new(&squashfs_data)?; + + let data_table = &squashfs_data + [core::mem::size_of::()..superblock.inode_table as usize]; + + let inode_table = + &squashfs_data[superblock.inode_table as usize..superblock.dir_table as usize]; + + let directory_table = + &squashfs_data[superblock.dir_table as usize..superblock.frag_table as usize]; + + let mut fragment_table: Option<&[u8]> = None; + + if superblock.frag_table != u64::MAX { + fragment_table = Some( + &squashfs_data[superblock.frag_table as usize..superblock.export_table as usize], + ); + } + + let mut export_table: Option<&[u8]> = None; + + if superblock.export_table != u64::MAX { + export_table = Some( + &squashfs_data[superblock.export_table as usize..superblock.id_table as usize], + ); + } + + let mut id_table: &[u8] = &squashfs_data[superblock.id_table as usize..]; + let mut xattr_table: Option<&[u8]> = None; + + if superblock.xattr_table != u64::MAX { + id_table = + &squashfs_data[superblock.id_table as usize..superblock.xattr_table as usize]; + xattr_table = Some(&squashfs_data[superblock.xattr_table as usize..]); + } + + return Ok(Squashfs { + ptr: unsafe { ptr.add(core::mem::size_of::()) }, + superblock, + data_table, + inode_table, + directory_table, + fragment_table, + export_table, + id_table, + xattr_table, + }); + } + + // big function that does stuff hard coded-ly before I rip it all out + pub fn test(&self) { + // the bottom 15 bits, I think the last bit indicates whether the data is uncompressed + let inode_table_header = u16::from_le_bytes(self.inode_table[0..2].try_into().unwrap()); + let inode_is_compressed = inode_table_header & 0x80 != 0; + let inode_table_size = inode_table_header & 0x7FFF; + + if inode_table_size >= 8192 { + panic!("Inode block is not less than 8KiB!"); + } + + let mut buffer: Vec = Vec::with_capacity(8192); + + if inode_is_compressed { + todo!("uncompress zlib data") + } else { + unsafe { + core::ptr::copy_nonoverlapping( + self.inode_table.as_ptr().add(2), + buffer.as_mut_ptr(), + inode_table_size as usize, + ); + + buffer.set_len(inode_table_size as usize); + } + } + + let root_inode_block = self.superblock.root_inode_block as usize; + let root_inode_offset = self.superblock.root_inode_offset as usize; + + let root_inode_header = self.read_inode(root_inode_offset as u32); + + let root_inode_header = InodeHeader { + file_type: u16::from_le_bytes( + buffer[root_inode_offset..root_inode_offset + 2] + .try_into() + .unwrap(), + ) + .into(), + _reserved: [ + u16::from_le_bytes( + buffer[root_inode_offset + 2..root_inode_offset + 4] + .try_into() + .unwrap(), + ), + u16::from_le_bytes( + buffer[root_inode_offset + 4..root_inode_offset + 6] + .try_into() + .unwrap(), + ), + u16::from_le_bytes( + buffer[root_inode_offset + 6..root_inode_offset + 8] + .try_into() + .unwrap(), + ), + ], + mtime: u32::from_le_bytes( + buffer[root_inode_offset + 8..root_inode_offset + 12] + .try_into() + .unwrap(), + ), + inode_num: u32::from_le_bytes( + buffer[root_inode_offset + 12..root_inode_offset + 16] + .try_into() + .unwrap(), + ), + }; + + crate::println!("{:X?}", root_inode_header); + + let root_inode = DirectoryInode { + block_index: u32::from_le_bytes( + buffer[root_inode_offset + 16..root_inode_offset + 20] + .try_into() + .unwrap(), + ), + link_count: u32::from_le_bytes( + buffer[root_inode_offset + 20..root_inode_offset + 24] + .try_into() + .unwrap(), + ), + file_size: u16::from_le_bytes( + buffer[root_inode_offset + 24..root_inode_offset + 26] + .try_into() + .unwrap(), + ), + block_offset: u16::from_le_bytes( + buffer[root_inode_offset + 26..root_inode_offset + 28] + .try_into() + .unwrap(), + ), + parent_inode: u32::from_le_bytes( + buffer[root_inode_offset + 28..root_inode_offset + 32] + .try_into() + .unwrap(), + ), + }; + + crate::println!("{:?}", root_inode); + } + + fn read_inode(&self, inode_num: u32) -> Option { + let inode_offset = inode_num as usize + 2; + + if inode_offset + core::mem::size_of::() > self.inode_table.len() { + return None; + } + + let inode_header_bytes = &self.inode_table[inode_offset..(inode_offset + 16)]; + + crate::println!("{:X?}", inode_header_bytes); + let inode_header = InodeHeader::from_bytes(inode_header_bytes)?; + + Some(inode_header) + } +} + +#[derive(Debug)] +struct InodeHeader { + file_type: InodeFileType, + _reserved: [u16; 3], + mtime: u32, + inode_num: u32, +} + +impl InodeHeader { + fn from_bytes(bytes: &[u8]) -> Option { + let file_type = u16::from_le_bytes(bytes[0..2].try_into().unwrap()).into(); + let mtime = u32::from_le_bytes(bytes[8..12].try_into().unwrap()); + let inode_num = u32::from_le_bytes(bytes[12..16].try_into().unwrap()); + + Some(InodeHeader { + file_type, + _reserved: [0; 3], + mtime, + inode_num, + }) + } +} + +#[derive(Debug)] +struct DirectoryInode { + block_index: u32, + link_count: u32, + file_size: u16, + block_offset: u16, + parent_inode: u32, +} + +#[derive(Debug)] +struct FileInode { + block_start: u32, + frag_idx: u32, + block_offset: u32, + file_size: u32, + block_size: [u32; 0], } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u16)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum InodeFileType { + BasicDirectory = 1, + BasicFile = 2, + BasicSymlink = 3, + BasicBlockDevice = 4, + BasicCharDevice = 5, + BasicPipe = 6, + BasicSocked = 7, + ExtendedDirectory = 8, + ExtendedFile = 9, + ExtendedSymlink = 10, + ExtendedBlockDevice = 11, + ExtendedPipe = 12, + ExtendedSocked = 13, +} + +impl Into for u16 { + fn into(self) -> InodeFileType { + match self { + 1 => InodeFileType::BasicDirectory, + 2 => InodeFileType::BasicFile, + 3 => InodeFileType::BasicSymlink, + 4 => InodeFileType::BasicBlockDevice, + 5 => InodeFileType::BasicCharDevice, + 6 => InodeFileType::BasicPipe, + 7 => InodeFileType::BasicSocked, + 8 => InodeFileType::ExtendedDirectory, + 9 => InodeFileType::ExtendedFile, + 10 => InodeFileType::ExtendedSymlink, + 11 => InodeFileType::ExtendedBlockDevice, + 12 => InodeFileType::ExtendedPipe, + 13 => InodeFileType::ExtendedSocked, + _ => panic!("Unexpected Inode file type {self}!"), + } + } +} + +#[repr(u16)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] enum SquashfsCompressionType { GZIP = 1, LZMA = 2, @@ -104,6 +389,7 @@ impl Into for u16 { } } +#[repr(C)] #[derive(Clone, Copy, Debug)] struct SquashfsSuperblock { magic: u32, // 0x73717368 @@ -117,7 +403,9 @@ struct SquashfsSuperblock { id_count: u16, // 0x01 ver_major: u16, // 0x04 ver_minor: u16, // 0x00 - root_inode: u64, // 0x20 + root_inode_offset: u16, // + root_inode_block: u32, // + _reserved: u16, // 0x20 bytes_used: u64, // 0x0103 id_table: u64, // 0x00FB xattr_table: u64, // 0xFFFFFFFFFFFFFFFF @@ -128,8 +416,8 @@ struct SquashfsSuperblock { } impl SquashfsSuperblock { - fn new(bytes: &[u8]) -> Self { - return Self { + fn new(bytes: &[u8]) -> Result { + let superblock = Self { magic: u32::from_le_bytes(bytes[0..4].try_into().unwrap()), inode_count: u32::from_le_bytes(bytes[4..8].try_into().unwrap()), mod_time: u32::from_le_bytes(bytes[8..12].try_into().unwrap()), @@ -141,7 +429,9 @@ impl SquashfsSuperblock { id_count: u16::from_le_bytes(bytes[26..28].try_into().unwrap()), ver_major: u16::from_le_bytes(bytes[28..30].try_into().unwrap()), ver_minor: u16::from_le_bytes(bytes[30..32].try_into().unwrap()), - root_inode: u64::from_le_bytes(bytes[32..40].try_into().unwrap()), + root_inode_offset: u16::from_le_bytes(bytes[32..34].try_into().unwrap()), + root_inode_block: u32::from_le_bytes(bytes[34..38].try_into().unwrap()), + _reserved: u16::from_le_bytes(bytes[38..40].try_into().unwrap()), bytes_used: u64::from_le_bytes(bytes[40..48].try_into().unwrap()), id_table: u64::from_le_bytes(bytes[48..56].try_into().unwrap()), xattr_table: u64::from_le_bytes(bytes[56..64].try_into().unwrap()), @@ -150,12 +440,39 @@ impl SquashfsSuperblock { frag_table: u64::from_le_bytes(bytes[80..88].try_into().unwrap()), export_table: u64::from_le_bytes(bytes[88..96].try_into().unwrap()), }; + + if superblock.magic != 0x73717368 { + return Err(()); + } + + if superblock.ver_major != 4 || superblock.ver_minor != 0 { + return Err(()); + } + + if superblock.block_size > 1048576 { + return Err(()); + } + + if superblock.block_log > 20 { + return Err(()); + } + + if superblock.block_size != (1 << superblock.block_log) { + return Err(()); + } + + if superblock.block_size == 0 { + return Err(()); + } + + if ((superblock.block_size - 1) & superblock.block_size) != 0 { + return Err(()); + } + + return Ok(superblock); } fn features(&self) -> SquashfsFeatures { - // let graphical_output = ((*self.feature_bits.lock().read()) & 0x01) != 0; - // let serial_output = ((*self.feature_bits.lock().read()) & 0x02) != 0; - // let doubled_buffered = ((*self.feature_bits.lock().read()) & 0x04) != 0; let uncompressed_inodes = (self.flags & SquashfsFlags::UncompressedInodes as u16) != 0; let uncompressed_data_blocks = (self.flags & SquashfsFlags::UncompressedDataBlocks as u16) != 0; @@ -189,74 +506,3 @@ impl SquashfsSuperblock { }; } } - -#[derive(Debug)] -struct Squashfs<'a> { - ptr: *mut u8, - superblock: SquashfsSuperblock, - data_table: &'a [u8], - inode_table: &'a [u8], - directory_table: &'a [u8], - fragment_table: Option<&'a [u8]>, - export_table: Option<&'a [u8]>, - id_table: &'a [u8], - xattr_table: Option<&'a [u8]>, -} - -fn init_fs(initramfs: *mut u8) { - crate::println!("Parsing initramfs fs at {:p}", initramfs); - - // bytes used from superblock - let length = unsafe { u64::from_le(*(initramfs.add(40) as *const u64)) as usize }; - - let squashfs_data: &[u8] = unsafe { core::slice::from_raw_parts(initramfs, length) }; - - let superblock = SquashfsSuperblock::new(&squashfs_data); - - let data_table = - &squashfs_data[core::mem::size_of::()..superblock.inode_table as usize]; - - let inode_table = - &squashfs_data[superblock.inode_table as usize..superblock.dir_table as usize]; - - let directory_table = - &squashfs_data[superblock.dir_table as usize..superblock.frag_table as usize]; - - let mut fragment_table: Option<&[u8]> = None; - - if superblock.frag_table != u64::MAX { - fragment_table = - Some(&squashfs_data[superblock.frag_table as usize..superblock.export_table as usize]); - } - - let mut export_table: Option<&[u8]> = None; - - if superblock.export_table != u64::MAX { - export_table = - Some(&squashfs_data[superblock.export_table as usize..superblock.id_table as usize]); - } - - let mut id_table: &[u8] = &squashfs_data[superblock.id_table as usize..]; - let mut xattr_table: Option<&[u8]> = None; - - if superblock.xattr_table != u64::MAX { - id_table = &squashfs_data[superblock.id_table as usize..superblock.xattr_table as usize]; - xattr_table = Some(&squashfs_data[superblock.xattr_table as usize..]); - } - - let squashfs = Squashfs { - ptr: initramfs, - superblock, - data_table, - inode_table, - directory_table, - fragment_table, - export_table, - id_table, - xattr_table, - }; - - crate::println!("{:#X?}", squashfs); - - crate::println!("{:?}", squashfs.superblock.features()); -} diff --git a/src/drivers/fs/vfs.rs b/src/drivers/fs/vfs.rs old mode 100644 new mode 100755 index a25ff10..9989ba3 --- a/src/drivers/fs/vfs.rs +++ b/src/drivers/fs/vfs.rs @@ -40,88 +40,3 @@ pub fn init() { // TODO: Deduce which storage medium(s) we're using crate::drivers::storage::ide::init(); } - -// //? Please, shield your eyes and hide your children - -// // This is... really bad to say the least, I think you can make it way better by using traits but I'm not sure - -// use alloc::{sync::Arc, vec::Vec}; - -// use crate::libs::mutex::Mutex; - -// pub struct VFSPartition { -// start_sector: usize, -// sectors: usize, -// } - -// pub struct VFSDrive { -// sectors: usize, -// read: fn(sector: u64, sector_count: usize) -> Result, ()>, -// write: fn(sector: u64, data: &[u8]) -> Result<(), ()>, -// partitions: Arc<[VFSPartition]>, -// } - -// pub struct VFSFileSystem<'a> { -// name: &'a str, -// mount_point: &'a str, -// open: Option, -// read: Option Result, ()>>, -// write: Option, usize, usize) -> Result<(), ()>>, -// } - -// pub struct VFSNode<'a> { -// filesystem: *const VFSFileSystem<'a>, -// size: usize, -// id: usize, -// path: &'a str, - -// next: Option<*const VFSNode<'a>>, -// } - -// static ROOT_FS: VFSFileSystem = VFSFileSystem { -// name: "rootfs", -// mount_point: "/", -// open: None, -// read: None, -// write: None, -// }; - -// static ROOT_NODE: Mutex = Mutex::new(VFSNode { -// filesystem: core::ptr::null(), -// size: 0, -// id: 0, -// path: "", -// next: None, -// }); - -// pub static VFS_INSTANCES: Mutex = Mutex::new(VFS::new()); - -// pub struct VFS { -// drives: Vec, -// } - -// impl VFS { -// pub const fn new() -> Self { -// return Self { drives: Vec::new() }; -// } - -// pub fn add_drive(&mut self, drive: VFSDrive) { -// self.drives.push(drive); - -// let mut drive_node = VFSNode { -// filesystem: core::ptr::null(), -// size: 0, -// id: 0, -// path: "", -// next: None, -// }; - -// drive_node.filesystem = &ROOT_FS; -// } -// } - -// pub fn init() { -// ROOT_NODE.lock().write().filesystem = &ROOT_FS; - -// crate::println!("VFS: Registered VFS on {}", ROOT_FS.mount_point); -// } diff --git a/src/drivers/keyboard.rs b/src/drivers/keyboard.rs old mode 100644 new mode 100755 diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs old mode 100644 new mode 100755 index a01631e..4044ea4 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -125,19 +125,8 @@ impl core::fmt::Display for PciDevice { pub static PCI_DEVICES: Mutex> = Mutex::new(Vec::new()); pub fn enumerate_pci_bus() { - let header_type = read_pci_header_type(0, 0, 0); - if (header_type & 0x80) == 0 { - // Single PCI host controller - check_bus(0); - } else { - // Multiple PCI host controllers - for function in 0..8 { - if read_pci_vendor_id(0, 0, function) != 0xFFFF { - break; - } - let bus = function; - check_bus(bus); - } + for bus in 0..=255 { + check_bus(bus); } crate::println!("====== PCI DEVICES ======"); @@ -153,7 +142,7 @@ fn check_bus(bus: u8) { } fn check_device(bus: u8, device: u8) { - let mut func: u8 = 0; + let func: u8 = 0; let vendor_id = read_pci_vendor_id(bus, device, func); @@ -165,15 +154,12 @@ fn check_device(bus: u8, device: u8) { let header_type = read_pci_header_type(bus, device, func); if header_type & 0x80 != 0 { - // It's a multi-function device - func += 1; + for func in 1..8 { + let vendor_id = read_pci_vendor_id(bus, device, func); - while func < 8 { - if read_pci_vendor_id(bus, device, func) != 0xFFFF { + if vendor_id != 0xFFFF { check_function(bus, device, func); } - - func += 1; } } } @@ -193,6 +179,7 @@ fn check_function(bus: u8, device: u8, func: u8) { if class_code == 0x06 && subclass_code == 0x04 { secondary_bus = read_pci_to_pci_secondary_bus(bus, device, func); - check_bus(secondary_bus); + // TODO: This causes an infinite loop on baremetal + // check_bus(secondary_bus); } } diff --git a/src/drivers/storage/ide.rs b/src/drivers/storage/ide.rs old mode 100644 new mode 100755 diff --git a/src/drivers/video/font.rs b/src/drivers/video/font.rs old mode 100644 new mode 100755 index e39c1b5..018fe62 --- a/src/drivers/video/font.rs +++ b/src/drivers/video/font.rs @@ -1,6 +1,10 @@ -pub const G_8X16_FONT: [[u8; 16]; 256] = [ +pub static G_8X16_FONT: [[u8; 16]; 256] = [ + // [ + // 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, + // 0x00, + // ], [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x81, 0x99, 0xA5, 0x85, 0x89, 0x89, 0x81, 0x89, 0x7E, 0x00, 0x00, 0x00, 0x00, ], [ diff --git a/src/drivers/video/mod.rs b/src/drivers/video/mod.rs old mode 100644 new mode 100755 index fb65f09..70c24b5 --- a/src/drivers/video/mod.rs +++ b/src/drivers/video/mod.rs @@ -41,7 +41,7 @@ pub fn put_char( let font = font::G_8X16_FONT; if character as usize > u8::MAX as usize { - character = '?'; + character = '\x00'; // rounded question mark fg = 0xFF0000; } diff --git a/src/libs/lazy.rs b/src/libs/lazy.rs old mode 100644 new mode 100755 index c937654..75c2b97 --- a/src/libs/lazy.rs +++ b/src/libs/lazy.rs @@ -6,7 +6,7 @@ use core::{ pub struct Lazy T> { value: UnsafeCell>, - init_func: Option, + init_func: F, initialized: AtomicBool, } @@ -14,7 +14,7 @@ impl T> Lazy { pub const fn new(init_func: F) -> Self { Lazy { value: UnsafeCell::new(None), - init_func: Some(init_func), + init_func: init_func, initialized: AtomicBool::new(false), } } @@ -25,13 +25,12 @@ impl T> Deref for Lazy { fn deref(&self) -> &Self::Target { if !self.initialized.load(Ordering::Acquire) { - if let Some(init_func) = &self.init_func { - let value = init_func(); - unsafe { - *(self.value.get()) = Some(value); - } - self.initialized.store(true, Ordering::Release); + let value = (self.init_func)(); + unsafe { + *(self.value.get()) = Some(value); } + + self.initialized.store(true, Ordering::Release); } unsafe { diff --git a/src/libs/mutex.rs b/src/libs/mutex.rs old mode 100644 new mode 100755 diff --git a/src/main.rs b/src/main.rs old mode 100644 new mode 100755 index 274a290..8ad2fac --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ use core::ffi::CStr; use alloc::vec::Vec; use drivers::serial; use libs::util::hcf; -use limine::{KernelFileRequest, ModuleRequest}; +use limine::KernelFileRequest; use crate::mem::LabelBytes; diff --git a/src/mem/mod.rs b/src/mem/mod.rs old mode 100644 new mode 100755 index 60c04f8..ce50587 --- a/src/mem/mod.rs +++ b/src/mem/mod.rs @@ -33,61 +33,6 @@ pub static HHDM_OFFSET: Lazy = Lazy::new(|| { return hhdm.offset as usize; }); -// fn stitch_memory_map(memmap: &mut [NonNullPtr]) -> &mut [NonNullPtr] { -// let mut null_index_ptr = 0; -// -// crate::println!("====== MEMORY MAP ======"); -// for entry in memmap.iter() { -// crate::println!( -// "[ {:#018X?} ] Type: {:?} Size: {:?}", -// entry.base..entry.base + entry.len, -// entry.typ, -// entry.len as usize -// ) -// } -// -// for i in 1..memmap.len() { -// let region = &memmap[i]; -// -// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -// if region.typ == limine::MemoryMapEntryType::Framebuffer { -// crate::arch::set_mtrr( -// region.base, -// region.len, -// crate::arch::MTRRMode::WriteCombining, -// ); -// } -// -// if !memory_section_is_usable(&memmap[i]) { -// memmap[null_index_ptr].len = memmap[i].len; -// memmap[null_index_ptr].base = memmap[i].base; -// memmap[null_index_ptr].typ = memmap[i].typ; -// -// null_index_ptr += 1; -// continue; -// } -// -// if null_index_ptr > 0 && memory_section_is_usable(&memmap[null_index_ptr - 1]) { -// memmap[null_index_ptr - 1].len += memmap[i].len; -// -// continue; -// } -// -// if memory_section_is_usable(&memmap[i - 1]) { -// memmap[i - 1].len += memmap[i].len; -// -// memmap[null_index_ptr].len = memmap[i - 1].len; -// memmap[null_index_ptr].base = memmap[i - 1].base; -// memmap[null_index_ptr].typ = memmap[i - 1].typ; -// -// null_index_ptr += 1; -// continue; -// } -// } -// -// return &mut memmap[0..null_index_ptr]; -// } - pub static PHYSICAL_MEMORY_MANAGER: Lazy = Lazy::new(|| PhysicalMemoryManager::new()); @@ -214,34 +159,3 @@ impl LabelBytes for usize { } } } - -pub fn test_page_frame_allocator(iterations: usize) { - crate::log_info!("Testing page allocator"); - - for i in 0..iterations { - let a = crate::mem::PHYSICAL_MEMORY_MANAGER.alloc(20); - - let percent_complete = (i as f64 / iterations as f64) * 100.0; - - crate::print!("[ "); - for j in 0..50 { - if (j * 2) < percent_complete as usize { - crate::print!("#"); - } else { - crate::print!("."); - } - } - crate::print!(" ] {percent_complete:.1}%\r"); - - if a.is_err() { - crate::log_error!( - "Page frame allocator failed to allocate {iterations} pages on iteration {i}!" - ); - break; - } - - crate::mem::PHYSICAL_MEMORY_MANAGER.dealloc(a.unwrap(), 20); - } - - crate::log_ok!("Page frame allocator successfully allocated {iterations} pages!"); -} diff --git a/src/usr/shell.rs b/src/usr/shell.rs old mode 100644 new mode 100755 index 414525d..c567fe0 --- a/src/usr/shell.rs +++ b/src/usr/shell.rs @@ -1,15 +1,17 @@ +use core::sync::atomic::{AtomicU8, Ordering}; + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use crate::drivers::keyboard::set_leds; -use crate::{drivers::keyboard::Key, libs::mutex::Mutex}; +use crate::drivers::keyboard::Key; struct ModStatus { - pub win: bool, // first bit - pub ctrl: bool, // second bit - pub alt: bool, // third bit - pub shift: bool, // forth bit - pub caps: bool, // fifth bit - pub num_lock: bool, // sixth bit - pub scr_lock: bool, // (possibly unnecessary) seventh bit + pub win: bool, // first bit (0000_0001) + pub ctrl: bool, // second bit (0000_0010) + pub alt: bool, // third bit (0000_0100) + pub shift: bool, // forth bit (0000_1000) + pub caps: bool, // fifth bit (0001_0000) + pub num_lock: bool, // sixth bit (0010_0000) + pub scr_lock: bool, // (possibly unnecessary) seventh bit (0100_0000) } impl ModStatus { @@ -41,21 +43,21 @@ impl ModStatus { } struct ModStatusBits { - status: Mutex, - led_status: Mutex, + status: AtomicU8, + led_status: AtomicU8, } impl ModStatusBits { #[inline] const fn new() -> Self { return Self { - status: Mutex::new(0u8), - led_status: Mutex::new(0u8), + status: AtomicU8::new(0u8), + led_status: AtomicU8::new(0u8), }; } fn get_status(&self) -> ModStatus { - let status = self.status.lock().read(); + let status = self.status.load(Ordering::SeqCst); return ModStatus { win: ((status >> 0) & 1) != 0, @@ -69,8 +71,7 @@ impl ModStatusBits { } fn set_modifier_key(&self, key: &str, status: bool) { - let mut led_status_lock = self.led_status.lock(); - let led_status = led_status_lock.write(); + let mut led_status = self.led_status.load(Ordering::SeqCst); let mut mod_status = self.get_status(); match key { @@ -79,15 +80,15 @@ impl ModStatusBits { "alt" => mod_status.alt = status, "shift" => mod_status.shift = status, "caps" => { - *led_status ^= 0b00000100; + led_status ^= 0b00000100; mod_status.caps = status } "num_lock" => { - *led_status ^= 0b00000010; + led_status ^= 0b00000010; mod_status.num_lock = status } "scr_lock" => { - *led_status ^= 0b00000100; + led_status ^= 0b00000100; mod_status.scr_lock = status } _ => return, @@ -95,10 +96,11 @@ impl ModStatusBits { // set Keyboard led (caps, num lock, scroll lock) #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - set_leds(*led_status); + set_leds(led_status); + self.led_status.store(led_status, Ordering::SeqCst); let new_value = mod_status.to_byte(); - *self.status.lock().write() = new_value; + self.status.store(new_value, Ordering::SeqCst); } } diff --git a/src/usr/tty.rs b/src/usr/tty.rs old mode 100644 new mode 100755 index f8bbfbb..1e86d01 --- a/src/usr/tty.rs +++ b/src/usr/tty.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; +use core::sync::atomic::{AtomicU16, AtomicU32, AtomicU8, Ordering}; use alloc::{ alloc::{alloc, dealloc}, @@ -23,7 +23,7 @@ pub struct Console { columns: AtomicU16, rows: AtomicU16, pub cursor: Cursor, - feature_bits: Mutex, + feature_bits: AtomicU8, pub second_buffer: Mutex>, } @@ -41,7 +41,7 @@ impl Console { columns: AtomicU16::new(0), rows: AtomicU16::new(0), cursor: Cursor::new(), - feature_bits: Mutex::new(0b00000000), + feature_bits: AtomicU8::new(0b00000000), second_buffer: Mutex::new(None), } } @@ -52,18 +52,27 @@ impl Console { // Enable serial if it initialized correctly if crate::drivers::serial::POISONED.load(Ordering::SeqCst) == false { - *self.feature_bits.lock().write() |= 1 << 1; + self.feature_bits.store( + self.feature_bits.load(Ordering::SeqCst) | 1 << 1, + Ordering::SeqCst, + ); } // Enable graphical output if framebuffer.is_some() { - *self.feature_bits.lock().write() |= 1; + self.feature_bits.store( + self.feature_bits.load(Ordering::SeqCst) | 1, + Ordering::SeqCst, + ); } else { return; } if back_buffer_region.is_some() { - *self.feature_bits.lock().write() |= 1 << 2; + self.feature_bits.store( + self.feature_bits.load(Ordering::SeqCst) | 1 << 2, + Ordering::SeqCst, + ); let mut back_buffer = crate::drivers::video::get_framebuffer().unwrap(); back_buffer.pointer = back_buffer_region.unwrap(); @@ -92,9 +101,11 @@ impl Console { } pub fn get_features(&self) -> ConsoleFeatures { - let graphical_output = ((*self.feature_bits.lock().read()) & 0x01) != 0; - let serial_output = ((*self.feature_bits.lock().read()) & 0x02) != 0; - let doubled_buffered = ((*self.feature_bits.lock().read()) & 0x04) != 0; + let feature_bits = self.feature_bits.load(Ordering::SeqCst); + + let graphical_output = (feature_bits & 0x01) != 0; + let serial_output = (feature_bits & 0x02) != 0; + let doubled_buffered = (feature_bits & 0x04) != 0; return ConsoleFeatures { _reserved: [0; 6], @@ -677,7 +688,9 @@ pub fn exec(command: &str) { return; } - let file = crate::drivers::fs::vfs::VFS_INSTANCES.lock().read()[0].open(&args[0]); + let vfs_lock = crate::drivers::fs::vfs::VFS_INSTANCES.lock(); + + let file = vfs_lock.read()[0].open(&args[0]); if file.is_err() { println!("read: Unable to read file!");