multiboot stage

Este commit está contenido en:
ale
2025-06-20 21:57:07 +02:00
padre 72e5221588
commit 315b8aa0f5
Se han modificado 20 ficheros con 371 adiciones y 51 borrados

9
.cargo/config.toml Archivo normal
Ver fichero

@@ -0,0 +1,9 @@
[build]
target = "x86_64-unknown-none"
[target.x86_64-unknown-none]
runner = "qemu-system-x86_64 -kernel"
[unstable]
build-std = ["core", "alloc"]
build-std-features = ["compiler-builtins-mem"]

Ver fichero

@@ -29,7 +29,7 @@ all: kernel modules drivers
# Build the core kernel # Build the core kernel
kernel: kernel:
@echo "Building Rust kernel ($(ARCH), $(BUILD_TYPE))" @echo "Building Rust kernel ($(ARCH), $(BUILD_TYPE))"
$(CARGO) build $(CARGO_FLAGS) cd kernel && $(CARGO) build $(CARGO_FLAGS) --target x86_64-unknown-none -Z build-std=core,alloc
# Build kernel modules # Build kernel modules
modules: $(RUST_MODULES) modules: $(RUST_MODULES)

Ver fichero

@@ -92,11 +92,11 @@ make clean && RUSTFLAGS="-Awarnings" make kernel
### Basic Execution ### Basic Execution
```bash ```bash
# Run kernel in QEMU (basic) # Run kernel in QEMU (basic)
qemu-system-x86_64 -kernel target/release/rust-kernel qemu-system-x86_64 -kernel kernel/target/x86_64-unknown-none/release/rust-kernel
# Run with more memory and serial output # Run with more memory and serial output
qemu-system-x86_64 \ qemu-system-x86_64 \
-kernel target/release/rust-kernel \ -kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
-m 128M \ -m 128M \
-serial stdio \ -serial stdio \
-no-reboot \ -no-reboot \
@@ -107,7 +107,7 @@ qemu-system-x86_64 \
```bash ```bash
# Full-featured QEMU run with debugging # Full-featured QEMU run with debugging
qemu-system-x86_64 \ qemu-system-x86_64 \
-kernel target/release/rust-kernel \ -kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
-m 256M \ -m 256M \
-smp 2 \ -smp 2 \
-serial stdio \ -serial stdio \
@@ -124,13 +124,13 @@ qemu-system-x86_64 \
```bash ```bash
# Run QEMU with GDB server # Run QEMU with GDB server
qemu-system-x86_64 \ qemu-system-x86_64 \
-kernel target/release/rust-kernel \ -kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
-s -S \ -s -S \
-m 128M \ -m 128M \
-serial stdio -serial stdio
# In another terminal, connect GDB # In another terminal, connect GDB
gdb target/release/rust-kernel gdb kernel/target/x86_64-unknown-none/release/rust-kernel
(gdb) target remote localhost:1234 (gdb) target remote localhost:1234
(gdb) continue (gdb) continue
``` ```

7
iso/boot/grub/grub.cfg Archivo normal
Ver fichero

@@ -0,0 +1,7 @@
set timeout=0
set default=0
menuentry "Rust Kernel" {
multiboot /boot/rust-kernel
boot
}

BIN
iso/boot/rust-kernel Archivo ejecutable

Archivo binario no mostrado.

Ver fichero

@@ -1,6 +1,18 @@
[target.x86_64-unknown-none] [target.x86_64-unknown-none]
rustflags = [ rustflags = [
"-C", "link-arg=-Tlinker.ld",
"-C", "link-arg=--no-dynamic-linker", "-C", "link-arg=--no-dynamic-linker",
"-C", "link-arg=-static", "-C", "link-arg=-static",
"-C", "relocation-model=static",
"-C", "link-arg=-no-pie",
"-C", "link-arg=-fno-pie",
"-C", "link-arg=-z",
"-C", "link-arg=max-page-size=0x1000",
"-C", "link-arg=-Wl,--oformat=elf64-x86-64",
] ]
[build]
target = "x86_64-unknown-none"
[unstable]
build-std = ["core", "alloc"]
build-std-features = ["compiler-builtins-mem"]

Ver fichero

@@ -10,11 +10,14 @@ license = "GPL-2.0"
name = "kernel" name = "kernel"
crate-type = ["rlib"] crate-type = ["rlib"]
[[bin]]
name = "rust-kernel"
path = "src/main.rs"
[dependencies] [dependencies]
spin = "0.9" spin = "0.9"
bitflags = "2.4" bitflags = "2.4"
linked_list_allocator = "0.10" linked_list_allocator = "0.10"
once_cell = { version = "1.19", default-features = false, features = ["critical-section"] }
[features] [features]
default = [] default = []

