Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-02 01:35:04 +01:00
padre 932310d08c
commit 52ddc25097
Se han modificado 21 ficheros con 715 adiciones y 801 borrados

Ver fichero

@@ -9,6 +9,9 @@ RUST_KERNEL_VERSION := 0.1.0
ARCH ?= x86_64 ARCH ?= x86_64
BUILD_TYPE ?= release BUILD_TYPE ?= release
# Enable unstable features on stable compiler
export RUSTC_BOOTSTRAP := 1
# Cargo configuration # Cargo configuration
CARGO := cargo CARGO := cargo
CARGO_FLAGS := --target-dir target CARGO_FLAGS := --target-dir target
@@ -19,17 +22,40 @@ else
CARGO_FLAGS += --release CARGO_FLAGS += --release
endif endif
# Kernel build command with proper flags
KERNEL_BUILD_CMD := cd kernel && $(CARGO) build $(CARGO_FLAGS) \
--target x86_64-unknown-none \
-Z build-std=core,alloc \
-Z build-std-features=compiler-builtins-mem
# Kernel modules # Kernel modules
RUST_MODULES := $(shell find modules -name "*.rs" -type f) RUST_MODULES := $(shell find modules -name "*.rs" -type f)
DRIVERS := $(shell find drivers -name "*.rs" -type f) DRIVERS := $(shell find drivers -name "*.rs" -type f)
# Binary locations
KERNEL_BIN := kernel/target/x86_64-unknown-none/$(BUILD_TYPE)/rust-kernel
ISO_BOOT := iso/boot/rust-kernel
# Default target # Default target
all: kernel modules drivers all: kernel iso
# 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) --bin rust-kernel --target x86_64-unknown-none $(KERNEL_BUILD_CMD)
@echo "Kernel binary: $(KERNEL_BIN)"
# Create bootable ISO
iso: kernel
@echo "Creating bootable ISO..."
@mkdir -p iso/boot/grub
@cp $(KERNEL_BIN) $(ISO_BOOT)
@if command -v grub-mkrescue >/dev/null 2>&1; then \
grub-mkrescue -o rust-kernel.iso iso && \
echo "ISO created: rust-kernel.iso"; \
else \
echo "Warning: grub-mkrescue not found. Install grub-common and xorriso."; \
fi
# Build kernel modules # Build kernel modules
modules: $(RUST_MODULES) modules: $(RUST_MODULES)
@@ -41,10 +67,23 @@ drivers: $(DRIVERS)
@echo "Building drivers" @echo "Building drivers"
cd drivers && $(CARGO) build $(CARGO_FLAGS) cd drivers && $(CARGO) build $(CARGO_FLAGS)
# Run in QEMU
run: iso
@echo "Starting kernel in QEMU..."
@echo "Press Ctrl+C to exit."
qemu-system-x86_64 -m 512M -cdrom rust-kernel.iso -serial stdio -no-reboot
# Quick test run with timeout
test-run: iso
@echo "Testing kernel in QEMU (10 second timeout)..."
timeout 10s qemu-system-x86_64 -m 512M -cdrom rust-kernel.iso -serial stdio -no-reboot || true
# Clean build artifacts # Clean build artifacts
clean: clean:
$(CARGO) clean $(CARGO) clean
cd kernel && $(CARGO) clean
rm -rf target/ rm -rf target/
rm -f rust-kernel.iso
# Run tests # Run tests
test: test:
@@ -75,4 +114,4 @@ test-kernel: kernel
install: install:
@echo "Install target not implemented yet" @echo "Install target not implemented yet"
.PHONY: all kernel modules drivers clean test fmt-check fmt clippy doc test-kernel install .PHONY: all kernel iso modules drivers run test-run clean test fmt-check fmt clippy doc test-kernel install

102
README.md
Ver fichero

@@ -2,6 +2,19 @@
A modern, feature-complete x86_64 kernel written in Rust with advanced scheduling, memory management, IPC, performance monitoring, and comprehensive system administration capabilities. A modern, feature-complete x86_64 kernel written in Rust with advanced scheduling, memory management, IPC, performance monitoring, and comprehensive system administration capabilities.
## 🎯 **Quick Start**
```bash
# Build the kernel and create bootable ISO
make iso
# Run in QEMU
make run
# Or quick test (10 second timeout)
make test-run
```
## 🚀 **Current Status: FULLY FUNCTIONAL** ## 🚀 **Current Status: FULLY FUNCTIONAL**
This kernel is now **production-ready** with all major subsystems implemented and thoroughly tested. It includes advanced features typically found in modern operating systems. This kernel is now **production-ready** with all major subsystems implemented and thoroughly tested. It includes advanced features typically found in modern operating systems.
@@ -36,14 +49,13 @@ This kernel is now **production-ready** with all major subsystems implemented an
### Prerequisites ### Prerequisites
```bash ```bash
# Install Rust nightly toolchain # Install Rust (stable or nightly)
rustup install nightly curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default nightly
# Install required tools # Install required tools
sudo apt-get install nasm make qemu-system-x86 sudo apt-get install nasm make qemu-system-x86 grub-common xorriso
# OR on macOS: # OR on macOS:
brew install nasm make qemu brew install nasm make qemu grub xorriso
# Add Rust bare metal target # Add Rust bare metal target
rustup target add x86_64-unknown-none rustup target add x86_64-unknown-none
@@ -53,14 +65,12 @@ rustup target add x86_64-unknown-none
#### 1. **Quick Build (Recommended)** #### 1. **Quick Build (Recommended)**
```bash ```bash
# Clean debug build # Build kernel using Makefile
RUSTFLAGS="-Awarnings" cargo check make kernel
# Release build with optimizations # Or build with cargo directly
RUSTFLAGS="-Awarnings" cargo build --release cd kernel
cargo build --release --target x86_64-unknown-none -Z build-std=core,alloc
# Build kernel binary
RUSTFLAGS="-Awarnings" make kernel
``` ```
#### 2. **Comprehensive Build & Test** #### 2. **Comprehensive Build & Test**
@@ -69,13 +79,16 @@ RUSTFLAGS="-Awarnings" make kernel
./build_and_test.sh ./build_and_test.sh
``` ```
#### 3. **Debug Build** #### 3. **Create Bootable ISO**
```bash ```bash
# Debug build with symbols # Build kernel binary
cargo build make kernel
# Debug kernel binary # Copy to ISO directory
make kernel-debug cp kernel/target/x86_64-unknown-none/release/rust-kernel iso/boot/
# Create ISO with GRUB
grub-mkrescue -o rust-kernel.iso iso
``` ```
#### 4. **Clean Build** #### 4. **Clean Build**
@@ -84,50 +97,49 @@ make kernel-debug
make clean make clean
# Clean and rebuild # Clean and rebuild
make clean && RUSTFLAGS="-Awarnings" make kernel make clean && make kernel
``` ```
## 🚀 **Running with QEMU** ## 🚀 **Running with QEMU**
### Basic Execution ### Basic Execution
```bash ```bash
# Run kernel in QEMU (basic) # Run kernel from ISO (recommended)
qemu-system-x86_64 -kernel kernel/target/x86_64-unknown-none/release/rust-kernel qemu-system-x86_64 -m 512M -cdrom rust-kernel.iso -serial stdio -no-reboot
# Run with more memory and serial output # Quick test with timeout
qemu-system-x86_64 \ timeout 10s qemu-system-x86_64 -m 512M -cdrom rust-kernel.iso -serial stdio -no-reboot
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \
-m 128M \
-serial stdio \
-no-reboot \
-no-shutdown
``` ```
### Advanced QEMU Configuration ### Advanced QEMU Configuration
```bash ```bash
# Full-featured QEMU run with debugging # Run with more debugging output
qemu-system-x86_64 \ qemu-system-x86_64 \
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \ -m 512M \
-m 256M \ -cdrom rust-kernel.iso \
-smp 2 \
-serial stdio \ -serial stdio \
-monitor tcp:localhost:4444,server,nowait \
-netdev user,id=net0 \
-device rtl8139,netdev=net0 \
-boot menu=on \
-no-reboot \ -no-reboot \
-no-shutdown \ -no-shutdown \
-d guest_errors -d guest_errors,int
# Run with VGA output and serial console
qemu-system-x86_64 \
-m 512M \
-cdrom rust-kernel.iso \
-serial stdio \
-vga std \
-no-reboot
``` ```
### Debugging with GDB ### Debugging with GDB
```bash ```bash
# Run QEMU with GDB server # Run QEMU with GDB server
qemu-system-x86_64 \ qemu-system-x86_64 \
-kernel kernel/target/x86_64-unknown-none/release/rust-kernel \ -m 512M \
-cdrom rust-kernel.iso \
-s -S \ -s -S \
-m 128M \ -serial stdio \
-serial stdio -no-reboot
# In another terminal, connect GDB # In another terminal, connect GDB
gdb kernel/target/x86_64-unknown-none/release/rust-kernel gdb kernel/target/x86_64-unknown-none/release/rust-kernel
@@ -135,6 +147,18 @@ gdb kernel/target/x86_64-unknown-none/release/rust-kernel
(gdb) continue (gdb) continue
``` ```
### Common QEMU Options
```bash
-m 512M # Allocate 512MB of RAM
-cdrom file.iso # Boot from ISO image
-serial stdio # Redirect serial output to terminal
-no-reboot # Exit instead of rebooting on triple fault
-no-shutdown # Don't exit QEMU on guest shutdown
-d guest_errors # Enable debug output for guest errors
-s # Start GDB server on port 1234
-S # Pause CPU at startup (for debugging)
```
### QEMU Key Combinations ### QEMU Key Combinations
- `Ctrl+A, X` - Exit QEMU - `Ctrl+A, X` - Exit QEMU
- `Ctrl+A, C` - Switch to QEMU monitor - `Ctrl+A, C` - Switch to QEMU monitor

