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.
134 lines
3.7 KiB
Rust
134 lines
3.7 KiB
Rust
extern crate orbclient;
|
|
extern crate syscall;
|
|
|
|
use driver_graphics::GraphicsScheme;
|
|
use event::{user_data, EventQueue};
|
|
use std::collections::HashMap;
|
|
use std::env;
|
|
use std::os::fd::AsRawFd;
|
|
|
|
use crate::scheme::{FbAdapter, FrameBuffer};
|
|
|
|
mod scheme;
|
|
|
|
fn main() {
|
|
common::init();
|
|
daemon::Daemon::new(daemon);
|
|
}
|
|
fn daemon(daemon: daemon::Daemon) -> ! {
|
|
if env::var("FRAMEBUFFER_WIDTH").is_err() {
|
|
println!("vesad: No boot framebuffer");
|
|
daemon.ready();
|
|
std::process::exit(0);
|
|
}
|
|
|
|
let width = usize::from_str_radix(
|
|
&env::var("FRAMEBUFFER_WIDTH").expect("FRAMEBUFFER_WIDTH not set"),
|
|
16,
|
|
)
|
|
.expect("failed to parse FRAMEBUFFER_WIDTH");
|
|
let height = usize::from_str_radix(
|
|
&env::var("FRAMEBUFFER_HEIGHT").expect("FRAMEBUFFER_HEIGHT not set"),
|
|
16,
|
|
)
|
|
.expect("failed to parse FRAMEBUFFER_HEIGHT");
|
|
let phys = usize::from_str_radix(
|
|
&env::var("FRAMEBUFFER_ADDR").expect("FRAMEBUFFER_ADDR not set"),
|
|
16,
|
|
)
|
|
.expect("failed to parse FRAMEBUFFER_ADDR");
|
|
let stride = usize::from_str_radix(
|
|
&env::var("FRAMEBUFFER_STRIDE").expect("FRAMEBUFFER_STRIDE not set"),
|
|
16,
|
|
)
|
|
.expect("failed to parse FRAMEBUFFER_STRIDE");
|
|
|
|
println!(
|
|
"vesad: {}x{} stride {} at 0x{:X}",
|
|
width, height, stride, phys
|
|
);
|
|
|
|
if phys == 0 {
|
|
println!("vesad: Boot framebuffer at address 0");
|
|
daemon.ready();
|
|
std::process::exit(0);
|
|
}
|
|
|
|
let mut framebuffers = vec![unsafe { FrameBuffer::new(phys, width, height, stride) }];
|
|
|
|
//TODO: ideal maximum number of outputs?
|
|
let bootloader_env = std::fs::read_to_string("/scheme/sys/env")
|
|
.expect("failed to read env")
|
|
.lines()
|
|
.map(|line| {
|
|
let (env, value) = line.split_once('=').unwrap();
|
|
(env.to_owned(), value.to_owned())
|
|
})
|
|
.collect::<HashMap<String, String>>();
|
|
for i in 1..1024 {
|
|
match bootloader_env.get(&format!("FRAMEBUFFER{}", i)) {
|
|
Some(var) => match unsafe { FrameBuffer::parse(&var) } {
|
|
Some(fb) => {
|
|
println!(
|
|
"vesad: framebuffer {}: {}x{} stride {} at 0x{:X}",
|
|
i, fb.width, fb.height, fb.stride, fb.phys
|
|
);
|
|
framebuffers.push(fb);
|
|
}
|
|
None => {
|
|
eprintln!("vesad: framebuffer {}: failed to parse '{}'", i, var);
|
|
}
|
|
},
|
|
None => break,
|
|
};
|
|
}
|
|
|
|
let mut scheme =
|
|
GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true);
|
|
|
|
user_data! {
|
|
enum Source {
|
|
Input,
|
|
Scheme,
|
|
}
|
|
}
|
|
|
|
let event_queue: EventQueue<Source> =
|
|
EventQueue::new().expect("vesad: failed to create event queue");
|
|
event_queue
|
|
.subscribe(
|
|
scheme.inputd_event_handle().as_raw_fd() as usize,
|
|
Source::Input,
|
|
event::EventFlags::READ,
|
|
)
|
|
.unwrap();
|
|
event_queue
|
|
.subscribe(
|
|
scheme.event_handle().raw(),
|
|
Source::Scheme,
|
|
event::EventFlags::READ,
|
|
)
|
|
.unwrap();
|
|
|
|
libredox::call::setrens(0, 0).expect("vesad: failed to enter null namespace");
|
|
|
|
daemon.ready();
|
|
|
|
let all = [Source::Input, Source::Scheme];
|
|
for event in all
|
|
.into_iter()
|
|
.chain(event_queue.map(|e| e.expect("vesad: failed to get next event").user_data))
|
|
{
|
|
match event {
|
|
Source::Input => scheme.handle_vt_events(),
|
|
Source::Scheme => {
|
|
scheme
|
|
.tick()
|
|
.expect("vesad: failed to handle scheme events");
|
|
}
|
|
}
|
|
}
|
|
|
|
panic!();
|
|
}
|