Initial userboot support
Some checks failed
Continuous Integration / Check (push) Failing after 43s
Continuous Integration / Clippy (push) Failing after 41s

This commit is contained in:
August 2026-06-30 21:25:33 +00:00
parent c6e032d9c9
commit 77355d3f25
Signed by: shibedrill
SSH Key Fingerprint: SHA256:M0m3JW1s38BgO2t0fG146Yxd9OJ2IOqkvCAsuRHQ6Pw
17 changed files with 79 additions and 62 deletions

2
Cargo.lock generated
View File

@ -69,7 +69,7 @@ checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
[[package]]
name = "gila"
version = "0.3.2"
version = "0.4.0"
dependencies = [
"acid_alloc",
"enumflags2",

View File

@ -1,6 +1,6 @@
[package]
name = "gila"
version = "0.3.2"
version = "0.4.0"
edition = "2024"
license = "MIT"
@ -28,6 +28,10 @@ test = false
doctest = false
bench = false
[[bin]]
name = "userboot"
path = "src/userboot/main.rs"
[lib]
name = "libgila"
name = "gila"
path = "src/lib/lib.rs"

View File

@ -84,23 +84,35 @@ args = ["build", "--profile", "${PROFILE}", "--lib"]
[tasks.kernel]
condition = { files_modified = { input = [
"src/kernel/**/*.rs",
"src/kernel/**/*.ld",
"src/linker_scripts/**/*.ld",
"${ARTIFACTDIR}/libgila.rlib"
], output = ["${ARTIFACTDIR}/kernel"] }, fail_message = "(inputs unchanged)" }
dependencies = ["lib"]
command = "cargo"
args = ["build", "--profile", "${PROFILE}", "--bin", "kernel"]
[tasks.userboot]
condition = { files_modified = { input = [
"src/userboot/**/*.rs",
"src/linker_scripts/**/*.ld",
"${ARTIFACTDIR}/libgila.rlib"
], output = ["${ARTIFACTDIR}/userboot"] }, fail_message = "(inputs unchanged)" }
dependencies = ["lib"]
command = "cargo"
args = ["build", "--profile", "${PROFILE}", "--bin", "userboot"]
[tasks.iso]
condition = { files_modified = { input = [
"${ARTIFACTDIR}/kernel",
"${ARTIFACTDIR}/userboot",
"configs/limine.conf",
"resources/wallpaper.png",
"${LIMINEDIR}/limine-bios.sys",
"${LIMINEDIR}/limine-bios-cd.bin",
"${LIMINEDIR}/limine-uefi-cd.bin",
"${LIMINEDIR}/${LIMINEBIN}"
], output = ["build/gila.iso"] }, fail_message = "(inputs unchanged)" }
dependencies = ["kernel"]
dependencies = ["kernel", "userboot"]
script = '''
mkdir -p build/iso/boot/limine
mkdir -p build/iso/EFI/BOOT
@ -113,7 +125,8 @@ script = '''
cp -f ${LIMINEDIR}/limine-uefi-cd.bin build/iso/boot/limine/
cp -f ${LIMINEDIR}/${LIMINEBIN} build/iso/EFI/BOOT
cp -f ${ARTIFACTDIR}/kernel build/iso/boot/${ARCH}/gila
cp -f ${ARTIFACTDIR}/kernel build/iso/boot/${ARCH}/kernel
cp -f ${ARTIFACTDIR}/userboot build/iso/boot/${ARCH}/userboot
xorriso -as mkisofs \
-b boot/limine/limine-bios-cd.bin \

View File

@ -1,6 +1,6 @@
# Gila v0.3.1 - a Rust Microkernel
# Gila v0.4.0 - a Rust Microkernel
![An illustrated Gila monster, and the text "Gila: A Minimal Rust Microkernel", superimposed over some serial log output.](gila_banner.png)
![An illustrated Gila monster, and the text "Gila: A Minimal Rust Microkernel", superimposed over some serial log output.](resources/gila_banner.png)
Gila is a Rust microkernel OS, inspired by microkernel projects such as seL4, Zircon, and Redox. I aim to implement multitasking, userspace drivers, IPC, and sandboxing. I do not aim to make it POSIX-compatible, but it will likely end up sharing many features with POSIX operating systems. Its design philosophy is focused around simplicity, isolation, modularity, and minimal privilege.

View File

@ -1,7 +1,7 @@
fn main() {
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
// Tell cargo to pass the linker script to the linker..
println!("cargo:rustc-link-arg=-Tsrc/kernel/arch/{arch}/linker.ld");
println!("cargo:rustc-link-arg=-Tsrc/linker_scripts/{arch}/linker.ld");
// ..and to re-run if it changes.
println!("cargo:rerun-if-changed=src/kernel/arch/{arch}linker.ld");
println!("cargo:rerun-if-changed=src/linker_scripts/{arch}linker.ld");
}

View File

@ -1,6 +0,0 @@
[deployment]
libgila_version = "0.1.0"
arch = "x86_64"
# Optional
name = "example"
version = "0.1.0"

View File

@ -1,10 +1,11 @@
timeout: 1
wallpaper: boot():/bg.png
wallpaper: boot():/wallpaper.png
wallpaper_style: centered
/Gila
protocol: limine
kernel_path: boot():/boot/${ARCH}/gila
cmdline: -loglevel=Info -logdev=display,serial -initramfs=/boot/${ARCH}/initramfs.tar.lzma
kernel_path: boot():/boot/${ARCH}/kernel
cmdline: -loglevel=Trace -logdev=display,serial
module_path: boot():/boot/${ARCH}/userboot
kaslr: yes
randomize_hhdm_base: yes

View File

@ -7,41 +7,43 @@ design details can be found in [SECURITY.md](SECURITY.md).
## Navigating
- [kernel/src/](../kernel/src/): Kernel-specific code.
- [arch/](../kernel/src/arch/): Architecture specific features like the
- [src/kernel/](../src/kernel/): Kernel-specific code.
- [arch/](../src/kernel/arch/): Architecture specific features like the
display, serial, and interrupts. Each architecture is a subfolder,
containing a file or module for each feature.
- [boot/](../kernel/src/boot/mod.rs): Handles bootloader-managed data
- [boot/](../src/kernel/boot/mod.rs): Handles bootloader-managed data
structures. Gila uses Limine. Other bootloaders are NOT supported.
- [params.rs](../kernel/src/boot/params.rs): Command line parameter parsing.
- [modules.rs](../kernel/src/boot/modules.rs): Kernel module handling.
- [constants.rs](../kernel/src/constants.rs): Constants referenced elsewhere
- [params.rs](../src/kernel/boot/params.rs): Command line parameter parsing.
- [modules.rs](../src/kernel/boot/modules.rs): Kernel module handling.
- [constants.rs](../src/kernel/constants.rs): Constants referenced elsewhere
in the kernel.
- [log.rs](../kernel/src/log.rs): Logging structures, macros, and singletons
- [log.rs](../src/kernel/log.rs): Logging structures, macros, and singletons
for logging to serial or the display.
- [interrupt/](../kernel/src/interrupt/mod.rs): Interrupt handlers with
- [interrupt/](../src/kernel/interrupt/mod.rs): Interrupt handlers with
platform-agnostic APIs.
- [main.rs](../kernel/src/main.rs): The entry point that gets called by the
- [main.rs](../src/kernel/main.rs): The entry point that gets called by the
bootloader.
- [memory.rs](../kernel/src/memory.rs): Types relating to memory regions and
- [memory.rs](../src/kernel/memory.rs): Types relating to memory regions and
allocation.
- [panic.rs](../kernel/src/panic.rs): The panic handler and associated
- [panic.rs](../src/kernel/panic.rs): The panic handler and associated
functionality.
- [process.rs](../kernel/src/process.rs): Process types and functions.
- [syscall\_runner.rs](../kernel/src/syscall_runner.rs): Chooses a system call
by its ID and defers actual syscall execution to code in `/libgila/src/`.
- [libgila/src/](../libgila/src/lib.rs): Shared between the kernel and any
- [process.rs](../src/kernel/process.rs): Process types and functions.
- [syscall\_runner.rs](../src/kernel/syscall_runner.rs): Chooses a system call
by its ID and defers actual syscall execution to code in `/src/lib/`.
- [src/userboot/](../src/userboot/): The first Ring 3 binary to run.
- [src/linker_scripts](../src/linker_scripts/): Linker scripts for binaries.
- [src/lib/](../src/lib/lib.rs): Shared between the kernel and any
binaries built for it. Contains any definitions, structures, and types that will
cross the boundary between userspace and kernelspace, including those sent over IPC.
- [arch/](../libgila/src/arch/mod.rs): Architecture specific functionality like
- [arch/](../src/lib/arch/mod.rs): Architecture specific functionality like
system call register storing/loading.
- [syscall.rs](../libgila/src/syscall.rs): System call types common to apps and
- [syscall.rs](../src/lib/syscall.rs): System call types common to apps and
the kernel.
## Building and running
Building a bootable kernel is easy. All you need to do is run
`cargo build -p kernel`, and a valid, bootable Limine executable will be
`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.
@ -72,18 +74,19 @@ If not, the following dependencies will need to be manually installed:
Run `cargo make` to invoke the [Makefile.toml](../Makefile.toml).
- `cargo make clean_all`: Cleans all built binaries, libraries, initramfs
files, and ISOs.
- `cargo make clean_all`: Cleans all built binaries, libraries, and ISO build files.
- `cargo make clean_iso`: Cleans the ISO build directory.
- `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 initramfs`: Build the init archive.
- `cargo make userboot`: Build the userspace init binary.
- `cargo make iso`: Builds the bootable ISO with Limine installed.
- `cargo make run`: Builds the ISO and boots it in QEMU.
- `cargo make gui_run`: Same as above, but with QEMU in GUI mode.
- `cargo make debug`: Launch the kernel in QEMU with debugging enabled, and
start and connect GDB.
You do not need to clean any files after making changes. The `lib`, `kernel`,
You do not need to clean any files after making changes. The `lib`, `kernel`, `userboot`,
and `iso` tasks will automatically be rerun if their input files change.
### Configuration
@ -139,16 +142,10 @@ one value supported. Current options are `Disabled`, `Trace`, `Info`,
- `-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:
`-loglevel=Info -initramfs=/boot/initramfs.tar.lzma`
The `.lzma` extension is removed from the default initramfs name when
compression is disabled. It must also be changed in
[limine.conf](../configs/limine.conf) or else Limine will not load it.
`-loglevel=Info`
## Writing Programs for Gila

View File

@ -1,12 +0,0 @@
[package]
name = "libgila"
version = "0.1.0"
edition = "2024"
[dependencies]
num-derive = { version = "0.4.2", default-features = false }
num-traits = { version = "0.2.19", default-features = false }
[lib]
# Stop appending lib to artifact names!!! it's already a library!!!
name = "gila"

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 320 KiB

View File

@ -41,8 +41,7 @@ use crate::{
gdt::dump_gdt,
interrupts::get_lapic_addr,
},
},
memory::paging::{self, active_root_table, map_page, phys_to_virt},
}, boot::modules::MODULE_RESPONSE, memory::paging::{self, active_root_table, map_page, phys_to_virt},
};
lazy_static! {
@ -204,5 +203,12 @@ unsafe extern "C" fn main() -> ! {
let res = map_page(phys_to_virt(lapic), mapping);
log_info!("Map status: {:?}", res);
if let Some(modules_list) = *MODULE_RESPONSE {
if modules_list.modules()[0].path().ends_with("/userboot") {
log_info!("Found userboot: {} {}", modules_list.modules()[0].path(), modules_list.modules()[0].cmdline());
log_info!("Start address: 0x{:x}", modules_list.modules()[0].data().as_ptr() as usize);
}
}
panic!("Finished boot, but cannot start init because processes not implemented!");
}

14
src/userboot/main.rs Normal file
View File

@ -0,0 +1,14 @@
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[unsafe(no_mangle)]
unsafe extern "C" fn main() -> ! {
loop {}
}
#[panic_handler]
pub fn panic(info: &PanicInfo) -> ! {
loop {}
}