multiboot stage
Este commit está contenido en:
9
.cargo/config.toml
Archivo normal
9
.cargo/config.toml
Archivo normal
@@ -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"]
|
||||
2
Makefile
2
Makefile
@@ -29,7 +29,7 @@ all: kernel modules drivers
|
||||
# Build the core kernel
|
||||
kernel:
|
||||
@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
|
||||
modules: $(RUST_MODULES)
|
||||
|
||||
10
README.md
10
README.md
@@ -92,11 +92,11 @@ make clean && RUSTFLAGS="-Awarnings" make kernel
|
||||
### Basic Execution
|
||||
```bash
|
||||
# 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
|
||||
qemu-system-x86_64 \
|
||||
-kernel target/release/rust-kernel \
|
||||
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
|
||||
-m 128M \
|
||||
-serial stdio \
|
||||
-no-reboot \
|
||||
@@ -107,7 +107,7 @@ qemu-system-x86_64 \
|
||||
```bash
|
||||
# Full-featured QEMU run with debugging
|
||||
qemu-system-x86_64 \
|
||||
-kernel target/release/rust-kernel \
|
||||
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
|
||||
-m 256M \
|
||||
-smp 2 \
|
||||
-serial stdio \
|
||||
@@ -124,13 +124,13 @@ qemu-system-x86_64 \
|
||||
```bash
|
||||
# Run QEMU with GDB server
|
||||
qemu-system-x86_64 \
|
||||
-kernel target/release/rust-kernel \
|
||||
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
|
||||
-s -S \
|
||||
-m 128M \
|
||||
-serial stdio
|
||||
|
||||
# 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) continue
|
||||
```
|
||||
|
||||
7
iso/boot/grub/grub.cfg
Archivo normal
7
iso/boot/grub/grub.cfg
Archivo normal
@@ -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
BIN
iso/boot/rust-kernel
Archivo ejecutable
Archivo binario no mostrado.
@@ -1,6 +1,18 @@
|
||||
[target.x86_64-unknown-none]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlinker.ld",
|
||||
"-C", "link-arg=--no-dynamic-linker",
|
||||
"-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"]
|
||||
|
||||
@@ -10,11 +10,14 @@ license = "GPL-2.0"
|
||||
name = "kernel"
|
||||
crate-type = ["rlib"]
|
||||
|
||||
[[bin]]
|
||||
name = "rust-kernel"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
spin = "0.9"
|
||||
bitflags = "2.4"
|
||||
linked_list_allocator = "0.10"
|
||||
once_cell = { version = "1.19", default-features = false, features = ["critical-section"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// Build assembly files with rustc
|
||||
println!("cargo:rerun-if-changed=src/arch/x86_64/boot.s");
|
||||
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
|
||||
println!("cargo:rustc-link-arg=-Tlinker.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());
|
||||
}
|
||||
|
||||
@@ -3,36 +3,50 @@
|
||||
|
||||
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
|
||||
{
|
||||
/* Start at 1MB (standard kernel load address) */
|
||||
. = 1M;
|
||||
. = 0x100000;
|
||||
|
||||
/* Multiboot header must be early */
|
||||
.multiboot_header : {
|
||||
*(.multiboot_header)
|
||||
}
|
||||
/* Multiboot header MUST be first */
|
||||
.multiboot_header : ALIGN(8) {
|
||||
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 */
|
||||
.rodata : ALIGN(4K) {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
/* Code section */
|
||||
.text : ALIGN(4K) {
|
||||
*(.text .text.*)
|
||||
}
|
||||
} :rodata
|
||||
|
||||
/* Read-write data */
|
||||
.data : ALIGN(4K) {
|
||||
*(.data .data.*)
|
||||
}
|
||||
} :data
|
||||
|
||||
/* BSS section (uninitialized data) */
|
||||
.bss : ALIGN(4K) {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
}
|
||||
} :data
|
||||
|
||||
/* Kernel end marker */
|
||||
__kernel_end = .;
|
||||
|
||||
67
kernel/src/arch/x86_64/boot.S
Archivo normal
67
kernel/src/arch/x86_64/boot.S
Archivo normal
@@ -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
41
kernel/src/boot.s
Archivo normal
@@ -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:
|
||||
@@ -257,25 +257,28 @@ impl DentryCache {
|
||||
}
|
||||
|
||||
/// Global dentry cache
|
||||
static DCACHE: once_cell::sync::Lazy<DentryCache> =
|
||||
once_cell::sync::Lazy::new(|| DentryCache::new());
|
||||
static DCACHE: spin::once::Once<DentryCache> = spin::once::Once::new();
|
||||
|
||||
fn get_dcache() -> &'static DentryCache {
|
||||
DCACHE.call_once(|| DentryCache::new())
|
||||
}
|
||||
|
||||
/// Look up dentry in cache
|
||||
pub fn dcache_lookup(path: &str) -> Option<Arc<Dentry>> {
|
||||
DCACHE.lookup(path)
|
||||
get_dcache().lookup(path)
|
||||
}
|
||||
|
||||
/// Insert dentry into cache
|
||||
pub fn dcache_insert(path: String, dentry: Arc<Dentry>) {
|
||||
DCACHE.insert(path, dentry);
|
||||
get_dcache().insert(path, dentry);
|
||||
}
|
||||
|
||||
/// Remove dentry from cache
|
||||
pub fn dcache_remove(path: &str) -> Option<Arc<Dentry>> {
|
||||
DCACHE.remove(path)
|
||||
get_dcache().remove(path)
|
||||
}
|
||||
|
||||
/// Prune dentry cache
|
||||
pub fn dcache_prune() {
|
||||
DCACHE.prune();
|
||||
get_dcache().prune();
|
||||
}
|
||||
|
||||
@@ -194,12 +194,15 @@ impl MountNamespace {
|
||||
}
|
||||
|
||||
/// Global mount namespace
|
||||
static INIT_MNT_NS: once_cell::sync::Lazy<Mutex<MountNamespace>> =
|
||||
once_cell::sync::Lazy::new(|| Mutex::new(MountNamespace::new(1)));
|
||||
static INIT_MNT_NS: spin::once::Once<Mutex<MountNamespace>> = spin::once::Once::new();
|
||||
|
||||
fn get_init_mnt_ns() -> &'static Mutex<MountNamespace> {
|
||||
INIT_MNT_NS.call_once(|| Mutex::new(MountNamespace::new(1)))
|
||||
}
|
||||
|
||||
/// Get the init mount namespace
|
||||
pub fn get_init_ns() -> &'static Mutex<MountNamespace> {
|
||||
&INIT_MNT_NS
|
||||
get_init_mnt_ns()
|
||||
}
|
||||
|
||||
/// Mount a filesystem
|
||||
|
||||
87
kernel/src/main.rs
Archivo normal
87
kernel/src/main.rs
Archivo normal
@@ -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
16
kernel/src/multiboot.s
Archivo normal
@@ -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
41
kernel/src/simple_boot.s
Archivo normal
@@ -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:
|
||||
@@ -69,7 +69,7 @@ impl CpuInfo {
|
||||
unsafe {
|
||||
asm!("mov {ebx_save}, rbx",
|
||||
"cpuid",
|
||||
"mov {ebx_out}, ebx",
|
||||
"mov {ebx_out:e}, ebx",
|
||||
"mov rbx, {ebx_save}",
|
||||
ebx_save = out(reg) _,
|
||||
ebx_out = out(reg) ebx,
|
||||
@@ -144,7 +144,7 @@ impl CpuInfo {
|
||||
|
||||
asm!("mov {ebx_save}, rbx",
|
||||
"cpuid",
|
||||
"mov {ebx_out}, ebx",
|
||||
"mov {ebx_out:e}, ebx",
|
||||
"mov rbx, {ebx_save}",
|
||||
ebx_save = out(reg) _,
|
||||
ebx_out = out(reg) vendor_ebx,
|
||||
|
||||
BIN
rust-kernel.iso
Archivo normal
BIN
rust-kernel.iso
Archivo normal
Archivo binario no mostrado.
@@ -1,24 +1,17 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
//! Rust Kernel
|
||||
//! Rust Kernel Library
|
||||
//!
|
||||
//! A modern kernel implementation in Rust, inspired by the Linux kernel
|
||||
//! and utilizing the Rust for Linux infrastructure.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate kernel;
|
||||
|
||||
// Re-export the kernel crate
|
||||
pub use kernel::*;
|
||||
|
||||
/// Main kernel entry point
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
kernel::kernel_main()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
|
||||
16
src/main.rs
Archivo normal
16
src/main.rs
Archivo normal
@@ -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()
|
||||
}
|
||||
Referencia en una nueva incidencia
Block a user