Ver fichero

@@ -110,9 +110,9 @@ print_success "Release build completed successfully"
# Build with make (if Makefile exists) # Build with make (if Makefile exists)
if [ -f "Makefile" ]; then if [ -f "Makefile" ]; then
print_status "Building with Makefile..." print_status "Building kernel binary with Makefile..."
run_with_status "make kernel" "Makefile build" run_with_status "make kernel" "Makefile kernel build"
print_success "Makefile build completed successfully" print_success "Kernel binary build completed successfully"
else else
print_warning "Makefile not found, skipping make build" print_warning "Makefile not found, skipping make build"
fi fi
@@ -123,18 +123,22 @@ run_with_status "cargo doc --no-deps" "Documentation generation"
print_success "Documentation generated successfully" print_success "Documentation generated successfully"
# Check binary size # Check binary size
if [ -f "target/release/deps/kernel-"*.rlib ]; then if [ -f "kernel/target/x86_64-unknown-none/release/rust-kernel" ]; then
KERNEL_SIZE=$(du -h target/release/deps/kernel-*.rlib | cut -f1) KERNEL_SIZE=$(du -h kernel/target/x86_64-unknown-none/release/rust-kernel | cut -f1)
print_status "Kernel library size: $KERNEL_SIZE" print_status "Kernel binary size: $KERNEL_SIZE"
fi fi
# Create ISO # Create ISO
print_status "Creating bootable ISO..." print_status "Creating bootable ISO..."
cp target/x86_64-unknown-none/release/rust-kernel iso/boot/rust-kernel if [ -f "kernel/target/x86_64-unknown-none/release/rust-kernel" ]; then
if grub-mkrescue -o rust-kernel.iso iso > /dev/null 2>&1; then cp kernel/target/x86_64-unknown-none/release/rust-kernel iso/boot/rust-kernel
print_success "ISO created: rust-kernel.iso" if grub-mkrescue -o rust-kernel.iso iso > /dev/null 2>&1; then
print_success "ISO created: rust-kernel.iso"
else
print_warning "Failed to create ISO (grub-mkrescue not found or failed)"
fi
else else
print_warning "Failed to create ISO (grub-mkrescue not found or failed)" print_warning "Kernel binary not found, skipping ISO creation"
fi fi
# Create build report # Create build report

Ver fichero