Ver fichero

@@ -1,11 +1,19 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
fn main() { use std::env;
// Build assembly files with rustc use std::fs;
println!("cargo:rerun-if-changed=src/arch/x86_64/boot.s"); use std::path::PathBuf;
println!("cargo:rerun-if-changed=src/arch/x86_64/exceptions.s");
println!("cargo:rerun-if-changed=linker.ld");
// Tell Cargo to link against the linker script fn main() {
println!("cargo:rustc-link-arg=-Tlinker.ld"); println!("cargo:rerun-if-changed=linker.ld");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
// Copy linker script to OUT_DIR so the linker can find it
let linker_script = out_dir.join("linker.ld");
fs::copy("linker.ld", &linker_script)
.expect("Failed to copy linker script");
// Tell cargo to pass the linker script to the linker
println!("cargo:rustc-link-arg=-T{}", linker_script.display());
} }

Ver fichero

@@ -3,36 +3,50 @@
ENTRY(_start) ENTRY(_start)
/* Program headers (segments) for ELF */
PHDRS
{
text PT_LOAD FLAGS(5); /* Read + Execute */
rodata PT_LOAD FLAGS(4); /* Read only */
data PT_LOAD FLAGS(6); /* Read + Write */
}
SECTIONS SECTIONS
{ {
/* Start at 1MB (standard kernel load address) */ /* Start at 1MB (standard kernel load address) */
. = 1M; . = 0x100000;
/* Multiboot header must be early */ /* Multiboot header MUST be first */
.multiboot_header : { .multiboot_header : ALIGN(8) {
*(.multiboot_header) KEEP(*(.multiboot_header))
} } :text
/* Boot and text sections */
.boot : ALIGN(8) {
*(.text._start)
*(.boot)
} :text
/* Rest of code section */
.text : ALIGN(4K) {
*(.text .text.*)
} :text
/* Read-only sections */ /* Read-only sections */
.rodata : ALIGN(4K) { .rodata : ALIGN(4K) {
*(.rodata .rodata.*) *(.rodata .rodata.*)
} } :rodata
/* Code section */
.text : ALIGN(4K) {
*(.text .text.*)
}
/* Read-write data */ /* Read-write data */
.data : ALIGN(4K) { .data : ALIGN(4K) {
*(.data .data.*) *(.data .data.*)
} } :data
/* BSS section (uninitialized data) */ /* BSS section (uninitialized data) */
.bss : ALIGN(4K) { .bss : ALIGN(4K) {
*(.bss .bss.*) *(.bss .bss.*)
*(COMMON) *(COMMON)
} } :data
/* Kernel end marker */ /* Kernel end marker */
__kernel_end = .; __kernel_end = .;

67
kernel/src/arch/x86_64/boot.S Archivo normal
Ver fichero

@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Multiboot header for the Rust kernel */
.section .multiboot_header
.align 8
/* Multiboot2 header */
multiboot_header_start:
.long 0xe85250d6 /* magic number */
.long 0 /* architecture: i386 */
.long multiboot_header_end - multiboot_header_start /* header length */
.long -(0xe85250d6 + 0 + (multiboot_header_end - multiboot_header_start)) /* checksum */
/* Information request tag */
.short 1 /* type */
.short 0 /* flags */
.long 12 /* size */
.long 6 /* memory map */
/* End tag */
.short 0 /* type */
.short 0 /* flags */
.long 8 /* size */
multiboot_header_end:
.section .text
.global _start
.code32
_start:
/* Set up stack */
mov $stack_top, %esp
/* Reset EFLAGS */
pushl $0
popf
/* Check if we were loaded by multiboot */
cmp $0x36d76289, %eax
jne .no_multiboot
/* Save multiboot info pointer */
push %ebx
/* Call kernel main */
call kernel_main
/* Halt if kernel returns */
cli
.hang:
hlt
jmp .hang
.no_multiboot:
/* No multiboot - just halt */
cli
hlt
.section .bss
.align 16
stack_bottom:
.skip 16384 /* 16KB stack */
stack_top:
.section .data
multiboot_info_ptr:
.long 0

41
kernel/src/boot.s Archivo normal
Ver fichero

@@ -0,0 +1,41 @@
# SPDX-License-Identifier: GPL-2.0
# Multiboot header and boot code
.code32
.section .multiboot_header, "a"
.align 4
# Multiboot header
multiboot_header_start:
.long 0x1BADB002 # magic number (multiboot 1)
.long 0x00000000 # flags
.long -(0x1BADB002 + 0x00000000) # checksum (must sum to zero)
multiboot_header_end:
.section .text
.global _start
.type _start, @function
_start:
# Disable interrupts
cli
# Set up a basic stack (16KB)
mov $stack_top, %esp
mov $stack_top, %ebp
# Call Rust main function
call rust_main
# If rust_main returns, halt
halt_loop:
hlt
jmp halt_loop
# Reserve stack space
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16KB stack
stack_top:

Ver fichero

@@ -257,25 +257,28 @@ impl DentryCache {
} }
/// Global dentry cache /// Global dentry cache
static DCACHE: once_cell::sync::Lazy<DentryCache> = static DCACHE: spin::once::Once<DentryCache> = spin::once::Once::new();
once_cell::sync::Lazy::new(|| DentryCache::new());
fn get_dcache() -> &'static DentryCache {
DCACHE.call_once(|| DentryCache::new())
}
/// Look up dentry in cache /// Look up dentry in cache
pub fn dcache_lookup(path: &str) -> Option<Arc<Dentry>> { pub fn dcache_lookup(path: &str) -> Option<Arc<Dentry>> {
DCACHE.lookup(path) get_dcache().lookup(path)
} }
/// Insert dentry into cache /// Insert dentry into cache
pub fn dcache_insert(path: String, dentry: Arc<Dentry>) { pub fn dcache_insert(path: String, dentry: Arc<Dentry>) {
DCACHE.insert(path, dentry); get_dcache().insert(path, dentry);
} }
/// Remove dentry from cache /// Remove dentry from cache
pub fn dcache_remove(path: &str) -> Option<Arc<Dentry>> { pub fn dcache_remove(path: &str) -> Option<Arc<Dentry>> {
DCACHE.remove(path) get_dcache().remove(path)
} }
/// Prune dentry cache /// Prune dentry cache
pub fn dcache_prune() { pub fn dcache_prune() {
DCACHE.prune(); get_dcache().prune();
} }

