saving before I sleep

This commit is contained in:
River 2025-05-28 01:38:19 -04:00
parent cd24c63e84
commit 76b7e7b93c
Signed by: shibedrill
GPG Key ID: 5FE0CB25945EFAA2
13 changed files with 138 additions and 89 deletions

39
Cargo.lock generated
View File

@ -106,16 +106,23 @@ dependencies = [
"enumflags2", "enumflags2",
"fdt", "fdt",
"flagset", "flagset",
"intbits",
"lazy_static", "lazy_static",
"limine", "limine",
"lzma-rs", "lzma-rs",
"once_cell", "once_cell",
"raw-cpuid",
"spin 0.10.0", "spin 0.10.0",
"talc", "talc",
"tar-no-std",
"x86_64", "x86_64",
] ]
[[package]]
name = "intbits"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5170c2c8ecda29c1bccb9d95ccbe107bc75fa084dc0c9c6087e719f9d46330e5"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -166,6 +173,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.3" version = "1.21.3"
@ -200,15 +216,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "raw-cpuid"
version = "11.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.20" version = "1.0.20"
@ -256,6 +263,18 @@ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "tar-no-std"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15574aa79d3c04a12f3cb53ff976d5571e53b9d8e0bdbe4021df0a06473dd1c9"
dependencies = [
"bitflags",
"log",
"memchr",
"num-traits",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.18" version = "1.0.18"

View File

@ -8,14 +8,14 @@ acpi = "5.1.0"
enumflags2 = "0.7.11" enumflags2 = "0.7.11"
fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" } fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" }
flagset = "0.4.7" flagset = "0.4.7"
intbits = "0.2.0"
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] } lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
limine = "0.4.0" limine = "0.4.0"
lzma-rs = { git = "https://github.com/glaeqen/lzma-no-std-rs/", version = "0.2.0", default-features = false } lzma-rs = { git = "https://github.com/glaeqen/lzma-no-std-rs/", version = "0.2.0", default-features = false }
once_cell = { version = "1.20.3", default-features = false, features = ["alloc", "critical-section"] } once_cell = { version = "1.20.3", default-features = false, features = ["alloc", "critical-section"] }
raw-cpuid = "11.5.0"
spin = "0.10.0" spin = "0.10.0"
talc = "4.4.2" talc = "4.4.2"
x86_64 = "0.15.2" tar-no-std = "0.3.4"
[target.'cfg(target_arch = "x86_64")'.dependencies] [target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = "0.15.2" x86_64 = "0.15.2"

View File

@ -7,7 +7,7 @@ Gila is a Rust microkernel OS, inspired by the Xinu embedded OS, as well as Linu
### Complete ### Complete
- Builds for multiple architectures - Builds for AArch64, RISCV64, x86_64, and LoongArch64
- Valid Limine kernel - Valid Limine kernel
- Boots on `x86_64` - Boots on `x86_64`
- Kernel command line parameters - Kernel command line parameters
@ -17,25 +17,34 @@ Gila is a Rust microkernel OS, inspired by the Xinu embedded OS, as well as Linu
### In-Progress ### In-Progress
- Multi-architecture feature support
- Display console - Display console
- Serial console - Serial console
- Device discovery & APIs
- Power management
- Paging
### Future/Desired ### Future/Desired
- Code execution - Userspace binaries/processes
- Interprocess communication
- Driver server interface
- Interrupts and timers - Interrupts and timers
- Context switching - Context switching
- Process scheduling - Process scheduling
- Shell and CLI
- System calls (multi-convention?) - System calls (multi-convention?)
- Multi-user support and access control - Capability access control
- Simultaneous multiprocessing support - Simultaneous multiprocessing support
- ACPI, USB, PCI(e), SATA - Hypervisor functionality
- Filesystem support (FAT32)
- Application sandboxing/permissions control ### Additional Future Features (Userspace)
- Graphical desktop environment
- Networking support - Device drivers
- Filesystem drivers
- Shell
- Standard system API
- Rust and C stdlib port
- Display/windowing
- Application sandboxing
## Licensing ## Licensing
@ -64,7 +73,7 @@ Licensed under the GNU Public License v3. See [LICENSE](LICENSE) for details.
## Building and running ## Building and running
Building a bootable kernel is easy. All you need to do is run `cargo build --bin kernel`, and a valid, bootable Limine executable will be generated. However, it cannot be booted without installing it in a bootable Limine filesystem, and it cannot do anything useful without an initramfs containing system servers such as the init server and Building a bootable kernel is easy. All you need to do is run `cargo build --bin kernel`, and a valid, bootable Limine executable will be generated. However, it cannot be booted without installing it in a bootable Limine filesystem, and it cannot do anything useful without an initramfs containing system servers, such as the init server and
device drivers. device drivers.
This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to handle building ISOs and managing files not associated with Cargo. You need to install it before you can build an ISO automatically. To do so, you can run `cargo install cargo-make`. In addition, you will also need: This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to handle building ISOs and managing files not associated with Cargo. You need to install it before you can build an ISO automatically. To do so, you can run `cargo install cargo-make`. In addition, you will also need:
@ -76,20 +85,13 @@ This project uses [cargo-make](https://github.com/sagiegurari/cargo-make) to han
Then run `cargo make` to invoke the [Makefile.toml](Makefile.toml). Then run `cargo make` to invoke the [Makefile.toml](Makefile.toml).
- `cargo make prepare`: Installs needed Rust toolchain.
- `cargo make clean_all`: Cleans all built binaries, libraries, initramfs files, and ISOs. - `cargo make clean_all`: Cleans all built binaries, libraries, initramfs files, and ISOs.
- `cargo make clean_iso`: Clean only files involved in building the ISO.
- `cargo make clean_initramfs`: Clean only files involved in building the initramfs.
- `cargo make clean_kernel`: Clean only kernel binaries and libraries.
- `cargo make lib`: Builds `libgila`, the library that the kernel and user code are linked against. - `cargo make lib`: Builds `libgila`, the library that the kernel and user code are linked against.
- `cargo make kernel`: Builds the kernel ELF file. - `cargo make kernel`: Builds the kernel ELF file.
- `cargo make bins`: Builds all binaries included in the system.
- `cargo make initramfs`: Build the init archive. - `cargo make initramfs`: Build the init archive.
- `cargo make iso`: Builds the bootable ISO with Limine installed. - `cargo make iso`: Builds the bootable ISO with Limine installed.
- `cargo make run`: Builds the ISO and boots it in QEMU. - `cargo make run`: Builds the ISO and boots it in QEMU.
- `cargo make debug`: Launch the kernel in QEMU with debugging enabled, and start and connect GDB. - `cargo make debug`: Launch the kernel in QEMU with debugging enabled, and start and connect GDB.
- `cargo make debug_run`: Launch the kernel in QEMU for debugging.
- `cargo make debug_view`: Attach to a running QEMU process to debug.
You do not need to clean any files after making changes. The `lib`, `kernel`, and `iso` tasks will automatically be rerun if their input files change. You do not need to clean any files after making changes. The `lib`, `kernel`, and `iso` tasks will automatically be rerun if their input files change.
@ -108,9 +110,9 @@ Kernel parameters are passed as part of the `cmdline` through [limine.conf](limi
List of current extant kernel parameters: List of current extant kernel parameters:
- `-loglevel`: Can be a number or string corresponding to a log level. Only one value supported. Current options are `Disabled`, `Trace`, `Info`, `Warning`, `Error`, and `Critical`. - `-loglevel`: Can be a number or string corresponding to a log level. Only one value supported. Current options are `Disabled`, `Trace`, `Info`, `Warning`, `Error`, and `Critical`. This parameter is case insensitive.
- `-logdev`: A sequence of one or more values representing devices to log to. Current options are `display` and `serial`. - `-logdev`: A sequence of one or more values representing devices to log to. Current options are `display` and `serial`. This parameter is case insensitive.
- `-initramfs`: A valid path to a module to serve as the initramfs (containing the init binary). Only one value supported. - `-initramfs`: A valid path to a module to serve as the initramfs (containing the init binary). Only one value supported. This parameter is case sensitive.
The default behavior for each parameter, when not supplied, is: The default behavior for each parameter, when not supplied, is:

View File

@ -1,25 +1,18 @@
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable}; // Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later
use lazy_static::lazy_static; use core::arch::asm;
use core::ptr::addr_of_mut;
use crate::log::{LOGGER, LogLevel}; use intbits::Bits;
use crate::{critical_section, format, log_trace};
lazy_static! { pub unsafe fn gdt() -> (u8, u64) {
pub static ref GDT: GlobalDescriptorTable = { let mut addr: u128 = 0;
let mut gdt = GlobalDescriptorTable::new(); unsafe {
gdt.append(Descriptor::kernel_code_segment()); asm! {
gdt "sgdt [rax]",
}; in("rax") addr_of_mut!(addr),
} }
}
#[allow(dead_code)] (addr.bits(0..=15) as u8, addr.bits(16..=79) as u64)
pub fn setup_gdt() {
critical_section!({
GDT.load();
log_trace!(
"GDT: Setting up global descriptor table at 0x{:x}",
core::ptr::addr_of!(GDT) as usize
);
});
} }

View File

@ -9,6 +9,7 @@ use limine::{BaseRevision, request::*};
#[used] #[used]
#[unsafe(link_section = ".requests_start_marker")] #[unsafe(link_section = ".requests_start_marker")]
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new(); static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
#[used] #[used]
#[unsafe(link_section = ".requests_end_marker")] #[unsafe(link_section = ".requests_end_marker")]
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new(); static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
@ -16,28 +17,15 @@ static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
#[used] #[used]
#[unsafe(link_section = ".requests")] #[unsafe(link_section = ".requests")]
pub static BASE_REVISION: BaseRevision = limine::BaseRevision::new(); pub static BASE_REVISION: BaseRevision = limine::BaseRevision::new();
#[used] #[used]
#[unsafe(link_section = ".requests")] #[unsafe(link_section = ".requests")]
pub static MP_REQUEST: MpRequest = limine::request::MpRequest::new(); pub static MP_REQUEST: MpRequest = limine::request::MpRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static FILE_REQUEST: ExecutableFileRequest = limine::request::ExecutableFileRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static RSDP_REQUEST: RsdpRequest = limine::request::RsdpRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static MODULE_REQUEST: ModuleRequest = limine::request::ModuleRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static ADDRESS_REQUEST: ExecutableAddressRequest =
limine::request::ExecutableAddressRequest::new();
#[used] #[used]
#[unsafe(link_section = ".requests")] #[unsafe(link_section = ".requests")]
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new(); pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new();
#[used] #[used]
#[unsafe(link_section = ".requests")] #[unsafe(link_section = ".requests")]
pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new(); pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new();

View File

@ -2,9 +2,18 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use lazy_static::lazy_static; use lazy_static::lazy_static;
use limine::response::ModuleResponse; use limine::{
request::{ExecutableFileRequest, ModuleRequest},
response::ModuleResponse,
};
use crate::boot::MODULE_REQUEST; #[used]
#[unsafe(link_section = ".requests")]
pub static FILE_REQUEST: ExecutableFileRequest = limine::request::ExecutableFileRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static MODULE_REQUEST: ModuleRequest = limine::request::ModuleRequest::new();
lazy_static! { lazy_static! {
pub static ref MODULE_RESPONSE: &'static ModuleResponse = MODULE_REQUEST pub static ref MODULE_RESPONSE: &'static ModuleResponse = MODULE_REQUEST

View File

@ -1,7 +1,7 @@
// Copyright (c) 2025 shibedrill // Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use crate::boot::FILE_REQUEST; use crate::boot::modules::FILE_REQUEST;
use crate::memory::alloc; use crate::memory::alloc;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;

View File

@ -2,3 +2,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// TODO: Implement per-arch memory handlers for ACPI memory map regions // TODO: Implement per-arch memory handlers for ACPI memory map regions
use limine::request::RsdpRequest;
#[used]
#[unsafe(link_section = ".requests")]
pub static RSDP_REQUEST: RsdpRequest = limine::request::RsdpRequest::new();

View File

@ -6,21 +6,12 @@ mod acpi;
use fdt::*; use fdt::*;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use limine::response::{DeviceTreeBlobResponse, RsdpResponse}; use limine::response::{DeviceTreeBlobResponse, RsdpResponse};
use raw_cpuid::native_cpuid::CpuIdReaderNative;
use raw_cpuid::*;
use crate::boot::{DTB_REQUEST, RSDP_REQUEST}; use crate::boot::DTB_REQUEST;
use crate::device::acpi::RSDP_REQUEST;
use crate::log::{LOGGER, LogLevel}; use crate::log::{LOGGER, LogLevel};
use crate::{format, log_info, log_trace, log_warning}; use crate::{format, log_info, log_trace, log_warning};
pub fn log_cpuid() {
let cpuid: CpuId<CpuIdReaderNative> = CpuId::with_cpuid_reader(CpuIdReaderNative);
log_trace!(
"Device: CPU vendor: {}",
cpuid.get_processor_brand_string().unwrap().as_str()
)
}
lazy_static! { lazy_static! {
pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() { pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() {
Some(resp) => { Some(resp) => {

View File

@ -1,3 +1,6 @@
// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later
pub fn double_fault(info: &str) -> ! { pub fn double_fault(info: &str) -> ! {
panic!("Double fault: {}", info); panic!("Double fault: {}", info);
} }

View File

@ -19,17 +19,21 @@ mod process;
#[macro_use] #[macro_use]
mod util; mod util;
use core::arch::asm;
use arch::x86_64::gdt::gdt;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::x86_64::serial::Serialport; use arch::x86_64::serial::Serialport;
use arch::asm::*; use arch::asm::*;
use boot::{modules::*, params, *}; use boot::{modules::*, params, *};
use constants::*; use constants::*;
use device::*;
use log::*; use log::*;
use memory::{MEMMAP_REQUEST, HHDM_RESPONSE};
use memory::alloc::{format, string::*, vec}; use memory::alloc::{format, string::*, vec};
use params::*; use params::*;
use intbits::{self, Bits};
use limine::file::File; use limine::file::File;
use limine::memory_map::EntryType; use limine::memory_map::EntryType;
#[allow(unused_imports)] #[allow(unused_imports)]
@ -195,8 +199,7 @@ unsafe extern "C" fn main() -> ! {
panic!("Memory map contains no entries"); panic!("Memory map contains no entries");
} }
//#[cfg(target_arch = "x86_64")] log_info!("HHDM offset: 0x{:x}", HHDM_RESPONSE.offset());
//gdt::setup_gdt();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
@ -208,9 +211,22 @@ unsafe extern "C" fn main() -> ! {
"Boot: Paging enable: {}", "Boot: Paging enable: {}",
unsafe { cr0() & (0b1 << 31) } == 1 unsafe { cr0() & (0b1 << 31) } == 1
); );
let pd_addr = {
let cr3: u64;
unsafe {
asm! {
"mov {}, cr3",
out(reg) cr3,
}
}
log_trace!("Boot: cr3 value: 0b{:b}", cr3);
cr3.bits(12..=31)
};
log_trace!("Boot: Physical address of page directory: 0x{:x}", pd_addr);
log_trace!("Boot: Virtual address of page directory: 0x{:x}", pd_addr + HHDM_RESPONSE.offset());
log_trace!("Boot: GDT: 0x{:x} bytes @ 0x{:x}", unsafe { gdt().0 }, unsafe { gdt().1} );
log_trace!("Boot: GDT: 0x{:x}", unsafe { *((gdt().1 + 0x0) as *const u64) })
} }
log_cpuid();
panic!("Bailing"); panic!("Bailing");

View File

@ -4,12 +4,31 @@
#![allow(unused_imports)] #![allow(unused_imports)]
use enumflags2::*; use enumflags2::*;
use lazy_static::lazy_static;
use limine::{request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest}, response::HhdmResponse};
use core::alloc::{Allocator, Layout}; use core::alloc::{Allocator, Layout};
use talc::*; use talc::*;
pub extern crate alloc; pub extern crate alloc;
#[used]
#[unsafe(link_section = ".requests")]
pub static ADDRESS_REQUEST: ExecutableAddressRequest =
limine::request::ExecutableAddressRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static HHDM_REQUEST: HhdmRequest = limine::request::HhdmRequest::new();
lazy_static! {
pub static ref HHDM_RESPONSE: &'static HhdmResponse = HHDM_REQUEST.get_response().expect("Did not get HHDM response from bootloader");
}
static mut ARENA: [u8; 10000] = [0; 10000]; static mut ARENA: [u8; 10000] = [0; 10000];
#[global_allocator] #[global_allocator]

View File

@ -1,3 +1,6 @@
// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later
#[macro_export] #[macro_export]
macro_rules! critical_section { macro_rules! critical_section {
($b:block) => { ($b:block) => {