update to limine v8 and other various stuff

This commit is contained in:
Zoe
2024-08-13 10:35:06 -05:00
parent 992863a112
commit 119e27129c
23 changed files with 346 additions and 316 deletions

15
Cargo.lock generated
View File

@@ -10,7 +10,16 @@ dependencies = [
]
[[package]]
name = "limine"
version = "0.1.11"
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f45c67c512034e8eb0064556e1db5da671b3ef50791cd6ac6376e7aefc0ef27e"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "limine"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "846c87e24d089e8717a61098cba72b378e3525c46a87cf75b71352dcf668e68c"
dependencies = [
"bitflags",
]

View File

@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
limine = "0.1.10"
limine = "0.2.0"
[profile.release]
opt-level = 3

View File

@@ -20,7 +20,7 @@ IMAGE_PATH = ${ARTIFACTS_PATH}/${IMAGE_NAME}
CARGO_OPTS = --target=src/arch/${ARCH}/${ARCH}-unknown-none.json
QEMU_OPTS += -m ${MEMORY} -drive id=hd0,format=raw,file=${IMAGE_PATH}
LIMINE_BOOT_VARIATION = X64
LIMINE_BRANCH = v7.x-binary
LIMINE_BRANCH = v8.x-binary
ifeq (${MODE},release)
CARGO_OPTS += --release
@@ -108,7 +108,7 @@ copy-iso-files:
mkdir -p ${ISO_PATH}/mnt
cp -v limine.cfg limine/limine-bios.sys ${ISO_PATH}/boot/limine
cp -v limine.conf limine/limine-bios.sys ${ISO_PATH}/boot/limine
cp -v limine/BOOT${LIMINE_BOOT_VARIATION}.EFI ${ISO_PATH}/EFI/BOOT/
# OS files

View File

@@ -49,7 +49,7 @@ Before building CappuccinOS, make sure you have the following installed on your
- rust
- python
- sgdisk
- mtools
- dosfstools
- squashfs-tools
- qemu (optional)
@@ -71,7 +71,7 @@ Install the dependencies:
<details>
<summary>Arch</summary>
sudo pacman -S gptfdisk mtools squashfs-tools python
sudo pacman -S gptfdisk dosfstools squashfs-tools python
# Optionally
sudo pacman -S qemu-system-x86
@@ -81,7 +81,7 @@ Install the dependencies:
<summary>Ubuntu</summary>
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 gdisk mtools squashfs-tools
sudo apt install gdisk dosfstools squashfs-tools
# Optionally
sudo apt install qemu

View File

@@ -1,10 +0,0 @@
# Timeout in seconds that Limine will use before automatically booting.
TIMEOUT=3
:CappuccinOS
PROTOCOL=limine
KERNEL_PATH=boot:///boot/CappuccinOS.elf
KERNEL_CMDLINE=fat_in_mem=false big_fat_phony
MODULE_PATH=boot:///boot/initramfs.img

View File

@@ -6,42 +6,52 @@ OUTPUT_ARCH(aarch64)
ENTRY(_start)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions */
/* MMU permissions; this also allows us to exert more control over the linking */
/* process. */
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
headers PT_PHDR PHDRS;
text PT_LOAD FILEHDR PHDRS;
rodata PT_LOAD;
data PT_LOAD;
dynamic PT_DYNAMIC;
}
SECTIONS
{
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
/* base load address. */
. = 0xffffffff80000000 + SIZEOF_HEADERS;
.text : {
*(.text .text.*)
} :text
/* Move to the next memory page for .rodata */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Move to the next memory page for .data */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data : {
*(.data .data.*)
/* Place the sections that contain the Limine requests as part of the .data */
/* output section. */
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
} :data
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR */
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR. */
.dynamic : {
*(.dynamic)
} :data :dynamic
@@ -55,9 +65,13 @@ SECTIONS
*(COMMON)
} :data
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/* Also discard the program interpreter section since we do not need one. This is */
/* more or less equivalent to the --no-dynamic-linker linker flag, except that it */
/* works with ld.gold. */
/DISCARD/ : {
*(.eh_frame)
*(.eh_frame*)
*(.note .note.*)
*(.interp)
}
}

View File

@@ -6,43 +6,54 @@ OUTPUT_ARCH(riscv:rv64)
ENTRY(_start)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions */
/* MMU permissions; this also allows us to exert more control over the linking */
/* process. */
PHDRS
{
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
headers PT_PHDR PHDRS;
text PT_LOAD FILEHDR PHDRS;
rodata PT_LOAD;
data PT_LOAD;
dynamic PT_DYNAMIC;
}
SECTIONS
{
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
/* base load address. */
. = 0xffffffff80000000 + SIZEOF_HEADERS;
.text : {
*(.text .text.*)
} :text
/* Move to the next memory page for .rodata */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Move to the next memory page for .data */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data : {
*(.data .data.*)
/* Place the sections that contain the Limine requests as part of the .data */
/* output section. */
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
*(.sdata .sdata.*)
} :data
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR */
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR. */
.dynamic : {
*(.dynamic)
} :data :dynamic
@@ -57,9 +68,13 @@ SECTIONS
*(COMMON)
} :data
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/* Also discard the program interpreter section since we do not need one. This is */
/* more or less equivalent to the --no-dynamic-linker linker flag, except that it */
/* works with ld.gold. */
/DISCARD/ : {
*(.eh_frame)
*(.eh_frame*)
*(.note .note.*)
*(.interp)
}
}

