Compare commits

...

3 Commits

9 changed files with 114 additions and 66 deletions

8
Cargo.lock generated
View File

@ -116,9 +116,9 @@ dependencies = [
[[package]]
name = "limine"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e6cb7fd182815ec1ea9e26061418ac37c3eebea47a14e773c563533f277bcef"
checksum = "af6d2ee42712e7bd2c787365cd1dab06ef59a61becbf87bec7b32b970bd2594b"
dependencies = [
"bitflags",
]
@ -249,9 +249,9 @@ dependencies = [
[[package]]
name = "talc"
version = "4.4.2"
version = "4.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fcad3be1cfe36eb7d716a04791eba36a197da9d9b6ea1e28e64ac569da3701d"
checksum = "a3ae828aa394de34c7de08f522d1b86bd1c182c668d27da69caadda00590f26d"
dependencies = [
"lock_api",
]

View File

@ -4,19 +4,19 @@ version = "0.3.0"
edition = "2024"
[dependencies]
acpi = "5.1.0"
acpi = { version = "5.2.0", optional = true }
bitflags = "2.9.1"
fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" }
fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1", optional = true }
flagset = "0.4.7"
intbits = "0.2.0"
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
limine = "0.4.0"
lzma-rs = { git = "https://github.com/glaeqen/lzma-no-std-rs/", version = "0.2.0", default-features = false }
limine = "0.5.0"
lzma-rs = { git = "https://github.com/glaeqen/lzma-no-std-rs/", version = "0.2.0", default-features = false, optional = true }
num-derive = "0.4.2"
num-traits = { version = "0.2.19", default-features = false }
once_cell = { version = "1.20.3", default-features = false, features = ["alloc", "critical-section"] }
once_cell = { version = "1.21.3", default-features = false, features = ["alloc", "critical-section"] }
spin = "0.10.0"
talc = "4.4.2"
talc = "4.4.3"
tar-no-std = "0.3.4"
[target.'cfg(target_arch = "x86_64")'.dependencies]
@ -33,3 +33,10 @@ test = false
doctest = false
bench = false
[features]
default = ["acpi", "dtb", "uefi", "compression"]
acpi = ["dep:acpi"] # Support ACPI
dtb = ["dep:fdt"] # Support device tree blobs
uefi = [] # Enable UEFI dependent features
compression = ["dep:lzma-rs"] # Enable compressed initramfs

View File

@ -1,5 +1,5 @@
# Gila v0.3.0 - a Rust Microkernel
# Gila v0.3.1 - a Rust Microkernel
Gila is a Rust microkernel OS, inspired by the Xinu embedded OS, as well as Linux. I aim to implement multitasking and different users for processes, and eventually a filesystem. I do not aim to make it POSIX-compatible, but it will likely end up sharing many features with POSIX operating systems.
@ -104,6 +104,15 @@ You do not need to clean any files after making changes. The `lib`, `kernel`, an
> [!NOTE]
> The `-p {profile}` argument must go between `cargo make` and the task argument.
### Features
Gila has four optional features, which I made optional in anticipation of a potential future port to older systems like i686 which might not support modern standards like UEFI or ACPI. They are all enabled by default. Disabling them reduces kernel size and forces the kernel to fall back to other implementations for some functionality like device discovery.
- `acpi`: Advanced Configuration and Power Interface, for device discovery & power management
- `dtb`: Device Tree Blob, for device discovery in embedded systems
- `compression`: Compressed initramfs archive
- `uefi`: UEFI-specific bootloader features
## Kernel Parameters
Kernel parameters are passed as part of the `cmdline` through [limine.conf](limine.conf). The parameters are passed as a space-delimited list of keys and values. Keys begin with a hyphen (`-`), and keys are separated from their values with equals signs (`=`). Keys can have a set of multiple values, separated by a comma (`,`). Gila does not currently support parameter values with spaces. That would require an *actual* parser.
@ -118,6 +127,8 @@ The default behavior for each parameter, when not supplied, is:
`-loglevel=Info -initramfs=/boot/initramfs.tar.lzma`
The `.lzma` extension is removed from the default initramfs name when compression is disabled.
## Credits
The linker script stuff is from [limine-rust-template](https://github.com/jasondyoungberg/limine-rust-template),

View File

@ -9,15 +9,16 @@ use crate::format;
lazy_static! {
pub static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.double_fault.set_handler_fn(double_fault);
// TODO: Re-implement this once the x86-interrupt ABI is fixed.
//idt.double_fault.set_handler_fn(double_fault);
idt.page_fault.set_handler_fn(page_fault);
idt
};
}
extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
crate::interrupt::double_fault(&format!("{info:#?}"));
}
//extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
// crate::interrupt::double_fault(&format!("{info:#?}"));
//}
extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFaultErrorCode) {
if errcode.contains(PageFaultErrorCode::USER_MODE) {

View File

@ -24,8 +24,4 @@ pub static MP_REQUEST: MpRequest = limine::request::MpRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new();
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new();

View File

@ -5,8 +5,18 @@ use crate::format;
use crate::log::LogLevel;
use crate::memory::alloc::string::String;
// TODO: Add API to query available features
pub static ACPI_ENABLED: bool = if cfg!(feature = "acpi") { true } else { false };
pub static DTB_ENABLED: bool = if cfg!(feature = "dtb") { true } else { false };
pub static COMPRESSION_ENABLED: bool = if cfg!(feature = "compression") { true } else { false };
pub static UEFI_ENABLED: bool = if cfg!(feature = "uefi") { true } else { false };
#[allow(dead_code)]
pub static INITRAMFS_DEFAULT_PATH: &str = "/boot/initramfs.tar.lzma";
pub static INITRAMFS_DEFAULT_PATH: &str = if cfg!(feature = "compression") {
"/boot/initramfs.tar.lzma"
} else {
"/boot/initramfs.tar"
};
pub static LOG_DEFAULT_LEVEL: LogLevel = LogLevel::Info;

View File

@ -3,8 +3,24 @@
// TODO: Implement per-arch memory handlers for ACPI memory map regions
use limine::request::RsdpRequest;
use limine::{request::RsdpRequest, response::RsdpResponse};
use lazy_static::lazy_static;
use crate::{format, log_info, log_warning, log::*};
#[used]
#[unsafe(link_section = ".requests")]
pub static RSDP_REQUEST: RsdpRequest = limine::request::RsdpRequest::new();
lazy_static! {
pub static ref RSDP: Option<&'static RsdpResponse> = match RSDP_REQUEST.get_response() {
Some(resp) => {
log_info!("Device: Got RSDP pointer");
Some(resp)
}
None => {
log_warning!("Device: Did not get RSDP pointer, ACPI unavailable");
None
}
};
}

View File

@ -0,0 +1,35 @@
use lazy_static::lazy_static;
use limine::{request::DeviceTreeBlobRequest, response::DeviceTreeBlobResponse};
use fdt::*;
use crate::{format, log_trace, log_info, log_warning, log::*};
#[used]
#[unsafe(link_section = ".requests")]
pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new();
lazy_static! {
pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() {
Some(resp) => {
log_info!("Device: Got DTB pointer");
Some(resp)
}
None => {
log_warning!("Device: Did not get DTB pointer");
None
}
};
}
#[allow(dead_code)]
pub fn device_tree_parsed() -> Option<Fdt<'static>> {
if let Some(ok_dtb) = *DTB
&& let Ok(ok_parsed_dt) = unsafe { fdt::Fdt::from_ptr(ok_dtb.dtb_ptr() as *const u8) }
{
log_trace!("Device: Parsed device tree");
Some(ok_parsed_dt)
} else {
None
}
}

