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",
"fdt",
"flagset",
"intbits",
"lazy_static",
"limine",
"lzma-rs",
"once_cell",
"raw-cpuid",
"spin 0.10.0",
"talc",
"tar-no-std",
"x86_64",
]
[[package]]
name = "intbits"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5170c2c8ecda29c1bccb9d95ccbe107bc75fa084dc0c9c6087e719f9d46330e5"
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -166,6 +173,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "once_cell"
version = "1.21.3"
@ -200,15 +216,6 @@ dependencies = [
"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]]
name = "rustversion"
version = "1.0.20"
@ -256,6 +263,18 @@ dependencies = [
"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]]
name = "unicode-ident"
version = "1.0.18"

View File

@ -8,14 +8,14 @@ acpi = "5.1.0"
enumflags2 = "0.7.11"
fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" }
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 }
once_cell = { version = "1.20.3", default-features = false, features = ["alloc", "critical-section"] }
raw-cpuid = "11.5.0"
spin = "0.10.0"
talc = "4.4.2"
x86_64 = "0.15.2"
tar-no-std = "0.3.4"
[target.'cfg(target_arch = "x86_64")'.dependencies]
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
- Builds for multiple architectures
- Builds for AArch64, RISCV64, x86_64, and LoongArch64
- Valid Limine kernel
- Boots on `x86_64`
- 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
- Multi-architecture feature support
- Display console
- Serial console
- Device discovery & APIs
- Power management
- Paging
### Future/Desired
- Code execution
- Userspace binaries/processes
- Interprocess communication
- Driver server interface
- Interrupts and timers
- Context switching
- Process scheduling
- Shell and CLI
- System calls (multi-convention?)
- Multi-user support and access control
- Capability access control
- Simultaneous multiprocessing support
- ACPI, USB, PCI(e), SATA
- Filesystem support (FAT32)
- Application sandboxing/permissions control
- Graphical desktop environment
- Networking support
- Hypervisor functionality
### Additional Future Features (Userspace)
- Device drivers
- Filesystem drivers
- Shell
- Standard system API
- Rust and C stdlib port
- Display/windowing
- Application sandboxing
## Licensing
@ -64,7 +73,7 @@ Licensed under the GNU Public License v3. See [LICENSE](LICENSE) for details.
## 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.
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).
- `cargo make prepare`: Installs needed Rust toolchain.
- `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 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 iso`: Builds the bootable ISO with Limine installed.
- `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_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.
@ -108,9 +110,9 @@ Kernel parameters are passed as part of the `cmdline` through [limine.conf](limi
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`.
- `-logdev`: A sequence of one or more values representing devices to log to. Current options are `display` and `serial`.
- `-initramfs`: A valid path to a module to serve as the initramfs (containing the init binary). Only one value supported.
- `-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`. 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. This parameter is case sensitive.
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 crate::{critical_section, format, log_trace};
use intbits::Bits;
lazy_static! {
pub static ref GDT: GlobalDescriptorTable = {
let mut gdt = GlobalDescriptorTable::new();
gdt.append(Descriptor::kernel_code_segment());
gdt
};
pub unsafe fn gdt() -> (u8, u64) {
let mut addr: u128 = 0;
unsafe {
asm! {
"sgdt [rax]",
in("rax") addr_of_mut!(addr),
}
#[allow(dead_code)]
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
);
});
}
(addr.bits(0..=15) as u8, addr.bits(16..=79) as u64)
}

View File

@ -9,6 +9,7 @@ use limine::{BaseRevision, request::*};
#[used]
#[unsafe(link_section = ".requests_start_marker")]
static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new();
#[used]
#[unsafe(link_section = ".requests_end_marker")]
static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
@ -16,28 +17,15 @@ static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static BASE_REVISION: BaseRevision = limine::BaseRevision::new();
#[used]
#[unsafe(link_section = ".requests")]
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]
#[unsafe(link_section = ".requests")]
pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::FramebufferRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new();
#[used]
#[unsafe(link_section = ".requests")]
pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new();

View File

@ -2,9 +2,18 @@
// SPDX-License-Identifier: GPL-3.0-or-later
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! {
pub static ref MODULE_RESPONSE: &'static ModuleResponse = MODULE_REQUEST

View File

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

View File

@ -2,3 +2,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// 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 lazy_static::lazy_static;
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::{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! {
pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = match DTB_REQUEST.get_response() {
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) -> ! {
panic!("Double fault: {}", info);
}

View File

@ -19,17 +19,21 @@ mod process;
#[macro_use]
mod util;
use core::arch::asm;
use arch::x86_64::gdt::gdt;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::serial::Serialport;
use arch::asm::*;
use boot::{modules::*, params, *};
use constants::*;
use device::*;
use log::*;
use memory::{MEMMAP_REQUEST, HHDM_RESPONSE};
use memory::alloc::{format, string::*, vec};
use params::*;
use intbits::{self, Bits};
use limine::file::File;
use limine::memory_map::EntryType;
#[allow(unused_imports)]
@ -195,8 +199,7 @@ unsafe extern "C" fn main() -> ! {
panic!("Memory map contains no entries");
}
//#[cfg(target_arch = "x86_64")]
//gdt::setup_gdt();
log_info!("HHDM offset: 0x{:x}", HHDM_RESPONSE.offset());
#[cfg(target_arch = "x86_64")]
{
@ -208,9 +211,22 @@ unsafe extern "C" fn main() -> ! {
"Boot: Paging enable: {}",
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");

View File

@ -4,12 +4,31 @@
#![allow(unused_imports)]
use enumflags2::*;
use lazy_static::lazy_static;
use limine::{request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest}, response::HhdmResponse};
use core::alloc::{Allocator, Layout};
use talc::*;
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];
#[global_allocator]

View File

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