@@ -2,15 +2,15 @@
//! RTL8139 Network Driver //! RTL8139 Network Driver
use kernel::driver::{Driver, PciDriver, PciDeviceId, PciDevice};
use kernel::error::{Error, Result};
use kernel::memory::{allocator, vmalloc};
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::string::ToString; use alloc::string::ToString;
use core::ptr;
use kernel::driver::{Driver, PciDevice, PciDeviceId, PciDriver};
use kernel::error::{Error, Result};
use kernel::memory::{allocator, vmalloc};
use kernel::network::NetworkInterface; use kernel::network::NetworkInterface;
use kernel::pci_driver; use kernel::pci_driver;
use kernel::types::PhysAddr; use kernel::types::PhysAddr;
use core::ptr;
const REG_MAC0: u16 = 0x00; const REG_MAC0: u16 = 0x00;
const REG_MAR0: u16 = 0x08; const REG_MAR0: u16 = 0x08;
@@ -33,252 +33,270 @@ const IMR_TOK: u16 = 1 << 2;
const RCR_AAP: u32 = 1 << 0; // AcceptAllPackets const RCR_AAP: u32 = 1 << 0; // AcceptAllPackets
const RCR_APM: u32 = 1 << 1; // AcceptPhysicalMatch const RCR_APM: u32 = 1 << 1; // AcceptPhysicalMatch
const RCR_AM: u32 = 1 << 2; // AcceptMulticast const RCR_AM: u32 = 1 << 2; // AcceptMulticast
const RCR_AB: u32 = 1 << 3; // AcceptBroadcast const RCR_AB: u32 = 1 << 3; // AcceptBroadcast
const RCR_WRAP: u32 = 1 << 7; const RCR_WRAP: u32 = 1 << 7;
#[derive(Debug)] #[derive(Debug)]
struct Rtl8139Device { struct Rtl8139Device {
mmio_base: usize, mmio_base: usize,
mac: [u8; 6], mac: [u8; 6],
rx_buffer: *mut u8, rx_buffer: *mut u8,
tx_buffer: *mut u8, tx_buffer: *mut u8,
rx_buffer_pos: usize, rx_buffer_pos: usize,
tx_cur: usize, tx_cur: usize,
up: bool, up: bool,
} }
impl Rtl8139Device { impl Rtl8139Device {
fn new(mmio_base: usize) -> Self { fn new(mmio_base: usize) -> Self {
Self { Self {
mmio_base, mmio_base,
mac: [0; 6], mac: [0; 6],
rx_buffer: ptr::null_mut(), rx_buffer: ptr::null_mut(),
tx_buffer: ptr::null_mut(), tx_buffer: ptr::null_mut(),
rx_buffer_pos: 0, rx_buffer_pos: 0,
tx_cur: 0, tx_cur: 0,
up: false, up: false,
} }
} }
fn read8(&self, offset: u16) -> u8 { fn read8(&self, offset: u16) -> u8 {
unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u8) } unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u8) }
} }
fn write8(&self, offset: u16, val: u8) { fn write8(&self, offset: u16, val: u8) {
unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u8, val) } unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u8, val) }
} }
fn read16(&self, offset: u16) -> u16 { fn read16(&self, offset: u16) -> u16 {
unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u16) } unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u16) }
} }
fn write16(&self, offset: u16, val: u16) { fn write16(&self, offset: u16, val: u16) {
unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u16, val) } unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u16, val) }
} }
fn read32(&self, offset: u16) -> u32 { fn read32(&self, offset: u16) -> u32 {
unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u32) } unsafe { ptr::read_volatile((self.mmio_base + offset as usize) as *const u32) }
} }
fn write32(&self, offset: u16, val: u32) { fn write32(&self, offset: u16, val: u32) {
unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u32, val) } unsafe { ptr::write_volatile((self.mmio_base + offset as usize) as *mut u32, val) }
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Rtl8139Driver; pub struct Rtl8139Driver;
impl NetworkInterface for Rtl8139Device { impl NetworkInterface for Rtl8139Device {
fn name(&self) -> &str { fn name(&self) -> &str {
"eth0" // Or some other name "eth0" // Or some other name
} }
fn ip_address(&self) -> Option<kernel::network::Ipv4Address> { fn ip_address(&self) -> Option<kernel::network::Ipv4Address> {
None // This will be set by the network stack None // This will be set by the network stack
} }
fn mac_address(&self) -> kernel::network::MacAddress { fn mac_address(&self) -> kernel::network::MacAddress {
kernel::network::MacAddress::new(self.mac) kernel::network::MacAddress::new(self.mac)
} }
fn mtu(&self) -> u16 { fn mtu(&self) -> u16 {
1500 1500
} }
fn is_up(&self) -> bool { fn is_up(&self) -> bool {
self.up self.up
} }
fn send_packet(&mut self, buffer: &kernel::network::NetworkBuffer) -> Result<()> { fn send_packet(&mut self, buffer: &kernel::network::NetworkBuffer) -> Result<()> {
let tx_status_reg = REG_TX_STATUS_0 + (self.tx_cur * 4) as u16; let tx_status_reg = REG_TX_STATUS_0 + (self.tx_cur * 4) as u16;
// The transmit buffers are laid out contiguously in memory after the receive buffer. // The transmit buffers are laid out contiguously in memory after the receive buffer.
let tx_buffer = unsafe { self.tx_buffer.add(self.tx_cur * 2048) }; let tx_buffer = unsafe { self.tx_buffer.add(self.tx_cur * 2048) };
// Copy the packet data to the transmit buffer. // Copy the packet data to the transmit buffer.
unsafe { unsafe {
ptr::copy_nonoverlapping(buffer.data().as_ptr(), tx_buffer, buffer.len()); ptr::copy_nonoverlapping(buffer.data().as_ptr(), tx_buffer, buffer.len());
} }
// Write the buffer address to the transmit start register. // Write the buffer address to the transmit start register.
let dma_addr = PhysAddr::new(tx_buffer as usize); let dma_addr = PhysAddr::new(tx_buffer as usize);
self.write32(REG_TX_START_0 + (self.tx_cur * 4) as u16, dma_addr.as_usize() as u32); self.write32(
REG_TX_START_0 + (self.tx_cur * 4) as u16,
dma_addr.as_usize() as u32,
);
// Write the packet size and flags to the transmit status register. // Write the packet size and flags to the transmit status register.
self.write32(tx_status_reg, buffer.len() as u32); self.write32(tx_status_reg, buffer.len() as u32);
self.tx_cur = (self.tx_cur + 1) % 4; self.tx_cur = (self.tx_cur + 1) % 4;
Ok(()) Ok(())
} }
fn receive_packet(&mut self) -> Result<Option<kernel::network::NetworkBuffer>> { fn receive_packet(&mut self) -> Result<Option<kernel::network::NetworkBuffer>> {
let isr = self.read16(REG_ISR); let isr = self.read16(REG_ISR);
if (isr & IMR_ROK) == 0 { if (isr & IMR_ROK) == 0 {
return Ok(None); return Ok(None);
} }
// Acknowledge the interrupt // Acknowledge the interrupt
self.write16(REG_ISR, IMR_ROK); self.write16(REG_ISR, IMR_ROK);
let rx_ptr = self.rx_buffer as *const u8; let rx_ptr = self.rx_buffer as *const u8;
let _header = unsafe { ptr::read_unaligned(rx_ptr.add(self.rx_buffer_pos) as *const u16) }; let _header = unsafe {
let len = unsafe { ptr::read_unaligned(rx_ptr.add(self.rx_buffer_pos + 2) as *const u16) }; ptr::read_unaligned(rx_ptr.add(self.rx_buffer_pos) as *const u16)
};
let len = unsafe {
ptr::read_unaligned(rx_ptr.add(self.rx_buffer_pos + 2) as *const u16)
};
let data_ptr = unsafe { rx_ptr.add(self.rx_buffer_pos + 4) }; let data_ptr = unsafe { rx_ptr.add(self.rx_buffer_pos + 4) };
let data = unsafe { core::slice::from_raw_parts(data_ptr, len as usize) }; let data = unsafe { core::slice::from_raw_parts(data_ptr, len as usize) };
// The data includes the Ethernet header. // The data includes the Ethernet header.
if data.len() < 14 { if data.len() < 14 {
return Err(Error::InvalidArgument); return Err(Error::InvalidArgument);
} }
let dest_mac = kernel::network::MacAddress::new([data[0], data[1], data[2], data[3], data[4], data[5]]); let dest_mac = kernel::network::MacAddress::new([
let src_mac = kernel::network::MacAddress::new([data[6], data[7], data[8], data[9], data[10], data[11]]); data[0], data[1], data[2], data[3], data[4], data[5],
let ethertype = u16::from_be_bytes([data[12], data[13]]); ]);
let src_mac = kernel::network::MacAddress::new([
data[6], data[7], data[8], data[9], data[10], data[11],
]);
let ethertype = u16::from_be_bytes([data[12], data[13]]);
let protocol = match ethertype { let protocol = match ethertype {
0x0800 => kernel::network::ProtocolType::IPv4, 0x0800 => kernel::network::ProtocolType::IPv4,
0x0806 => kernel::network::ProtocolType::ARP, 0x0806 => kernel::network::ProtocolType::ARP,
_ => return Ok(None), // Unknown protocol _ => return Ok(None), // Unknown protocol
}; };
let mut buffer = kernel::network::NetworkBuffer::from_data(data[14..].to_vec()); let mut buffer = kernel::network::NetworkBuffer::from_data(data[14..].to_vec());
buffer.set_protocol(protocol); buffer.set_protocol(protocol);
buffer.set_mac_addresses(src_mac, dest_mac); buffer.set_mac_addresses(src_mac, dest_mac);
self.rx_buffer_pos = (self.rx_buffer_pos + len as usize + 4 + 3) & !3; self.rx_buffer_pos = (self.rx_buffer_pos + len as usize + 4 + 3) & !3;
if self.rx_buffer_pos > 8192 { if self.rx_buffer_pos > 8192 {
self.rx_buffer_pos -= 8192; self.rx_buffer_pos -= 8192;
} }
self.write16(0x38, self.rx_buffer_pos as u16 - 16); self.write16(0x38, self.rx_buffer_pos as u16 - 16);
Ok(Some(buffer)) Ok(Some(buffer))
} }
fn set_up(&mut self, up: bool) -> Result<()> { fn set_up(&mut self, up: bool) -> Result<()> {
if up { if up {
self.write8(REG_CMD, CMD_RX_ENB | CMD_TX_ENB); self.write8(REG_CMD, CMD_RX_ENB | CMD_TX_ENB);
} else { } else {
self.write8(REG_CMD, 0x00); self.write8(REG_CMD, 0x00);
} }
self.up = up; self.up = up;
Ok(()) Ok(())
} }
fn set_mac_address(&mut self, _mac: kernel::network::MacAddress) -> Result<()> { fn set_mac_address(&mut self, _mac: kernel::network::MacAddress) -> Result<()> {
// Not supported // Not supported
Err(Error::NotSupported) Err(Error::NotSupported)
} }
} }
impl Driver for Rtl8139Driver { impl Driver for Rtl8139Driver {
fn name(&self) -> &str { fn name(&self) -> &str {
"rtl8139" "rtl8139"
} }
fn probe(&self, _device: &mut kernel::device::Device) -> Result<()> { fn probe(&self, _device: &mut kernel::device::Device) -> Result<()> {
// This will be called for a generic device. // This will be called for a generic device.
// We are a PCI driver, so we'll do our work in pci_probe. // We are a PCI driver, so we'll do our work in pci_probe.
Ok(()) Ok(())
} }
fn remove(&self, _device: &mut kernel::device::Device) -> Result<()> { fn remove(&self, _device: &mut kernel::device::Device) -> Result<()> {
Ok(()) Ok(())
} }
} }
impl PciDriver for Rtl8139Driver { impl PciDriver for Rtl8139Driver {
fn pci_ids(&self) -> &[PciDeviceId] { fn pci_ids(&self) -> &[PciDeviceId] {
&[PciDeviceId::new(0x10EC, 0x8139)] &[PciDeviceId::new(0x10EC, 0x8139)]
} }
fn pci_probe(&self, pci_dev: &mut PciDevice) -> Result<()> { fn pci_probe(&self, pci_dev: &mut PciDevice) -> Result<()> {
kernel::info!("Probing rtl8139 device"); kernel::info!("Probing rtl8139 device");
let bar0 = pci_dev.bars[0]; let bar0 = pci_dev.bars[0];
if bar0.is_io() { if bar0.is_io() {
return Err(Error::NotSupported); return Err(Error::NotSupported);
} }
let mmio_base = bar0.address; let mmio_base = bar0.address;
kernel::info!("RTL8139 MMIO base: {:#x}", mmio_base); kernel::info!("RTL8139 MMIO base: {:#x}", mmio_base);
let mmio_virt = vmalloc::vmap_phys(PhysAddr::new(mmio_base as usize), 0x100)?; let mmio_virt = vmalloc::vmap_phys(PhysAddr::new(mmio_base as usize), 0x100)?;
kernel::info!("RTL8139 MMIO mapped to: {:#x}", mmio_virt.as_usize()); kernel::info!("RTL8139 MMIO mapped to: {:#x}", mmio_virt.as_usize());
let mut device = Rtl8139Device::new(mmio_virt.as_usize()); let mut device = Rtl8139Device::new(mmio_virt.as_usize());
// Power on // Power on
device.write8(REG_CONFIG1, 0x00); device.write8(REG_CONFIG1, 0x00);
// Reset // Reset
device.write8(REG_CMD, CMD_RESET); device.write8(REG_CMD, CMD_RESET);
while (device.read8(REG_CMD) & CMD_RESET) != 0 {} while (device.read8(REG_CMD) & CMD_RESET) != 0 {}
// Read MAC address // Read MAC address
for i in 0..6 { for i in 0..6 {
device.mac[i] = device.read8(REG_MAC0 + i as u16); device.mac[i] = device.read8(REG_MAC0 + i as u16);
} }
kernel::info!("RTL8139 MAC address: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", kernel::info!(
device.mac[0], device.mac[1], device.mac[2], device.mac[3], device.mac[4], device.mac[5]); "RTL8139 MAC address: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
device.mac[0],
device.mac[1],
device.mac[2],
device.mac[3],
device.mac[4],
device.mac[5]
);
// Allocate DMA buffers // Allocate DMA buffers
let dma_pfn = allocator::alloc_pages(2, allocator::GfpFlags::DMA)?; let dma_pfn = allocator::alloc_pages(2, allocator::GfpFlags::DMA)?;
let dma_addr = dma_pfn.to_phys_addr(); let dma_addr = dma_pfn.to_phys_addr();
device.rx_buffer = dma_addr.as_usize() as *mut u8; device.rx_buffer = dma_addr.as_usize() as *mut u8;
device.tx_buffer = (dma_addr.as_usize() + 8192) as *mut u8; device.tx_buffer = (dma_addr.as_usize() + 8192) as *mut u8;
// Initialize receive buffer // Initialize receive buffer
device.write32(REG_RBSTART, dma_addr.as_usize() as u32); device.write32(REG_RBSTART, dma_addr.as_usize() as u32);
// Initialize transmit buffers // Initialize transmit buffers
for i in 0..4 { for i in 0..4 {
// Nothing to do here yet, we will set the buffer address when we send a packet. // Nothing to do here yet, we will set the buffer address when we send a packet.
} }
// Enable RX and TX // Enable RX and TX
device.write8(REG_CMD, CMD_RX_ENB | CMD_TX_ENB); device.write8(REG_CMD, CMD_RX_ENB | CMD_TX_ENB);
// Set RCR // Set RCR
device.write32(REG_RCR, RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_WRAP); device.write32(REG_RCR, RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_WRAP);
// Enable interrupts // Enable interrupts
device.write16(REG_IMR, IMR_TOK | IMR_ROK); device.write16(REG_IMR, IMR_TOK | IMR_ROK);
kernel::info!("RTL8139 device initialized"); kernel::info!("RTL8139 device initialized");
let mut boxed_device = Box::new(device); let mut boxed_device = Box::new(device);
boxed_device.set_up(true)?; boxed_device.set_up(true)?;
kernel::network::add_network_interface("eth0".to_string(), boxed_device)?; kernel::network::add_network_interface("eth0".to_string(), boxed_device)?;
Ok(()) Ok(())
} }
fn pci_remove(&self, _pci_dev: &mut PciDevice) -> Result<()> { fn pci_remove(&self, _pci_dev: &mut PciDevice) -> Result<()> {
Ok(()) Ok(())
} }
} }
pci_driver!(Rtl8139Driver); pci_driver!(Rtl8139Driver);

Ver fichero

@@ -10,6 +10,10 @@ 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"

Ver fichero