View File

@@ -66,8 +66,8 @@ pub struct APIC {
pub cpus: Arc<[LAPIC]>,
}
extern "C" fn test(info: *const limine::SmpInfo) -> ! {
crate::log_ok!("hey from CPU {:<02}", unsafe { (*info).processor_id });
unsafe extern "C" fn test<'a>(cpu: &'a limine::smp::Cpu) -> ! {
crate::log_ok!("hey from CPU {:<02}", cpu.id);
hcf();
}
@@ -175,21 +175,21 @@ impl APIC {
crate::println!("{number_of_inputs}");
let smp_request = SMP_REQUEST.get_response().get_mut();
let smp_request = unsafe { SMP_REQUEST.get_response_mut() };
if smp_request.is_none() {
panic!("Failed to get smp from limine!");
}
let smp_request = smp_request.unwrap();
let bsp_lapic_id = smp_request.bsp_lapic_id;
let bsp_lapic_id = smp_request.bsp_lapic_id();
for cpu in smp_request.cpus() {
if cpu.processor_id == bsp_lapic_id {
if cpu.id == bsp_lapic_id {
continue;
}
cpu.goto_address = test;
cpu.goto_address.write(test);
}
// Set and enable keyboard interrupt
@@ -220,7 +220,7 @@ impl APIC {
pub fn write_lapic(&self, reg: u32, value: u32) {
unsafe {
*self.local_apic.add(reg as usize).cast::<u32>() = value;
core::ptr::write_volatile(self.local_apic.add(reg as usize).cast::<u32>(), value);
}
}

View File

@@ -36,43 +36,43 @@ struct Registers {
extern "C" fn exception_handler(registers: u64) {
let registers = unsafe { *(registers as *const Registers) };
crate::println!("{:X?}", registers);
// crate::println!("{:X?}", registers);
let int = registers.int;
match int {
0x00 => {
log_error!("DIVISION ERROR!");
crate::drivers::serial::write_string("DIVISION ERROR!");
}
0x06 => {
log_error!("INVALID OPCODE!");
crate::drivers::serial::write_string("INVALID OPCODE!");
}
0x08 => {
log_error!("DOUBLE FAULT!");
crate::drivers::serial::write_string("DOUBLE FAULT!");
}
0x0D => {
log_error!("GENERAL PROTECTION FAULT!");
crate::drivers::serial::write_string("GENERAL PROTECTION FAULT!");
}
0x0E => {
log_error!("PAGE FAULT!");
crate::drivers::serial::write_string("PAGE FAULT!");
}
0xFF => {
log_error!("EXCEPTION!");
crate::drivers::serial::write_string("EXCEPTION!");
}
_ => {
log_error!("EXCEPTION!");
crate::drivers::serial::write_string("EXCEPTION!");
}
}
log_info!(
"INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}",
int,
registers.rip,
registers.cs,
registers.rflags
);
// log_info!(
// "INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}",
// int,
// registers.rip,
// registers.cs,
// registers.rflags
// );
crate::arch::stack_trace::print_stack_trace(6, registers.rbp as u64);
// crate::arch::stack_trace::print_stack_trace(6, registers.rbp as u64);
}
// *macro intensifies*

View File

@@ -1,11 +1,6 @@
pub mod apic;
pub mod exceptions;
use crate::{
// arch::{apic, x86_common::pic::ChainedPics},
libs::sync::Mutex,
};
use self::apic::APIC;
#[repr(C, packed)]
@@ -34,13 +29,15 @@ impl IdtEntry {
}
}
impl !Sync for IdtEntry {}
#[repr(C, packed)]
struct IdtPtr {
limit: u16,
base: u64,
}
static IDT: Mutex<[IdtEntry; 256]> = Mutex::new([IdtEntry::new(); 256]);
static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256];
#[derive(Clone, Copy)]
#[repr(u8)]
@@ -62,15 +59,17 @@ static mut IDT_PTR: IdtPtr = IdtPtr {
pub fn idt_set_gate(num: u8, function_ptr: usize) {
let base = function_ptr;
IDT.lock()[num as usize] = IdtEntry {
base_lo: (base & 0xFFFF) as u16,
base_mid: ((base >> 16) & 0xFFFF) as u16,
base_hi: ((base >> 32) & 0xFFFFFFFF) as u32,
sel: 0x28,
ist: 0,
always0: 0,
flags: 0xEE,
};
unsafe {
IDT[num as usize] = IdtEntry {
base_lo: (base & 0xFFFF) as u16,
base_mid: ((base >> 16) & 0xFFFF) as u16,
base_hi: ((base >> 32) & 0xFFFFFFFF) as u32,
sel: 0x28,
ist: 0,
always0: 0,
flags: 0xEE,
};
}
// If the interrupt with this number occurred with the "null" interrupt handler
// We will need to tell the PIC that interrupt is over, this stops new interrupts
@@ -83,31 +82,18 @@ extern "x86-interrupt" fn null_interrupt_handler() {
signal_end_of_interrupt();
}
extern "x86-interrupt" fn timer_handler() {
// crate::usr::tty::puts(".");
signal_end_of_interrupt();
}
pub fn idt_init() {
unsafe {
let idt_size = core::mem::size_of::<IdtEntry>() * 256;
{
let mut idt_lock = IDT.lock();
IDT_PTR.base = idt_lock.as_ptr() as u64;
IDT_PTR.base = IDT.as_ptr() as u64;
core::ptr::write_bytes(
idt_lock.as_mut_ptr().cast::<core::ffi::c_void>(),
0,
idt_size,
);
}
core::ptr::write_bytes(IDT.as_mut_ptr().cast::<core::ffi::c_void>(), 0, idt_size);
// Set every interrupt to the "null" interrupt handler (it does nothing)
for num in 0..=255 {
idt_set_gate(num, null_interrupt_handler as usize);
}
idt_set_gate(InterruptIndex::Timer.as_u8(), timer_handler as usize);
idt_set_gate(0x80, syscall as usize);
core::arch::asm!(

View File

@@ -6,58 +6,56 @@ OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions */
/* MMU permissions; this also allows us to exert more control over the linking */
/* process. */
PHDRS
{
requests PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
headers PT_PHDR PHDRS;
text PT_LOAD FILEHDR PHDRS;
rodata PT_LOAD;
data PT_LOAD;
dynamic PT_DYNAMIC;
}
SECTIONS
{
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
/* Define a section to contain the Limine requests and assign it to its own PHDR */
.requests : {
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
} :requests
/* Move to the next memory page for .text */
. += CONSTANT(MAXPAGESIZE);
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
/* base load address. */
. = 0xffffffff80000000 + SIZEOF_HEADERS;
.text : {
*(.text .text.*)
} :text
/* Move to the next memory page for .rodata */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : {
*(.rodata .rodata.*)
} :rodata
/* Move to the next memory page for .data */
. += CONSTANT(MAXPAGESIZE);
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data : {
*(.data .data.*)
/* Place the sections that contain the Limine requests as part of the .data */
/* output section. */
KEEP(*(.requests_start_marker))
KEEP(*(.requests))
KEEP(*(.requests_end_marker))
} :data
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR */
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR. */
.dynamic : {
*(.dynamic)
} :data :dynamic
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
@@ -67,9 +65,13 @@ SECTIONS
*(COMMON)
} :data
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/* Also discard the program interpreter section since we do not need one. This is */
/* more or less equivalent to the --no-dynamic-linker linker flag, except that it */
/* works with ld.gold. */
/DISCARD/ : {
*(.eh_frame)
*(.eh_frame*)
*(.note .note.*)
*(.interp)
}
}

View File

@@ -1,5 +1,8 @@
use core::ops::Add;
use alloc::vec::Vec;
use limine::SmpRequest;
use limine::request::RsdpRequest;
use limine::request::SmpRequest;
use crate::{
arch::io::{inw, outb},
@@ -7,7 +10,9 @@ use crate::{
mem::HHDM_OFFSET,
};
pub static SMP_REQUEST: SmpRequest = SmpRequest::new(0);
#[used]
#[link_section = ".requests"]
pub static mut SMP_REQUEST: SmpRequest = SmpRequest::new();
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
@@ -33,7 +38,9 @@ pub struct SDT<'a, T> {
impl<'a, T> SDT<'a, T> {
unsafe fn new(mut ptr: *const u8) -> Self {
ptr = ptr.add(*HHDM_OFFSET);
if (ptr as usize) < *HHDM_OFFSET {
ptr = ptr.add(*HHDM_OFFSET);
}
let length = core::ptr::read_unaligned(ptr.add(4).cast::<u32>());
let data = core::slice::from_raw_parts(ptr, length as usize);
@@ -121,12 +128,12 @@ impl<'a> RootSDT<'a> {
let root_ptr = match self {
RootSDT::RSDT(rsdt) => {
let ptrs = rsdt.inner.pointers as *const u8;
let ptrs = (rsdt.inner.pointers as usize).add(*HHDM_OFFSET) as *const u8;
assert!(!ptrs.is_null());
ptrs.add(offset)
}
RootSDT::XSDT(xsdt) => {
let ptrs = xsdt.inner.pointers as *const u8;
let ptrs = (xsdt.inner.pointers as usize).add(*HHDM_OFFSET) as *const u8;
assert!(!ptrs.is_null());
ptrs.add(offset)
}
@@ -149,22 +156,22 @@ struct ACPI<'a> {
static ACPI: OnceCell<ACPI> = OnceCell::new();
static RSDP_REQ: limine::RsdpRequest = limine::RsdpRequest::new(0);
static RSDP_REQ: RsdpRequest = RsdpRequest::new();
fn resolve_acpi() {
let rsdp_ptr = RSDP_REQ.get_response().get();
let rsdp_ptr = RSDP_REQ.get_response();
if rsdp_ptr.is_none() {
panic!("RSDP not found!");
}
let rsdp = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::<RSDP>() };
let rsdp = unsafe { &*rsdp_ptr.unwrap().address().cast::<RSDP>() };
// TODO: validate RSDT
let root_sdt = {
if rsdp.revision == 0 {
RootSDT::RSDT(unsafe { SDT::new(rsdp.rsdt_addr as *mut u8) })
} else {
let xsdt = unsafe { &*rsdp_ptr.unwrap().address.as_ptr().unwrap().cast::<XSDP>() };
let xsdt = unsafe { &*rsdp_ptr.unwrap().address().cast::<XSDP>() };
RootSDT::XSDT(unsafe { SDT::new(xsdt.xsdt_addr as *mut u8) })
}
};
@@ -256,6 +263,7 @@ struct FADT {
x_gpe1_block: GenericAddressStructure,
}
#[no_mangle]
pub fn init_acpi() {
resolve_acpi();

View File

@@ -39,20 +39,20 @@ enum FatType {
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct BIOSParameterBlock {
_jmp_instruction: [u8; 3], // EB 58 90
pub oem_identifier: [u8; 8], // MTOO4043 (hey, mtools)
pub bytes_per_sector: u16, // 00 02 (little endian so 512)
pub sectors_per_cluster: u8, // 01
pub reserved_sectors: u16, // 20 00 (32)
pub fat_count: u8, // 02
pub root_directory_count: u16, // 00 00 (what)
pub total_sectors: u16, // equal to zero when sector count is more than 65535
pub media_descriptor_type: u8, // F0
pub sectors_per_fat: u16, // Fat12/Fat16 only
pub sectors_per_track: u16, // 3F 00 (63)
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)
_jmp_instruction: [u8; 3],
pub oem_identifier: [u8; 8],
pub bytes_per_sector: u16,
pub sectors_per_cluster: u8,
pub reserved_sectors: u16,
pub fat_count: u8,
pub root_directory_count: u16,
pub total_sectors: u16,
pub media_descriptor_type: u8,
pub sectors_per_fat: u16,
pub sectors_per_track: u16,
pub head_count: u16,
pub hidden_sectors: u32,
pub large_sector_count: u32,
pub ebpb_bytes: [u8; 54],
}
@@ -71,19 +71,19 @@ pub struct Fat16EBPB {
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Fat32EBPB {
pub sectors_per_fat_ext: u32, // E1 03 00 00 (993, wtf)
pub flags: [u8; 2], // 00 00
pub fat_version: u16, // 00 00
pub root_dir_cluster: u32, // 2C 00 00 00 (2)
pub fsinfo_sector: u16, // 01 00 (1)
pub backup_bootsector: u16, // 06 00 (6)
_reserved: [u8; 12], // all zero
pub drive_number: u8, // 00
_reserved2: u8, // 00
pub signature: u8, // either 0x28 of 0x29: 29
pub volume_id: u32, // Varies
pub volume_label: [u8; 11], // "NO NAME "
pub system_identifier_string: [u8; 8], // Always "FAT32 " but never trust the contents of this string (for some reason)
pub sectors_per_fat_ext: u32,
pub flags: [u8; 2],
pub fat_version: u16,
pub root_dir_cluster: u32,
pub fsinfo_sector: u16,
pub backup_bootsector: u16,
_reserved: [u8; 12],
pub drive_number: u8,
_reserved2: u8,
pub signature: u8,
pub volume_id: u32,
pub volume_label: [u8; 11],
pub system_identifier_string: [u8; 8],
}
#[repr(C, packed)]
@@ -358,30 +358,28 @@ impl FatFs {
}
}
if name.replacen('.', "", 1).len() <= 11 {
let search_parts: Vec<&str> = name.split('.').collect();
let raw_short_filename = core::str::from_utf8(&file_entry.file_name)
.unwrap()
.trim_end();
let raw_short_extension = core::str::from_utf8(&file_entry.extension)
.unwrap()
.trim_end();
let formatted_short_filename = match raw_short_extension.is_empty() {
true => raw_short_filename.to_string(),
false => alloc::format!("{}.{}", raw_short_filename, raw_short_extension),
};
let filename = core::str::from_utf8(&file_entry.file_name).unwrap();
let extension = core::str::from_utf8(&file_entry.extension).unwrap();
if (search_parts.len() == 1
&& !filename.contains(&search_parts[0].to_ascii_uppercase()))
|| (search_parts.len() > 1
&& (!filename.contains(&search_parts[0].to_ascii_uppercase())
|| !extension.contains(&search_parts[1].to_ascii_uppercase())))
{
if let Some(ref filename) = long_filename_string {
if filename != name {
continue;
}
return Ok(file_entry);
} else {
// Long file name
if long_filename_string != Some(name.to_string()) {
if name.to_uppercase() != formatted_short_filename {
continue;
}
return Ok(file_entry);
}
return Ok(file_entry);
}
return Err(());
@@ -533,9 +531,7 @@ impl FsOps for FatFs {
),
};
let file = File::Dir(FatDirectory {
directory_cluster: root_cluster,
});
let file = File::Dir(root_cluster);
return VNode::new(Box::new(file), super::vfs::VNodeType::Directory, vfsp);
}
@@ -562,8 +558,9 @@ impl FsOps for FatFs {
}
enum File {
Archive(FatFile),
Dir(FatDirectory),
Archive(FileEntry),
// directory cluster
Dir(usize),
}
impl VNodeOperations for File {
@@ -585,8 +582,8 @@ impl VNodeOperations for File {
let mut file: Vec<u8> = Vec::with_capacity(count);
let mut cluster = ((archive.file_entry.high_first_cluster_number as u32) << 16)
| archive.file_entry.low_first_cluster_number as u32;
let mut cluster = ((archive.high_first_cluster_number as u32) << 16)
| archive.low_first_cluster_number as u32;
let cluster_size = unsafe { (*fat_fs).cluster_size };
@@ -685,8 +682,7 @@ impl VNodeOperations for File {
match self {
File::Dir(directory) => unsafe {
let file_entry =
(*fat_fs).find_entry_in_directory(directory.directory_cluster, nm)?;
let file_entry = (*fat_fs).find_entry_in_directory(*directory, nm)?;
let file_typ = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
crate::drivers::fs::vfs::VNodeType::Directory
@@ -695,11 +691,9 @@ impl VNodeOperations for File {
};
let file = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
File::Dir(FatDirectory {
directory_cluster: file_entry.cluster() as usize,
})
File::Dir(file_entry.cluster() as usize)
} else {
File::Archive(FatFile { file_entry })
File::Archive(file_entry)
};
let vnode = VNode::new(Box::new(file), file_typ, (*vp.as_ptr()).parent_vfs);
@@ -788,16 +782,8 @@ impl VNodeOperations for File {
fn len(&self, _vp: NonNull<VNode>) -> usize {
match self {
File::Archive(archive) => archive.file_entry.file_size as usize,
File::Archive(archive) => archive.file_size as usize,
_ => panic!("idk"),
}
}
}
struct FatFile {
file_entry: FileEntry,
}
struct FatDirectory {
directory_cluster: usize,
}

View File

@@ -64,7 +64,10 @@ pub struct ChunkReader<'a, F> {
decompressor: F,
}
impl<'a, F: Fn(&[u8]) -> Result<Vec<u8>, ()>> ChunkReader<'a, F> {
impl<'a, F> ChunkReader<'a, F>
where
F: Fn(&[u8]) -> Result<Vec<u8>, ()>,
{
pub fn new(data: &'a [u8], decompressor: F) -> Self {
let mut chunks: Vec<Chunk<'_>> = Vec::new();

View File

@@ -4,30 +4,32 @@ mod superblock;
use core::{fmt::Debug, mem::MaybeUninit, ptr::NonNull};
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
use limine::ModuleRequest;
use limine::request::ModuleRequest;
use super::vfs::{FsOps, VNode, VNodeOperations, VNodeType};
pub static MODULE_REQUEST: ModuleRequest = ModuleRequest::new(0);
#[used]
#[link_section = ".requests"]
pub static MODULE_REQUEST: ModuleRequest = ModuleRequest::new();
pub fn init() -> Squashfs<'static> {
// TODO: Put the module request stuff in another file?
if MODULE_REQUEST.get_response().get().is_none() {
if MODULE_REQUEST.get_response().is_none() {
panic!("Module request in none!");
}
let module_response = MODULE_REQUEST.get_response().get().unwrap();
let module_response = MODULE_REQUEST.get_response().unwrap();
let mut initramfs = None;
let module_name = "initramfs.img";
for module in module_response.modules() {
let c_path = module.path.to_str();
if c_path.is_none() {
let path = core::str::from_utf8(module.path());
if path.is_err() {
continue;
}
if !c_path.unwrap().to_str().unwrap().contains(module_name) {
if !path.unwrap().contains(module_name) {
continue;
}
@@ -40,7 +42,7 @@ pub fn init() -> Squashfs<'static> {
}
let initramfs = initramfs.unwrap();
let squashfs = Squashfs::new(initramfs.base.as_ptr().unwrap());
let squashfs = Squashfs::new(initramfs.addr());
if squashfs.is_err() {
panic!("Initramfs in corrupt!");
@@ -173,6 +175,7 @@ impl Squashfs<'_> {
});
}
#[inline(always)]
fn get_inode_block_offset(&self, inode: u64) -> (u64, u16) {
let inode_block = (inode >> 16) & 0x0000FFFFFFFFFFFF;
let inode_offset = (inode & 0xFFFF) as u16;

View File

@@ -632,6 +632,22 @@ pub trait VNodeOperations {
// fn strategy(&mut self, bp: (), vp: NonNull<VNode>);
// fn bread(&mut self, block_number: u32, vp: NonNull<VNode>) -> Arc<[u8]>;
fn len(&self, vp: NonNull<VNode>) -> usize;
// TODO: not object safe
// fn get_fs<'a, T>(&self, vp: NonNull<VNode>) -> &'a mut T
// where
// T: FsOps,
// {
// unsafe {
// let vfs = (*vp.as_ptr()).parent_vfs.as_mut();
// let fs = vfs
// .fs
// .as_mut()
// .expect("Tried to call get_fs on root VFS")
// .as_mut() as *mut dyn FsOps;
// &mut *fs.cast::<T>()
// }
// }
}
#[allow(unused)]
@@ -667,7 +683,10 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
return Err(());
}
unsafe { NODE_TREE = Some(TreeNode::new(vfs.fs.as_mut().unwrap().as_mut().root(vfsp))) }
crate::println!("reading the root");
let root = vfs.fs.as_mut().unwrap().as_mut().root(vfsp);
crate::println!("successfully read the root");
unsafe { NODE_TREE = Some(TreeNode::new(root)) }
} else {
if unsafe { ROOT_VFS.next.is_none() } {
return Err(());

View File

@@ -30,8 +30,14 @@ pub extern "x86-interrupt" fn keyboard_interrupt_handler() {
let key = parse_key(scancode);
if let Some(key) = key {
// crate::usr::shell::handle_key(key)
write_serial(key.character.unwrap() as u8);
if !key.pressed {
return;
}
if let Some(character) = key.character {
// crate::usr::shell::handle_key(key)
write_serial(character as u8);
}
}
}

View File

@@ -1,4 +1,4 @@
use limine::FramebufferRequest;
use limine::{framebuffer, request::FramebufferRequest};
use crate::libs::cell::OnceCell;
@@ -69,27 +69,28 @@ impl Framebuffer {
}
}
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new(0);
#[used]
#[link_section = ".requests"]
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
pub static FRAMEBUFFER: OnceCell<Option<Framebuffer>> = OnceCell::new();
pub fn get_framebuffer() -> Option<Framebuffer> {
*FRAMEBUFFER.get_or_set(|| {
let framebuffer_response = crate::drivers::video::FRAMEBUFFER_REQUEST
.get_response()
.get()?;
let framebuffer_response = crate::drivers::video::FRAMEBUFFER_REQUEST.get_response()?;
let framebuffer = framebuffer_response.framebuffers().next();
if framebuffer_response.framebuffer_count < 1 {
if framebuffer.is_none() {
return None;
}
let framebuffer_response = &framebuffer_response.framebuffers()[0];
let framebuffer_response = framebuffer.as_ref().unwrap();
let framebuffer = Framebuffer::new(
framebuffer_response.bpp as usize,
framebuffer_response.pitch as usize,
framebuffer_response.address.as_ptr().unwrap(),
framebuffer_response.width as usize,
framebuffer_response.height as usize,
framebuffer_response.bpp() as usize,
framebuffer_response.pitch() as usize,
framebuffer_response.addr(),
framebuffer_response.width() as usize,
framebuffer_response.height() as usize,
);
return Some(framebuffer);

View File

@@ -1,7 +1,5 @@
use alloc::vec::Vec;
use crate::libs::sync::Mutex;
#[derive(Debug)]
#[repr(u8)]
enum ZlibCompressionLevel {
@@ -109,15 +107,6 @@ struct Huff {
symbols: [u16; 288],
}
static FIXED_LENGTHS: Mutex<Huff> = Mutex::new(Huff {
counts: [0_u16; 16],
symbols: [0_u16; 288],
});
static FIXED_DISTS: Mutex<Huff> = Mutex::new(Huff {
counts: [0_u16; 16],
symbols: [0_u16; 288],
});
struct HuffRing {
pointer: usize,
data: Vec<u8>,
@@ -183,7 +172,16 @@ impl InflateContext {
}
pub fn decompress(&mut self) -> Result<Vec<u8>, ()> {
build_fixed();
let mut lengths = Huff {
counts: [0_u16; 16],
symbols: [0_u16; 288],
};
let mut dists = Huff {
counts: [0_u16; 16],
symbols: [0_u16; 288],
};
build_fixed(&mut lengths, &mut dists);
loop {
let is_final = self.get_bit();
@@ -194,7 +192,7 @@ impl InflateContext {
self.uncompressed()?;
}
0x01 => {
self.inflate(&mut FIXED_LENGTHS.lock(), &mut FIXED_DISTS.lock())?;
self.inflate(&mut lengths, &mut dists)?;
}
0x02 => {
self.decode_huffman()?;
@@ -418,7 +416,7 @@ fn build_huffman(lengths: &[u8], size: usize, out: &mut Huff) {
}
}
fn build_fixed() {
fn build_fixed(out_length: &mut Huff, out_dist: &mut Huff) {
let mut lengths = [0_u8; 288];
lengths[0..144].fill(8);
@@ -426,9 +424,9 @@ fn build_fixed() {
lengths[256..280].fill(7);
lengths[280..288].fill(8);
build_huffman(&lengths, 288, &mut FIXED_LENGTHS.lock());
build_huffman(&lengths, 288, out_length);
lengths[0..30].fill(5);
build_huffman(&lengths, 30, &mut FIXED_DISTS.lock());
build_huffman(&lengths, 30, out_dist);
}

View File

@@ -27,6 +27,7 @@ impl<T> Mutex<T> {
.is_err()
{
// spin lock
core::hint::spin_loop()
}
return MutexGuard { mutex: self };
}

View File

@@ -1,18 +1,11 @@
#![feature(
allocator_api,
abi_x86_interrupt,
naked_functions,
const_mut_refs,
negative_impls
)]
#![feature(abi_x86_interrupt, naked_functions, negative_impls)]
#![allow(clippy::needless_return)]
#![no_std]
#![no_main]
use core::ffi::CStr;
use alloc::vec::Vec;
use limine::KernelFileRequest;
use limine::{request::KernelFileRequest, BaseRevision};
use mem::HHDM_OFFSET;
use crate::drivers::fs::{
initramfs,
@@ -26,7 +19,15 @@ pub mod drivers;
pub mod libs;
pub mod mem;
pub static KERNEL_REQUEST: KernelFileRequest = KernelFileRequest::new(0);
// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
#[used]
// The .requests section allows limine to find the requests faster and more safely.
#[link_section = ".requests"]
static BASE_REVISION: BaseRevision = BaseRevision::new();
#[used]
#[link_section = ".requests"]
pub static KERNEL_REQUEST: KernelFileRequest = KernelFileRequest::new();
#[no_mangle]
pub extern "C" fn _start() -> ! {
@@ -65,7 +66,7 @@ pub fn kmain() -> ! {
crate::println!(
"LIMINE BOOT: {:X?}",
limine_dir
.lookup("limine.cfg")
.lookup("limine.conf")
.unwrap()
.open(0, UserCred { uid: 0, gid: 0 })
.read(0, 0, 0)
@@ -82,7 +83,7 @@ pub fn kmain() -> ! {
.unwrap()
.lookup("limine")
.unwrap()
.lookup("limine.cfg")
.lookup("limine.conf")
.unwrap()
.open(0, UserCred { uid: 0, gid: 0 })
.read(0, 10, 0)
@@ -95,7 +96,7 @@ pub fn kmain() -> ! {
crate::println!(
"LIMINE BOOT: {:X?}",
limine_dir
.lookup("limine.cfg")
.lookup("limine.conf")
.unwrap()
.open(0, UserCred { uid: 0, gid: 0 })
.read(0, 0, 0)
@@ -132,20 +133,14 @@ fn draw_gradient() {
let length = (fb.height * fb.width) * (fb.bpp / 8);
let pages = length / crate::mem::pmm::PAGE_SIZE;
let buffer_ptr = crate::mem::PHYSICAL_MEMORY_MANAGER.alloc(pages);
let buffer_ptr =
(crate::mem::PHYSICAL_MEMORY_MANAGER.alloc(pages) as usize + *HHDM_OFFSET) as *mut u8;
if buffer_ptr.is_null() {
panic!("Failed to allocate screen buffer")
}
let buffer = unsafe {
core::slice::from_raw_parts_mut(
crate::mem::PHYSICAL_MEMORY_MANAGER
.alloc(pages)
.cast::<u32>(),
length,
)
};
let buffer = unsafe { core::slice::from_raw_parts_mut(buffer_ptr.cast::<u32>(), length) };
for y in 0..fb.height {
for x in 0..fb.width {
@@ -160,7 +155,8 @@ fn draw_gradient() {
fb.blit_screen(buffer, None);
crate::mem::PHYSICAL_MEMORY_MANAGER.dealloc(buffer_ptr, pages);
crate::mem::PHYSICAL_MEMORY_MANAGER
.dealloc((buffer_ptr as usize - *HHDM_OFFSET) as *mut u8, pages);
}
#[macro_export]
@@ -219,31 +215,15 @@ pub static KERNEL_FEATURES: libs::cell::OnceCell<KernelFeatures> = libs::cell::O
fn parse_kernel_cmdline() {
let mut kernel_features: KernelFeatures = KernelFeatures { fat_in_mem: true };
let kernel_file_response = KERNEL_REQUEST.get_response().get();
let kernel_file_response = KERNEL_REQUEST.get_response();
if kernel_file_response.is_none() {
KERNEL_FEATURES.set(kernel_features);
return;
}
let cmdline_ptr = kernel_file_response
.unwrap()
.kernel_file
.get()
.unwrap()
.cmdline
.as_ptr();
let cmdline = core::str::from_utf8(kernel_file_response.unwrap().file().cmdline());
if cmdline_ptr.is_none() {
KERNEL_FEATURES.set(kernel_features);
return;
}
let cmdline = unsafe { CStr::from_ptr(cmdline_ptr.unwrap()) };
let kernel_arguments = cmdline
.to_str()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>();
let kernel_arguments = cmdline.unwrap().split_whitespace().collect::<Vec<&str>>();
crate::println!("{kernel_arguments:?}");

View File

@@ -5,8 +5,14 @@ use crate::libs::{cell::OnceCell, sync::Mutex};
use self::{allocator::LinkedListAllocator, pmm::PhysicalMemoryManager};
static MEMMAP_REQUEST: limine::MemmapRequest = limine::MemmapRequest::new(0);
static HHDM_REQUEST: limine::HhdmRequest = limine::HhdmRequest::new(0);
#[used]
#[link_section = ".requests"]
static mut MEMMAP_REQUEST: limine::request::MemoryMapRequest =
limine::request::MemoryMapRequest::new();
#[used]
#[link_section = ".requests"]
static HHDM_REQUEST: limine::request::HhdmRequest = limine::request::HhdmRequest::new();
pub static HHDM_OFFSET: OnceCell<usize> = OnceCell::new();
pub static PHYSICAL_MEMORY_MANAGER: OnceCell<PhysicalMemoryManager> = OnceCell::new();
@@ -21,26 +27,27 @@ const HEAP_PAGES: usize = 1024; // 4 MiB heap
#[global_allocator]
pub static ALLOCATOR: Mutex<LinkedListAllocator> = Mutex::new(LinkedListAllocator::new());
pub fn log_memory_map() {
let memmap_request = MEMMAP_REQUEST.get_response().get_mut();
if memmap_request.is_none() {
panic!("Memory map was None!");
}
// TODO: Limine-rs 0.2.0 does NOT have debug implemented for a lot of it's types, so until that is fixed, either go without Type, or hack limine-rs locally
// pub fn log_memory_map() {
// let memmap_request = unsafe { MEMMAP_REQUEST.get_response_mut() };
// if memmap_request.is_none() {
// panic!("Memory map was None!");
// }
let memmap = memmap_request.unwrap().memmap();
// let memmap = memmap_request.unwrap().entries();
crate::log_serial!("====== MEMORY MAP ======\n");
for entry in memmap.iter() {
let label = (entry.len as usize).label_bytes();
// crate::log_serial!("====== MEMORY MAP ======\n");
// for entry in memmap.iter() {
// let label = (entry.length as usize).label_bytes();
crate::log_serial!(
"[ {:#018X?} ] Type: {:?} Size: {}\n",
entry.base..entry.base + entry.len,
entry.typ,
label
)
}
}
// crate::log_serial!(
// "[ {:#018X?} ] Type: {:?} Size: {}\n",
// entry.base..entry.base + entry.length,
// entry.entry_type,
// label
// )
// }
// }
pub fn init_allocator() {
let mut allocator_lock = ALLOCATOR.lock();
@@ -51,7 +58,9 @@ pub fn init_allocator() {
crate::println!(
"{} of memory available",
PHYSICAL_MEMORY_MANAGER.total_memory().label_bytes()
)
);
// log_memory_map();
}
pub enum Label {

View File

@@ -31,27 +31,27 @@ impl PhysicalMemoryManager {
let hhdm_req = HHDM_REQUEST
.get_response()
.get()
.expect("Failed to get Higher Half Direct Map!");
let hhdm_offset = hhdm_req.offset as usize;
let hhdm_offset = hhdm_req.offset() as usize;
HHDM_OFFSET.set(hhdm_offset);
let memmap = MEMMAP_REQUEST
.get_response()
.get_mut()
.expect("Failed to get Memory map!")
.memmap_mut();
let memmap = unsafe {
MEMMAP_REQUEST
.get_response_mut()
.expect("Failed to get Memory map!")
.entries_mut()
};
let mut highest_addr: usize = 0;
for entry in memmap.iter() {
if entry.typ == limine::MemoryMapEntryType::Usable {
if entry.entry_type == limine::memory_map::EntryType::USABLE {
pmm.usable_pages
.fetch_add(entry.len as usize / PAGE_SIZE, Ordering::SeqCst);
if highest_addr < (entry.base + entry.len) as usize {
highest_addr = (entry.base + entry.len) as usize;
.fetch_add(entry.length as usize / PAGE_SIZE, Ordering::SeqCst);
if highest_addr < (entry.base + entry.length) as usize {
highest_addr = (entry.base + entry.length) as usize;
}
}
}
@@ -62,11 +62,11 @@ impl PhysicalMemoryManager {
((pmm.highest_page_idx.load(Ordering::SeqCst) / 8) + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
for entry in memmap.iter_mut() {
if entry.typ != limine::MemoryMapEntryType::Usable {
if entry.entry_type != limine::memory_map::EntryType::USABLE {
continue;
}
if entry.len as usize >= bitmap_size {
if entry.length as usize >= bitmap_size {
let ptr = (entry.base as usize + hhdm_offset) as *mut u8;
pmm.bitmap.store(ptr, Ordering::SeqCst);
@@ -75,7 +75,7 @@ impl PhysicalMemoryManager {
core::ptr::write_bytes(ptr, 0xFF, bitmap_size);
};
entry.len -= bitmap_size as u64;
entry.length -= bitmap_size as u64;
entry.base += bitmap_size as u64;
break;
@@ -83,11 +83,11 @@ impl PhysicalMemoryManager {
}
for entry in memmap.iter() {
if entry.typ != limine::MemoryMapEntryType::Usable {
if entry.entry_type != limine::memory_map::EntryType::USABLE {
continue;
}
for i in 0..(entry.len as usize / PAGE_SIZE) {
for i in 0..(entry.length as usize / PAGE_SIZE) {
pmm.bitmap_reset((entry.base as usize + (i * PAGE_SIZE)) / PAGE_SIZE);
}
}
@@ -147,7 +147,7 @@ impl PhysicalMemoryManager {
}
unsafe {
core::ptr::write_bytes(ret, 0x00, pages * PAGE_SIZE);
core::ptr::write_bytes(ret.add(*HHDM_OFFSET), 0x00, pages * PAGE_SIZE);
};
return ret;