From 77355d3f25dada77e44a20854133feedeeefca0c Mon Sep 17 00:00:00 2001 From: August Date: Tue, 30 Jun 2026 21:25:33 +0000 Subject: [PATCH] Initial userboot support --- Cargo.lock | 2 +- Cargo.toml | 8 ++- Makefile.toml | 19 +++++- README.md | 4 +- build.rs | 4 +- configs/init.toml | 6 -- configs/limine.conf | 7 ++- docs/DEVELOPMENT.MD | 55 +++++++++--------- libgila/Cargo.toml | 12 ---- gila_banner.png => resources/gila_banner.png | Bin .../gila_gilbert.png | Bin src/kernel/main.rs | 10 +++- .../arch => linker_scripts}/aarch64/linker.ld | 0 .../loongarch64/linker.ld | 0 .../arch => linker_scripts}/riscv64/linker.ld | 0 .../arch => linker_scripts}/x86_64/linker.ld | 0 src/userboot/main.rs | 14 +++++ 17 files changed, 79 insertions(+), 62 deletions(-) delete mode 100644 configs/init.toml delete mode 100644 libgila/Cargo.toml rename gila_banner.png => resources/gila_banner.png (100%) rename gila_gilbert.png => resources/gila_gilbert.png (100%) rename src/{kernel/arch => linker_scripts}/aarch64/linker.ld (100%) rename src/{kernel/arch => linker_scripts}/loongarch64/linker.ld (100%) rename src/{kernel/arch => linker_scripts}/riscv64/linker.ld (100%) rename src/{kernel/arch => linker_scripts}/x86_64/linker.ld (100%) create mode 100644 src/userboot/main.rs diff --git a/Cargo.lock b/Cargo.lock index d270d29..04991a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,7 +69,7 @@ checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "gila" -version = "0.3.2" +version = "0.4.0" dependencies = [ "acid_alloc", "enumflags2", diff --git a/Cargo.toml b/Cargo.toml index 44a5b66..d68ecbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/Makefile.toml b/Makefile.toml index e4bf1bc..d3d4024 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -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 \ diff --git a/README.md b/README.md index 36c0d43..0a01db9 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/build.rs b/build.rs index 481f7a6..db2e744 100644 --- a/build.rs +++ b/build.rs @@ -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"); } \ No newline at end of file diff --git a/configs/init.toml b/configs/init.toml deleted file mode 100644 index 2d8ad7d..0000000 --- a/configs/init.toml +++ /dev/null @@ -1,6 +0,0 @@ -[deployment] -libgila_version = "0.1.0" -arch = "x86_64" -# Optional -name = "example" -version = "0.1.0" \ No newline at end of file diff --git a/configs/limine.conf b/configs/limine.conf index 2a5d8ca..9195447 100644 --- a/configs/limine.conf +++ b/configs/limine.conf @@ -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 diff --git a/docs/DEVELOPMENT.MD b/docs/DEVELOPMENT.MD index 27b11c1..c10eb7f 100644 --- a/docs/DEVELOPMENT.MD +++ b/docs/DEVELOPMENT.MD @@ -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 diff --git a/libgila/Cargo.toml b/libgila/Cargo.toml deleted file mode 100644 index 5961147..0000000 --- a/libgila/Cargo.toml +++ /dev/null @@ -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" \ No newline at end of file diff --git a/gila_banner.png b/resources/gila_banner.png similarity index 100% rename from gila_banner.png rename to resources/gila_banner.png diff --git a/gila_gilbert.png b/resources/gila_gilbert.png similarity index 100% rename from gila_gilbert.png rename to resources/gila_gilbert.png diff --git a/src/kernel/main.rs b/src/kernel/main.rs index 82e1419..f650ab1 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -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!"); } diff --git a/src/kernel/arch/aarch64/linker.ld b/src/linker_scripts/aarch64/linker.ld similarity index 100% rename from src/kernel/arch/aarch64/linker.ld rename to src/linker_scripts/aarch64/linker.ld diff --git a/src/kernel/arch/loongarch64/linker.ld b/src/linker_scripts/loongarch64/linker.ld similarity index 100% rename from src/kernel/arch/loongarch64/linker.ld rename to src/linker_scripts/loongarch64/linker.ld diff --git a/src/kernel/arch/riscv64/linker.ld b/src/linker_scripts/riscv64/linker.ld similarity index 100% rename from src/kernel/arch/riscv64/linker.ld rename to src/linker_scripts/riscv64/linker.ld diff --git a/src/kernel/arch/x86_64/linker.ld b/src/linker_scripts/x86_64/linker.ld similarity index 100% rename from src/kernel/arch/x86_64/linker.ld rename to src/linker_scripts/x86_64/linker.ld diff --git a/src/userboot/main.rs b/src/userboot/main.rs new file mode 100644 index 0000000..077bd11 --- /dev/null +++ b/src/userboot/main.rs @@ -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 {} +} \ No newline at end of file