@@ -460,14 +460,14 @@ pub fn profile_function(function_name: &str) -> Result<ProfileGuard> {
#[macro_export] #[macro_export]
macro_rules! perf_counter { macro_rules! perf_counter {
($counter_type:expr, $value:expr) => { ($counter_type:expr, $value:expr) => {
crate::advanced_perf::record_event($counter_type, $value); $crate::advanced_perf::record_event($counter_type, $value);
}; };
} }
#[macro_export] #[macro_export]
macro_rules! perf_profile { macro_rules! perf_profile {
($name:expr, $code:block) => {{ ($name:expr, $code:block) => {{
let _guard = crate::advanced_perf::profile($name.to_string()); let _guard = $crate::advanced_perf::profile($name.to_string());
$code $code
}}; }};
} }

Ver fichero

@@ -2,7 +2,6 @@
//! Interrupt Descriptor Table (IDT) for x86_64 //! Interrupt Descriptor Table (IDT) for x86_64
use core::arch::asm;
use core::mem::size_of; use core::mem::size_of;
use crate::arch::x86_64::port::outb; use crate::arch::x86_64::port::outb;

Ver fichero

@@ -8,90 +8,90 @@ use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArpOperation { pub enum ArpOperation {
Request = 1, Request = 1,
Reply = 2, Reply = 2,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C, packed)] #[repr(C, packed)]
pub struct ArpPacket { pub struct ArpPacket {
pub htype: [u8; 2], pub htype: [u8; 2],
pub ptype: [u8; 2], pub ptype: [u8; 2],
pub hlen: u8, pub hlen: u8,
pub plen: u8, pub plen: u8,
pub oper: [u8; 2], pub oper: [u8; 2],
pub sha: MacAddress, pub sha: MacAddress,
pub spa: Ipv4Address, pub spa: Ipv4Address,
pub tha: MacAddress, pub tha: MacAddress,
pub tpa: Ipv4Address, pub tpa: Ipv4Address,
} }
impl ArpPacket { impl ArpPacket {
pub fn new( pub fn new(
oper: ArpOperation, oper: ArpOperation,
sha: MacAddress, sha: MacAddress,
spa: Ipv4Address, spa: Ipv4Address,
tha: MacAddress, tha: MacAddress,
tpa: Ipv4Address, tpa: Ipv4Address,
) -> Self { ) -> Self {
Self { Self {
htype: (1 as u16).to_be_bytes(), // Ethernet htype: (1 as u16).to_be_bytes(), // Ethernet
ptype: (0x0800 as u16).to_be_bytes(), // IPv4 ptype: (0x0800 as u16).to_be_bytes(), // IPv4
hlen: 6, hlen: 6,
plen: 4, plen: 4,
oper: (oper as u16).to_be_bytes(), oper: (oper as u16).to_be_bytes(),
sha, sha,
spa, spa,
tha, tha,
tpa, tpa,
} }
} }
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(28); let mut bytes = Vec::with_capacity(28);
bytes.extend_from_slice(&self.htype); bytes.extend_from_slice(&self.htype);
bytes.extend_from_slice(&self.ptype); bytes.extend_from_slice(&self.ptype);
bytes.push(self.hlen); bytes.push(self.hlen);
bytes.push(self.plen); bytes.push(self.plen);
bytes.extend_from_slice(&self.oper); bytes.extend_from_slice(&self.oper);
bytes.extend_from_slice(self.sha.bytes()); bytes.extend_from_slice(self.sha.bytes());
bytes.extend_from_slice(self.spa.bytes()); bytes.extend_from_slice(self.spa.bytes());
bytes.extend_from_slice(self.tha.bytes()); bytes.extend_from_slice(self.tha.bytes());
bytes.extend_from_slice(self.tpa.bytes()); bytes.extend_from_slice(self.tpa.bytes());
bytes bytes
} }
pub fn from_bytes(bytes: &[u8]) -> Result<Self> { pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
if bytes.len() < 28 { if bytes.len() < 28 {
return Err(Error::InvalidArgument); return Err(Error::InvalidArgument);
} }
let mut htype = [0u8; 2]; let mut htype = [0u8; 2];
htype.copy_from_slice(&bytes[0..2]); htype.copy_from_slice(&bytes[0..2]);
let mut ptype = [0u8; 2]; let mut ptype = [0u8; 2];
ptype.copy_from_slice(&bytes[2..4]); ptype.copy_from_slice(&bytes[2..4]);
let hlen = bytes[4]; let hlen = bytes[4];
let plen = bytes[5]; let plen = bytes[5];
let mut oper = [0u8; 2]; let mut oper = [0u8; 2];
oper.copy_from_slice(&bytes[6..8]); oper.copy_from_slice(&bytes[6..8]);
let mut sha_bytes = [0u8; 6]; let mut sha_bytes = [0u8; 6];
sha_bytes.copy_from_slice(&bytes[8..14]); sha_bytes.copy_from_slice(&bytes[8..14]);
let mut spa_bytes = [0u8; 4]; let mut spa_bytes = [0u8; 4];
spa_bytes.copy_from_slice(&bytes[14..18]); spa_bytes.copy_from_slice(&bytes[14..18]);
let mut tha_bytes = [0u8; 6]; let mut tha_bytes = [0u8; 6];
tha_bytes.copy_from_slice(&bytes[18..24]); tha_bytes.copy_from_slice(&bytes[18..24]);
let mut tpa_bytes = [0u8; 4]; let mut tpa_bytes = [0u8; 4];
tpa_bytes.copy_from_slice(&bytes[24..28]); tpa_bytes.copy_from_slice(&bytes[24..28]);
Ok(Self { Ok(Self {
htype, htype,
ptype, ptype,
hlen, hlen,
plen, plen,
oper, oper,
sha: MacAddress::new(sha_bytes), sha: MacAddress::new(sha_bytes),
spa: Ipv4Address::from_bytes(spa_bytes), spa: Ipv4Address::from_bytes(spa_bytes),
tha: MacAddress::new(tha_bytes), tha: MacAddress::new(tha_bytes),
tpa: Ipv4Address::from_bytes(tpa_bytes), tpa: Ipv4Address::from_bytes(tpa_bytes),
}) })
} }
} }

Ver fichero

@@ -9,7 +9,7 @@ use alloc::{
}; };
use crate::error::Result; use crate::error::Result;
use crate::time::{get_jiffies, monotonic_time, TimeSpec}; use crate::time::{get_jiffies, monotonic_time};
use crate::{info, warn}; use crate::{info, warn};
/// Benchmark result /// Benchmark result

Ver fichero

@@ -149,15 +149,26 @@ pub mod multiboot {
/// Parse multiboot2 information and initialize memory management /// Parse multiboot2 information and initialize memory management
pub fn init_memory_from_multiboot(multiboot_addr: usize) -> Result<()> { pub fn init_memory_from_multiboot(multiboot_addr: usize) -> Result<()> {
crate::println!("Parsing multiboot information at 0x{:x}", multiboot_addr); crate::console::write_str("Parsing multiboot\n");
// Validate multiboot address is in identity-mapped range (0-1GB)
if multiboot_addr >= 0x40000000 {
// 1GB
crate::console::write_str("ERROR: multiboot addr out of range\n");
return Err(crate::error::Error::InvalidArgument);
}
crate::console::write_str("Multiboot addr validated\n");
let multiboot_info = unsafe { &*(multiboot_addr as *const MultibootInfo) }; let multiboot_info = unsafe { &*(multiboot_addr as *const MultibootInfo) };
crate::println!("Multiboot info size: {} bytes", multiboot_info.total_size); crate::console::write_str("Got multiboot info\n");
// Parse memory map from multiboot info // Parse memory map from multiboot info
let mut memory_info = BootMemoryInfo::new(); let mut memory_info = BootMemoryInfo::new();
crate::console::write_str("Created BootMemoryInfo\n");
// For now, assume a basic memory layout if we can't parse multiboot properly // For now, assume a basic memory layout if we can't parse multiboot properly
// This is a fallback to make the kernel bootable // This is a fallback to make the kernel bootable
let default_memory = MemoryMapEntry { let default_memory = MemoryMapEntry {
@@ -167,6 +178,7 @@ pub mod multiboot {
reserved: 0, reserved: 0,
}; };
crate::console::write_str("Adding default memory region\n");
memory_info.add_region(default_memory); memory_info.add_region(default_memory);
// Update global boot info // Update global boot info
@@ -178,29 +190,43 @@ pub mod multiboot {
} }
// Initialize page allocator with available memory // Initialize page allocator with available memory
// Note: Only first 1GB is identity-mapped in boot.s
const MAX_IDENTITY_MAPPED: u64 = 1024 * 1024 * 1024; // 1GB
crate::console::write_str("Processing memory regions\n");
for i in 0..memory_info.region_count { for i in 0..memory_info.region_count {
crate::console::write_str("Region loop iteration\n");
let region = &memory_info.memory_regions[i]; let region = &memory_info.memory_regions[i];
if region.type_ == memory_type::AVAILABLE { if region.type_ == memory_type::AVAILABLE {
let start_pfn = region.base_addr / 4096; let start_addr = region.base_addr;
let end_pfn = (region.base_addr + region.length) / 4096; let end_addr = region.base_addr + region.length;
crate::println!( crate::console::write_str("Available region found\n");
"Adding memory region: 0x{:x}-0x{:x}",
region.base_addr,
region.base_addr + region.length
);
// Clamp to identity-mapped region
let safe_start = start_addr.max(0x100000); // Skip first 1MB (BIOS/kernel)
let safe_end = end_addr.min(MAX_IDENTITY_MAPPED);
crate::console::write_str("Clamped region\n");
if safe_start >= safe_end {
crate::console::write_str("Skipping invalid range\n");
continue; // Skip invalid/unmapped region
}
crate::console::write_str("About to call add_free_range\n");
// Add this memory region to the page allocator // Add this memory region to the page allocator
crate::memory::page::add_free_range( crate::memory::page::add_free_range(
PhysAddr::new(region.base_addr as usize), PhysAddr::new(safe_start as usize),
PhysAddr::new((region.base_addr + region.length) as usize), PhysAddr::new(safe_end as usize),
)?; )?;
crate::console::write_str("Successfully added free range\n");
} }
} }
crate::println!("Memory initialization from multiboot completed"); crate::console::write_str("Memory init completed\n");
crate::println!("Total memory: {} bytes", memory_info.total_memory);
crate::println!("Available memory: {} bytes", memory_info.available_memory);
Ok(()) Ok(())
} }

Ver fichero

@@ -382,7 +382,7 @@ macro_rules! platform_driver {
} }
pub fn pci_config_read(bus: u8, device: u8, function: u8, offset: u8) -> u32 { pub fn pci_config_read(bus: u8, device: u8, function: u8, offset: u8) -> u32 {
crate::hardware::pci_config_read(bus, device, function, offset) crate::hardware::pci_config_read(bus, device, function, offset)
} }
#[macro_export] #[macro_export]

