update to limine v8 and other various stuff
This commit is contained in:
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -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",
|
||||
]
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
limine = "0.1.10"
|
||||
limine = "0.2.0"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
|
||||
4
Makefile
4
Makefile
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
10
limine.cfg
10
limine.cfg
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ impl<T> Mutex<T> {
|
||||
.is_err()
|
||||
{
|
||||
// spin lock
|
||||
core::hint::spin_loop()
|
||||
}
|
||||
return MutexGuard { mutex: self };
|
||||
}
|
||||
|
||||
66
src/main.rs
66
src/main.rs
@@ -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:?}");
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user