Ver fichero

@@ -194,12 +194,15 @@ impl MountNamespace {
} }
/// Global mount namespace /// Global mount namespace
static INIT_MNT_NS: once_cell::sync::Lazy<Mutex<MountNamespace>> = static INIT_MNT_NS: spin::once::Once<Mutex<MountNamespace>> = spin::once::Once::new();
once_cell::sync::Lazy::new(|| Mutex::new(MountNamespace::new(1)));
fn get_init_mnt_ns() -> &'static Mutex<MountNamespace> {
INIT_MNT_NS.call_once(|| Mutex::new(MountNamespace::new(1)))
}
/// Get the init mount namespace /// Get the init mount namespace
pub fn get_init_ns() -> &'static Mutex<MountNamespace> { pub fn get_init_ns() -> &'static Mutex<MountNamespace> {
&INIT_MNT_NS get_init_mnt_ns()
} }
/// Mount a filesystem /// Mount a filesystem

87
kernel/src/main.rs Archivo normal
Ver fichero

@@ -0,0 +1,87 @@
// SPDX-License-Identifier: GPL-2.0
//! Kernel main entry point
#![no_std]
#![no_main]
/// Multiboot1 header - placed at the very beginning
#[repr(C)]
#[repr(packed)]
struct MultibootHeader {
magic: u32,
flags: u32,
checksum: u32,
}
/// Multiboot header must be in the first 8KB and be 4-byte aligned
#[link_section = ".multiboot_header"]
#[no_mangle]
#[used]
static MULTIBOOT_HEADER: MultibootHeader = MultibootHeader {
magic: 0x1BADB002,
flags: 0x00000000,
checksum: 0u32.wrapping_sub(0x1BADB002u32.wrapping_add(0x00000000)),
};
/// Entry point called by boot.s assembly code
#[no_mangle]
pub extern "C" fn rust_main() -> ! {
kernel_main()
}
/// Main kernel function
fn kernel_main() -> ! {
// Start with the simplest possible approach
unsafe {
let vga_buffer = 0xb8000 as *mut u16;
// Clear screen
for i in 0..80*25 {
*vga_buffer.offset(i) = 0x0f20; // White space on black background
}
// Display kernel info
let messages = [
"Rust Kernel v1.0 - Successfully Booted!",
"",
"Available commands:",
" help - Show this help",
" version - Show kernel version",
" clear - Clear screen",
" reboot - Restart system",
"",
"rustos> ",
];
let mut row = 0;
for message in &messages {
let mut col = 0;
for byte in message.bytes() {
if col < 80 {
let vga_entry = (0x0f00 | byte as u16); // White text on black background
*vga_buffer.offset((row * 80 + col) as isize) = vga_entry;
col += 1;
}
}
row += 1;
}
}
// Simple command loop (just display, no real interaction yet)
loop {
unsafe {
core::arch::asm!("hlt");
}
}
}
/// Panic handler - required for no_std
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {
unsafe {
core::arch::asm!("hlt");
}
}
}

