From 383365f50510855adb8090811307b3a0985bc293 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sat, 5 Sep 2026 16:46:26 +0200 Subject: [PATCH 1/6] Allow running test in debug mode --- Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ce20c046..558270d0 100644 --- a/Makefile +++ b/Makefile @@ -137,8 +137,13 @@ endif qemu: $(qemu) $(qemu-opts) +test-opts = --lib +ifeq ($(mode),release) +test-opts += --release +endif + test: - cargo test --release --lib --no-default-features --features serial -- \ + cargo test $(test-opts) --no-default-features --features serial -- \ -m $(memory) -cpu $(cpu) -display none -serial stdio \ -device isa-debug-exit,iobase=0xF4,iosize=0x04 @@ -172,7 +177,7 @@ limine-image: limine-test: RUSTFLAGS = -C link-arg=-Trun/boot/multiboot.ld -C link-arg=-z -C link-arg=norelro limine-test: LIMINE_DIR = $(limine-dir) limine-test: - cargo test --release --lib --no-default-features --features serial,multiboot --target i686-moros.json -- \ + cargo test $(test-opts) --no-default-features --features serial,multiboot --target i686-moros.json -- \ -m $(memory) -cpu pentium3 -display none -serial stdio \ -device isa-debug-exit,iobase=0xF4,iosize=0x04 From 71b7f8cc9a0b0d8af9dd2df54693b009437232bf Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sat, 5 Sep 2026 16:47:59 +0200 Subject: [PATCH 2/6] Fix E1000 driver usage of io --- src/sys/net/mod.rs | 10 +++-- src/sys/net/nic/e1000.rs | 95 +++++++++++++++++++--------------------- src/sys/pci.rs | 16 +++---- 3 files changed, 60 insertions(+), 61 deletions(-) diff --git a/src/sys/net/mod.rs b/src/sys/net/mod.rs index fdbb0915..64501d41 100644 --- a/src/sys/net/mod.rs +++ b/src/sys/net/mod.rs @@ -297,10 +297,12 @@ pub fn init() { } for id in E1000_DEVICES { if let Some(dev) = find_device(0x8086, id) { - let io = dev.bar_io(0); - let mem = dev.mem_base(); - let bar = dev.bar_type(); - let nic = nic::e1000::Device::new(io, mem, bar); + let base = if dev.is_io() { + nic::e1000::Base::IO(dev.bar_io(0)) + } else { + nic::e1000::Base::Mem(dev.mem_base()) + }; + let nic = nic::e1000::Device::new(base); add(EthernetDevice::E1000(nic), "E1000"); } } diff --git a/src/sys/net/nic/e1000.rs b/src/sys/net/nic/e1000.rs index 28226044..c42bd231 100644 --- a/src/sys/net/nic/e1000.rs +++ b/src/sys/net/nic/e1000.rs @@ -4,7 +4,6 @@ use crate::sys::net::{EthernetDeviceIO, Config, Stats}; use crate::sys::x86::addr::PhysAddr; use crate::sys::x86::port::*; -use alloc::slice; use alloc::sync::Arc; use alloc::vec::Vec; use bit_field::BitField; @@ -18,7 +17,7 @@ use spin::Mutex; // Registers const REG_CTRL: u16 = 0x0000; // Device Control Register const REG_STATUS: u16 = 0x0008; // Device Status Register -const REG_EECD: u16 = 0x0014; // EEPROM/Flash Control & Data Register +const REG_EERD: u16 = 0x0014; // EEPROM Read Register const REG_ICR: u16 = 0x00C0; // Interrupt Cause Read Register const REG_IMS: u16 = 0x00D0; // Interrupt Mask Set/Read Register const REG_IMC: u16 = 0x00D8; // Interrupt Mask Clear Register @@ -35,6 +34,8 @@ const REG_TDBAH: u16 = 0x3804; // Transmit Descriptor Base Address High const REG_TDLEN: u16 = 0x3808; // Transmit Descriptor Length const REG_TDH: u16 = 0x3810; // Transmit Descriptor Head const REG_TDT: u16 = 0x3818; // Transmit Descriptor Tail +const REG_RAL: u16 = 0x5400; // Receive Address Low +const REG_RAH: u16 = 0x5404; // Receive Address High const REG_MTA: u16 = 0x5200; // Multicast Table Array const CTRL_LRST: u32 = 1 << 3; // Link Reset @@ -118,11 +119,15 @@ struct TxDesc { special: u16, } +#[derive(Clone)] +pub enum Base { + IO(u16), + Mem(PhysAddr), +} + #[derive(Clone)] pub struct Device { - mem_base: PhysAddr, - io_base: u16, - bar_type: u16, + base: Base, has_eeprom: bool, config: Arc, stats: Arc, @@ -135,14 +140,12 @@ pub struct Device { } impl Device { - pub fn new(io_base: u16, mem_base: PhysAddr, bar_type: u16) -> Self { + pub fn new(base: Base) -> Self { const RX: usize = RX_BUFFERS_COUNT; const TX: usize = TX_BUFFERS_COUNT; let mut device = Self { - bar_type: bar_type, - io_base: io_base, - mem_base: mem_base, + base, has_eeprom: false, config: Arc::new(Config::new()), stats: Arc::new(Stats::new()), @@ -263,28 +266,14 @@ impl Device { fn read_mac(&self) -> EthernetAddress { let mut mac = [0; 6]; if self.has_eeprom { - let mut tmp; - tmp = self.read_eeprom(0); - mac[0] = (tmp &0xff) as u8; - mac[1] = (tmp >> 8) as u8; - tmp = self.read_eeprom(1); - mac[2] = (tmp &0xff) as u8; - mac[3] = (tmp >> 8) as u8; - tmp = self.read_eeprom(2); - mac[4] = (tmp &0xff) as u8; - mac[5] = (tmp >> 8) as u8; + mac[0..2].copy_from_slice(&self.read_eeprom(0).to_le_bytes()); + mac[2..4].copy_from_slice(&self.read_eeprom(1).to_le_bytes()); + mac[4..6].copy_from_slice(&self.read_eeprom(2).to_le_bytes()); } else { - unsafe { - let phys = self.mem_base + 0x5400; - let addr = sys::mem::phys_to_virt(phys).as_usize(); - let mac_32 = core::ptr::read_volatile(addr as *const u32); - if mac_32 != 0 { - let mac_8 = slice::from_raw_parts(addr as *const u8, 6); - mac[..].clone_from_slice(mac_8); - } - } + mac[0..4].copy_from_slice(&self.read(REG_RAL).to_le_bytes()); + mac[4..6].copy_from_slice(&self.read(REG_RAH).to_le_bytes()[0..2]); } - EthernetAddress::from_bytes(&mac[..]) + EthernetAddress::from_bytes(&mac) } fn link_up(&self) { @@ -294,47 +283,55 @@ impl Device { fn write(&self, addr: u16, data: u32) { unsafe { - if self.bar_type == 0 { - let phys = self.mem_base + addr as usize; - let addr = sys::mem::phys_to_virt(phys).as_usize() as *mut u32; - core::ptr::write_volatile(addr, data); - } else { - outl(self.io_base + IO_ADDR, addr as u32); - outl(self.io_base + IO_DATA, data); + match self.base { + Base::Mem(mem_base) => { + let phys = mem_base + addr as usize; + let virt = sys::mem::phys_to_virt(phys); + let ptr = virt.as_mut_ptr::(); + core::ptr::write_volatile(ptr, data); + } + Base::IO(io_base) => { + outl(io_base + IO_ADDR, addr as u32); + outl(io_base + IO_DATA, data); + } } } } fn read(&self, addr: u16) -> u32 { unsafe { - if self.bar_type == 0 { - let phys = self.mem_base + addr as usize; - let addr = sys::mem::phys_to_virt(phys).as_usize() as *mut u32; - core::ptr::read_volatile(addr) - } else { - outl(self.io_base + IO_ADDR, addr as u32); - inl(self.io_base + IO_DATA) + match self.base { + Base::Mem(mem_base) => { + let phys = mem_base + addr as usize; + let virt = sys::mem::phys_to_virt(phys); + let ptr = virt.as_ptr::(); + core::ptr::read_volatile(ptr) + } + Base::IO(io_base) => { + outl(io_base + IO_ADDR, addr as u32); + inl(io_base + IO_DATA) + } } } } fn detect_eeprom(&mut self) { - self.write(REG_EECD, 1); + self.write(REG_EERD, 1); let mut i = 0; while !self.has_eeprom && i < 1000 { - self.has_eeprom = self.read(REG_EECD) & 0x10 > 0; + self.has_eeprom = self.read(REG_EERD) & 0x10 > 0; i += 1; } } - fn read_eeprom(&self, addr: u16) -> u32 { + fn read_eeprom(&self, addr: u16) -> u16 { let e = if self.has_eeprom { 4 } else { 0 }; - self.write(REG_EECD, 1 | ((addr as u32) << (2 * e))); + self.write(REG_EERD, 1 | ((addr as u32) << (2 * e))); let mut res = 0; while res & (1 << e) == 0 { - res = self.read(REG_EECD); + res = self.read(REG_EERD); } - (res >> 16) & 0xFFFF + (res >> 16) as u16 } #[allow(dead_code)] diff --git a/src/sys/pci.rs b/src/sys/pci.rs index a73fbd3b..7aaf9c3c 100644 --- a/src/sys/pci.rs +++ b/src/sys/pci.rs @@ -96,12 +96,17 @@ impl DeviceConfig { self.command = register.read() as u16; } - pub fn bar_type(&self) -> u16 { - self.base_addresses[0].get_bits(1..3) as u16 + pub fn is_io(&self) -> bool { + self.base_addresses[0].get_bit(0) + } + + pub fn bar_io(&self, n: usize) -> u16 { + debug_assert!(self.is_io()); + (self.base_addresses[n] as u16) & 0xFFFC } pub fn mem_base(&self) -> PhysAddr { - debug_assert!(self.base_addresses[0].get_bit(0) == false); + debug_assert!(!self.is_io()); let bar0 = self.base_addresses[0]; let bar1 = self.base_addresses[1]; let addr = match bar0.get_bits(1..3) { @@ -126,11 +131,6 @@ impl DeviceConfig { }; PhysAddr::new(addr as usize) } - - pub fn bar_io(&self, n: usize) -> u16 { - debug_assert!(self.base_addresses[n].get_bit(0) == true); - (self.base_addresses[n] as u16) & 0xFFF0 - } } lazy_static! { From 94708fd2568f5d9e8f748ee86e41144728b9c018 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sat, 5 Sep 2026 16:48:11 +0200 Subject: [PATCH 3/6] Fix VGA palette parsing --- src/sys/vga/mod.rs | 1 - src/sys/vga/writer.rs | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sys/vga/mod.rs b/src/sys/vga/mod.rs index 77bf67dc..dc6d2439 100644 --- a/src/sys/vga/mod.rs +++ b/src/sys/vga/mod.rs @@ -19,7 +19,6 @@ use bit_field::BitField; use core::cmp; use core::fmt; use core::fmt::Write; -use core::num::ParseIntError; const ATTR_ADDR_REG: u16 = 0x3C0; const ATTR_WRITE_REG: u16 = 0x3C0; diff --git a/src/sys/vga/writer.rs b/src/sys/vga/writer.rs index 3795c013..1dc6315d 100644 --- a/src/sys/vga/writer.rs +++ b/src/sys/vga/writer.rs @@ -549,14 +549,15 @@ impl fmt::Write for Writer { } } -fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ParseIntError> { - debug_assert!(palette.len() == 8); - debug_assert!(palette.starts_with('P')); +fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ()> { + if palette.len() != 8 || !palette.starts_with('P') { + return Err(()); + } - let i = usize::from_str_radix(&palette[1..2], 16)?; - let r = u8::from_str_radix(&palette[2..4], 16)?; - let g = u8::from_str_radix(&palette[4..6], 16)?; - let b = u8::from_str_radix(&palette[6..8], 16)?; + let i = usize::from_str_radix(&palette[1..2], 16).map_err(|_| ())?; + let r = u8::from_str_radix(&palette[2..4], 16).map_err(|_| ())?; + let g = u8::from_str_radix(&palette[4..6], 16).map_err(|_| ())?; + let b = u8::from_str_radix(&palette[6..8], 16).map_err(|_| ())?; Ok((i, r, g, b)) } @@ -565,6 +566,6 @@ fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ParseIntError> { fn test_parse_palette() { assert_eq!(parse_palette("P0282828"), Ok((0, 0x28, 0x28, 0x28))); assert_eq!(parse_palette("P4CC241D"), Ok((4, 0xCC, 0x24, 0x1D))); - assert!(parse_palette("BAAAAAAD").is_ok()); - assert!(parse_palette("GOOOOOOD").is_err()); + assert!(parse_palette("BAD").is_err()); + assert!(parse_palette("BAAAAAAD").is_err()); } From 57e72b62da599b23ae3c8a2624238953861e3949 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sat, 5 Sep 2026 17:07:57 +0200 Subject: [PATCH 4/6] Add nic to test --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 558270d0..20174ec0 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ endif test: cargo test $(test-opts) --no-default-features --features serial -- \ -m $(memory) -cpu $(cpu) -display none -serial stdio \ - -device isa-debug-exit,iobase=0xF4,iosize=0x04 + -device isa-debug-exit,iobase=0xF4,iosize=0x04 -device $(nic) limine-version = 11.3.1 limine-url = https://github.com/Limine-Bootloader/Limine/releases/download/v$(limine-version)/limine-$(limine-version).tar.gz @@ -179,7 +179,7 @@ limine-test: LIMINE_DIR = $(limine-dir) limine-test: cargo test $(test-opts) --no-default-features --features serial,multiboot --target i686-moros.json -- \ -m $(memory) -cpu pentium3 -display none -serial stdio \ - -device isa-debug-exit,iobase=0xF4,iosize=0x04 + -device isa-debug-exit,iobase=0xF4,iosize=0x04 -device $(nic) grub-dir = /usr/lib/grub/i386-pc grub-modules = multiboot2 $(shell cat $(grub-dir)/partmap.lst) From 181e87c452bd2d5153b7abb4aa9f973f6383f39a Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sat, 5 Sep 2026 23:21:59 +0200 Subject: [PATCH 5/6] Update palette test --- src/sys/vga/writer.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sys/vga/writer.rs b/src/sys/vga/writer.rs index 1dc6315d..463afb60 100644 --- a/src/sys/vga/writer.rs +++ b/src/sys/vga/writer.rs @@ -564,8 +564,8 @@ fn parse_palette(palette: &str) -> Result<(usize, u8, u8, u8), ()> { #[test_case] fn test_parse_palette() { - assert_eq!(parse_palette("P0282828"), Ok((0, 0x28, 0x28, 0x28))); - assert_eq!(parse_palette("P4CC241D"), Ok((4, 0xCC, 0x24, 0x1D))); - assert!(parse_palette("BAD").is_err()); - assert!(parse_palette("BAAAAAAD").is_err()); + assert_eq!(parse_palette("P0282828"), Ok((0x0, 0x28, 0x28, 0x28))); + assert_eq!(parse_palette("PADDDDED"), Ok((0xA, 0xDD, 0xDD, 0xED))); + assert_eq!(parse_palette("BAAAAAAD"), Err(())); + assert_eq!(parse_palette("BAD"), Err(())); } From f4eaf099331792bf3d2b5590ae60804a4b16f582 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Sun, 6 Sep 2026 08:47:01 +0200 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e5f1af3..329ac716 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- Allow running test in debug mode (#915) - Use usize milliseconds instead of float seconds for sleep (#916) - Enable process, syscall, and file system on i686 (#914) - Add sys::x86::addr module (#912)