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]]
|
[[package]]
|
||||||
name = "limine"
|
name = "bitflags"
|
||||||
version = "0.1.11"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
limine = "0.1.10"
|
limine = "0.2.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
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
|
CARGO_OPTS = --target=src/arch/${ARCH}/${ARCH}-unknown-none.json
|
||||||
QEMU_OPTS += -m ${MEMORY} -drive id=hd0,format=raw,file=${IMAGE_PATH}
|
QEMU_OPTS += -m ${MEMORY} -drive id=hd0,format=raw,file=${IMAGE_PATH}
|
||||||
LIMINE_BOOT_VARIATION = X64
|
LIMINE_BOOT_VARIATION = X64
|
||||||
LIMINE_BRANCH = v7.x-binary
|
LIMINE_BRANCH = v8.x-binary
|
||||||
|
|
||||||
ifeq (${MODE},release)
|
ifeq (${MODE},release)
|
||||||
CARGO_OPTS += --release
|
CARGO_OPTS += --release
|
||||||
@@ -108,7 +108,7 @@ copy-iso-files:
|
|||||||
|
|
||||||
mkdir -p ${ISO_PATH}/mnt
|
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/
|
cp -v limine/BOOT${LIMINE_BOOT_VARIATION}.EFI ${ISO_PATH}/EFI/BOOT/
|
||||||
|
|
||||||
# OS files
|
# OS files
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Before building CappuccinOS, make sure you have the following installed on your
|
|||||||
- rust
|
- rust
|
||||||
- python
|
- python
|
||||||
- sgdisk
|
- sgdisk
|
||||||
- mtools
|
- dosfstools
|
||||||
- squashfs-tools
|
- squashfs-tools
|
||||||
- qemu (optional)
|
- qemu (optional)
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Install the dependencies:
|
|||||||
<details>
|
<details>
|
||||||
<summary>Arch</summary>
|
<summary>Arch</summary>
|
||||||
|
|
||||||
sudo pacman -S gptfdisk mtools squashfs-tools python
|
sudo pacman -S gptfdisk dosfstools squashfs-tools python
|
||||||
# Optionally
|
# Optionally
|
||||||
sudo pacman -S qemu-system-x86
|
sudo pacman -S qemu-system-x86
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ Install the dependencies:
|
|||||||
<summary>Ubuntu</summary>
|
<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
|
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
|
# Optionally
|
||||||
sudo apt install qemu
|
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)
|
ENTRY(_start)
|
||||||
|
|
||||||
/* Define the program headers we want so the bootloader gives us the right */
|
/* 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
|
PHDRS
|
||||||
{
|
{
|
||||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
headers PT_PHDR PHDRS;
|
||||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
text PT_LOAD FILEHDR PHDRS;
|
||||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
rodata PT_LOAD;
|
||||||
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
|
data PT_LOAD;
|
||||||
|
dynamic PT_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
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. */
|
/* and because that is what the Limine spec mandates. */
|
||||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
/* that is the beginning of the region. */
|
/* 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.*)
|
*(.text .text.*)
|
||||||
} :text
|
} :text
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
/* Move to the next memory page for .rodata */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
/* Move to the next memory page for .data */
|
/* Move to the next memory page for .data */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .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
|
} :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 : {
|
||||||
*(.dynamic)
|
*(.dynamic)
|
||||||
} :data :dynamic
|
} :data :dynamic
|
||||||
@@ -55,9 +65,13 @@ SECTIONS
|
|||||||
*(COMMON)
|
*(COMMON)
|
||||||
} :data
|
} :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/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame)
|
*(.eh_frame*)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
|
*(.interp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,43 +6,54 @@ OUTPUT_ARCH(riscv:rv64)
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
/* Define the program headers we want so the bootloader gives us the right */
|
/* 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
|
PHDRS
|
||||||
{
|
{
|
||||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
headers PT_PHDR PHDRS;
|
||||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
text PT_LOAD FILEHDR PHDRS;
|
||||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
rodata PT_LOAD;
|
||||||
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
|
data PT_LOAD;
|
||||||
|
dynamic PT_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
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. */
|
/* and because that is what the Limine spec mandates. */
|
||||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
/* that is the beginning of the region. */
|
/* 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.*)
|
*(.text .text.*)
|
||||||
} :text
|
} :text
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
/* Move to the next memory page for .rodata */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
/* Move to the next memory page for .data */
|
/* Move to the next memory page for .data */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .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.*)
|
*(.sdata .sdata.*)
|
||||||
} :data
|
} :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 : {
|
||||||
*(.dynamic)
|
*(.dynamic)
|
||||||
} :data :dynamic
|
} :data :dynamic
|
||||||
@@ -57,9 +68,13 @@ SECTIONS
|
|||||||
*(COMMON)
|
*(COMMON)
|
||||||
} :data
|
} :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/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame)
|
*(.eh_frame*)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
|
*(.interp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,8 +66,8 @@ pub struct APIC {
|
|||||||
pub cpus: Arc<[LAPIC]>,
|
pub cpus: Arc<[LAPIC]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn test(info: *const limine::SmpInfo) -> ! {
|
unsafe extern "C" fn test<'a>(cpu: &'a limine::smp::Cpu) -> ! {
|
||||||
crate::log_ok!("hey from CPU {:<02}", unsafe { (*info).processor_id });
|
crate::log_ok!("hey from CPU {:<02}", cpu.id);
|
||||||
|
|
||||||
hcf();
|
hcf();
|
||||||
}
|
}
|
||||||
@@ -175,21 +175,21 @@ impl APIC {
|
|||||||
|
|
||||||
crate::println!("{number_of_inputs}");
|
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() {
|
if smp_request.is_none() {
|
||||||
panic!("Failed to get smp from limine!");
|
panic!("Failed to get smp from limine!");
|
||||||
}
|
}
|
||||||
|
|
||||||
let smp_request = smp_request.unwrap();
|
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() {
|
for cpu in smp_request.cpus() {
|
||||||
if cpu.processor_id == bsp_lapic_id {
|
if cpu.id == bsp_lapic_id {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu.goto_address = test;
|
cpu.goto_address.write(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set and enable keyboard interrupt
|
// Set and enable keyboard interrupt
|
||||||
@@ -220,7 +220,7 @@ impl APIC {
|
|||||||
|
|
||||||
pub fn write_lapic(&self, reg: u32, value: u32) {
|
pub fn write_lapic(&self, reg: u32, value: u32) {
|
||||||
unsafe {
|
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) {
|
extern "C" fn exception_handler(registers: u64) {
|
||||||
let registers = unsafe { *(registers as *const Registers) };
|
let registers = unsafe { *(registers as *const Registers) };
|
||||||
|
|
||||||
crate::println!("{:X?}", registers);
|
// crate::println!("{:X?}", registers);
|
||||||
|
|
||||||
let int = registers.int;
|
let int = registers.int;
|
||||||
|
|
||||||
match int {
|
match int {
|
||||||
0x00 => {
|
0x00 => {
|
||||||
log_error!("DIVISION ERROR!");
|
crate::drivers::serial::write_string("DIVISION ERROR!");
|
||||||
}
|
}
|
||||||
0x06 => {
|
0x06 => {
|
||||||
log_error!("INVALID OPCODE!");
|
crate::drivers::serial::write_string("INVALID OPCODE!");
|
||||||
}
|
}
|
||||||
0x08 => {
|
0x08 => {
|
||||||
log_error!("DOUBLE FAULT!");
|
crate::drivers::serial::write_string("DOUBLE FAULT!");
|
||||||
}
|
}
|
||||||
0x0D => {
|
0x0D => {
|
||||||
log_error!("GENERAL PROTECTION FAULT!");
|
crate::drivers::serial::write_string("GENERAL PROTECTION FAULT!");
|
||||||
}
|
}
|
||||||
0x0E => {
|
0x0E => {
|
||||||
log_error!("PAGE FAULT!");
|
crate::drivers::serial::write_string("PAGE FAULT!");
|
||||||
}
|
}
|
||||||
0xFF => {
|
0xFF => {
|
||||||
log_error!("EXCEPTION!");
|
crate::drivers::serial::write_string("EXCEPTION!");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log_error!("EXCEPTION!");
|
crate::drivers::serial::write_string("EXCEPTION!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info!(
|
// log_info!(
|
||||||
"INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}",
|
// "INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}",
|
||||||
int,
|
// int,
|
||||||
registers.rip,
|
// registers.rip,
|
||||||
registers.cs,
|
// registers.cs,
|
||||||
registers.rflags
|
// 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*
|
// *macro intensifies*
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
pub mod apic;
|
pub mod apic;
|
||||||
pub mod exceptions;
|
pub mod exceptions;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
// arch::{apic, x86_common::pic::ChainedPics},
|
|
||||||
libs::sync::Mutex,
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::apic::APIC;
|
use self::apic::APIC;
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
@@ -34,13 +29,15 @@ impl IdtEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl !Sync for IdtEntry {}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
struct IdtPtr {
|
struct IdtPtr {
|
||||||
limit: u16,
|
limit: u16,
|
||||||
base: u64,
|
base: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
static IDT: Mutex<[IdtEntry; 256]> = Mutex::new([IdtEntry::new(); 256]);
|
static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256];
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@@ -62,7 +59,8 @@ static mut IDT_PTR: IdtPtr = IdtPtr {
|
|||||||
|
|
||||||
pub fn idt_set_gate(num: u8, function_ptr: usize) {
|
pub fn idt_set_gate(num: u8, function_ptr: usize) {
|
||||||
let base = function_ptr;
|
let base = function_ptr;
|
||||||
IDT.lock()[num as usize] = IdtEntry {
|
unsafe {
|
||||||
|
IDT[num as usize] = IdtEntry {
|
||||||
base_lo: (base & 0xFFFF) as u16,
|
base_lo: (base & 0xFFFF) as u16,
|
||||||
base_mid: ((base >> 16) & 0xFFFF) as u16,
|
base_mid: ((base >> 16) & 0xFFFF) as u16,
|
||||||
base_hi: ((base >> 32) & 0xFFFFFFFF) as u32,
|
base_hi: ((base >> 32) & 0xFFFFFFFF) as u32,
|
||||||
@@ -71,6 +69,7 @@ pub fn idt_set_gate(num: u8, function_ptr: usize) {
|
|||||||
always0: 0,
|
always0: 0,
|
||||||
flags: 0xEE,
|
flags: 0xEE,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// If the interrupt with this number occurred with the "null" interrupt handler
|
// 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
|
// 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();
|
signal_end_of_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer_handler() {
|
|
||||||
// crate::usr::tty::puts(".");
|
|
||||||
signal_end_of_interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn idt_init() {
|
pub fn idt_init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let idt_size = core::mem::size_of::<IdtEntry>() * 256;
|
let idt_size = core::mem::size_of::<IdtEntry>() * 256;
|
||||||
{
|
IDT_PTR.base = IDT.as_ptr() as u64;
|
||||||
let mut idt_lock = IDT.lock();
|
|
||||||
IDT_PTR.base = idt_lock.as_ptr() as u64;
|
|
||||||
|
|
||||||
core::ptr::write_bytes(
|
core::ptr::write_bytes(IDT.as_mut_ptr().cast::<core::ffi::c_void>(), 0, idt_size);
|
||||||
idt_lock.as_mut_ptr().cast::<core::ffi::c_void>(),
|
|
||||||
0,
|
|
||||||
idt_size,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set every interrupt to the "null" interrupt handler (it does nothing)
|
// Set every interrupt to the "null" interrupt handler (it does nothing)
|
||||||
for num in 0..=255 {
|
for num in 0..=255 {
|
||||||
idt_set_gate(num, null_interrupt_handler as usize);
|
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);
|
idt_set_gate(0x80, syscall as usize);
|
||||||
|
|
||||||
core::arch::asm!(
|
core::arch::asm!(
|
||||||
|
|||||||
@@ -6,58 +6,56 @@ OUTPUT_ARCH(i386:x86-64)
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
/* Define the program headers we want so the bootloader gives us the right */
|
/* 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
|
PHDRS
|
||||||
{
|
{
|
||||||
requests PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
headers PT_PHDR PHDRS;
|
||||||
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
text PT_LOAD FILEHDR PHDRS;
|
||||||
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
rodata PT_LOAD;
|
||||||
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
data PT_LOAD;
|
||||||
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
|
dynamic PT_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
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. */
|
/* and because that is what the Limine spec mandates. */
|
||||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
/* that is the beginning of the region. */
|
/* that is the beginning of the region. */
|
||||||
. = 0xffffffff80000000;
|
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
|
||||||
|
/* base load address. */
|
||||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
. = 0xffffffff80000000 + SIZEOF_HEADERS;
|
||||||
.requests : {
|
|
||||||
KEEP(*(.requests_start_marker))
|
|
||||||
KEEP(*(.requests))
|
|
||||||
KEEP(*(.requests_end_marker))
|
|
||||||
} :requests
|
|
||||||
|
|
||||||
/* Move to the next memory page for .text */
|
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
} :text
|
} :text
|
||||||
|
|
||||||
/* Move to the next memory page for .rodata */
|
/* Move to the next memory page for .rodata */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} :rodata
|
} :rodata
|
||||||
|
|
||||||
/* Move to the next memory page for .data */
|
/* Move to the next memory page for .data */
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .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
|
} :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 : {
|
||||||
*(.dynamic)
|
*(.dynamic)
|
||||||
} :data :dynamic
|
} :data :dynamic
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||||
/* unnecessary zeros will be written to the binary. */
|
/* unnecessary zeros will be written to the binary. */
|
||||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||||
@@ -67,9 +65,13 @@ SECTIONS
|
|||||||
*(COMMON)
|
*(COMMON)
|
||||||
} :data
|
} :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/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame)
|
*(.eh_frame*)
|
||||||
*(.note .note.*)
|
*(.note .note.*)
|
||||||
|
*(.interp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
|
use core::ops::Add;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use limine::SmpRequest;
|
use limine::request::RsdpRequest;
|
||||||
|
use limine::request::SmpRequest;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::io::{inw, outb},
|
arch::io::{inw, outb},
|
||||||
@@ -7,7 +10,9 @@ use crate::{
|
|||||||
mem::HHDM_OFFSET,
|
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)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
@@ -33,7 +38,9 @@ pub struct SDT<'a, T> {
|
|||||||
|
|
||||||
impl<'a, T> SDT<'a, T> {
|
impl<'a, T> SDT<'a, T> {
|
||||||
unsafe fn new(mut ptr: *const u8) -> Self {
|
unsafe fn new(mut ptr: *const u8) -> Self {
|
||||||
|
if (ptr as usize) < *HHDM_OFFSET {
|
||||||
ptr = ptr.add(*HHDM_OFFSET);
|
ptr = ptr.add(*HHDM_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
let length = core::ptr::read_unaligned(ptr.add(4).cast::<u32>());
|
let length = core::ptr::read_unaligned(ptr.add(4).cast::<u32>());
|
||||||
let data = core::slice::from_raw_parts(ptr, length as usize);
|
let data = core::slice::from_raw_parts(ptr, length as usize);
|
||||||
@@ -121,12 +128,12 @@ impl<'a> RootSDT<'a> {
|
|||||||
|
|
||||||
let root_ptr = match self {
|
let root_ptr = match self {
|
||||||
RootSDT::RSDT(rsdt) => {
|
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());
|
assert!(!ptrs.is_null());
|
||||||
ptrs.add(offset)
|
ptrs.add(offset)
|
||||||
}
|
}
|
||||||
RootSDT::XSDT(xsdt) => {
|
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());
|
assert!(!ptrs.is_null());
|
||||||
ptrs.add(offset)
|
ptrs.add(offset)
|
||||||
}
|
}
|
||||||
@@ -149,22 +156,22 @@ struct ACPI<'a> {
|
|||||||
|
|
||||||
static ACPI: OnceCell<ACPI> = OnceCell::new();
|
static ACPI: OnceCell<ACPI> = OnceCell::new();
|
||||||
|
|
||||||
static RSDP_REQ: limine::RsdpRequest = limine::RsdpRequest::new(0);
|
static RSDP_REQ: RsdpRequest = RsdpRequest::new();
|
||||||
|
|
||||||
fn resolve_acpi() {
|
fn resolve_acpi() {
|
||||||
let rsdp_ptr = RSDP_REQ.get_response().get();
|
let rsdp_ptr = RSDP_REQ.get_response();
|
||||||
if rsdp_ptr.is_none() {
|
if rsdp_ptr.is_none() {
|
||||||
panic!("RSDP not found!");
|
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
|
// TODO: validate RSDT
|
||||||
let root_sdt = {
|
let root_sdt = {
|
||||||
if rsdp.revision == 0 {
|
if rsdp.revision == 0 {
|
||||||
RootSDT::RSDT(unsafe { SDT::new(rsdp.rsdt_addr as *mut u8) })
|
RootSDT::RSDT(unsafe { SDT::new(rsdp.rsdt_addr as *mut u8) })
|
||||||
} else {
|
} 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) })
|
RootSDT::XSDT(unsafe { SDT::new(xsdt.xsdt_addr as *mut u8) })
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -256,6 +263,7 @@ struct FADT {
|
|||||||
x_gpe1_block: GenericAddressStructure,
|
x_gpe1_block: GenericAddressStructure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
pub fn init_acpi() {
|
pub fn init_acpi() {
|
||||||
resolve_acpi();
|
resolve_acpi();
|
||||||
|
|
||||||
|
|||||||
@@ -39,20 +39,20 @@ enum FatType {
|
|||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct BIOSParameterBlock {
|
pub struct BIOSParameterBlock {
|
||||||
_jmp_instruction: [u8; 3], // EB 58 90
|
_jmp_instruction: [u8; 3],
|
||||||
pub oem_identifier: [u8; 8], // MTOO4043 (hey, mtools)
|
pub oem_identifier: [u8; 8],
|
||||||
pub bytes_per_sector: u16, // 00 02 (little endian so 512)
|
pub bytes_per_sector: u16,
|
||||||
pub sectors_per_cluster: u8, // 01
|
pub sectors_per_cluster: u8,
|
||||||
pub reserved_sectors: u16, // 20 00 (32)
|
pub reserved_sectors: u16,
|
||||||
pub fat_count: u8, // 02
|
pub fat_count: u8,
|
||||||
pub root_directory_count: u16, // 00 00 (what)
|
pub root_directory_count: u16,
|
||||||
pub total_sectors: u16, // equal to zero when sector count is more than 65535
|
pub total_sectors: u16,
|
||||||
pub media_descriptor_type: u8, // F0
|
pub media_descriptor_type: u8,
|
||||||
pub sectors_per_fat: u16, // Fat12/Fat16 only
|
pub sectors_per_fat: u16,
|
||||||
pub sectors_per_track: u16, // 3F 00 (63)
|
pub sectors_per_track: u16,
|
||||||
pub head_count: u16, // 10 00 (16)
|
pub head_count: u16,
|
||||||
pub hidden_sectors: u32, // 00 00 00 00
|
pub hidden_sectors: u32,
|
||||||
pub large_sector_count: u32, // 00 F8 01 00 (129024)
|
pub large_sector_count: u32,
|
||||||
pub ebpb_bytes: [u8; 54],
|
pub ebpb_bytes: [u8; 54],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,19 +71,19 @@ pub struct Fat16EBPB {
|
|||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Fat32EBPB {
|
pub struct Fat32EBPB {
|
||||||
pub sectors_per_fat_ext: u32, // E1 03 00 00 (993, wtf)
|
pub sectors_per_fat_ext: u32,
|
||||||
pub flags: [u8; 2], // 00 00
|
pub flags: [u8; 2],
|
||||||
pub fat_version: u16, // 00 00
|
pub fat_version: u16,
|
||||||
pub root_dir_cluster: u32, // 2C 00 00 00 (2)
|
pub root_dir_cluster: u32,
|
||||||
pub fsinfo_sector: u16, // 01 00 (1)
|
pub fsinfo_sector: u16,
|
||||||
pub backup_bootsector: u16, // 06 00 (6)
|
pub backup_bootsector: u16,
|
||||||
_reserved: [u8; 12], // all zero
|
_reserved: [u8; 12],
|
||||||
pub drive_number: u8, // 00
|
pub drive_number: u8,
|
||||||
_reserved2: u8, // 00
|
_reserved2: u8,
|
||||||
pub signature: u8, // either 0x28 of 0x29: 29
|
pub signature: u8,
|
||||||
pub volume_id: u32, // Varies
|
pub volume_id: u32,
|
||||||
pub volume_label: [u8; 11], // "NO NAME "
|
pub volume_label: [u8; 11],
|
||||||
pub system_identifier_string: [u8; 8], // Always "FAT32 " but never trust the contents of this string (for some reason)
|
pub system_identifier_string: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
@@ -358,31 +358,29 @@ impl FatFs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.replacen('.', "", 1).len() <= 11 {
|
let raw_short_filename = core::str::from_utf8(&file_entry.file_name)
|
||||||
let search_parts: Vec<&str> = name.split('.').collect();
|
.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();
|
if let Some(ref filename) = long_filename_string {
|
||||||
let extension = core::str::from_utf8(&file_entry.extension).unwrap();
|
if filename != name {
|
||||||
|
|
||||||
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())))
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(file_entry);
|
|
||||||
} else {
|
} else {
|
||||||
// Long file name
|
if name.to_uppercase() != formatted_short_filename {
|
||||||
if long_filename_string != Some(name.to_string()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(file_entry);
|
return Ok(file_entry);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@@ -533,9 +531,7 @@ impl FsOps for FatFs {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = File::Dir(FatDirectory {
|
let file = File::Dir(root_cluster);
|
||||||
directory_cluster: root_cluster,
|
|
||||||
});
|
|
||||||
|
|
||||||
return VNode::new(Box::new(file), super::vfs::VNodeType::Directory, vfsp);
|
return VNode::new(Box::new(file), super::vfs::VNodeType::Directory, vfsp);
|
||||||
}
|
}
|
||||||
@@ -562,8 +558,9 @@ impl FsOps for FatFs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum File {
|
enum File {
|
||||||
Archive(FatFile),
|
Archive(FileEntry),
|
||||||
Dir(FatDirectory),
|
// directory cluster
|
||||||
|
Dir(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VNodeOperations for File {
|
impl VNodeOperations for File {
|
||||||
@@ -585,8 +582,8 @@ impl VNodeOperations for File {
|
|||||||
|
|
||||||
let mut file: Vec<u8> = Vec::with_capacity(count);
|
let mut file: Vec<u8> = Vec::with_capacity(count);
|
||||||
|
|
||||||
let mut cluster = ((archive.file_entry.high_first_cluster_number as u32) << 16)
|
let mut cluster = ((archive.high_first_cluster_number as u32) << 16)
|
||||||
| archive.file_entry.low_first_cluster_number as u32;
|
| archive.low_first_cluster_number as u32;
|
||||||
|
|
||||||
let cluster_size = unsafe { (*fat_fs).cluster_size };
|
let cluster_size = unsafe { (*fat_fs).cluster_size };
|
||||||
|
|
||||||
@@ -685,8 +682,7 @@ impl VNodeOperations for File {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
File::Dir(directory) => unsafe {
|
File::Dir(directory) => unsafe {
|
||||||
let file_entry =
|
let file_entry = (*fat_fs).find_entry_in_directory(*directory, nm)?;
|
||||||
(*fat_fs).find_entry_in_directory(directory.directory_cluster, nm)?;
|
|
||||||
|
|
||||||
let file_typ = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
|
let file_typ = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
|
||||||
crate::drivers::fs::vfs::VNodeType::Directory
|
crate::drivers::fs::vfs::VNodeType::Directory
|
||||||
@@ -695,11 +691,9 @@ impl VNodeOperations for File {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let file = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
|
let file = if file_entry.attributes == FileEntryAttributes::Directory as u8 {
|
||||||
File::Dir(FatDirectory {
|
File::Dir(file_entry.cluster() as usize)
|
||||||
directory_cluster: file_entry.cluster() as usize,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
File::Archive(FatFile { file_entry })
|
File::Archive(file_entry)
|
||||||
};
|
};
|
||||||
|
|
||||||
let vnode = VNode::new(Box::new(file), file_typ, (*vp.as_ptr()).parent_vfs);
|
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 {
|
fn len(&self, _vp: NonNull<VNode>) -> usize {
|
||||||
match self {
|
match self {
|
||||||
File::Archive(archive) => archive.file_entry.file_size as usize,
|
File::Archive(archive) => archive.file_size as usize,
|
||||||
_ => panic!("idk"),
|
_ => panic!("idk"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FatFile {
|
|
||||||
file_entry: FileEntry,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FatDirectory {
|
|
||||||
directory_cluster: usize,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ pub struct ChunkReader<'a, F> {
|
|||||||
decompressor: 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 {
|
pub fn new(data: &'a [u8], decompressor: F) -> Self {
|
||||||
let mut chunks: Vec<Chunk<'_>> = Vec::new();
|
let mut chunks: Vec<Chunk<'_>> = Vec::new();
|
||||||
|
|
||||||
|
|||||||
@@ -4,30 +4,32 @@ mod superblock;
|
|||||||
use core::{fmt::Debug, mem::MaybeUninit, ptr::NonNull};
|
use core::{fmt::Debug, mem::MaybeUninit, ptr::NonNull};
|
||||||
|
|
||||||
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
|
||||||
use limine::ModuleRequest;
|
use limine::request::ModuleRequest;
|
||||||
|
|
||||||
use super::vfs::{FsOps, VNode, VNodeOperations, VNodeType};
|
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> {
|
pub fn init() -> Squashfs<'static> {
|
||||||
// TODO: Put the module request stuff in another file?
|
// 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!");
|
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 mut initramfs = None;
|
||||||
|
|
||||||
let module_name = "initramfs.img";
|
let module_name = "initramfs.img";
|
||||||
|
|
||||||
for module in module_response.modules() {
|
for module in module_response.modules() {
|
||||||
let c_path = module.path.to_str();
|
let path = core::str::from_utf8(module.path());
|
||||||
if c_path.is_none() {
|
if path.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c_path.unwrap().to_str().unwrap().contains(module_name) {
|
if !path.unwrap().contains(module_name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ pub fn init() -> Squashfs<'static> {
|
|||||||
}
|
}
|
||||||
let initramfs = initramfs.unwrap();
|
let initramfs = initramfs.unwrap();
|
||||||
|
|
||||||
let squashfs = Squashfs::new(initramfs.base.as_ptr().unwrap());
|
let squashfs = Squashfs::new(initramfs.addr());
|
||||||
|
|
||||||
if squashfs.is_err() {
|
if squashfs.is_err() {
|
||||||
panic!("Initramfs in corrupt!");
|
panic!("Initramfs in corrupt!");
|
||||||
@@ -173,6 +175,7 @@ impl Squashfs<'_> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
fn get_inode_block_offset(&self, inode: u64) -> (u64, u16) {
|
fn get_inode_block_offset(&self, inode: u64) -> (u64, u16) {
|
||||||
let inode_block = (inode >> 16) & 0x0000FFFFFFFFFFFF;
|
let inode_block = (inode >> 16) & 0x0000FFFFFFFFFFFF;
|
||||||
let inode_offset = (inode & 0xFFFF) as u16;
|
let inode_offset = (inode & 0xFFFF) as u16;
|
||||||
|
|||||||
@@ -632,6 +632,22 @@ pub trait VNodeOperations {
|
|||||||
// fn strategy(&mut self, bp: (), vp: NonNull<VNode>);
|
// fn strategy(&mut self, bp: (), vp: NonNull<VNode>);
|
||||||
// fn bread(&mut self, block_number: u32, vp: NonNull<VNode>) -> Arc<[u8]>;
|
// fn bread(&mut self, block_number: u32, vp: NonNull<VNode>) -> Arc<[u8]>;
|
||||||
fn len(&self, vp: NonNull<VNode>) -> usize;
|
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)]
|
#[allow(unused)]
|
||||||
@@ -667,7 +683,10 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
|
|||||||
return Err(());
|
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 {
|
} else {
|
||||||
if unsafe { ROOT_VFS.next.is_none() } {
|
if unsafe { ROOT_VFS.next.is_none() } {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|||||||
@@ -30,8 +30,14 @@ pub extern "x86-interrupt" fn keyboard_interrupt_handler() {
|
|||||||
let key = parse_key(scancode);
|
let key = parse_key(scancode);
|
||||||
|
|
||||||
if let Some(key) = key {
|
if let Some(key) = key {
|
||||||
|
if !key.pressed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(character) = key.character {
|
||||||
// crate::usr::shell::handle_key(key)
|
// crate::usr::shell::handle_key(key)
|
||||||
write_serial(key.character.unwrap() as u8);
|
write_serial(character as u8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use limine::FramebufferRequest;
|
use limine::{framebuffer, request::FramebufferRequest};
|
||||||
|
|
||||||
use crate::libs::cell::OnceCell;
|
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 static FRAMEBUFFER: OnceCell<Option<Framebuffer>> = OnceCell::new();
|
||||||
|
|
||||||
pub fn get_framebuffer() -> Option<Framebuffer> {
|
pub fn get_framebuffer() -> Option<Framebuffer> {
|
||||||
*FRAMEBUFFER.get_or_set(|| {
|
*FRAMEBUFFER.get_or_set(|| {
|
||||||
let framebuffer_response = crate::drivers::video::FRAMEBUFFER_REQUEST
|
let framebuffer_response = crate::drivers::video::FRAMEBUFFER_REQUEST.get_response()?;
|
||||||
.get_response()
|
let framebuffer = framebuffer_response.framebuffers().next();
|
||||||
.get()?;
|
|
||||||
|
|
||||||
if framebuffer_response.framebuffer_count < 1 {
|
if framebuffer.is_none() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let framebuffer_response = &framebuffer_response.framebuffers()[0];
|
let framebuffer_response = framebuffer.as_ref().unwrap();
|
||||||
|
|
||||||
let framebuffer = Framebuffer::new(
|
let framebuffer = Framebuffer::new(
|
||||||
framebuffer_response.bpp as usize,
|
framebuffer_response.bpp() as usize,
|
||||||
framebuffer_response.pitch as usize,
|
framebuffer_response.pitch() as usize,
|
||||||
framebuffer_response.address.as_ptr().unwrap(),
|
framebuffer_response.addr(),
|
||||||
framebuffer_response.width as usize,
|
framebuffer_response.width() as usize,
|
||||||
framebuffer_response.height as usize,
|
framebuffer_response.height() as usize,
|
||||||
);
|
);
|
||||||
|
|
||||||
return Some(framebuffer);
|
return Some(framebuffer);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::libs::sync::Mutex;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum ZlibCompressionLevel {
|
enum ZlibCompressionLevel {
|
||||||
@@ -109,15 +107,6 @@ struct Huff {
|
|||||||
symbols: [u16; 288],
|
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 {
|
struct HuffRing {
|
||||||
pointer: usize,
|
pointer: usize,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
@@ -183,7 +172,16 @@ impl InflateContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn decompress(&mut self) -> Result<Vec<u8>, ()> {
|
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 {
|
loop {
|
||||||
let is_final = self.get_bit();
|
let is_final = self.get_bit();
|
||||||
@@ -194,7 +192,7 @@ impl InflateContext {
|
|||||||
self.uncompressed()?;
|
self.uncompressed()?;
|
||||||
}
|
}
|
||||||
0x01 => {
|
0x01 => {
|
||||||
self.inflate(&mut FIXED_LENGTHS.lock(), &mut FIXED_DISTS.lock())?;
|
self.inflate(&mut lengths, &mut dists)?;
|
||||||
}
|
}
|
||||||
0x02 => {
|
0x02 => {
|
||||||
self.decode_huffman()?;
|
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];
|
let mut lengths = [0_u8; 288];
|
||||||
|
|
||||||
lengths[0..144].fill(8);
|
lengths[0..144].fill(8);
|
||||||
@@ -426,9 +424,9 @@ fn build_fixed() {
|
|||||||
lengths[256..280].fill(7);
|
lengths[256..280].fill(7);
|
||||||
lengths[280..288].fill(8);
|
lengths[280..288].fill(8);
|
||||||
|
|
||||||
build_huffman(&lengths, 288, &mut FIXED_LENGTHS.lock());
|
build_huffman(&lengths, 288, out_length);
|
||||||
|
|
||||||
lengths[0..30].fill(5);
|
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()
|
.is_err()
|
||||||
{
|
{
|
||||||
// spin lock
|
// spin lock
|
||||||
|
core::hint::spin_loop()
|
||||||
}
|
}
|
||||||
return MutexGuard { mutex: self };
|
return MutexGuard { mutex: self };
|
||||||
}
|
}
|
||||||
|
|||||||
66
src/main.rs
66
src/main.rs
@@ -1,18 +1,11 @@
|
|||||||
#![feature(
|
#![feature(abi_x86_interrupt, naked_functions, negative_impls)]
|
||||||
allocator_api,
|
|
||||||
abi_x86_interrupt,
|
|
||||||
naked_functions,
|
|
||||||
const_mut_refs,
|
|
||||||
negative_impls
|
|
||||||
)]
|
|
||||||
#![allow(clippy::needless_return)]
|
#![allow(clippy::needless_return)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::ffi::CStr;
|
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use limine::KernelFileRequest;
|
use limine::{request::KernelFileRequest, BaseRevision};
|
||||||
|
use mem::HHDM_OFFSET;
|
||||||
|
|
||||||
use crate::drivers::fs::{
|
use crate::drivers::fs::{
|
||||||
initramfs,
|
initramfs,
|
||||||
@@ -26,7 +19,15 @@ pub mod drivers;
|
|||||||
pub mod libs;
|
pub mod libs;
|
||||||
pub mod mem;
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
@@ -65,7 +66,7 @@ pub fn kmain() -> ! {
|
|||||||
crate::println!(
|
crate::println!(
|
||||||
"LIMINE BOOT: {:X?}",
|
"LIMINE BOOT: {:X?}",
|
||||||
limine_dir
|
limine_dir
|
||||||
.lookup("limine.cfg")
|
.lookup("limine.conf")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.open(0, UserCred { uid: 0, gid: 0 })
|
.open(0, UserCred { uid: 0, gid: 0 })
|
||||||
.read(0, 0, 0)
|
.read(0, 0, 0)
|
||||||
@@ -82,7 +83,7 @@ pub fn kmain() -> ! {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.lookup("limine")
|
.lookup("limine")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lookup("limine.cfg")
|
.lookup("limine.conf")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.open(0, UserCred { uid: 0, gid: 0 })
|
.open(0, UserCred { uid: 0, gid: 0 })
|
||||||
.read(0, 10, 0)
|
.read(0, 10, 0)
|
||||||
@@ -95,7 +96,7 @@ pub fn kmain() -> ! {
|
|||||||
crate::println!(
|
crate::println!(
|
||||||
"LIMINE BOOT: {:X?}",
|
"LIMINE BOOT: {:X?}",
|
||||||
limine_dir
|
limine_dir
|
||||||
.lookup("limine.cfg")
|
.lookup("limine.conf")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.open(0, UserCred { uid: 0, gid: 0 })
|
.open(0, UserCred { uid: 0, gid: 0 })
|
||||||
.read(0, 0, 0)
|
.read(0, 0, 0)
|
||||||
@@ -132,20 +133,14 @@ fn draw_gradient() {
|
|||||||
let length = (fb.height * fb.width) * (fb.bpp / 8);
|
let length = (fb.height * fb.width) * (fb.bpp / 8);
|
||||||
let pages = length / crate::mem::pmm::PAGE_SIZE;
|
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() {
|
if buffer_ptr.is_null() {
|
||||||
panic!("Failed to allocate screen buffer")
|
panic!("Failed to allocate screen buffer")
|
||||||
}
|
}
|
||||||
|
|
||||||
let buffer = unsafe {
|
let buffer = unsafe { core::slice::from_raw_parts_mut(buffer_ptr.cast::<u32>(), length) };
|
||||||
core::slice::from_raw_parts_mut(
|
|
||||||
crate::mem::PHYSICAL_MEMORY_MANAGER
|
|
||||||
.alloc(pages)
|
|
||||||
.cast::<u32>(),
|
|
||||||
length,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
for y in 0..fb.height {
|
for y in 0..fb.height {
|
||||||
for x in 0..fb.width {
|
for x in 0..fb.width {
|
||||||
@@ -160,7 +155,8 @@ fn draw_gradient() {
|
|||||||
|
|
||||||
fb.blit_screen(buffer, None);
|
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]
|
#[macro_export]
|
||||||
@@ -219,31 +215,15 @@ pub static KERNEL_FEATURES: libs::cell::OnceCell<KernelFeatures> = libs::cell::O
|
|||||||
fn parse_kernel_cmdline() {
|
fn parse_kernel_cmdline() {
|
||||||
let mut kernel_features: KernelFeatures = KernelFeatures { fat_in_mem: true };
|
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() {
|
if kernel_file_response.is_none() {
|
||||||
KERNEL_FEATURES.set(kernel_features);
|
KERNEL_FEATURES.set(kernel_features);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmdline_ptr = kernel_file_response
|
let cmdline = core::str::from_utf8(kernel_file_response.unwrap().file().cmdline());
|
||||||
.unwrap()
|
|
||||||
.kernel_file
|
|
||||||
.get()
|
|
||||||
.unwrap()
|
|
||||||
.cmdline
|
|
||||||
.as_ptr();
|
|
||||||
|
|
||||||
if cmdline_ptr.is_none() {
|
let kernel_arguments = cmdline.unwrap().split_whitespace().collect::<Vec<&str>>();
|
||||||
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>>();
|
|
||||||
|
|
||||||
crate::println!("{kernel_arguments:?}");
|
crate::println!("{kernel_arguments:?}");
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,14 @@ use crate::libs::{cell::OnceCell, sync::Mutex};
|
|||||||
|
|
||||||
use self::{allocator::LinkedListAllocator, pmm::PhysicalMemoryManager};
|
use self::{allocator::LinkedListAllocator, pmm::PhysicalMemoryManager};
|
||||||
|
|
||||||
static MEMMAP_REQUEST: limine::MemmapRequest = limine::MemmapRequest::new(0);
|
#[used]
|
||||||
static HHDM_REQUEST: limine::HhdmRequest = limine::HhdmRequest::new(0);
|
#[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 HHDM_OFFSET: OnceCell<usize> = OnceCell::new();
|
||||||
|
|
||||||
pub static PHYSICAL_MEMORY_MANAGER: OnceCell<PhysicalMemoryManager> = 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]
|
#[global_allocator]
|
||||||
pub static ALLOCATOR: Mutex<LinkedListAllocator> = Mutex::new(LinkedListAllocator::new());
|
pub static ALLOCATOR: Mutex<LinkedListAllocator> = Mutex::new(LinkedListAllocator::new());
|
||||||
|
|
||||||
pub fn log_memory_map() {
|
// 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
|
||||||
let memmap_request = MEMMAP_REQUEST.get_response().get_mut();
|
// pub fn log_memory_map() {
|
||||||
if memmap_request.is_none() {
|
// let memmap_request = unsafe { MEMMAP_REQUEST.get_response_mut() };
|
||||||
panic!("Memory map was None!");
|
// 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");
|
// crate::log_serial!("====== MEMORY MAP ======\n");
|
||||||
for entry in memmap.iter() {
|
// for entry in memmap.iter() {
|
||||||
let label = (entry.len as usize).label_bytes();
|
// let label = (entry.length as usize).label_bytes();
|
||||||
|
|
||||||
crate::log_serial!(
|
// crate::log_serial!(
|
||||||
"[ {:#018X?} ] Type: {:?} Size: {}\n",
|
// "[ {:#018X?} ] Type: {:?} Size: {}\n",
|
||||||
entry.base..entry.base + entry.len,
|
// entry.base..entry.base + entry.length,
|
||||||
entry.typ,
|
// entry.entry_type,
|
||||||
label
|
// label
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn init_allocator() {
|
pub fn init_allocator() {
|
||||||
let mut allocator_lock = ALLOCATOR.lock();
|
let mut allocator_lock = ALLOCATOR.lock();
|
||||||
@@ -51,7 +58,9 @@ pub fn init_allocator() {
|
|||||||
crate::println!(
|
crate::println!(
|
||||||
"{} of memory available",
|
"{} of memory available",
|
||||||
PHYSICAL_MEMORY_MANAGER.total_memory().label_bytes()
|
PHYSICAL_MEMORY_MANAGER.total_memory().label_bytes()
|
||||||
)
|
);
|
||||||
|
|
||||||
|
// log_memory_map();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Label {
|
pub enum Label {
|
||||||
|
|||||||
@@ -31,27 +31,27 @@ impl PhysicalMemoryManager {
|
|||||||
|
|
||||||
let hhdm_req = HHDM_REQUEST
|
let hhdm_req = HHDM_REQUEST
|
||||||
.get_response()
|
.get_response()
|
||||||
.get()
|
|
||||||
.expect("Failed to get Higher Half Direct Map!");
|
.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);
|
HHDM_OFFSET.set(hhdm_offset);
|
||||||
|
|
||||||
let memmap = MEMMAP_REQUEST
|
let memmap = unsafe {
|
||||||
.get_response()
|
MEMMAP_REQUEST
|
||||||
.get_mut()
|
.get_response_mut()
|
||||||
.expect("Failed to get Memory map!")
|
.expect("Failed to get Memory map!")
|
||||||
.memmap_mut();
|
.entries_mut()
|
||||||
|
};
|
||||||
|
|
||||||
let mut highest_addr: usize = 0;
|
let mut highest_addr: usize = 0;
|
||||||
|
|
||||||
for entry in memmap.iter() {
|
for entry in memmap.iter() {
|
||||||
if entry.typ == limine::MemoryMapEntryType::Usable {
|
if entry.entry_type == limine::memory_map::EntryType::USABLE {
|
||||||
pmm.usable_pages
|
pmm.usable_pages
|
||||||
.fetch_add(entry.len as usize / PAGE_SIZE, Ordering::SeqCst);
|
.fetch_add(entry.length as usize / PAGE_SIZE, Ordering::SeqCst);
|
||||||
if highest_addr < (entry.base + entry.len) as usize {
|
if highest_addr < (entry.base + entry.length) as usize {
|
||||||
highest_addr = (entry.base + entry.len) 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);
|
((pmm.highest_page_idx.load(Ordering::SeqCst) / 8) + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
|
||||||
|
|
||||||
for entry in memmap.iter_mut() {
|
for entry in memmap.iter_mut() {
|
||||||
if entry.typ != limine::MemoryMapEntryType::Usable {
|
if entry.entry_type != limine::memory_map::EntryType::USABLE {
|
||||||
continue;
|
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;
|
let ptr = (entry.base as usize + hhdm_offset) as *mut u8;
|
||||||
pmm.bitmap.store(ptr, Ordering::SeqCst);
|
pmm.bitmap.store(ptr, Ordering::SeqCst);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ impl PhysicalMemoryManager {
|
|||||||
core::ptr::write_bytes(ptr, 0xFF, bitmap_size);
|
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;
|
entry.base += bitmap_size as u64;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -83,11 +83,11 @@ impl PhysicalMemoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for entry in memmap.iter() {
|
for entry in memmap.iter() {
|
||||||
if entry.typ != limine::MemoryMapEntryType::Usable {
|
if entry.entry_type != limine::memory_map::EntryType::USABLE {
|
||||||
continue;
|
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);
|
pmm.bitmap_reset((entry.base as usize + (i * PAGE_SIZE)) / PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ impl PhysicalMemoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::write_bytes(ret, 0x00, pages * PAGE_SIZE);
|
core::ptr::write_bytes(ret.add(*HHDM_OFFSET), 0x00, pages * PAGE_SIZE);
|
||||||
};
|
};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user