16
kernel/src/multiboot.s Archivo normal
Ver fichero

@@ -0,0 +1,16 @@
.section .multiboot_header
.align 4
.long 0x1BADB002 /* magic */
.long 0x00000000 /* flags */
.long -(0x1BADB002 + 0x00000000) /* checksum */
.section .text
.global _start
_start:
/* Call Rust main function */
call rust_main
/* If rust_main returns, halt */
1: hlt
jmp 1b

41
kernel/src/simple_boot.s Archivo normal
Ver fichero

@@ -0,0 +1,41 @@
# Simple multiboot2 header and boot code
.section .multiboot_header, "a", @progbits
.align 8
multiboot2_header_start:
.long 0xe85250d6 # multiboot2 magic
.long 0 # architecture (i386)
.long multiboot2_header_end - multiboot2_header_start # header length
.long -(0xe85250d6 + 0 + (multiboot2_header_end - multiboot2_header_start)) # checksum
# End tag
.word 0 # type
.word 0 # flags
.long 8 # size
multiboot2_header_end:
.section .text
.global _start
.code32
_start:
# Disable interrupts
cli
# Set up a simple stack
mov $stack_top, %esp
mov $stack_top, %ebp
# Call main Rust function
call main
# If main returns, halt
halt:
hlt
jmp halt
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16KB stack
stack_top:

Ver fichero

@@ -69,7 +69,7 @@ impl CpuInfo {
unsafe { unsafe {
asm!("mov {ebx_save}, rbx", asm!("mov {ebx_save}, rbx",
"cpuid", "cpuid",
"mov {ebx_out}, ebx", "mov {ebx_out:e}, ebx",
"mov rbx, {ebx_save}", "mov rbx, {ebx_save}",
ebx_save = out(reg) _, ebx_save = out(reg) _,
ebx_out = out(reg) ebx, ebx_out = out(reg) ebx,
@@ -144,7 +144,7 @@ impl CpuInfo {
asm!("mov {ebx_save}, rbx", asm!("mov {ebx_save}, rbx",
"cpuid", "cpuid",
"mov {ebx_out}, ebx", "mov {ebx_out:e}, ebx",
"mov rbx, {ebx_save}", "mov rbx, {ebx_save}",
ebx_save = out(reg) _, ebx_save = out(reg) _,
ebx_out = out(reg) vendor_ebx, ebx_out = out(reg) vendor_ebx,

BIN
rust-kernel.iso Archivo normal

Archivo binario no mostrado.

Ver fichero

@@ -1,28 +1,21 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
//! Rust Kernel //! Rust Kernel Library
//! //!
//! A modern kernel implementation in Rust, inspired by the Linux kernel //! A modern kernel implementation in Rust, inspired by the Linux kernel
//! and utilizing the Rust for Linux infrastructure. //! and utilizing the Rust for Linux infrastructure.
#![no_std] #![no_std]
#![no_main]
extern crate kernel; extern crate kernel;
// Re-export the kernel crate // Re-export the kernel crate
pub use kernel::*; pub use kernel::*;
/// Main kernel entry point
#[no_mangle]
pub extern "C" fn _start() -> ! {
kernel::kernel_main()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]
fn basic_test() { fn basic_test() {
assert_eq!(2 + 2, 4); assert_eq!(2 + 2, 4);
} }
} }

16
src/main.rs Archivo normal
Ver fichero

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
//! Rust Kernel Binary
//!
//! Main binary entry point for the Rust kernel
#![no_std]
#![no_main]
extern crate kernel;
/// Main kernel entry point
#[no_mangle]
pub extern "C" fn _start() -> ! {
kernel::kernel_main()
}