From 7f216fdfdd7e9948410011ffe819c837d8160da1 Mon Sep 17 00:00:00 2001 From: juls0730 <62722391+juls0730@users.noreply.github.com> Date: Sun, 17 Dec 2023 01:46:31 -0600 Subject: [PATCH] zlib driver & experimental riscv support this commit adds the last piece to get the initramfs completely finished --- .gitignore | 1 + Cargo.toml | 2 +- Makefile | 48 ++- README.md | 17 +- TODO.md | 10 +- limine.cfg | 2 +- src/arch/mod.rs | 6 + src/arch/x86_64/x86_64-unknown-none.json | 5 +- src/bin/hello.rs | 3 +- src/drivers/fs/fat.rs | 15 +- src/drivers/fs/initramfs/compressors/gzip.rs | 383 ++++++++++++++++++- src/drivers/fs/initramfs/mod.rs | 192 +++++----- src/drivers/fs/vfs.rs | 15 +- src/drivers/keyboard.rs | 2 + src/drivers/mod.rs | 1 + src/drivers/serial.rs | 15 + src/drivers/storage/drive.rs | 7 +- src/drivers/storage/ide.rs | 78 ++-- src/drivers/video/mod.rs | 11 +- src/libs/util.rs | 21 +- src/main.rs | 22 +- src/usr/shell.rs | 8 +- src/usr/tty.rs | 92 ++++- test.log | 43 --- 24 files changed, 744 insertions(+), 255 deletions(-) delete mode 100644 test.log 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>, + // pub lines: Mutex>, } pub struct ConsoleFeatures { @@ -43,6 +44,7 @@ impl Console { cursor: Cursor::new(), feature_bits: AtomicU8::new(0b00000000), second_buffer: Mutex::new(None), + // lines: Mutex::new(Vec::new()), } } @@ -98,6 +100,13 @@ impl Console { let rows = framebuffer.height / 16; self.columns.store(columns as u16, Ordering::SeqCst); self.rows.store(rows as u16, Ordering::SeqCst); + + // let mut lines_lock = self.lines.lock(); + // lines_lock.write().reserve_exact(rows); + // for _ in 0..rows { + // let string = String::with_capacity(columns); + // lines_lock.write().push(string); + // } } pub fn get_features(&self) -> ConsoleFeatures { @@ -115,6 +124,54 @@ impl Console { }; } + // pub fn puts(&self, string: &str) { + // let mut lines = Vec::new(); + + // // let mut text_lock = self.text.lock(); + // // let text = text_lock.write(); + + // let mut col_idx = 0_usize; + // let mut line_string = String::new(); + // for ch in string.chars() { + // if col_idx > self.columns.load(Ordering::SeqCst) as usize - 1 { + // col_idx = 0; + // lines.push(line_string.clone()); + // line_string.clear(); + // } + + // if ch == '\n' { + // col_idx = 0; + // lines.push(line_string.clone()); + // line_string.clear(); + // continue; + // } + + // line_string.push(ch); + // col_idx += 1; + // } + + // let mut new_lines = [self.lines.lock().read().as_slice(), lines.as_slice()].concat(); + // if new_lines.len() > self.rows.load(Ordering::SeqCst) as usize { + // new_lines.reverse(); + // new_lines.resize(self.rows.load(Ordering::SeqCst) as usize - 1, String::new()); + // new_lines.reverse(); + // } + + // (*self.lines.lock().write()) = new_lines; + + // crate::drivers::video::fill_screen(0x000000, *self.second_buffer.lock().read()); + // self.cursor.set_pos(0, 0); + // for line in self.lines.lock().read() { + // self._puts(line); + // self.cursor + // .set_pos(0, self.cursor.cy.load(Ordering::SeqCst) + 1); + // crate::drivers::serial::write_serial('\r'); + // crate::drivers::serial::write_serial('\n') + // } + + // // self._puts(string); + // } + // Uses a stripped down version of ANSI color codes: // \033[FG;BGm pub fn puts(&self, string: &str) { @@ -191,6 +248,7 @@ impl Console { self.cursor.bg.load(Ordering::SeqCst), *self.second_buffer.lock().read(), ); + continue; } @@ -227,6 +285,15 @@ impl Console { self.cursor.set_color(0xbababa, 0x000000); } + // pub fn reblit(&self) { + // self.cursor.set_pos(0, 0); + // self.reblit.store(true, Ordering::SeqCst); + + // self.puts(&self.text.lock().read().trim_end_matches('\n')); + + // self.reblit.store(false, Ordering::SeqCst); + // } + pub fn scroll_console(&self) { let framebuffer_attributes = crate::drivers::video::get_framebuffer() .expect("Tried to scroll console but we have no framebuffer."); @@ -695,17 +762,20 @@ pub fn exec(command: &str) { } if command == "test" { - let message = "Hello from syscall!\n"; - unsafe { - core::arch::asm!( - "mov rdi, 0x01", // write syscall - "mov rsi, 0x01", // stdio (but it doesnt matter) - "mov rdx, {0:r}", // pointer - "mov rcx, {1:r}", // count - "int 0x80", - in(reg) message.as_ptr(), - in(reg) message.len() - ); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + let message = "Hello from syscall!\n"; + unsafe { + core::arch::asm!( + "mov rdi, 0x01", // write syscall + "mov rsi, 0x01", // stdio (but it doesnt matter) + "mov rdx, {0:r}", // pointer + "mov rcx, {1:r}", // count + "int 0x80", + in(reg) message.as_ptr(), + in(reg) message.len() + ); + } } return; diff --git a/test.log b/test.log deleted file mode 100644 index 7fccb4a..0000000 --- a/test.log +++ /dev/null @@ -1,43 +0,0 @@ -[ * ] Serial Driver successfully initialized -[ ? ] Initialized heap with 4MiB of memory at 0x4E8000 -[ ? ] Initialized framebuffer mirroring with 3MiB at 0x100000 -====== MEMORY MAP ====== -[ 0x0000000000001000..0x0000000000052000 ] Type: BootloaderReclaimable Size: 324KiB -[ 0x0000000000053000..0x000000000009F000 ] Type: Usable Size: 304KiB -[ 0x000000000009FC00..0x00000000000A0000 ] Type: Reserved Size: 1KiB -[ 0x00000000000F0000..0x0000000000100000 ] Type: Reserved Size: 64KiB -[ 0x0000000000100000..0x0000000007AC3000 ] Type: Usable Size: 121MiB -[ 0x0000000007AC3000..0x0000000007AC4000 ] Type: KernelAndModules Size: 4KiB -[ 0x0000000007AC4000..0x0000000007AC5000 ] Type: BootloaderReclaimable Size: 4KiB -[ 0x0000000007AC5000..0x0000000007AC8000 ] Type: Usable Size: 12KiB -[ 0x0000000007AC8000..0x0000000007AD0000 ] Type: BootloaderReclaimable Size: 32KiB -[ 0x0000000007AD0000..0x0000000007AFE000 ] Type: KernelAndModules Size: 184KiB -[ 0x0000000007AFE000..0x0000000007B3C000 ] Type: BootloaderReclaimable Size: 248KiB -[ 0x0000000007B3C000..0x0000000007F26000 ] Type: Usable Size: 3MiB -[ 0x0000000007F26000..0x0000000007FE0000 ] Type: BootloaderReclaimable Size: 744KiB -[ 0x0000000007FE0000..0x0000000008000000 ] Type: Reserved Size: 128KiB -[ 0x00000000FD000000..0x00000000FD3E8000 ] Type: Framebuffer Size: 3MiB -[ 0x00000000FFFC0000..0x0000000100000000 ] Type: Reserved Size: 256KiB -[ 0x000000FD00000000..0x0000010000000000 ] Type: Reserved Size: 12GiB -Initramfs is located at: 0xffff800007ac3000..0xffff800007ac4000 -Parsing initramfs fs at 0xffff800007ac3000 -Squashfs { ptr: 0xffff800007ac3060, superblock: SquashfsSuperblock { magic: 73717368, inode_count: 2, mod_time: 6566B6A1, block_size: 20000, frag_count: 1, compressor: GZIP, block_log: 11, flags: 1CB, id_count: 1, ver_major: 4, ver_minor: 0, root_inode_offset: 20, root_inode_block: 0, _reserved: 0, bytes_used: 120, id_table: 118, xattr_table: FFFFFFFFFFFFFFFF, inode_table: 7B, dir_table: BD, frag_table: F0, export_table: 10A }, data_table: [48, 65, 6C, 6C, 6F, 20, 57, 6F, 72, 6C, 64, 20, 66, 72, 6F, 6D, 20, 49, 6E, 69, 74, 72, 61, 6D, 66, 73, A], inode_table: [40, 80, 2, 0, A4, 1, 0, 0, 0, 0, A1, B6, 66, 65, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1B, 0, 0, 0, 1, 0, ED, 1, 0, 0, 0, 0, A1, B6, 66, 65, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 22, 0, 0, 0, 3, 0, 0, 0], directory_table: [1F, 80, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, A, 0, 65, 78, 61, 6D, 70, 6C, 65, 2E, 74, 78, 74, 10, 80, 60, 0, 0, 0, 0, 0, 0, 0, 1B, 0, 0, 1, 0, 0, 0, 0], fragment_table: Some([DE, 0, 0, 0, 0, 0, 0, 0, 10, 80, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0]), export_table: Some([F8, 0, 0, 0, 0, 0, 0, 0, 4, 80, E8, 3, 0, 0]), id_table: [12, 1, 0, 0, 0, 0, 0, 0], xattr_table: None } -SquashfsFeatures { uncompressed_inodes: true, uncompressed_data_blocks: true, _reserved: false, uncompressed_fragments: true, unused_fragments: false, fragments_always_present: false, deduplicated_data: true, nfs_table_present: true, uncompressed_xattrs: true, no_xattrs: false, compressor_options_present: false, uncompressed_id_table: false } -[1, 0, ED, 1, 0, 0, 0, 0, A1, B6, 66, 65, 2, 0, 0, 0] -InodeHeader { file_type: BasicDirectory, _reserved: [0, 0, 0], mtime: 6566B6A1, inode_num: 2 } -root_inode: DirectoryInode { block_index: 0, link_count: 2, file_size: 22, block_offset: 0, parent_inode: 3 } -====== PCI DEVICES ====== -Entry 0: Bus: 0 Device: 0 Function: 0 VendorID: 0x8086 DeviceID: 0x1237 ClassCode: 0x06 SubclassCode: 0x00 ProgIF: 0x00 -Entry 1: Bus: 0 Device: 1 Function: 0 VendorID: 0x8086 DeviceID: 0x7000 ClassCode: 0x06 SubclassCode: 0x01 ProgIF: 0x00 -Entry 2: Bus: 0 Device: 1 Function: 1 VendorID: 0x8086 DeviceID: 0x7010 ClassCode: 0x01 SubclassCode: 0x01 ProgIF: 0x80 -Entry 3: Bus: 0 Device: 1 Function: 3 VendorID: 0x8086 DeviceID: 0x7113 ClassCode: 0x06 SubclassCode: 0x80 ProgIF: 0x00 -Entry 4: Bus: 0 Device: 2 Function: 0 VendorID: 0x1234 DeviceID: 0x1111 ClassCode: 0x03 SubclassCode: 0x00 ProgIF: 0x00 -Entry 5: Bus: 0 Device: 3 Function: 0 VendorID: 0x8086 DeviceID: 0x100E ClassCode: 0x02 SubclassCode: 0x00 ProgIF: 0x00 -[ ? ] ATA: Detected 1 drive -[ ? ] ATA: Drive 0 has 131072 sectors (64 MB) -11, 44, 128 -[ ? ] WARNING: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower. -Found Fat32 FS -[GPTPartitionEntry { partition_type_guid: [40, 115, 42, 193, 31, 248, 210, 17, 186, 75, 0, 160, 201, 62, 201, 59], start_sector: 2048, end_sector: 34815 }, GPTPartitionEntry { partition_type_guid: [175, 61, 198, 15, 131, 132, 114, 71, 142, 121, 61, 105, 216, 71, 125, 228], start_sector: 34816, end_sector: 131038 }] -Total memory: 125MiB -> \ No newline at end of file