From 525ae40054f2768592854f5d1a8445a160489168 Mon Sep 17 00:00:00 2001
From: juls0730 <62722391+juls0730@users.noreply.github.com>
Date: Fri, 24 Nov 2023 03:58:30 -0600
Subject: [PATCH] non-working squashfs driver updates, partial stack traces,
and more
---
.cargo/config.toml | 3 +-
Makefile | 3 +
README.md | 12 +-
scripts/README.md | 4 +-
scripts/demangle-symbols.py | 20 ++
scripts/initramfs.py | 25 --
src/arch/x86_64/interrupts/exceptions.rs | 7 +
src/arch/x86_64/interrupts/mod.rs | 0
src/arch/x86_common/mod.rs | 1 +
src/arch/x86_common/stack_trace.rs | 26 ++
src/drivers/fs/fat.rs | 23 +-
src/drivers/fs/initramfs/mod.rs | 408 ++++++++++++++++++-----
src/drivers/fs/vfs.rs | 85 -----
src/drivers/keyboard.rs | 0
src/drivers/pci.rs | 29 +-
src/drivers/storage/ide.rs | 0
src/drivers/video/font.rs | 8 +-
src/drivers/video/mod.rs | 2 +-
src/libs/lazy.rs | 15 +-
src/libs/mutex.rs | 0
src/main.rs | 2 +-
src/mem/mod.rs | 86 -----
src/usr/shell.rs | 42 +--
src/usr/tty.rs | 33 +-
24 files changed, 477 insertions(+), 357 deletions(-)
create mode 100644 scripts/demangle-symbols.py
delete mode 100644 scripts/initramfs.py
mode change 100644 => 100755 src/arch/x86_64/interrupts/mod.rs
create mode 100644 src/arch/x86_common/stack_trace.rs
mode change 100644 => 100755 src/drivers/fs/fat.rs
mode change 100644 => 100755 src/drivers/fs/initramfs/mod.rs
mode change 100644 => 100755 src/drivers/fs/vfs.rs
mode change 100644 => 100755 src/drivers/keyboard.rs
mode change 100644 => 100755 src/drivers/pci.rs
mode change 100644 => 100755 src/drivers/storage/ide.rs
mode change 100644 => 100755 src/drivers/video/font.rs
mode change 100644 => 100755 src/drivers/video/mod.rs
mode change 100644 => 100755 src/libs/lazy.rs
mode change 100644 => 100755 src/libs/mutex.rs
mode change 100644 => 100755 src/main.rs
mode change 100644 => 100755 src/mem/mod.rs
mode change 100644 => 100755 src/usr/shell.rs
mode change 100644 => 100755 src/usr/tty.rs
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