b9874d0941
Add redbear-usb-storage-check in-guest binary that validates USB mass storage read and write I/O: discovers /scheme/disk/ devices, writes a test pattern to sector 2048, reads it back, verifies match, restores original content. Updates test-usb-storage-qemu.sh with write-proof verification step. Includes all accumulated Red Bear OS work: kernel patches, relibc patches, driver infrastructure, DRM/GPU, KDE recipes, firmware, validation tooling, build system hardening, and documentation.
116 lines
3.1 KiB
Rust
116 lines
3.1 KiB
Rust
use std::io::{Read, Write};
|
|
use std::os::unix::io::AsRawFd;
|
|
|
|
use driver_network::NetworkScheme;
|
|
use event::{user_data, EventQueue};
|
|
use pcid_interface::irq_helpers::pci_allocate_interrupt_vector;
|
|
use pcid_interface::PciFunctionHandle;
|
|
|
|
pub mod device;
|
|
|
|
use std::ops::{Add, Div, Rem};
|
|
pub fn div_round_up<T>(a: T, b: T) -> T
|
|
where
|
|
T: Add<Output = T> + Div<Output = T> + Rem<Output = T> + PartialEq + From<u8> + Copy,
|
|
{
|
|
if a % b != T::from(0u8) {
|
|
a / b + T::from(1u8)
|
|
} else {
|
|
a / b
|
|
}
|
|
}
|
|
|
|
fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
|
|
let config = pcid_handle.config();
|
|
|
|
// RTL8139 uses BAR2, RTL8169 uses BAR1, search in that order
|
|
for &barnum in &[2, 1] {
|
|
match config.func.bars[usize::from(barnum)] {
|
|
pcid_interface::PciBar::Memory32 { .. } | pcid_interface::PciBar::Memory64 { .. } => unsafe {
|
|
return pcid_handle.map_bar(barnum).ptr.as_ptr();
|
|
},
|
|
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
|
|
}
|
|
}
|
|
panic!("rtl8139d: failed to find BAR");
|
|
}
|
|
|
|
fn main() {
|
|
pcid_interface::pci_daemon(daemon);
|
|
}
|
|
|
|
fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
|
|
let pci_config = pcid_handle.config();
|
|
|
|
let mut name = pci_config.func.name();
|
|
name.push_str("_rtl8139");
|
|
|
|
common::setup_logging(
|
|
"net",
|
|
"pci",
|
|
&name,
|
|
common::output_level(),
|
|
common::file_level(),
|
|
);
|
|
|
|
log::info!(" + RTL8139 {}", pci_config.func.display());
|
|
|
|
let bar = map_bar(&mut pcid_handle);
|
|
|
|
let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8139d");
|
|
|
|
let mut scheme = NetworkScheme::new(
|
|
move || unsafe {
|
|
device::Rtl8139::new(bar as usize).expect("rtl8139d: failed to allocate device")
|
|
},
|
|
daemon,
|
|
format!("network.{name}"),
|
|
);
|
|
|
|
user_data! {
|
|
enum Source {
|
|
Irq,
|
|
Scheme,
|
|
}
|
|
}
|
|
|
|
let event_queue = EventQueue::<Source>::new().expect("rtl8139d: Could not create event queue.");
|
|
event_queue
|
|
.subscribe(
|
|
irq_file.irq_handle().as_raw_fd() as usize,
|
|
Source::Irq,
|
|
event::EventFlags::READ,
|
|
)
|
|
.unwrap();
|
|
event_queue
|
|
.subscribe(
|
|
scheme.event_handle().raw(),
|
|
Source::Scheme,
|
|
event::EventFlags::READ,
|
|
)
|
|
.unwrap();
|
|
|
|
libredox::call::setrens(0, 0).expect("rtl8139d: failed to enter null namespace");
|
|
|
|
scheme.tick().unwrap();
|
|
|
|
for event in event_queue.map(|e| e.expect("rtl8139d: failed to get next event")) {
|
|
match event.user_data {
|
|
Source::Irq => {
|
|
let mut irq = [0; 8];
|
|
irq_file.irq_handle().read(&mut irq).unwrap();
|
|
//TODO: This may be causing spurious interrupts
|
|
if unsafe { scheme.adapter_mut().irq() } {
|
|
irq_file.irq_handle().write(&mut irq).unwrap();
|
|
|
|
scheme.tick().unwrap();
|
|
}
|
|
}
|
|
Source::Scheme => {
|
|
scheme.tick().unwrap();
|
|
}
|
|
}
|
|
}
|
|
unreachable!()
|
|
}
|