Ver fichero

@@ -6,8 +6,8 @@ use alloc::format;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
use alloc::vec::Vec; use alloc::vec::Vec;
use crate::driver::{PciBar, PciDevice};
use crate::error::Result; use crate::error::Result;
use crate::driver::{PciDevice, PciBar};
/// CPU Information /// CPU Information
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CpuInfo { pub struct CpuInfo {
@@ -180,18 +180,26 @@ pub fn detect_pci_devices() -> Result<Vec<PciDevice>> {
let device_id = let device_id =
(pci_config_read(0, device, function, 0x00) >> 16) as u16; (pci_config_read(0, device, function, 0x00) >> 16) as u16;
let class_info = pci_config_read(0, device, function, 0x08); let class_info = pci_config_read(0, device, function, 0x08);
let revision = (pci_config_read(0, device, function, 0x08) & 0xFF) as u8; let revision =
(pci_config_read(0, device, function, 0x08) & 0xFF) as u8;
let mut bars = [PciBar::new(); 6]; let mut bars = [PciBar::new(); 6];
for i in 0..6 { for i in 0..6 {
let bar_val = pci_config_read(0, device, function, 0x10 + (i * 4)); let bar_val = pci_config_read(
0,
device,
function,
0x10 + (i * 4),
);
if bar_val == 0 { if bar_val == 0 {
continue; continue;
} }
let is_io = bar_val & 1 != 0; let is_io = bar_val & 1 != 0;
if is_io { if is_io {
bars[i as usize].address = (bar_val & 0xFFFFFFFC) as u64; bars[i as usize].address =
(bar_val & 0xFFFFFFFC) as u64;
} else { } else {
bars[i as usize].address = (bar_val & 0xFFFFFFF0) as u64; bars[i as usize].address =
(bar_val & 0xFFFFFFF0) as u64;
} }
bars[i as usize].flags = bar_val & 0xF; bars[i as usize].flags = bar_val & 0xF;
} }
@@ -206,7 +214,7 @@ pub fn detect_pci_devices() -> Result<Vec<PciDevice>> {
revision, revision,
subsystem_vendor: 0, // Not implemented subsystem_vendor: 0, // Not implemented
subsystem_device: 0, // Not implemented subsystem_device: 0, // Not implemented
irq: 0, // Not implemented irq: 0, // Not implemented
bars, bars,
}); });
} }

Ver fichero

@@ -5,14 +5,14 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)] #[repr(u8)]
pub enum IcmpType { pub enum IcmpType {
EchoReply = 0, EchoReply = 0,
EchoRequest = 8, EchoRequest = 8,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)] #[repr(u8)]
pub enum IcmpCode { pub enum IcmpCode {
Echo = 0, Echo = 0,
} }
use alloc::vec::Vec; use alloc::vec::Vec;
@@ -20,21 +20,21 @@ use alloc::vec::Vec;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C, packed)] #[repr(C, packed)]
pub struct IcmpPacket { pub struct IcmpPacket {
pub icmp_type: IcmpType, pub icmp_type: IcmpType,
pub icmp_code: IcmpCode, pub icmp_code: IcmpCode,
pub checksum: u16, pub checksum: u16,
pub identifier: u16, pub identifier: u16,
pub sequence_number: u16, pub sequence_number: u16,
} }
impl IcmpPacket { impl IcmpPacket {
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
bytes.push(self.icmp_type as u8); bytes.push(self.icmp_type as u8);
bytes.push(self.icmp_code as u8); bytes.push(self.icmp_code as u8);
bytes.extend_from_slice(&self.checksum.to_be_bytes()); bytes.extend_from_slice(&self.checksum.to_be_bytes());
bytes.extend_from_slice(&self.identifier.to_be_bytes()); bytes.extend_from_slice(&self.identifier.to_be_bytes());
bytes.extend_from_slice(&self.sequence_number.to_be_bytes()); bytes.extend_from_slice(&self.sequence_number.to_be_bytes());
bytes bytes
} }
} }

Ver fichero

@@ -8,251 +8,44 @@ use crate::{error, info, warn};
/// Early kernel initialization /// Early kernel initialization
pub fn early_init() { pub fn early_init() {
info!("Starting Rust Kernel v{}", crate::VERSION); crate::console::write_str("[+] Early initialization complete\n");
info!("Early initialization phase");
// Initialize basic console output
if let Err(e) = crate::console::init() {
// Can't print error since console isn't initialized yet
loop {}
}
info!("Console initialized");
} }
/// Main kernel initialization /// Main kernel initialization
pub fn main_init() -> ! { pub fn main_init() -> ! {
info!("Main initialization phase"); crate::console::write_str("\n");
crate::console::write_str("========================================\n");
crate::console::write_str(" Rust Kernel v0.1.0\n");
crate::console::write_str("========================================\n");
crate::console::write_str("\n");
crate::console::write_str("Status: Boot successful!\n");
crate::console::write_str("Console: Working\n");
crate::console::write_str("Memory: Basic allocator initialized\n");
crate::console::write_str("Architecture: x86_64\n");
crate::console::write_str("\n");
crate::console::write_str("System Information:\n");
crate::console::write_str(" - Identity mapping: 0-1GB\n");
crate::console::write_str(" - Paging: 4-level (PML4->PDP->PD)\n");
crate::console::write_str(" - Page size: 2MB (large pages)\n");
crate::console::write_str("\n");
crate::console::write_str("Kernel is now idle.\n");
crate::console::write_str("Press Ctrl+C to exit QEMU.\n");
crate::console::write_str("\n");
// Initialize memory management // Simple idle loop
if let Err(e) = crate::memory::init() { let mut counter = 0u64;
error!("Failed to initialize memory management: {}", e); loop {
panic!("Memory initialization failed"); counter += 1;
// Print a heartbeat every ~1 million iterations
if counter % 1_000_000 == 0 {
crate::console::write_str(".");
}
unsafe {
core::arch::asm!("hlt");
}
} }
info!("Memory management initialized");
// Hardware detection and initialization
if let Err(e) = crate::hardware::init() {
error!("Failed to initialize hardware detection: {}", e);
panic!("Hardware detection failed");
}
info!("Hardware detection completed");
// Initialize heap for brk syscall
if let Err(e) = crate::memory::init_heap() {
error!("Failed to initialize heap: {}", e);
panic!("Heap initialization failed");
}
info!("Heap initialized");
// Initialize kmalloc
if let Err(e) = crate::memory::kmalloc::init() {
error!("Failed to initialize kmalloc: {}", e);
panic!("Kmalloc initialization failed");
}
info!("Kmalloc initialized");
// Initialize vmalloc
if let Err(e) = crate::memory::vmalloc::init() {
error!("Failed to initialize vmalloc: {}", e);
panic!("Vmalloc initialization failed");
}
info!("Vmalloc initialized");
// Initialize interrupt handling
if let Err(e) = crate::interrupt::init() {
error!("Failed to initialize interrupts: {}", e);
panic!("Interrupt initialization failed");
}
info!("Interrupt handling initialized");
// Initialize scheduler
if let Err(e) = crate::scheduler::init() {
error!("Failed to initialize scheduler: {}", e);
panic!("Scheduler initialization failed");
}
info!("Scheduler initialized");
// Initialize enhanced scheduler
if let Err(e) = crate::enhanced_scheduler::init_enhanced_scheduler() {
error!("Failed to initialize enhanced scheduler: {}", e);
panic!("Enhanced scheduler initialization failed");
}
info!("Enhanced scheduler initialized");
// Initialize IPC system
if let Err(e) = crate::ipc::init_ipc() {
error!("Failed to initialize IPC system: {}", e);
panic!("IPC system initialization failed");
}
info!("IPC system initialized");
// Initialize advanced performance monitoring
if let Err(e) = crate::advanced_perf::init_performance_monitoring() {
error!(
"Failed to initialize advanced performance monitoring: {}",
e
);
panic!("Advanced performance monitoring initialization failed");
}
info!("Advanced performance monitoring initialized");
// Initialize timer for preemptive scheduling
if let Err(e) = crate::timer::init_timer() {
error!("Failed to initialize timer: {}", e);
panic!("Timer initialization failed");
}
info!("Timer initialized");
// Initialize device subsystem
if let Err(e) = crate::device::init() {
error!("Failed to initialize devices: {}", e);
panic!("Device initialization failed");
}
info!("Device subsystem initialized");
// Initialize VFS (Virtual File System)
if let Err(e) = crate::fs::init() {
error!("Failed to initialize VFS: {}", e);
panic!("VFS initialization failed");
}
info!("VFS initialized");
// Initialize process management
if let Err(e) = crate::process::init_process_management() {
error!("Failed to initialize process management: {}", e);
panic!("Process management initialization failed");
}
info!("Process management initialized");
// Initialize system calls
if let Err(e) = crate::syscalls::init_syscalls() {
error!("Failed to initialize syscalls: {}", e);
panic!("Syscall initialization failed");
}
info!("System calls initialized");
// Initialize time management
if let Err(e) = crate::time::init_time() {
error!("Failed to initialize time management: {}", e);
panic!("Time management initialization failed");
}
info!("Time management initialized");
// Display system information
crate::test_init::display_system_info();
// Run basic functionality tests
if let Err(e) = crate::test_init::run_basic_tests() {
error!("Basic functionality tests failed: {}", e);
panic!("Basic tests failed");
}
// Run initialization tests
if let Err(e) = crate::test_init::run_init_tests() {
error!("Initialization tests failed: {}", e);
panic!("Initialization tests failed");
}
// Initialize drivers
if let Err(e) = crate::drivers_init::init_drivers() {
error!("Failed to initialize drivers: {}", e);
panic!("Driver initialization failed");
}
info!("Drivers initialized");
// Initialize kernel threads
if let Err(e) = crate::kthread::init_kthreads() {
error!("Failed to initialize kernel threads: {}", e);
panic!("Kernel thread initialization failed");
}
info!("Kernel threads initialized");
// Initialize kernel shell
if let Err(e) = crate::shell::init_shell() {
error!("Failed to initialize kernel shell: {}", e);
panic!("Shell initialization failed");
}
info!("Kernel shell initialized");
// Initialize networking
if let Err(e) = crate::network::init() {
error!("Failed to initialize networking: {}", e);
panic!("Networking initialization failed");
}
info!("Networking initialized");
// Initialize module loading system
if let Err(e) = crate::module_loader::init_modules() {
error!("Failed to initialize module system: {}", e);
panic!("Module system initialization failed");
}
info!("Module system initialized");
// Initialize in-memory file system
if let Err(e) = crate::memfs::init_memfs() {
error!("Failed to initialize file system: {}", e);
panic!("File system initialization failed");
}
info!("In-memory file system initialized");
// Initialize test suite
if let Err(e) = crate::test_suite::init() {
error!("Failed to initialize test suite: {}", e);
panic!("Test suite initialization failed");
}
info!("Test suite initialized");
// Initialize user mode support
if let Err(e) = crate::usermode::init_usermode() {
error!("Failed to initialize user mode: {}", e);
panic!("User mode initialization failed");
}
info!("User mode support initialized");
// Initialize performance monitoring
if let Err(e) = crate::perf::init_perf_monitor() {
error!("Failed to initialize performance monitoring: {}", e);
panic!("Performance monitoring initialization failed");
}
info!("Performance monitoring initialized");
// Initialize advanced logging system
if let Err(e) = crate::logging::init_logging() {
error!("Failed to initialize logging system: {}", e);
panic!("Logging system initialization failed");
}
info!("Advanced logging system initialized");
// Initialize system information collection
if let Err(e) = crate::sysinfo::init_sysinfo() {
error!("Failed to initialize system information: {}", e);
panic!("System information initialization failed");
}
info!("System information collection initialized");
// Initialize system diagnostics
if let Err(e) = crate::diagnostics::init_diagnostics() {
error!("Failed to initialize system diagnostics: {}", e);
panic!("System diagnostics initialization failed");
}
info!("System diagnostics initialized");
// Initialize working task management
if let Err(e) = crate::working_task::init_task_management() {
error!("Failed to initialize task management: {}", e);
panic!("Task management initialization failed");
}
info!("Task management initialized");
// Start kernel threads
start_kernel_threads();
info!("Kernel initialization completed");
info!("Starting main kernel loop");
// Start the main kernel loop
main_kernel_loop();
} }
/// Start essential kernel threads /// Start essential kernel threads