View File

@ -1,57 +1,29 @@
// Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later
#[cfg(feature = "acpi")]
mod acpi;
#[cfg(feature = "dtb")]
mod devtree;
use fdt::*;
use lazy_static::lazy_static;
use limine::response::{DeviceTreeBlobResponse, RsdpResponse};
use crate::boot::DTB_REQUEST;
use crate::device::acpi::RSDP_REQUEST;
use crate::log::{LOGGER, LogLevel};
use crate::{format, log_error, log_info, log_trace, log_warning};
lazy_static! {
pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() {
Some(resp) => {
log_info!("Device: Got DTB pointer");
Some(resp)
}
None => {
log_warning!("Device: Did not get DTB pointer");
None
}
};
pub static ref RSDP: Option<&'static RsdpResponse> = match RSDP_REQUEST.get_response() {
Some(resp) => {
log_info!("Device: Got RSDP pointer");
Some(resp)
}
None => {
log_warning!("Device: Did not get RSDP pointer, ACPI unavailable");
None
}
};
}
use crate::{format, log_error};
// Just to check
pub fn init_statics() {
let dtb = DTB.is_some();
let rdsp = RSDP.is_some();
let dtb = {
#[cfg(feature = "dtb")]
{ devtree::DTB.is_some() }
#[cfg(not(feature = "dtb"))]
false
};
let rdsp = {
#[cfg(feature = "acpi")]
{ acpi::RSDP.is_some() }
#[cfg(not(feature = "acpi"))]
false
};
if !dtb & !rdsp {
log_error!("Device: Neither DTB nor ACPI available, booted system will be useless")
}
}
#[allow(dead_code)]
pub fn device_tree_parsed() -> Option<Fdt<'static>> {
if let Some(ok_dtb) = *DTB
&& let Ok(ok_parsed_dt) = unsafe { fdt::Fdt::from_ptr(ok_dtb.dtb_ptr() as *const u8) }
{
log_trace!("Device: Parsed device tree");
Some(ok_parsed_dt)
} else {
None
}
}