diff --git a/.gitignore b/.gitignore
index 7663cb0..3377494 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
/target
/bin
+/ovmf
# Bochs
bx_enh_dbg.ini
diff --git a/Cargo.toml b/Cargo.toml
index 1019133..fa6078a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,4 +7,4 @@ edition = "2021"
limine = "0.1.10"
[profile.release]
-opt-level = 3
\ No newline at end of file
+opt-level = 3
diff --git a/Makefile b/Makefile
index a893398..98e2419 100644
--- a/Makefile
+++ b/Makefile
@@ -5,13 +5,14 @@ MODE ?= release
ARCH ?= x86_64
MEMORY ?= 512M
QEMU_OPTS ?=
-MKSQUASHFS_OPTS ?= -no-compression
+MKSQUASHFS_OPTS ?=
ISO_PATH = ${ARTIFACTS_PATH}/iso_root
INITRAMFS_PATH = ${ARTIFACTS_PATH}/initramfs
IMAGE_PATH = ${ARTIFACTS_PATH}/${IMAGE_NAME}
CARGO_OPTS = --target=src/arch/${ARCH}/${ARCH}-unknown-none.json
-QEMU_OPTS += -m ${MEMORY} -drive format=raw,file=${IMAGE_PATH}
+QEMU_OPTS += -m ${MEMORY} -drive id=hd0,format=raw,file=${IMAGE_PATH}
+LIMINE_BOOT_VARIATION = X64
ifeq (${MODE},release)
CARGO_OPTS += --release
@@ -19,9 +20,18 @@ else
QEMU_OPTS += -s -S
endif
+ifeq (${ARCH},riscv64)
+ LIMINE_BOOT_VARIATION := RISCV64
+ UEFI := true
+endif
+
ifneq (${UEFI},)
- RUN_OPTS := ovmf
- QEMU_OPTS += -bios bin/ovmf/OVMF.fd
+ RUN_OPTS := ovmf-${ARCH}
+ ifeq (${ARCH},riscv64)
+ QEMU_OPTS += -drive if=pflash,unit=0,format=raw,file=bin/ovmf-riscv64/OVMF.fd -M virt
+ else
+ QEMU_OPTS += -bios ovmf/ovmf-${ARCH}/OVMF.fd
+ endif
endif
.PHONY: all check prepare-bin-files copy-initramfs-files compile-initramfs copy-iso-files build-iso compile-bootloader compile-binaries ovmf clean run build line-count
@@ -44,7 +54,6 @@ prepare-bin-files:
mkdir -p ${INITRAMFS_PATH}
copy-initramfs-files:
- # Stub for now ;)
echo "Hello World from Initramfs" > ${INITRAMFS_PATH}/example.txt
echo "Second file for testing" > ${INITRAMFS_PATH}/example2.txt
mkdir -p ${INITRAMFS_PATH}/firstdir/seconddirbutlonger/
@@ -60,7 +69,7 @@ copy-iso-files:
mkdir -p ${ISO_PATH}/EFI/BOOT
cp -v limine.cfg limine/limine-bios.sys ${ISO_PATH}/boot/limine
- cp -v limine/BOOTX64.EFI ${ISO_PATH}/EFI/BOOT/
+ cp -v limine/BOOT${LIMINE_BOOT_VARIATION}.EFI ${ISO_PATH}/EFI/BOOT/
# OS files
cp -v target/${ARCH}-unknown-none/${MODE}/CappuccinOS.elf ${ISO_PATH}/boot
@@ -100,8 +109,10 @@ build-iso: partition-iso
fi
python scripts/demangle-symbols.py
mv scripts/symbols.table ${ISO_PATH}/boot
- # Install the Limine bootloader on the ISO
+ifeq (${ARCH},x86_64)
+ # Install the Limine bootloader for bios installs
./limine/limine bios-install ${IMAGE_PATH}
+endif
# Make a FAT32 FS and copy files in /bin/iso_root into the ISO starting at 1M or exactly 2048 sectors
mformat -F -i ${IMAGE_PATH}@@1M
@@ -120,15 +131,28 @@ compile-bootloader:
compile-binaries:
cargo build ${CARGO_OPTS}
-ovmf:
- mkdir -p bin/ovmf
- cd bin/ovmf && curl -Lo OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd
+ovmf-x86_64: ovmf
+ mkdir -p ovmf/ovmf-x86_64
+ @if [ ! -d "ovmf/ovmf-x86_64/OVMF.fd" ]; then \
+ cd ovmf/ovmf-x86_64 && curl -Lo OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd; \
+ fi
+
+ovmf-riscv64: ovmf
+ mkdir -p ovmf/ovmf-riscv64
+ @if [ ! -d "ovmf/ovmf-riscv64/OVMF.fd" ]; then \
+ cd ovmf/ovmf-riscv64 && curl -o OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASERISCV64_VIRT_CODE.fd && dd if=/dev/zero of=OVMF.fd bs=1 count=0 seek=33554432; \
+ fi
# In debug mode, open a terminal and run this command:
# gdb target/x86_64-unknown-none/debug/CappuccinOS.elf -ex "target remote :1234"
-run: build ${RUN_OPTS}
- qemu-system-x86_64 ${QEMU_OPTS}
+run: build ${RUN_OPTS} run-${ARCH}
+
+run-x86_64:
+ qemu-system-x86_64 ${QEMU_OPTS}
+
+run-riscv64:
+ qemu-system-riscv64 ${QEMU_OPTS} -M virt -cpu rv64 -device ramfb -device qemu-xhci -device usb-kbd -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd0
line-count:
cloc --quiet --exclude-dir=bin --csv src/ | tail -n 1 | awk -F, '{print $$5}'
diff --git a/README.md b/README.md
index 3cd622f..087cf3f 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,10 @@ CappuccinOS is a small x86-64 operating system written from scratch in rust. Thi
- [X] ANSI color codes in console
- [X] Heap allocation
- [ ] Externalized kernel modules
- - [ ] Initramfs
+ - [X] Initramfs
+ - [X] Squashfs driver
+ - [X] Programmatic reads
+ - [X] Decompression
- [ ] SMP
- [ ] Use APIC instead of PIC
- [ ] Pre-emptive multitasking
@@ -27,7 +30,7 @@ CappuccinOS is a small x86-64 operating system written from scratch in rust. Thi
- [ ] M.2 NVME device support
- [ ] Basic shell
- [X] Basic I/O
- - [ ] Executing Programs
+ - [ ] Executing Programs from disk
- [ ] Lua interpreter
- [ ] Memory management
- [ ] Network support
@@ -37,7 +40,6 @@ CappuccinOS is a small x86-64 operating system written from scratch in rust. Thi
- [ ] User authentication
- [ ] Power management
- [ ] Paging
-- [ ] Hardware abstraction layer
- [ ] RTC Clock
## Setup
@@ -45,7 +47,6 @@ Before building CappuccinOS, make sure you have the following installed on your
- rust
- python
-- binutils
- sgdisk
- mtools
- squashfs-tools
@@ -66,7 +67,7 @@ Install the dependencies:
Arch
- sudo pacman -S binutils gptfdisk mtools squashfs-tools python
+ sudo pacman -S gptfdisk mtools squashfs-tools python
# Optionally
sudo pacman -S qemu-system-x86
@@ -75,7 +76,7 @@ Install the dependencies:
Ubuntu
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
+ sudo apt install gdisk mtools squashfs-tools
# Optionally
sudo apt install qemu
@@ -99,6 +100,10 @@ sudo dd if=bin/CappuccinOS.iso of=/dev/sdX bs=1M && sync
```
**Be careful not to overwrite your hard drive when using `dd`!**
+## Supported Architectures
+- x86_64
+- RISC-V64 (experimental until I can get my hands on some RISC-V hardware)
+
## Credits an attributions
Inspiration was mainly from [JDH's Tetris OS](https://www.youtube.com/watch?v=FaILnmUYS_U), mixed with a growing interest in low level in general and an interest in learning rust (yeah, I started this project with not that much rust experience, maybe a CLI app or two, and trust me it shows).
diff --git a/TODO.md b/TODO.md
index 84c7602..5162cd8 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,10 +2,12 @@
not really meant to be looked at, just writing down my thoughts
- [ ] finish fat fs
- - [ ] follow cluster chains
- - [ ] Search for file in code
- - [ ] search into folders
- - [ ] Integrate with VFS
+ - [X] follow cluster chains
+ - [X] Search for file in code
+ - [X] search into folders
+ - [X] Integrate with VFS
+ - [ ] Writes
+ - [ ] Read directory contents
- [ ] Custom FS
2 partitions, one that is the FAT fs that the system boot from, the directory structure looks like this:
diff --git a/limine.cfg b/limine.cfg
index 6411c62..d290387 100644
--- a/limine.cfg
+++ b/limine.cfg
@@ -5,6 +5,6 @@ TIMEOUT=3
PROTOCOL=limine
KERNEL_PATH=boot:///boot/CappuccinOS.elf
- KERNEL_CMDLINE=fat_in_mem=true big_fat_phony
+ KERNEL_CMDLINE=fat_in_mem=false big_fat_phony
MODULE_PATH=boot:///boot/initramfs.img
\ No newline at end of file
diff --git a/src/arch/mod.rs b/src/arch/mod.rs
index e9b49a6..a012068 100644
--- a/src/arch/mod.rs
+++ b/src/arch/mod.rs
@@ -9,3 +9,9 @@ mod x86_64;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86_common;
+
+#[cfg(target_arch = "riscv64")]
+mod riscv64;
+
+#[cfg(target_arch = "riscv64")]
+pub use self::riscv64::*;
diff --git a/src/arch/x86_64/x86_64-unknown-none.json b/src/arch/x86_64/x86_64-unknown-none.json
index eb5b9d2..ea72956 100644
--- a/src/arch/x86_64/x86_64-unknown-none.json
+++ b/src/arch/x86_64/x86_64-unknown-none.json
@@ -8,9 +8,10 @@
"features": "-mmx,-sse,+soft-float",
"os": "CappuccinOS",
"arch": "x86_64",
- "linker-flavor": "ld",
+ "linker": "rust-lld",
+ "linker-flavor": "ld.lld",
"pre-link-args": {
- "ld": [
+ "ld.lld": [
"-melf_x86_64",
"--script=./src/arch/x86_64/linker.ld"
]
diff --git a/src/bin/hello.rs b/src/bin/hello.rs
index 2033148..95fb6fb 100644
--- a/src/bin/hello.rs
+++ b/src/bin/hello.rs
@@ -4,7 +4,7 @@
// use alloc::format;
// // piggyback off of the CappuccinOS allocator
-// // TODO: make a syscall for memory operations
+// // TODO: make a malloc lib for memory operations
// #[allow(unused_imports)]
// use CappuccinOS;
@@ -20,6 +20,7 @@ pub fn _start(_args: &[&str]) {
}
fn print(message: &str) {
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe {
core::arch::asm!(
"mov rdi, 0x01", // write syscall
diff --git a/src/drivers/fs/fat.rs b/src/drivers/fs/fat.rs
index 9e31632..4612d34 100755
--- a/src/drivers/fs/fat.rs
+++ b/src/drivers/fs/fat.rs
@@ -23,7 +23,7 @@ use super::vfs::{VfsDirectory, VfsFile, VfsFileSystem};
// End Of Chain
const EOC: u32 = 0x0FFFFFF8;
-#[derive(Debug)]
+#[derive(Clone, Copy, Debug)]
enum FatType {
Fat12,
Fat16,
@@ -47,6 +47,7 @@ pub struct BIOSParameterBlock {
pub head_count: u16, // 10 00 (16)
pub hidden_sectors: u32, // 00 00 00 00
pub large_sector_count: u32, // 00 F8 01 00 (129024)
+ // pub ebpb: [u8; 54],
// ---------------------------------
// - Extended BIOS Parameter Block -
// ---------------------------------
@@ -193,19 +194,15 @@ impl<'a> FatFs<'a> {
if crate::KERNEL_FEATURES.fat_in_mem {
let mut fat_vec: Vec = Vec::with_capacity(bytes_per_fat / 4);
- unsafe { fat_vec.set_len(fat_vec.capacity()) };
for i in 0..(bpb.sectors_per_fat_ext as usize) {
let sector = drive
.read(fat_start + i as u64, 1)
.expect("Failed to read FAT");
for j in 0..(512 / 4) {
- fat_vec[i * (512 / 4) + j] = u32::from_le_bytes([
- sector[j * 4],
- sector[(j * 4) + 1],
- sector[(j * 4) + 2],
- sector[(j * 4) + 3],
- ])
+ fat_vec.push(u32::from_le_bytes(
+ sector[j * 4..(j * 4 + 4)].try_into().unwrap(),
+ ))
}
}
@@ -288,7 +285,7 @@ impl<'a> FatFs<'a> {
continue; // Directory is unused, ignore it
} else if bytes[11] == FileEntryAttributes::LongFileName as u8 {
// Entry is LFN (step 3)
- // read long filename somehow (step 4)
+ // read long filename (step 4)
let long_filename_part: LongFileName;
unsafe {
diff --git a/src/drivers/fs/initramfs/compressors/gzip.rs b/src/drivers/fs/initramfs/compressors/gzip.rs
index d1ca684..2a8fb03 100644
--- a/src/drivers/fs/initramfs/compressors/gzip.rs
+++ b/src/drivers/fs/initramfs/compressors/gzip.rs
@@ -1,3 +1,7 @@
+use alloc::{sync::Arc, vec::Vec};
+
+use crate::libs::mutex::Mutex;
+
#[derive(Debug)]
#[repr(u8)]
enum ZlibCompressionLevel {
@@ -21,15 +25,14 @@ impl From for ZlibCompressionLevel {
// RFC 1950: "ZLIB Compressed Data Format Specification"
// RFC 1951: "DEFLATE Compressed Data Format Specification"
-pub fn uncompress_data(bytes: &[u8]) -> &[u8] {
+pub fn uncompress_data(bytes: &[u8]) -> Result, ()> {
assert!(bytes.len() > 2);
// Compression Method and flags
let cmf = bytes[0];
- let flags = bytes[1];
- if cmf & 0x0F != 0x08 {
- panic!("Compression method is not GZIP!",);
+ if (cmf & 0x0F) != 0x08 {
+ panic!("Compression method is not deflate!");
}
let window_log2 = cmf >> 4 & 0x0F;
@@ -38,10 +41,378 @@ pub fn uncompress_data(bytes: &[u8]) -> &[u8] {
panic!("Unsupported window size {window_log2:X}!");
}
+ let flags = bytes[1];
+ if (cmf as u32 * 256 + flags as u32) % 31 != 0 {
+ return Err(());
+ }
+
// TODO: Check if FCheck is valid
let present_dictionary = flags >> 5 & 0x01 != 0;
- let compression_level: ZlibCompressionLevel = (flags >> 6 & 0x03).into();
+ let _compression_level: ZlibCompressionLevel = (flags >> 6 & 0x03).into();
- todo!("Uncompress data");
+ if present_dictionary {
+ // cry
+ return Err(());
+ }
+
+ let mut inflate_context = InflateContext::new(&bytes[2..bytes.len() - 4]);
+
+ let data = inflate_context.decompress()?;
+
+ // last 4 bytes
+ let checksum = u32::from_le_bytes(bytes[bytes.len() - 4..].try_into().unwrap());
+
+ if adler32(&data) != checksum {
+ return Err(());
+ }
+
+ return Ok(data.into());
+}
+
+fn adler32(bytes: &[u8]) -> u32 {
+ let mut a = 1_u32;
+ let mut b = 0_u32;
+
+ for &byte in bytes {
+ a = (a + byte as u32) % 65521;
+ b = (b + a) % 65521;
+ }
+
+ return u32::from_be((b << 16) | a);
+}
+
+#[derive(Debug)]
+struct Huff {
+ counts: [u16; 16],
+ symbols: [u16; 288],
+}
+
+static FIXED_LENGTHS: Mutex = Mutex::new(Huff {
+ counts: [0_u16; 16],
+ symbols: [0_u16; 288],
+});
+static FIXED_DISTS: Mutex = Mutex::new(Huff {
+ counts: [0_u16; 16],
+ symbols: [0_u16; 288],
+});
+
+struct HuffRing {
+ pointer: usize,
+ data: Vec,
+}
+
+impl HuffRing {
+ fn new() -> Self {
+ let mut data = Vec::with_capacity(32 * 1024);
+ unsafe {
+ data.set_len(32 * 1024);
+ };
+
+ return Self { pointer: 0, data };
+ }
+}
+
+struct InflateContext {
+ input_buf: Vec,
+ bit_index: usize,
+ output_buf: alloc::vec::Vec,
+ ring: HuffRing,
+}
+
+impl InflateContext {
+ fn new(bytes: &[u8]) -> Self {
+ return Self {
+ input_buf: bytes.to_vec(),
+ bit_index: 0,
+ output_buf: Vec::new(),
+ ring: HuffRing::new(),
+ };
+ }
+
+ pub fn get_bit(&mut self) -> bool {
+ if self.bit_index == 8 {
+ self.input_buf.remove(0);
+ if self.input_buf.len() == 0 {
+ panic!("Not enough data! {:X?}", self.output_buf);
+ }
+
+ self.bit_index = 0;
+ }
+
+ let byte = self.input_buf[0] & (1 << self.bit_index) != 0;
+ self.bit_index += 1;
+
+ return byte;
+ }
+
+ pub fn get_bits(&mut self, num_bits: usize) -> u32 {
+ let mut byte = 0_u32;
+
+ for bit in 0..num_bits {
+ byte |= (self.get_bit() as u32) << bit;
+ }
+
+ return byte;
+ }
+
+ fn get_bits_base(&mut self, num: usize, base: usize) -> u32 {
+ return (base + if num != 0 { self.get_bits(num) } else { 0 } as usize) as u32;
+ }
+
+ pub fn decompress(&mut self) -> Result, ()> {
+ build_fixed();
+
+ loop {
+ let is_final = self.get_bit();
+ let block_type = self.get_bits(2);
+
+ match block_type {
+ 0x00 => {
+ self.uncompressed()?;
+ }
+ 0x01 => {
+ self.inflate(FIXED_LENGTHS.lock().write(), FIXED_DISTS.lock().write())?;
+ }
+ 0x02 => {
+ self.decode_huffman()?;
+ }
+ _ => {
+ return Err(());
+ }
+ }
+
+ if is_final {
+ break;
+ }
+ }
+
+ return Ok(Arc::from(self.output_buf.clone()));
+ }
+
+ fn decode(&mut self, huff: &mut Huff) -> u32 {
+ let mut base: i32 = 0;
+ let mut offs: i32 = 0;
+
+ let mut i = 1;
+ loop {
+ offs = 2 * offs + self.get_bit() as i32;
+
+ assert!(i <= 15);
+
+ if offs < huff.counts[i] as i32 {
+ break;
+ }
+
+ base += huff.counts[i] as i32;
+ offs -= huff.counts[i] as i32;
+ i += 1;
+ }
+
+ assert!(base + offs >= 0 && base + offs < 288);
+
+ return huff.symbols[(base + offs) as usize] as u32;
+ }
+
+ fn emit(&mut self, byte: u8) {
+ if self.ring.pointer == 32768 {
+ self.ring.pointer = 0;
+ }
+
+ self.ring.data[self.ring.pointer] = byte;
+ self.output_buf.push(byte);
+ self.ring.pointer += 1;
+ }
+
+ fn peek(&mut self, offset: usize) -> u8 {
+ self.ring.data[(self.ring.pointer - offset) % 32768]
+ }
+
+ fn uncompressed(&mut self) -> Result<(), ()> {
+ let len = u16::from_le(self.get_bits(16).try_into().unwrap());
+ let nlen = u16::from_le(self.get_bits(16).try_into().unwrap());
+
+ if nlen != !len {
+ return Err(());
+ }
+
+ for _ in 0..len {
+ // TODO: is this right?
+ let byte = self.get_bits(8) as u8;
+ self.emit(byte);
+ }
+
+ return Ok(());
+ }
+
+ fn inflate(&mut self, huff_len: &mut Huff, huff_dist: &mut Huff) -> Result<(), ()> {
+ let length_bits = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
+ 127,
+ ];
+ let length_base = [
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99,
+ 115, 131, 163, 195, 227, 258, 0,
+ ];
+
+ let dist_bits = [
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
+ 12, 13, 13,
+ ];
+ let dist_base = [
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025,
+ 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
+ ];
+
+ loop {
+ let mut symbol = self.decode(huff_len);
+
+ if symbol < 256 {
+ self.emit(symbol as u8);
+ } else {
+ if symbol == 256 {
+ break;
+ }
+
+ symbol -= 257;
+
+ let length =
+ self.get_bits_base(length_bits[symbol as usize], length_base[symbol as usize]);
+ let distance = self.decode(huff_dist);
+ let offset =
+ self.get_bits_base(dist_bits[distance as usize], dist_base[distance as usize]);
+
+ for _ in 0..length {
+ let b = self.peek(offset as usize);
+ self.emit(b);
+ }
+ }
+ }
+
+ return Ok(());
+ }
+
+ fn decode_huffman(&mut self) -> Result<(), ()> {
+ let clens = [
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+ ];
+
+ let mut lengths = [0_u8; 320];
+
+ let literals = self.get_bits_base(5, 257);
+ let distances = self.get_bits_base(5, 1);
+ let clengths = self.get_bits_base(4, 4);
+
+ for i in 0..clengths {
+ lengths[clens[i as usize] as usize] = self.get_bits(3) as u8;
+ }
+
+ let mut codes = Huff {
+ counts: [0_u16; 16],
+ symbols: [0_u16; 288],
+ };
+ build_huffman(&lengths, 19, &mut codes);
+
+ let mut count = 0_u32;
+ while count < literals + distances {
+ let symbol = self.decode(&mut codes);
+
+ if symbol < 16 {
+ lengths[count as usize] = symbol as u8;
+ count += 1;
+ } else if symbol < 19 {
+ let mut rep = 0_u32;
+ let mut length;
+
+ if symbol == 16 {
+ rep = lengths[count as usize - 1] as u32;
+ length = self.get_bits_base(2, 3);
+ } else if symbol == 17 {
+ length = self.get_bits_base(3, 3);
+ } else {
+ length = self.get_bits_base(7, 11);
+ }
+
+ while length != 0 {
+ lengths[count as usize] = rep as u8;
+ count += 1;
+ length -= 1;
+ }
+ } else {
+ break;
+ }
+ }
+
+ let mut huff_len = Huff {
+ counts: [0_u16; 16],
+ symbols: [0_u16; 288],
+ };
+ build_huffman(&lengths, literals as usize, &mut huff_len);
+ let mut huff_dist = Huff {
+ counts: [0_u16; 16],
+ symbols: [0_u16; 288],
+ };
+ build_huffman(
+ &lengths[literals as usize..],
+ distances as usize,
+ &mut huff_dist,
+ );
+
+ self.inflate(&mut huff_len, &mut huff_dist)?;
+
+ return Ok(());
+ }
+}
+
+fn build_huffman(lengths: &[u8], size: usize, out: &mut Huff) {
+ let mut offsets = [0_u32; 16];
+ let mut count: u32 = 0;
+
+ assert!(size <= 288);
+
+ for i in 0..16 {
+ out.counts[i] = 0;
+ }
+
+ for i in 0..size {
+ assert!(lengths[i] <= 15);
+
+ out.counts[lengths[i] as usize] += 1;
+ }
+
+ out.counts[0] = 0;
+
+ for i in 0..16 {
+ offsets[i] = count;
+ count += out.counts[i] as u32;
+ }
+
+ for i in 0..size {
+ if lengths[i] != 0 {
+ out.symbols[offsets[lengths[i] as usize] as usize] = i.try_into().unwrap();
+ offsets[lengths[i] as usize] += 1;
+ }
+ }
+}
+
+fn build_fixed() {
+ let mut lengths = [0_u8; 288];
+ for i in 0..144 {
+ lengths[i] = 8;
+ }
+ for i in 144..256 {
+ lengths[i] = 9;
+ }
+ for i in 256..280 {
+ lengths[i] = 7;
+ }
+ for i in 280..288 {
+ lengths[i] = 8;
+ }
+ build_huffman(&lengths, 288, FIXED_LENGTHS.lock().write());
+
+ for i in 0..30 {
+ lengths[i] = 5;
+ }
+ build_huffman(&lengths, 30, FIXED_DISTS.lock().write());
}
diff --git a/src/drivers/fs/initramfs/mod.rs b/src/drivers/fs/initramfs/mod.rs
index 66bc6df..0ce8996 100755
--- a/src/drivers/fs/initramfs/mod.rs
+++ b/src/drivers/fs/initramfs/mod.rs
@@ -43,15 +43,6 @@ pub fn init() {
}
let initramfs = initramfs.unwrap();
- crate::println!("Initramfs is located at: {:#018X?}", unsafe {
- initramfs.base.as_ptr().unwrap()
- ..initramfs
- .base
- .as_ptr()
- .unwrap()
- .add(initramfs.length as usize)
- });
-
let squashfs = Squashfs::new(initramfs.base.as_ptr().unwrap());
if squashfs.is_err() {
@@ -61,15 +52,15 @@ pub fn init() {
let squashfs = squashfs.unwrap();
- crate::println!("{:X?}", squashfs);
- crate::println!("{:?}", squashfs.superblock.features());
-
crate::println!(
- "{:X?}",
- squashfs
- .open("/firstdir/seconddirbutlonger/yeah.txt")
- .unwrap()
- .read()
+ "\033[92m{:?}",
+ core::str::from_utf8(
+ &squashfs
+ .open("/firstdir/seconddirbutlonger/yeah.txt")
+ .unwrap()
+ .read()
+ .unwrap()
+ )
);
}
@@ -88,9 +79,9 @@ struct Squashfs<'a> {
impl Squashfs<'_> {
fn new(ptr: *mut u8) -> Result, ()> {
- crate::println!("Parsing initramfs fs at {:p}", ptr);
+ crate::log_info!("Parsing initramfs at {:p}", ptr);
- // bytes used from superblock
+ // 40 is the offset for bytes used by the archive in the 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) };
@@ -100,36 +91,81 @@ impl Squashfs<'_> {
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];
+ macro_rules! get_metadata_table {
+ ($table_type:ident) => {{
+ // get table size minus the top bit (indicates compression) plus 2, because
+ // The table size is minus the size of the size header (two bytes)
+ let table_size = (u16::from_le_bytes(
+ squashfs_data
+ [superblock.$table_type as usize..superblock.$table_type as usize + 2]
+ .try_into()
+ .unwrap(),
+ ) & 0x7FFF)
+ + 2;
- 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],
- );
+ &squashfs_data[superblock.$table_type as usize
+ ..superblock.$table_type as usize + table_size as usize]
+ }};
}
- let mut export_table: Option<&[u8]> = None;
+ let inode_table = get_metadata_table!(inode_table);
- if superblock.export_table != u64::MAX {
- export_table = Some(
- &squashfs_data[superblock.export_table as usize..superblock.id_table as usize],
- );
- }
+ let directory_table = get_metadata_table!(dir_table);
- let mut id_table: &[u8] = &squashfs_data[superblock.id_table as usize..];
- let mut xattr_table: Option<&[u8]> = None;
+ let fragment_table: Option<&[u8]> = {
+ if superblock.frag_table == u64::MAX {
+ None
+ } else {
+ if superblock.export_table != u64::MAX {
+ Some(
+ &squashfs_data
+ [superblock.frag_table as usize..superblock.export_table as usize],
+ )
+ } else if superblock.xattr_table != u64::MAX {
+ Some(
+ &squashfs_data
+ [superblock.frag_table as usize..superblock.xattr_table as usize],
+ )
+ } else {
+ Some(
+ &squashfs_data
+ [superblock.frag_table as usize..superblock.id_table as usize],
+ )
+ }
+ }
+ };
- 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 export_table: Option<&[u8]> = {
+ if superblock.export_table == u64::MAX {
+ None
+ } else {
+ if superblock.xattr_table != u64::MAX {
+ Some(
+ &squashfs_data
+ [superblock.export_table as usize..superblock.xattr_table as usize],
+ )
+ } else {
+ Some(
+ &squashfs_data
+ [superblock.export_table as usize..superblock.id_table as usize],
+ )
+ }
+ }
+ };
+
+ let id_table: &[u8] = if superblock.xattr_table != u64::MAX {
+ &squashfs_data[superblock.id_table as usize..superblock.xattr_table as usize]
+ } else {
+ &squashfs_data[superblock.id_table as usize..]
+ };
+
+ let xattr_table: Option<&[u8]> = {
+ if superblock.xattr_table == u64::MAX {
+ None
+ } else {
+ Some(&squashfs_data[superblock.xattr_table as usize..])
+ }
+ };
return Ok(Squashfs {
superblock,
@@ -212,7 +248,7 @@ impl Squashfs<'_> {
match self.superblock.compressor {
SquashfsCompressionType::Gzip => {
- buffer.extend_from_slice(compressors::gzip::uncompress_data(bytes));
+ buffer.extend_from_slice(&compressors::gzip::uncompress_data(bytes).unwrap());
}
_ => {
crate::println!("Unsupported compression type")
@@ -239,13 +275,7 @@ impl<'a> VfsFileSystem for Squashfs<'a> {
let path_components: Vec<&str> = path.trim_start_matches('/').split('/').collect();
let mut current_dir = self.read_root_dir();
- crate::println!("\033[94m{}\033[0m", "-".repeat(40));
for (i, &part) in path_components.iter().enumerate() {
- crate::println!(
- "{}\ncur: {current_dir:?}\n{part}\n{path}\n{0}",
- "-".repeat(20)
- );
-
let file = current_dir.find(part).ok_or(())?;
match file {
@@ -261,7 +291,6 @@ impl<'a> VfsFileSystem for Squashfs<'a> {
}
}
}
- crate::println!("\033[94m{}\033[0m", "-".repeat(40));
return Err(());
}
@@ -370,20 +399,10 @@ impl<'a> BasicDirectoryInode<'a> {
fn entries(&self) -> Arc<[Inode]> {
let mut entries: Vec = Vec::new();
- let directory_table = &self.header.squashfs.get_decompressed_table(
- self.header.squashfs.directory_table,
- (
- false,
- Some(
- !self
- .header
- .squashfs
- .superblock
- .features()
- .uncompressed_data_blocks,
- ),
- ),
- );
+ let directory_table = &self
+ .header
+ .squashfs
+ .get_decompressed_table(self.header.squashfs.directory_table, (true, None));
let directory_table_header =
DirectoryTableHeader::from_bytes(&directory_table[self.block_offset as usize..]);
@@ -408,22 +427,10 @@ impl<'a> BasicDirectoryInode<'a> {
}
fn find(&self, name: &str) -> Option> {
- crate::println!("Searching for file {name} in directory");
-
- let directory_table = &self.header.squashfs.get_decompressed_table(
- self.header.squashfs.directory_table,
- (
- false,
- Some(
- !self
- .header
- .squashfs
- .superblock
- .features()
- .uncompressed_data_blocks,
- ),
- ),
- );
+ let directory_table = &self
+ .header
+ .squashfs
+ .get_decompressed_table(self.header.squashfs.directory_table, (true, None));
let directory_table_header =
DirectoryTableHeader::from_bytes(&directory_table[self.block_offset as usize..]);
@@ -436,8 +443,6 @@ impl<'a> BasicDirectoryInode<'a> {
offset += 8 + directroy_table_entry.name.len();
- crate::println!("{}", directroy_table_entry.name);
-
if directroy_table_entry.name == name {
return Some(
self.header
@@ -490,12 +495,23 @@ impl<'a> VfsFile for BasicFileInode<'a> {
let mut block_data: Vec = Vec::with_capacity(8192 * block_count);
unsafe {
+ let data_table = self.header.squashfs.get_decompressed_table(
+ self.header.squashfs.data_table,
+ (
+ false,
+ Some(
+ !self
+ .header
+ .squashfs
+ .superblock
+ .features()
+ .uncompressed_data_blocks,
+ ),
+ ),
+ );
+
core::ptr::copy_nonoverlapping(
- self.header
- .squashfs
- .data_table
- .as_ptr()
- .add(self.block_offset as usize),
+ data_table.as_ptr().add(self.block_offset as usize),
block_data.as_mut_ptr(),
self.file_size as usize,
);
diff --git a/src/drivers/fs/vfs.rs b/src/drivers/fs/vfs.rs
index f820ef2..b3d65b4 100755
--- a/src/drivers/fs/vfs.rs
+++ b/src/drivers/fs/vfs.rs
@@ -1,4 +1,9 @@
-use alloc::{boxed::Box, sync::Arc, vec::Vec};
+use alloc::{
+ boxed::Box,
+ string::{String, ToString},
+ sync::Arc,
+ vec::Vec,
+};
use crate::libs::mutex::Mutex;
@@ -18,12 +23,16 @@ pub trait VfsDirectory {
pub static VFS_INSTANCES: Mutex> = Mutex::new(Vec::new());
pub struct Vfs {
+ identifier: String,
file_system: Box,
}
impl Vfs {
- pub fn new(file_system: Box) -> Self {
- return Self { file_system };
+ pub fn new(file_system: Box, identifier: &str) -> Self {
+ return Self {
+ identifier: identifier.to_string(),
+ file_system,
+ };
}
pub fn open(&self, path: &str) -> Result, ()> {
diff --git a/src/drivers/keyboard.rs b/src/drivers/keyboard.rs
index 7ffd7f3..19fe023 100755
--- a/src/drivers/keyboard.rs
+++ b/src/drivers/keyboard.rs
@@ -1,3 +1,4 @@
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use crate::arch::interrupts::{idt_set_gate, InterruptIndex};
// Shitty keyboard driver
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -39,6 +40,7 @@ pub enum KBDError {
TestFailed,
}
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn init() -> Result<(), KBDError> {
// flush output buffer
while (inb(KBD_COMMAND_AND_STATUS_PORT) & 1) != 0 {
diff --git a/src/drivers/mod.rs b/src/drivers/mod.rs
index ff4e79c..3286f8f 100644
--- a/src/drivers/mod.rs
+++ b/src/drivers/mod.rs
@@ -1,6 +1,7 @@
pub mod acpi;
pub mod fs;
pub mod keyboard;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod pci;
pub mod serial;
pub mod storage;
diff --git a/src/drivers/serial.rs b/src/drivers/serial.rs
index d95e713..574db13 100644
--- a/src/drivers/serial.rs
+++ b/src/drivers/serial.rs
@@ -5,6 +5,7 @@ use crate::arch::io::{inb, outb};
// COM1
pub static PORT: u16 = 0x3f8;
+pub const UART: *mut char = 0x10000000 as *mut char;
pub static POISONED: AtomicBool = AtomicBool::new(false);
@@ -56,3 +57,17 @@ pub fn write_serial(character: char) {
while is_transmit_empty() {}
outb(PORT, character as u8);
}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+pub fn is_transmit_empty() -> bool {
+ return true;
+}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+pub fn write_serial(character: char) {
+ unsafe {
+ *UART = character;
+ };
+
+ return;
+}
diff --git a/src/drivers/storage/drive.rs b/src/drivers/storage/drive.rs
index a1464f3..688bd49 100644
--- a/src/drivers/storage/drive.rs
+++ b/src/drivers/storage/drive.rs
@@ -3,14 +3,17 @@ use alloc::sync::Arc;
pub trait BlockDevice {
fn sector_count(&self) -> u64;
fn read(&self, sector: u64, sector_count: usize) -> Result, ()>;
- fn write(&self, sector: u64, data: &mut [u8]) -> Result<(), ()>;
+ fn write(&self, sector: u64, data: &[u8]) -> Result<(), ()>;
}
-#[derive(Clone, Copy, Debug, Default)]
+#[derive(Clone, Copy, Debug)]
pub struct GPTPartitionEntry {
pub partition_type_guid: [u8; 16],
+ pub unique_partition_guid: [u8; 16],
pub start_sector: u64,
pub end_sector: u64,
+ pub attributes: u64,
+ pub partition_name: [u8; 72],
}
#[derive(Debug)]
diff --git a/src/drivers/storage/ide.rs b/src/drivers/storage/ide.rs
index 719b940..6cc5d39 100755
--- a/src/drivers/storage/ide.rs
+++ b/src/drivers/storage/ide.rs
@@ -1,9 +1,7 @@
-use core::mem::size_of;
-
-use alloc::{boxed::Box, sync::Arc, vec::Vec};
+use alloc::{boxed::Box, format, sync::Arc, vec::Vec};
use crate::{
- arch::io::{inb, insw, inw, outb, outsw, outw},
+ arch::io::{inb, inw, outb, outw},
drivers::{
fs::fat,
storage::drive::{GPTBlock, GPTPartitionEntry},
@@ -296,7 +294,7 @@ impl ATABus {
sector,
sector_count,
ATADriveDirection::Read,
- buffer.as_mut_slice(),
+ (buffer.as_mut_ptr(), buffer.len()),
)?;
return Ok(Arc::from(buffer));
@@ -307,7 +305,7 @@ impl ATABus {
drive: ATADriveType,
sector: u64,
sector_count: usize,
- buffer: &mut [u8],
+ buffer: &[u8],
) -> Result<(), ()> {
if buffer.len() < ATA_SECTOR_SIZE * sector_count {
return Err(());
@@ -318,7 +316,7 @@ impl ATABus {
sector,
sector_count,
ATADriveDirection::Write,
- buffer,
+ (buffer.as_ptr() as *mut u8, buffer.len()),
)?;
return Ok(());
@@ -330,8 +328,10 @@ impl ATABus {
sector: u64,
sector_count: usize,
direction: ATADriveDirection,
- buffer: &mut [u8],
+ buffer: (*mut u8, usize),
) -> Result<(), ()> {
+ let buffer = unsafe { core::slice::from_raw_parts_mut(buffer.0, buffer.1) };
+
self.await_busy();
let using_lba48 = sector >= (1 << 28) - 1;
@@ -413,30 +413,10 @@ impl ATABus {
// Allocate memory for the array that stores the sector data
let mut buffer_offset = 0;
- for i in 0..sector_count {
+ for _ in 0..sector_count {
self.wait_for_drive_ready()
.map_err(|_| crate::log_error!("Error reading IDE Device"))?;
- // # Safety
- //
- // We know that buffer is at least sector_count * ATA_SECTOR_SIZE, so it will never panic:tm:
- // unsafe {
- // match direction {
- // ATADriveDirection::Read => insw(
- // self.io_bar + ATADriveDataRegister::Data as u16,
- // (buffer.as_mut_ptr() as *mut u16)
- // .add((i * ATA_SECTOR_SIZE) / size_of::()),
- // ATA_SECTOR_SIZE / size_of::(),
- // ),
- // ATADriveDirection::Write => outsw(
- // self.io_bar + ATADriveDataRegister::Data as u16,
- // (buffer.as_mut_ptr() as *mut u16)
- // .add((i * ATA_SECTOR_SIZE) / size_of::()),
- // ATA_SECTOR_SIZE / size_of::(),
- // ),
- // }
- // }
-
for chunk in
buffer[buffer_offset..(buffer_offset + ATA_SECTOR_SIZE)].chunks_exact_mut(2)
{
@@ -525,7 +505,7 @@ impl BlockDevice for ATADrive {
return unsafe { *(sectors as *const u32) } as u64;
}
- fn write(&self, sector: u64, buffer: &mut [u8]) -> Result<(), ()> {
+ fn write(&self, sector: u64, buffer: &[u8]) -> Result<(), ()> {
let sector_count = buffer.len() / 512;
self.bus.software_reset();
@@ -612,10 +592,11 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
.expect("Failed to read partition table");
crate::println!(
- "{}, {}, {}",
+ "{}, {}, {}, {:X?}",
(gpt.partition_entry_count * gpt.partition_entry_size) as usize / ATA_SECTOR_SIZE,
gpt.partition_entry_count,
- gpt.partition_entry_size
+ gpt.partition_entry_size,
+ gpt.guid
);
for i in 0..gpt.partition_entry_count {
@@ -637,6 +618,11 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
continue;
}
+ let unique_partition_guid: [u8; 16] = partition_sector
+ [entry_offset + 16..entry_offset + 32]
+ .try_into()
+ .unwrap();
+
let start_sector = u64::from_le_bytes(
partition_sector[entry_offset + 32..entry_offset + 40]
.try_into()
@@ -648,11 +634,24 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
.unwrap(),
);
+ let attributes = u64::from_le_bytes(
+ partition_sector[entry_offset + 48..entry_offset + 56]
+ .try_into()
+ .unwrap(),
+ );
+
+ let partition_name = partition_sector[entry_offset + 56..entry_offset + 128]
+ .try_into()
+ .unwrap();
+
// Store the parsed information in the partition_entries array
partitions.push(GPTPartitionEntry {
partition_type_guid,
+ unique_partition_guid,
start_sector,
end_sector,
+ attributes,
+ partition_name,
});
}
@@ -665,7 +664,10 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
let fat_fs = fat_fs.unwrap();
- let vfs = crate::drivers::fs::vfs::Vfs::new(Box::new(fat_fs));
+ let vfs = crate::drivers::fs::vfs::Vfs::new(
+ Box::new(fat_fs),
+ &format!("{:?}", partition.partition_type_guid),
+ );
crate::drivers::fs::vfs::VFS_INSTANCES
.lock()
@@ -685,16 +687,6 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
);
}
- let mut buffer = Vec::with_capacity(4096);
- unsafe { buffer.set_len(buffer.capacity()) };
- buffer.fill(0x69_u8);
-
- let _ = drive.write(0, &mut buffer);
-
- let data = drive.read(0, 1);
-
- crate::println!("{:X?}", data);
-
crate::println!("{:?}", partitions);
}
}
diff --git a/src/drivers/video/mod.rs b/src/drivers/video/mod.rs
index d9a6682..b04ed49 100755
--- a/src/drivers/video/mod.rs
+++ b/src/drivers/video/mod.rs
@@ -1,6 +1,7 @@
mod font;
use crate::libs::mutex::Mutex;
+use alloc::vec;
use limine::FramebufferRequest;
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new(0);
@@ -35,6 +36,8 @@ pub fn put_char(
mirror_buffer: Option,
) {
let font = font::G_8X16_FONT;
+ let font_width = 8;
+ let font_height = 16;
if character as usize > u8::MAX as usize {
character = '\x00'; // rounded question mark
@@ -46,13 +49,13 @@ pub fn put_char(
let framebuffer =
get_framebuffer().expect("Tried to use framebuffer, but framebuffer was not found");
- let start_x = cx * 8;
- let start_y = cy * 16;
+ let start_x = cx * font_width as u16;
+ let start_y = cy * font_height as u16;
for (row_idx, &character_byte) in character_array.iter().enumerate() {
- let mut byte = [bg; 8];
+ let mut byte = vec![bg; font_width];
for (i, bit) in byte.iter_mut().enumerate() {
- *bit = [bg, fg][((character_byte >> (7 - i)) & 0b00000001) as usize]
+ *bit = [bg, fg][((character_byte >> ((font_width - 1) - i)) & 0b00000001) as usize]
}
let row_start_offset = (start_y as usize + row_idx) * framebuffer.pitch
diff --git a/src/libs/util.rs b/src/libs/util.rs
index a444123..0778cd0 100644
--- a/src/libs/util.rs
+++ b/src/libs/util.rs
@@ -1,6 +1,6 @@
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub unsafe fn memset32(dst: *mut u32, val: u32, count: usize) {
- if cfg!(not(any(target_arch = "x86", target_arch = "x86_64"))) {
+ #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+ {
let mut buf = dst;
unsafe {
while buf < dst.add(count) {
@@ -11,12 +11,15 @@ pub unsafe fn memset32(dst: *mut u32, val: u32, count: usize) {
return;
}
- core::arch::asm!(
- "rep stosd",
- inout("ecx") count => _,
- inout("edi") dst => _,
- inout("eax") val => _
- );
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ core::arch::asm!(
+ "rep stosd",
+ inout("ecx") count => _,
+ inout("edi") dst => _,
+ inout("eax") val => _
+ );
+ }
}
pub fn hcf() -> ! {
@@ -25,7 +28,7 @@ pub fn hcf() -> ! {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
core::arch::asm!("hlt");
- #[cfg(target_arch = "aarch64")]
+ #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
core::arch::asm!("wfi");
}
}
diff --git a/src/main.rs b/src/main.rs
index 6c20190..4bec0be 100755
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,4 @@
-#![feature(abi_x86_interrupt)]
-#![feature(naked_functions)]
+#![feature(abi_x86_interrupt, naked_functions)]
#![no_std]
#![no_main]
@@ -35,10 +34,15 @@ pub extern "C" fn _start() -> ! {
// drivers::acpi::init_acpi();
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
drivers::pci::enumerate_pci_bus();
drivers::fs::vfs::init();
+ if let Some(kernel) = KERNEL_REQUEST.get_response().get() {
+ crate::println!("{:X?}", kernel.kernel_file.get().unwrap().gpt_disk_uuid);
+ }
+
crate::println!(
"Total memory: {}",
crate::mem::PHYSICAL_MEMORY_MANAGER
@@ -58,6 +62,7 @@ pub struct KernelFeatures {
impl KernelFeatures {
fn update_option(&mut self, option: &str, value: &str) {
+ #[allow(clippy::single_match)]
match option {
"fat_in_mem" => self.fat_in_mem = value == "true",
_ => {}
@@ -113,11 +118,14 @@ fn parse_kernel_cmdline() -> KernelFeatures {
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
crate::log_error!("{}", info);
- let rbp: u64;
- unsafe {
- core::arch::asm!("mov {0:r}, rbp", out(reg) rbp);
- };
- crate::arch::stack_trace::print_stack_trace(6, rbp);
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ let rbp: u64;
+ unsafe {
+ core::arch::asm!("mov {0:r}, rbp", out(reg) rbp);
+ };
+ crate::arch::stack_trace::print_stack_trace(6, rbp);
+ }
hcf();
}
diff --git a/src/usr/shell.rs b/src/usr/shell.rs
index 47e4f77..cff1991 100755
--- a/src/usr/shell.rs
+++ b/src/usr/shell.rs
@@ -110,10 +110,12 @@ pub fn init_shell() {
prompt();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- let kbd_result = crate::drivers::keyboard::init();
+ {
+ let kbd_result = crate::drivers::keyboard::init();
- if kbd_result.is_err() {
- crate::log_error!("Unable to initialize keyboard! {:?}", kbd_result);
+ if kbd_result.is_err() {
+ crate::log_error!("Unable to initialize keyboard! {:?}", kbd_result);
+ }
}
// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
diff --git a/src/usr/tty.rs b/src/usr/tty.rs
index 2c5be90..dc0a227 100755
--- a/src/usr/tty.rs
+++ b/src/usr/tty.rs
@@ -25,6 +25,7 @@ pub struct Console {
pub cursor: Cursor,
feature_bits: AtomicU8,
pub second_buffer: Mutex