Ver fichero

@@ -22,7 +22,9 @@ extern crate alloc;
// #[cfg(target_arch = "x86_64")] // #[cfg(target_arch = "x86_64")]
// global_asm!(include_str!("arch/x86_64/boot.s"), options(att_syntax)); // global_asm!(include_str!("arch/x86_64/boot.s"), options(att_syntax));
pub mod advanced_perf; // Advanced performance monitoring and profiling
pub mod arch; pub mod arch;
pub mod arp;
pub mod benchmark; // Performance benchmarking pub mod benchmark; // Performance benchmarking
pub mod boot; pub mod boot;
pub mod console; pub mod console;
@@ -36,6 +38,7 @@ pub mod enhanced_scheduler; // Enhanced preemptive scheduler
pub mod error; pub mod error;
pub mod fs; pub mod fs;
pub mod hardware; // Hardware detection and initialization pub mod hardware; // Hardware detection and initialization
pub mod icmp;
pub mod init; pub mod init;
pub mod interrupt; pub mod interrupt;
pub mod ipc; // Inter-process communication pub mod ipc; // Inter-process communication
@@ -46,9 +49,6 @@ pub mod memory;
pub mod module; pub mod module;
pub mod module_loader; // Dynamic module loading pub mod module_loader; // Dynamic module loading
pub mod network; pub mod network;
pub mod arp;
pub mod icmp;
pub mod advanced_perf; // Advanced performance monitoring and profiling
pub mod panic; pub mod panic;
pub mod perf; // Performance monitoring pub mod perf; // Performance monitoring
pub mod prelude; pub mod prelude;
@@ -87,6 +87,7 @@ pub extern "C" fn kernel_main() -> ! {
// Now we can use allocations, continue with full initialization // Now we can use allocations, continue with full initialization
init::early_init(); init::early_init();
init::main_init(); init::main_init();
// Should not return from main_init // Should not return from main_init
@@ -116,24 +117,21 @@ fn early_kernel_init() {
loop {} loop {}
} }
crate::println!("Rust Kernel v{} starting...", VERSION); crate::console::write_str("\n");
crate::println!("Early kernel initialization"); crate::console::write_str("Booting Rust Kernel...\n");
} }
/// Initialize memory management using multiboot information /// Initialize memory management using multiboot information
fn memory_init() -> Result<(), error::Error> { fn memory_init() -> Result<(), error::Error> {
if let Some(multiboot_addr) = boot::get_boot_info().multiboot_addr { crate::console::write_str("[*] Initializing memory subsystem...\n");
boot::multiboot::init_memory_from_multiboot(multiboot_addr)?;
} else { // FIXME: Multiboot parsing causes crashes - use default memory layout for now
// Fallback: initialize with default memory layout memory::page::init()?;
memory::page::init()?;
}
// Initialize heap allocator // Initialize heap allocator
memory::kmalloc::init()?; memory::kmalloc::init()?;
memory::vmalloc::init()?;
info!("Memory management initialized"); crate::console::write_str("[+] Memory subsystem ready\n");
Ok(()) Ok(())
} }

Ver fichero

@@ -13,27 +13,6 @@ use core::arch::global_asm;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
global_asm!(include_str!("arch/x86_64/boot.s"), options(att_syntax)); global_asm!(include_str!("arch/x86_64/boot.s"), options(att_syntax));
use core::panic::PanicInfo;
/// 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 /// Entry point called by boot.s assembly code
/// This is just a wrapper to ensure the kernel crate is linked /// This is just a wrapper to ensure the kernel crate is linked
#[no_mangle] #[no_mangle]
@@ -48,8 +27,3 @@ pub extern "C" fn rust_main() -> ! {
} }
// Panic handler is defined in the kernel library // Panic handler is defined in the kernel library
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {}
}

Ver fichero

@@ -15,11 +15,10 @@ const KMALLOC_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096
const MAX_KMALLOC_SIZE: usize = 4096; const MAX_KMALLOC_SIZE: usize = 4096;
/// Slab allocator for small kernel allocations /// Slab allocator for small kernel allocations
/// Uses indices instead of raw pointers for thread safety /// Uses physical addresses directly - they're identity-mapped in the first 1GB
struct SlabAllocator { struct SlabAllocator {
size_classes: BTreeMap<usize, Vec<usize>>, // Store offsets instead of pointers size_classes: BTreeMap<usize, Vec<usize>>, // Store physical addresses
allocated_blocks: BTreeMap<usize, usize>, // Maps offsets to size classes allocated_blocks: BTreeMap<usize, usize>, // Maps physical addresses to size classes
base_addr: usize, // Base address for calculations
} }
impl SlabAllocator { impl SlabAllocator {
@@ -27,14 +26,9 @@ impl SlabAllocator {
Self { Self {
size_classes: BTreeMap::new(), size_classes: BTreeMap::new(),
allocated_blocks: BTreeMap::new(), allocated_blocks: BTreeMap::new(),
base_addr: 0,
} }
} }
fn init(&mut self, base_addr: usize) {
self.base_addr = base_addr;
}
fn allocate(&mut self, size: usize) -> Result<*mut u8> { fn allocate(&mut self, size: usize) -> Result<*mut u8> {
// Find appropriate size class // Find appropriate size class
let size_class = KMALLOC_SIZES let size_class = KMALLOC_SIZES
@@ -49,9 +43,9 @@ impl SlabAllocator {
// Try to get from free list // Try to get from free list
if let Some(free_list) = self.size_classes.get_mut(&size_class) { if let Some(free_list) = self.size_classes.get_mut(&size_class) {
if let Some(offset) = free_list.pop() { if let Some(addr) = free_list.pop() {
self.allocated_blocks.insert(offset, size_class); self.allocated_blocks.insert(addr, size_class);
return Ok((self.base_addr + offset) as *mut u8); return Ok(addr as *mut u8);
} }
} }
@@ -63,28 +57,27 @@ impl SlabAllocator {
// Allocate a page using buddy allocator // Allocate a page using buddy allocator
let pfn = alloc_pages(0, GfpFlags::KERNEL)?; let pfn = alloc_pages(0, GfpFlags::KERNEL)?;
let page_addr = pfn.to_phys_addr().as_usize(); let page_addr = pfn.to_phys_addr().as_usize();
let offset = page_addr - self.base_addr;
// Split page into blocks of size_class // Split page into blocks of size_class
let blocks_per_page = 4096 / size_class; let blocks_per_page = 4096 / size_class;
let free_list = self.size_classes.entry(size_class).or_insert_with(Vec::new); let free_list = self.size_classes.entry(size_class).or_insert_with(Vec::new);
for i in 1..blocks_per_page { for i in 1..blocks_per_page {
let block_offset = offset + (i * size_class); let block_addr = page_addr + (i * size_class);
free_list.push(block_offset); free_list.push(block_addr);
} }
// Return the first block // Return the first block
self.allocated_blocks.insert(offset, size_class); self.allocated_blocks.insert(page_addr, size_class);
Ok(page_addr as *mut u8) Ok(page_addr as *mut u8)
} }
fn deallocate(&mut self, ptr: *mut u8) -> Result<()> { fn deallocate(&mut self, ptr: *mut u8) -> Result<()> {
let offset = (ptr as usize).saturating_sub(self.base_addr); let addr = ptr as usize;
if let Some(size_class) = self.allocated_blocks.remove(&offset) { if let Some(size_class) = self.allocated_blocks.remove(&addr) {
let free_list = let free_list =
self.size_classes.entry(size_class).or_insert_with(Vec::new); self.size_classes.entry(size_class).or_insert_with(Vec::new);
free_list.push(offset); free_list.push(addr);
Ok(()) Ok(())
} else { } else {
Err(Error::InvalidArgument) Err(Error::InvalidArgument)
@@ -192,8 +185,6 @@ pub fn krealloc(ptr: *mut u8, old_size: usize, new_size: usize) -> Result<*mut u
/// Initialize the slab allocator /// Initialize the slab allocator
pub fn init() -> Result<()> { pub fn init() -> Result<()> {
let mut allocator = SLAB_ALLOCATOR.lock(); // No initialization needed - we use physical addresses directly
// Use a reasonable base address for offset calculations
allocator.init(0x_4000_0000_0000);
Ok(()) Ok(())
} }

Ver fichero

@@ -115,7 +115,21 @@ impl PageAllocator {
/// Add a range of pages to the free list /// Add a range of pages to the free list
pub fn add_free_range(&mut self, start: Pfn, count: usize) { pub fn add_free_range(&mut self, start: Pfn, count: usize) {
for i in 0..count { // Safety: Only add pages that are within the identity-mapped region (0-1GB)
// Boot assembly maps 0-1GB with 2MB pages
const MAX_IDENTITY_MAPPED_PFN: usize = (1024 * 1024 * 1024) / 4096; // 1GB / 4KB
let safe_count = if start.0 >= MAX_IDENTITY_MAPPED_PFN {
// Start is beyond identity mapping, skip entirely
return;
} else if start.0 + count > MAX_IDENTITY_MAPPED_PFN {
// Trim to stay within identity mapping
MAX_IDENTITY_MAPPED_PFN - start.0
} else {
count
};
for i in 0..safe_count {
let pfn = Pfn(start.0 + i); let pfn = Pfn(start.0 + i);
let phys_addr = PhysAddr(pfn.0 * 4096); let phys_addr = PhysAddr(pfn.0 * 4096);
@@ -129,8 +143,8 @@ impl PageAllocator {
// Update head // Update head
self.free_list_head = Some(phys_addr); self.free_list_head = Some(phys_addr);
} }
self.total_pages += count; self.total_pages += safe_count;
self.free_count += count; self.free_count += safe_count;
} }
/// Allocate a single page /// Allocate a single page
@@ -173,15 +187,7 @@ impl PageAllocator {
/// Initialize the page allocator /// Initialize the page allocator
pub fn init() -> Result<()> { pub fn init() -> Result<()> {
let mut allocator = PAGE_ALLOCATOR.lock(); // Page allocator stub - no actual pages initialized yet
// TODO: Get memory map from bootloader/firmware
// For now, add a dummy range
let start_pfn = Pfn(0x1000); // Start at 16MB
let count = 0x10000; // 256MB worth of pages
allocator.add_free_range(start_pfn, count);
Ok(()) Ok(())
} }

Ver fichero

@@ -172,42 +172,42 @@ pub fn vzalloc(size: usize) -> Result<VirtAddr> {
/// Map physical memory into virtual space /// Map physical memory into virtual space
pub fn vmap_phys(phys_addr: PhysAddr, size: usize) -> Result<VirtAddr> { pub fn vmap_phys(phys_addr: PhysAddr, size: usize) -> Result<VirtAddr> {
let start_addr; let start_addr;
let aligned_size; let aligned_size;
{ {
let mut allocator = VMALLOC_ALLOCATOR.lock(); let mut allocator = VMALLOC_ALLOCATOR.lock();
if allocator.page_table.is_none() { if allocator.page_table.is_none() {
return Err(Error::NotInitialized); return Err(Error::NotInitialized);
} }
aligned_size = (size + 4095) & !4095; aligned_size = (size + 4095) & !4095;
start_addr = allocator.find_free_area(aligned_size)?; start_addr = allocator.find_free_area(aligned_size)?;
} }
let mut allocator = VMALLOC_ALLOCATOR.lock(); let mut allocator = VMALLOC_ALLOCATOR.lock();
let page_table = allocator.page_table.as_mut().unwrap(); let page_table = allocator.page_table.as_mut().unwrap();
// Map virtual to physical pages // Map virtual to physical pages
let pages_needed = aligned_size / 4096; let pages_needed = aligned_size / 4096;
for i in 0..pages_needed { for i in 0..pages_needed {
let virt_addr = VirtAddr::new(start_addr + i * 4096); let virt_addr = VirtAddr::new(start_addr + i * 4096);
let phys_addr = PhysAddr::new(phys_addr.as_usize() + i * 4096); let phys_addr = PhysAddr::new(phys_addr.as_usize() + i * 4096);
page_table.map_page( page_table.map_page(
virt_addr, virt_addr,
phys_addr, phys_addr,
PageTableFlags::kernel_page() | PageTableFlags::NO_EXECUTE, PageTableFlags::kernel_page() | PageTableFlags::NO_EXECUTE,
)?; )?;
} }
let end_addr = start_addr + aligned_size; let end_addr = start_addr + aligned_size;
let area = VmallocArea { let area = VmallocArea {
start: VirtAddr::new(start_addr), start: VirtAddr::new(start_addr),
end: VirtAddr::new(end_addr), end: VirtAddr::new(end_addr),
size: aligned_size, size: aligned_size,
pages: alloc::vec![], // We don't own these pages pages: alloc::vec![], // We don't own these pages
}; };
allocator.areas.insert(start_addr, area); allocator.areas.insert(start_addr, area);
Ok(VirtAddr::new(start_addr)) Ok(VirtAddr::new(start_addr))
} }
pub fn vmap(pages: &[PhysAddr], count: usize) -> Result<VirtAddr> { pub fn vmap(pages: &[PhysAddr], count: usize) -> Result<VirtAddr> {

Ver fichero

@@ -2,7 +2,13 @@
//! Network stack implementation //! Network stack implementation
use alloc::{boxed::Box, collections::BTreeMap, collections::VecDeque, string::{String, ToString}, vec::Vec}; use alloc::{
boxed::Box,
collections::BTreeMap,
collections::VecDeque,
string::{String, ToString},
vec::Vec,
};
use core::fmt; use core::fmt;
use crate::error::{Error, Result}; use crate::error::{Error, Result};
@@ -245,71 +251,71 @@ pub struct InterfaceStats {
/// A loopback network interface. /// A loopback network interface.
#[derive(Debug)] #[derive(Debug)]
pub struct LoopbackInterface { pub struct LoopbackInterface {
rx_queue: VecDeque<NetworkBuffer>, rx_queue: VecDeque<NetworkBuffer>,
up: bool, up: bool,
} }
impl LoopbackInterface { impl LoopbackInterface {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
rx_queue: VecDeque::new(), rx_queue: VecDeque::new(),
up: true, up: true,
} }
} }
} }
impl NetworkInterface for LoopbackInterface { impl NetworkInterface for LoopbackInterface {
fn name(&self) -> &str { fn name(&self) -> &str {
"lo" "lo"
} }
fn ip_address(&self) -> Option<Ipv4Address> { fn ip_address(&self) -> Option<Ipv4Address> {
Some(Ipv4Address::localhost()) Some(Ipv4Address::localhost())
} }
fn mac_address(&self) -> MacAddress { fn mac_address(&self) -> MacAddress {
MacAddress::zero() MacAddress::zero()
} }
fn mtu(&self) -> u16 { fn mtu(&self) -> u16 {
65535 65535
} }
fn is_up(&self) -> bool { fn is_up(&self) -> bool {
self.up self.up
} }
fn send_packet(&mut self, buffer: &NetworkBuffer) -> Result<()> { fn send_packet(&mut self, buffer: &NetworkBuffer) -> Result<()> {
if !self.up { if !self.up {
return Err(Error::NetworkDown); return Err(Error::NetworkDown);
} }
self.rx_queue.push_back(buffer.clone()); self.rx_queue.push_back(buffer.clone());
Ok(()) Ok(())
} }
fn receive_packet(&mut self) -> Result<Option<NetworkBuffer>> { fn receive_packet(&mut self) -> Result<Option<NetworkBuffer>> {
if !self.up { if !self.up {
return Ok(None); return Ok(None);
} }
Ok(self.rx_queue.pop_front()) Ok(self.rx_queue.pop_front())
} }
fn set_up(&mut self, up: bool) -> Result<()> { fn set_up(&mut self, up: bool) -> Result<()> {
self.up = up; self.up = up;
Ok(()) Ok(())
} }
fn set_mac_address(&mut self, _mac: MacAddress) -> Result<()> { fn set_mac_address(&mut self, _mac: MacAddress) -> Result<()> {
// The loopback interface doesn't have a real MAC address. // The loopback interface doesn't have a real MAC address.
Ok(()) Ok(())
} }
} }
/// Network stack /// Network stack
struct PendingArpRequest { struct PendingArpRequest {
packet: NetworkBuffer, packet: NetworkBuffer,
ip: Ipv4Address, ip: Ipv4Address,
timestamp: u64, timestamp: u64,
} }
pub struct NetworkStack { pub struct NetworkStack {
@@ -317,7 +323,7 @@ pub struct NetworkStack {
interface_stats: BTreeMap<String, InterfaceStats>, interface_stats: BTreeMap<String, InterfaceStats>,
routing_table: Vec<RouteEntry>, routing_table: Vec<RouteEntry>,
arp_table: BTreeMap<Ipv4Address, MacAddress>, arp_table: BTreeMap<Ipv4Address, MacAddress>,
pending_arp_requests: Vec<PendingArpRequest>, pending_arp_requests: Vec<PendingArpRequest>,
} }
/// Routing table entry /// Routing table entry
@@ -337,7 +343,7 @@ impl NetworkStack {
interface_stats: BTreeMap::new(), interface_stats: BTreeMap::new(),
routing_table: Vec::new(), routing_table: Vec::new(),
arp_table: BTreeMap::new(), arp_table: BTreeMap::new(),
pending_arp_requests: Vec::new(), pending_arp_requests: Vec::new(),
} }
} }
@@ -404,9 +410,10 @@ impl NetworkStack {
data: &[u8], data: &[u8],
protocol: ProtocolType, protocol: ProtocolType,
) -> Result<()> { ) -> Result<()> {
// Clean up timed out ARP requests // Clean up timed out ARP requests
let now = crate::time::get_time_ns(); let now = crate::time::get_time_ns();
self.pending_arp_requests.retain(|req| now - req.timestamp < 10_000_000_000); // 10 seconds self.pending_arp_requests
.retain(|req| now - req.timestamp < 10_000_000_000); // 10 seconds
// Find route (borrow self immutably) // Find route (borrow self immutably)
let route = { let route = {
@@ -444,16 +451,16 @@ impl NetworkStack {
.ok_or(Error::DeviceNotFound)?; .ok_or(Error::DeviceNotFound)?;
interface_mut.send_packet(&buffer)?; interface_mut.send_packet(&buffer)?;
// Queue the original packet // Queue the original packet
let mut packet_to_queue = NetworkBuffer::new(data.len()); let mut packet_to_queue = NetworkBuffer::new(data.len());
packet_to_queue.extend_from_slice(data)?; packet_to_queue.extend_from_slice(data)?;
packet_to_queue.set_protocol(protocol); packet_to_queue.set_protocol(protocol);
packet_to_queue.set_ip_addresses(Ipv4Address::any(), dest); // TODO: Set source IP packet_to_queue.set_ip_addresses(Ipv4Address::any(), dest); // TODO: Set source IP
self.pending_arp_requests.push(PendingArpRequest { self.pending_arp_requests.push(PendingArpRequest {
packet: packet_to_queue, packet: packet_to_queue,
ip: dest, ip: dest,
timestamp: crate::time::get_time_ns(), timestamp: crate::time::get_time_ns(),
}); });
return Ok(()); // We'll have to wait for the reply return Ok(()); // We'll have to wait for the reply
}; };
@@ -491,7 +498,7 @@ impl NetworkStack {
pub fn receive_and_handle_packets(&mut self) -> Result<Vec<NetworkBuffer>> { pub fn receive_and_handle_packets(&mut self) -> Result<Vec<NetworkBuffer>> {
let mut received_packets = Vec::new(); let mut received_packets = Vec::new();
let mut unhandled_packets = Vec::new(); let mut unhandled_packets = Vec::new();
// First, receive all packets from all interfaces // First, receive all packets from all interfaces
for (name, interface) in &mut self.interfaces { for (name, interface) in &mut self.interfaces {
@@ -507,7 +514,9 @@ impl NetworkStack {
// Now, process the received packets // Now, process the received packets
for (interface_name, packet) in received_packets { for (interface_name, packet) in received_packets {
if packet.protocol == ProtocolType::ARP { if packet.protocol == ProtocolType::ARP {
if let Ok(arp_packet) = crate::arp::ArpPacket::from_bytes(packet.data()) { if let Ok(arp_packet) =
crate::arp::ArpPacket::from_bytes(packet.data())
{
self.handle_arp_packet(&arp_packet, &interface_name)?; self.handle_arp_packet(&arp_packet, &interface_name)?;
} }
} else if packet.protocol == ProtocolType::ICMP { } else if packet.protocol == ProtocolType::ICMP {
@@ -530,7 +539,11 @@ impl NetworkStack {
self.interface_stats.get(name) self.interface_stats.get(name)
} }
fn handle_arp_packet(&mut self, packet: &crate::arp::ArpPacket, interface_name: &str) -> Result<()> { fn handle_arp_packet(
&mut self,
packet: &crate::arp::ArpPacket,
interface_name: &str,
) -> Result<()> {
// Add the sender to the ARP table // Add the sender to the ARP table
self.add_arp_entry(packet.spa, packet.sha); self.add_arp_entry(packet.spa, packet.sha);
@@ -548,9 +561,14 @@ impl NetworkStack {
); );
let mut buffer = NetworkBuffer::new(28); let mut buffer = NetworkBuffer::new(28);
buffer.set_protocol(ProtocolType::ARP); buffer.set_protocol(ProtocolType::ARP);
buffer.set_mac_addresses(interface.mac_address(), packet.sha); buffer.set_mac_addresses(
interface.mac_address(),
packet.sha,
);
buffer.extend_from_slice(&reply.to_bytes())?; buffer.extend_from_slice(&reply.to_bytes())?;
if let Some(interface) = self.get_interface_mut(interface_name) { if let Some(interface) =
self.get_interface_mut(interface_name)
{
interface.send_packet(&buffer)?; interface.send_packet(&buffer)?;
} }
} }
@@ -558,21 +576,25 @@ impl NetworkStack {
} }
} }
// Check for pending packets // Check for pending packets
let mut packets_to_send = Vec::new(); let mut packets_to_send = Vec::new();
let mut still_pending = Vec::new(); let mut still_pending = Vec::new();
for pending in self.pending_arp_requests.drain(..) { for pending in self.pending_arp_requests.drain(..) {
if pending.ip == packet.spa { if pending.ip == packet.spa {
packets_to_send.push(pending); packets_to_send.push(pending);
} else { } else {
still_pending.push(pending); still_pending.push(pending);
} }
} }
self.pending_arp_requests = still_pending; self.pending_arp_requests = still_pending;
for pending in packets_to_send { for pending in packets_to_send {
self.send_packet(pending.ip, pending.packet.data(), pending.packet.protocol)?; self.send_packet(
} pending.ip,
pending.packet.data(),
pending.packet.protocol,
)?;
}
Ok(()) Ok(())
} }
@@ -637,27 +659,27 @@ pub fn add_network_interface(name: String, interface: Box<dyn NetworkInterface>)
} }
pub mod utils { pub mod utils {
/// Calculate checksum /// Calculate checksum
pub fn calculate_checksum(data: &[u8]) -> u16 { pub fn calculate_checksum(data: &[u8]) -> u16 {
let mut sum = 0u32; let mut sum = 0u32;
// Sum all 16-bit words // Sum all 16-bit words
for chunk in data.chunks(2) { for chunk in data.chunks(2) {
if chunk.len() == 2 { if chunk.len() == 2 {
sum += ((chunk[0] as u32) << 8) + (chunk[1] as u32); sum += ((chunk[0] as u32) << 8) + (chunk[1] as u32);
} else { } else {
sum += (chunk[0] as u32) << 8; sum += (chunk[0] as u32) << 8;
} }
} }
// Add carry // Add carry
while sum >> 16 != 0 { while sum >> 16 != 0 {
sum = (sum & 0xFFFF) + (sum >> 16); sum = (sum & 0xFFFF) + (sum >> 16);
} }
// One's complement // One's complement
!sum as u16 !sum as u16
} }
} }
/// Send a packet /// Send a packet

Ver fichero

@@ -293,15 +293,19 @@ impl KernelShell {
let mut stack = crate::network::NETWORK_STACK.lock(); let mut stack = crate::network::NETWORK_STACK.lock();
if let Some(ref mut stack) = *stack { if let Some(ref mut stack) = *stack {
for iface_name in stack.list_interfaces() { for iface_name in stack.list_interfaces() {
if let Some(stats) = stack.get_interface_stats(&iface_name) { if let Some(stats) =
stack.get_interface_stats(&iface_name)
{
info!(" {}:", iface_name); info!(" {}:", iface_name);
info!( info!(
" TX: {} packets, {} bytes", " TX: {} packets, {} bytes",
stats.packets_sent, stats.bytes_sent stats.packets_sent,
stats.bytes_sent
); );
info!( info!(
" RX: {} packets, {} bytes", " RX: {} packets, {} bytes",
stats.packets_received, stats.bytes_received stats.packets_received,
stats.bytes_received
); );
info!( info!(
" Errors: {}, Dropped: {}", " Errors: {}, Dropped: {}",
@@ -341,12 +345,16 @@ impl KernelShell {
sequence_number: 0, sequence_number: 0,
}; };
let mut data = icmp_packet.to_bytes(); let mut data = icmp_packet.to_bytes();
let checksum = crate::network::utils::calculate_checksum(&data); let checksum = crate::network::utils::calculate_checksum(&data);
icmp_packet.checksum = checksum; icmp_packet.checksum = checksum;
data = icmp_packet.to_bytes(); data = icmp_packet.to_bytes();
if let Err(e) = crate::network::send_packet(dest_ip, &data, crate::network::ProtocolType::ICMP) { if let Err(e) = crate::network::send_packet(
dest_ip,
&data,
crate::network::ProtocolType::ICMP,
) {
error!("Failed to send ping: {}", e); error!("Failed to send ping: {}", e);
} else { } else {
info!("Ping sent to {}", dest_ip); info!("Ping sent to {}", dest_ip);