Merge branch 'daemon_improvements2' into 'main'

Various improvements to the way daemons work

See merge request redox-os/base!48
This commit is contained in:
Jeremy Soller
2025-12-05 17:31:52 -07:00
40 changed files with 977 additions and 1006 deletions
+6 -2
View File
@@ -88,7 +88,11 @@ fn daemon(daemon: Daemon) -> anyhow::Result<()> {
}
fn main() {
Daemon::new(|x| match daemon(x) {
Daemon::new(inner);
}
fn inner(x: Daemon) -> ! {
match daemon(x) {
Ok(()) => {
process::exit(0);
}
@@ -96,5 +100,5 @@ fn main() {
eprintln!("audiod: {}", err);
process::exit(1);
}
});
}
}
+3 -1
View File
@@ -20,11 +20,13 @@ plain = "0.2"
redox-initfs = { path = "../initfs", default-features = false }
redox_syscall = { version = "0.5.4", default-features = false }
redox-scheme = { version = "0.6", default-features = false }
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false }
redox-path = "0.3.1"
slab = { version = "0.4.9", default-features = false }
arrayvec = { version = "0.7.6", default-features = false }
[target.'cfg(target_os = "redox")'.dependencies]
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false }
[profile.release]
panic = "abort"
lto = "fat"
+1 -1
View File
@@ -90,7 +90,7 @@ pub fn main() -> ! {
// from this point, this_thr_fd is no longer valid
const CWD: &[u8] = b"/scheme/initfs";
const DEFAULT_SCHEME: &[u8] = b"initfs";
const DEFAULT_SCHEME: &[u8] = b"file";
let extrainfo = ExtraInfo {
cwd: Some(CWD),
default_scheme: Some(DEFAULT_SCHEME),
+97 -99
View File
@@ -18,7 +18,10 @@ use std::cell::RefCell;
pub mod device;
fn main() {
let pcid_handle = PciFunctionHandle::connect_default();
pcid_interface::pci_daemon(daemon);
}
fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -34,106 +37,101 @@ fn main() {
println!(" + ac97 {}", pci_config.func.display());
// Daemonize
daemon::Daemon::new(move |daemon| {
common::setup_logging(
"audio",
"pci",
&name,
common::output_level(),
common::file_level(),
);
common::setup_logging(
"audio",
"pci",
&name,
common::output_level(),
common::file_level(),
);
common::acquire_port_io_rights()
.expect("ac97d: failed to set I/O privilege level to Ring 3");
common::acquire_port_io_rights().expect("ac97d: failed to set I/O privilege level to Ring 3");
let mut irq_file = irq.irq_handle("ac97d");
let mut irq_file = irq.irq_handle("ac97d");
let device = RefCell::new(unsafe {
device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device")
});
let socket = Socket::nonblock("audiohw").expect("ac97d: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue =
EventQueue::<Source>::new().expect("ac97d: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
daemon.ready();
libredox::call::setrens(0, 0).expect("ac97d: failed to enter null namespace");
let all = [Source::Irq, Source::Scheme];
for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("ac97d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("ac97d: failed to poll requests");
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("ac97d: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("ac97d: failed to write to socket")
{
break;
}
/*
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
}
std::process::exit(0);
let device = RefCell::new(unsafe {
device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device")
});
let socket = Socket::nonblock("audiohw").expect("ac97d: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue = EventQueue::<Source>::new().expect("ac97d: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
daemon.ready();
libredox::call::setrens(0, 0).expect("ac97d: failed to enter null namespace");
let all = [Source::Irq, Source::Scheme];
for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("ac97d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("ac97d: failed to poll requests");
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("ac97d: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("ac97d: failed to write to socket")
{
break;
}
/*
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
}
std::process::exit(0);
}
+4 -7
View File
@@ -23,9 +23,11 @@ QEMU ICH9 8086:293E
82801H ICH8 8086:284B
*/
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -138,8 +140,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
std::process::exit(0);
}
}
fn main() {
// Daemonize
daemon::Daemon::new(daemon);
}
+79 -80
View File
@@ -11,6 +11,10 @@ use event::{user_data, EventQueue};
pub mod device;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut args = env::args().skip(1);
let addr_str = args.next().unwrap_or("220".to_string());
@@ -18,99 +22,94 @@ fn main() {
println!(" + sb16 at 0x{:X}\n", addr);
// Daemonize
daemon::Daemon::new(move |daemon| {
common::setup_logging(
"audio",
"pci",
"sb16",
common::output_level(),
common::file_level(),
);
common::setup_logging(
"audio",
"pci",
"sb16",
common::output_level(),
common::file_level(),
);
common::acquire_port_io_rights().expect("sb16d: failed to acquire port IO rights");
common::acquire_port_io_rights().expect("sb16d: failed to acquire port IO rights");
let device = RefCell::new(unsafe {
device::Sb16::new(addr).expect("sb16d: failed to allocate device")
});
let socket = Socket::nonblock("audiohw").expect("sb16d: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
let device =
RefCell::new(unsafe { device::Sb16::new(addr).expect("sb16d: failed to allocate device") });
let socket = Socket::nonblock("audiohw").expect("sb16d: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
//TODO: error on multiple IRQs?
let irq_file = match device.borrow().irqs.first() {
Some(irq) => Fd::open(&format!("/scheme/irq/{}", irq), flag::O_RDWR, 0)
.expect("sb16d: failed to open IRQ file"),
None => panic!("sb16d: no IRQs found"),
};
user_data! {
enum Source {
Irq,
Scheme,
}
//TODO: error on multiple IRQs?
let irq_file = match device.borrow().irqs.first() {
Some(irq) => Fd::open(&format!("/scheme/irq/{}", irq), flag::O_RDWR, 0)
.expect("sb16d: failed to open IRQ file"),
None => panic!("sb16d: no IRQs found"),
};
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue =
EventQueue::<Source>::new().expect("sb16d: Could not create event queue.");
event_queue
.subscribe(irq_file.raw(), Source::Irq, event::EventFlags::READ)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
let event_queue = EventQueue::<Source>::new().expect("sb16d: Could not create event queue.");
event_queue
.subscribe(irq_file.raw(), Source::Irq, event::EventFlags::READ)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
daemon.ready();
daemon.ready();
libredox::call::setrens(0, 0).expect("sb16d: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("sb16d: failed to enter null namespace");
let all = [Source::Irq, Source::Scheme];
let all = [Source::Irq, Source::Scheme];
for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("sb16d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("sb16d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !device.borrow_mut().irq() {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("sb16d: failed to poll requests");
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
if !device.borrow_mut().irq() {
continue;
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("sb16d: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("sb16d: failed to write to socket")
{
break;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("sb16d: failed to poll requests");
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("sb16d: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("sb16d: failed to write to socket")
{
break;
}
}
}
}
std::process::exit(0);
});
std::process::exit(0);
}
+37 -36
View File
@@ -13,7 +13,10 @@ mod scheme;
// FIXME add a driver-graphics implementation
fn main() {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -29,46 +32,44 @@ fn main() {
log::info!("BGA {}", pci_config.func.display());
daemon::Daemon::new(move |daemon| {
let socket = Socket::create("bga").expect("bgad: failed to create bga scheme");
let socket = Socket::create("bga").expect("bgad: failed to create bga scheme");
let bar = unsafe { pcid_handle.map_bar(2) }.ptr.as_ptr();
let bar = unsafe { pcid_handle.map_bar(2) }.ptr.as_ptr();
let mut bga = unsafe { Bga::new(bar) };
log::debug!("BGA {}x{}", bga.width(), bga.height());
let mut bga = unsafe { Bga::new(bar) };
log::debug!("BGA {}x{}", bga.width(), bga.height());
let mut scheme = BgaScheme {
bga,
display: ProducerHandle::new().ok(),
let mut scheme = BgaScheme {
bga,
display: ProducerHandle::new().ok(),
};
scheme.update_size();
libredox::call::setrens(0, 0).expect("bgad: failed to enter null namespace");
daemon.ready();
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("bgad: failed to get next scheme request")
else {
// Scheme likely got unmounted
std::process::exit(0);
};
match request.kind() {
RequestKind::Call(call) => {
let response = call.handle_sync(&mut scheme);
scheme.update_size();
libredox::call::setrens(0, 0).expect("bgad: failed to enter null namespace");
daemon.ready();
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("bgad: failed to get next scheme request")
else {
// Scheme likely got unmounted
std::process::exit(0);
};
match request.kind() {
RequestKind::Call(call) => {
let response = call.handle_sync(&mut scheme);
socket
.write_response(response, SignalBehavior::Restart)
.expect("bgad: failed to write next scheme response");
}
RequestKind::OnClose { id } => {
scheme.on_close(id);
}
_ => (),
socket
.write_response(response, SignalBehavior::Restart)
.expect("bgad: failed to write next scheme response");
}
RequestKind::OnClose { id } => {
scheme.on_close(id);
}
_ => (),
}
});
}
}
+2 -2
View File
@@ -21,9 +21,9 @@ use crate::scheme::FbbootlogScheme;
mod scheme;
fn main() {
daemon::Daemon::new(|daemon| inner(daemon));
daemon::Daemon::new(daemon);
}
fn inner(daemon: daemon::Daemon) -> ! {
fn daemon(daemon: daemon::Daemon) -> ! {
let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue");
event::user_data! {
+4 -4
View File
@@ -13,6 +13,9 @@ mod scheme;
mod text;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let vt_ids = env::args()
.skip(1)
.map(|arg| arg.parse().expect("invalid vt number"))
@@ -26,9 +29,6 @@ fn main() {
common::file_level(),
);
daemon::Daemon::new(|daemon| inner(daemon, &vt_ids));
}
fn inner(daemon: daemon::Daemon, vt_ids: &[usize]) -> ! {
let mut event_queue = EventQueue::new().expect("fbcond: failed to create event queue");
// FIXME listen for resize events from inputd and handle them
@@ -42,7 +42,7 @@ fn inner(daemon: daemon::Daemon, vt_ids: &[usize]) -> ! {
)
.expect("fbcond: failed to subscribe to scheme events");
let mut scheme = FbconScheme::new(vt_ids, &mut event_queue);
let mut scheme = FbconScheme::new(&vt_ids, &mut event_queue);
// This is not possible for now as fbcond needs to open new displays at runtime for graphics
// driver handoff. In the future inputd may directly pass a handle to the display instead.
+7 -5
View File
@@ -12,9 +12,13 @@ use crate::scheme::{FbAdapter, FrameBuffer};
mod scheme;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
if env::var("FRAMEBUFFER_WIDTH").is_err() {
println!("vesad: No boot framebuffer");
return;
daemon.ready();
std::process::exit(0);
}
let width = usize::from_str_radix(
@@ -45,7 +49,8 @@ fn main() {
if phys == 0 {
println!("vesad: Boot framebuffer at address 0");
return;
daemon.ready();
std::process::exit(0);
}
let mut framebuffers = vec![unsafe { FrameBuffer::new(phys, width, height, stride) }];
@@ -69,9 +74,6 @@ fn main() {
};
}
daemon::Daemon::new(|daemon| inner(daemon, framebuffers));
}
fn inner(daemon: daemon::Daemon, framebuffers: Vec<FrameBuffer>) -> ! {
let mut inputd_display_handle = DisplayHandle::new_early("vesa").unwrap();
let mut scheme = GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned());
+17 -18
View File
@@ -430,8 +430,23 @@ impl MoveCursor {
static DEVICE: spin::Once<virtio_core::Device> = spin::Once::new();
fn deamon(deamon: daemon::Daemon) -> anyhow::Result<()> {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn main() {
pcid_interface::pci_daemon(daemon_runner);
}
fn daemon_runner(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
deamon(daemon, pcid_handle).unwrap();
unreachable!();
}
fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow::Result<()> {
common::setup_logging(
"graphics",
"pci",
"virtio-gpud",
common::output_level(),
common::file_level(),
);
// Double check that we have the right device.
//
@@ -542,19 +557,3 @@ fn deamon(deamon: daemon::Daemon) -> anyhow::Result<()> {
std::process::exit(0);
}
fn daemon_runner(daemon: daemon::Daemon) -> ! {
deamon(daemon).unwrap();
unreachable!();
}
pub fn main() {
common::setup_logging(
"graphics",
"pci",
"virtio-gpud",
common::output_level(),
common::file_level(),
);
daemon::Daemon::new(daemon_runner);
}
+86 -86
View File
@@ -19,6 +19,10 @@ use std::cell::RefCell;
pub mod device;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut args = env::args().skip(1);
let mut name = args.next().expect("alxd: no name provided");
@@ -32,106 +36,102 @@ fn main() {
println!(" + ALX {} on: {:X}, IRQ: {}\n", name, bar, irq);
// Daemonize
daemon::Daemon::new(move |daemon| {
let socket = Socket::nonblock("network").expect("alxd: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
let socket = Socket::nonblock("network").expect("alxd: failed to create socket");
let mut readiness_based = ReadinessBased::new(&socket, 16);
daemon.ready();
daemon.ready();
let mut irq_file =
File::open(format!("/scheme/irq/{}", irq)).expect("alxd: failed to open IRQ file");
let mut irq_file =
File::open(format!("/scheme/irq/{}", irq)).expect("alxd: failed to open IRQ file");
let address = unsafe {
common::physmap(
bar,
128 * 1024,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
.expect("alxd: failed to map address") as usize
};
{
let device = RefCell::new(unsafe {
device::Alx::new(address).expect("alxd: failed to allocate device")
});
let address = unsafe {
common::physmap(
bar,
128 * 1024,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
.expect("alxd: failed to map address") as usize
};
{
let device = RefCell::new(unsafe {
device::Alx::new(address).expect("alxd: failed to allocate device")
});
user_data! {
enum Source {
Irq,
Scheme,
}
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue =
EventQueue::<Source>::new().expect("alxd: failed to create event queue");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
let event_queue = EventQueue::<Source>::new().expect("alxd: failed to create event queue");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
socket.inner().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
libredox::call::setrens(0, 0).expect("alxd: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("alxd: failed to enter null namespace");
for event in iter::once(Source::Scheme)
.chain(event_queue.map(|e| e.expect("alxd: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !unsafe { device.borrow_mut().intr_legacy() } {
continue;
}
irq_file.write(&mut irq).unwrap();
for event in iter::once(Source::Scheme)
.chain(event_queue.map(|e| e.expect("alxd: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if !unsafe { device.borrow_mut().intr_legacy() } {
continue;
}
irq_file.write(&mut irq).unwrap();
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("ihdad: failed to poll requests");
readiness_based
.poll_all_requests(|| device.borrow_mut())
.expect("ihdad: failed to poll requests");
/* TODO: Currently a no-op
let next_read = device.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
/* TODO: Currently a no-op
let next_read = device.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("alxd: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("alxd: failed to write to socket")
{
break;
}
Source::Scheme => {
if !readiness_based
.read_requests()
.expect("alxd: failed to read from socket")
{
break;
}
readiness_based.process_requests(|| device.borrow_mut());
if !readiness_based
.write_responses()
.expect("alxd: failed to write to socket")
{
break;
}
// TODO
/*
let next_read = device.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
// TODO
/*
let next_read = device.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
}
std::process::exit(0);
});
}
std::process::exit(0);
}
+46 -46
View File
@@ -8,7 +8,10 @@ use pcid_interface::PciFunctionHandle;
pub mod device;
fn main() {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -29,62 +32,59 @@ fn main() {
log::info!("E1000 {}", pci_config.func.display());
daemon::Daemon::new(move |daemon| {
let mut irq_file = irq.irq_handle("e1000d");
let mut irq_file = irq.irq_handle("e1000d");
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
let mut scheme = NetworkScheme::new(
move || unsafe {
device::Intel8254x::new(address).expect("e1000d: failed to allocate device")
},
daemon,
format!("network.{name}"),
);
let mut scheme = NetworkScheme::new(
move || unsafe {
device::Intel8254x::new(address).expect("e1000d: failed to allocate device")
},
daemon,
format!("network.{name}"),
);
user_data! {
enum Source {
Irq,
Scheme,
}
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue =
EventQueue::<Source>::new().expect("e1000d: failed to create event queue");
let event_queue = EventQueue::<Source>::new().expect("e1000d: failed to create event queue");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to IRQ fd");
event_queue
.subscribe(
scheme.event_handle().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to scheme fd");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to IRQ fd");
event_queue
.subscribe(
scheme.event_handle().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to scheme fd");
libredox::call::setrens(0, 0).expect("e1000d: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("e1000d: failed to enter null namespace");
scheme.tick().unwrap();
scheme.tick().unwrap();
for event in event_queue.map(|e| e.expect("e1000d: failed to get event")) {
match event.user_data {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if unsafe { scheme.adapter().irq() } {
irq_file.write(&mut irq).unwrap();
for event in event_queue.map(|e| e.expect("e1000d: failed to get event")) {
match event.user_data {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if unsafe { scheme.adapter().irq() } {
irq_file.write(&mut irq).unwrap();
scheme.tick().expect("e1000d: failed to handle IRQ")
}
scheme.tick().expect("e1000d: failed to handle IRQ")
}
Source::Scheme => scheme.tick().expect("e1000d: failed to handle scheme op"),
}
Source::Scheme => scheme.tick().expect("e1000d: failed to handle scheme op"),
}
unreachable!()
});
}
unreachable!()
}
+50 -50
View File
@@ -10,7 +10,10 @@ pub mod device;
mod ixgbe;
fn main() {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -23,66 +26,63 @@ fn main() {
println!(" + IXGBE {}", pci_config.func.display());
daemon::Daemon::new(move |daemon| {
let mut irq_file = irq.irq_handle("ixgbed");
let mut irq_file = irq.irq_handle("ixgbed");
let mapped_bar = unsafe { pcid_handle.map_bar(0) };
let address = mapped_bar.ptr.as_ptr();
let size = mapped_bar.bar_size;
let mapped_bar = unsafe { pcid_handle.map_bar(0) };
let address = mapped_bar.ptr.as_ptr();
let size = mapped_bar.bar_size;
let mut scheme = NetworkScheme::new(
move || {
device::Intel8259x::new(address as usize, size)
.expect("ixgbed: failed to allocate device")
},
daemon,
format!("network.{name}"),
);
let mut scheme = NetworkScheme::new(
move || {
device::Intel8259x::new(address as usize, size)
.expect("ixgbed: failed to allocate device")
},
daemon,
format!("network.{name}"),
);
user_data! {
enum Source {
Irq,
Scheme,
}
user_data! {
enum Source {
Irq,
Scheme,
}
}
let event_queue =
EventQueue::<Source>::new().expect("ixgbed: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
scheme.event_handle().raw(),
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
let event_queue = EventQueue::<Source>::new().expect("ixgbed: Could not create event queue.");
event_queue
.subscribe(
irq_file.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("ixgbed: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("ixgbed: failed to enter null namespace");
scheme.tick().unwrap();
scheme.tick().unwrap();
for event in event_queue.map(|e| e.expect("ixgbed: failed to get next event")) {
match event.user_data {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if scheme.adapter().irq() {
irq_file.write(&mut irq).unwrap();
for event in event_queue.map(|e| e.expect("ixgbed: failed to get next event")) {
match event.user_data {
Source::Irq => {
let mut irq = [0; 8];
irq_file.read(&mut irq).unwrap();
if scheme.adapter().irq() {
irq_file.write(&mut irq).unwrap();
scheme.tick().unwrap();
}
}
Source::Scheme => {
scheme.tick().unwrap();
}
}
Source::Scheme => {
scheme.tick().unwrap();
}
}
unreachable!()
});
}
unreachable!()
}
+4 -6
View File
@@ -35,9 +35,11 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
panic!("rtl8139d: failed to find BAR");
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -111,7 +113,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
}
unreachable!()
}
fn main() {
daemon::Daemon::new(daemon);
}
+4 -6
View File
@@ -35,9 +35,11 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
panic!("rtl8168d: failed to find BAR");
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -111,7 +113,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
}
unreachable!()
}
fn main() {
daemon::Daemon::new(daemon);
}
+19 -18
View File
@@ -26,9 +26,26 @@ pub struct VirtHeader {
static_assertions::const_assert_eq!(core::mem::size_of::<VirtHeader>(), 12);
const MAX_BUFFER_LEN: usize = 65535;
fn main() {
pcid_interface::pci_daemon(daemon_runner);
}
fn deamon(daemon: daemon::Daemon) -> Result<(), Box<dyn std::error::Error>> {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn daemon_runner(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
deamon(daemon, pcid_handle).unwrap();
unreachable!();
}
fn deamon(
daemon: daemon::Daemon,
mut pcid_handle: PciFunctionHandle,
) -> Result<(), Box<dyn std::error::Error>> {
common::setup_logging(
"net",
"pci",
"virtio-netd",
common::output_level(),
common::file_level(),
);
// Double check that we have the right device.
//
@@ -118,19 +135,3 @@ fn deamon(daemon: daemon::Daemon) -> Result<(), Box<dyn std::error::Error>> {
scheme.tick()?;
}
}
fn daemon_runner(daemon: daemon::Daemon) -> ! {
deamon(daemon).unwrap();
unreachable!();
}
pub fn main() {
common::setup_logging(
"net",
"pci",
"virtio-netd",
common::output_level(),
common::file_level(),
);
daemon::Daemon::new(daemon_runner);
}
+9 -1
View File
@@ -6,6 +6,7 @@ use std::ptr::NonNull;
use std::{env, io};
use std::{fmt, process};
use daemon::Daemon;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub use bar::PciBar;
@@ -297,7 +298,7 @@ fn recv<T: DeserializeOwned>(r: &mut File) -> T {
}
impl PciFunctionHandle {
pub fn connect_default() -> Self {
fn connect_default() -> Self {
let channel_fd = match env::var("PCID_CLIENT_CHANNEL") {
Ok(channel_fd) => channel_fd,
Err(err) => {
@@ -471,3 +472,10 @@ impl PciFunctionHandle {
}
}
}
pub fn pci_daemon<F: FnOnce(Daemon, PciFunctionHandle) -> !>(f: F) -> ! {
Daemon::new(|daemon| {
let pcid_handle = PciFunctionHandle::connect_default();
f(daemon, pcid_handle)
})
}
+2
View File
@@ -1,4 +1,6 @@
//! Interface to `pcid`.
#![feature(never_type)]
mod driver_interface;
pub use driver_interface::*;
+4 -4
View File
@@ -187,6 +187,10 @@ fn enable_function(
}
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut args = pico_args::Arguments::from_env();
let verbosity = (0..).find(|_| !args.contains("-v")).unwrap_or(0);
let log_level = match verbosity {
@@ -197,10 +201,6 @@ fn main() {
common::setup_logging("bus", "pci", "pcid", log_level, log::LevelFilter::Info);
daemon::Daemon::new(move |daemon| main_inner(daemon));
}
fn main_inner(daemon: daemon::Daemon) -> ! {
let pcie = Pcie::new();
let mut tree = BTreeMap::new();
+2 -3
View File
@@ -14,11 +14,10 @@ use log::{error, info};
pub mod ahci;
fn main() {
daemon::Daemon::new(daemon);
pcid_interface::pci_daemon(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
+2 -4
View File
@@ -18,12 +18,10 @@ use crate::ide::{AtaCommand, AtaDisk, Channel};
pub mod ide;
fn main() {
daemon::Daemon::new(daemon);
pcid_interface::pci_daemon(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let pcid_handle = PciFunctionHandle::connect_default();
fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
+44 -40
View File
@@ -103,13 +103,18 @@ impl Disk for LiveDisk {
}
}
fn main() -> anyhow::Result<()> {
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut phys = 0;
let mut size = 0;
// TODO: handle error
for line in std::fs::read_to_string("/scheme/sys/env")
.context("failed to read env")?
.context("failed to read env")
.unwrap()
.lines()
{
let mut parts = line.splitn(2, '=');
@@ -126,48 +131,47 @@ fn main() -> anyhow::Result<()> {
}
if phys == 0 || size == 0 {
// No live disk data, no need to say anything or exit with error
// No live disk data, no need to say anything or exit with
daemon.ready();
std::process::exit(0);
}
daemon::Daemon::new(move |daemon| {
let event_queue = event::EventQueue::new().unwrap();
let event_queue = event::EventQueue::new().unwrap();
event::user_data! {
enum Event {
Scheme,
}
};
let mut scheme = DiskScheme::new(
Some(daemon),
"disk.live".to_owned(),
BTreeMap::from([(
0,
LiveDisk::new(phys, size).unwrap_or_else(|err| {
eprintln!("failed to initialize livedisk scheme: {}", err);
std::process::exit(1)
}),
)]),
&TrivialExecutor,
);
libredox::call::setrens(0, 0).expect("nvmed: failed to enter null namespace");
event_queue
.subscribe(
scheme.event_handle().raw(),
Event::Scheme,
event::EventFlags::READ,
)
.unwrap();
for event in event_queue {
match event.unwrap().user_data {
Event::Scheme => TrivialExecutor.block_on(scheme.tick()).unwrap(),
}
event::user_data! {
enum Event {
Scheme,
}
};
std::process::exit(0);
});
let mut scheme = DiskScheme::new(
Some(daemon),
"disk.live".to_owned(),
BTreeMap::from([(
0,
LiveDisk::new(phys, size).unwrap_or_else(|err| {
eprintln!("failed to initialize livedisk scheme: {}", err);
std::process::exit(1)
}),
)]),
&TrivialExecutor,
);
libredox::call::setrens(0, 0).expect("nvmed: failed to enter null namespace");
event_queue
.subscribe(
scheme.event_handle().raw(),
Event::Scheme,
event::EventFlags::READ,
)
.unwrap();
for event in event_queue {
match event.unwrap().user_data {
Event::Scheme => TrivialExecutor.block_on(scheme.tick()).unwrap(),
}
}
std::process::exit(0);
}
+3 -3
View File
@@ -57,10 +57,10 @@ fn time_arm(time_handle: &mut File, secs: i64) -> io::Result<()> {
}
fn main() {
daemon::Daemon::new(daemon);
pcid_interface::pci_daemon(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
let pci_config = pcid_handle.config();
let scheme_name = format!("disk.{}-nvme", pci_config.func.name());
+3 -3
View File
@@ -12,6 +12,9 @@ use crate::protocol::Protocol;
use crate::scsi::Scsi;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut args = env::args().skip(1);
const USAGE: &'static str = "usbscsid <scheme> <port> <protocol>";
@@ -33,9 +36,6 @@ fn main() {
scheme, port, protocol
);
daemon::Daemon::new(move |d| daemon(d, scheme, port, protocol));
}
fn daemon(daemon: daemon::Daemon, scheme: String, port: PortId, protocol: u8) -> ! {
let disk_scheme_name = format!("disk.usb-{scheme}+{port}-scsi");
// TODO: Use eventfds.
+17 -18
View File
@@ -30,17 +30,6 @@ pub enum Error {
SyscallError(syscall::Error),
}
pub fn main() {
common::setup_logging(
"disk",
"pci",
"virtio-blkd",
common::output_level(),
common::file_level(),
);
daemon::Daemon::new(daemon_runner);
}
#[repr(C)]
pub struct BlockGeometry {
pub cylinders: VolatileCell<u16>,
@@ -109,8 +98,23 @@ pub struct BlockVirtRequest {
const_assert_eq!(core::mem::size_of::<BlockVirtRequest>(), 16);
fn daemon(daemon: daemon::Daemon) -> anyhow::Result<()> {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn main() {
pcid_interface::pci_daemon(daemon_runner);
}
fn daemon_runner(redox_daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! {
daemon(redox_daemon, pcid_handle).unwrap();
unreachable!();
}
fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow::Result<()> {
common::setup_logging(
"disk",
"pci",
"virtio-blkd",
common::output_level(),
common::file_level(),
);
// Double check that we have the right device.
//
@@ -176,8 +180,3 @@ fn daemon(daemon: daemon::Daemon) -> anyhow::Result<()> {
Ok(())
}
fn daemon_runner(redox_daemon: daemon::Daemon) -> ! {
daemon(redox_daemon).unwrap();
unreachable!();
}
+5 -6
View File
@@ -115,10 +115,6 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
}
}
fn main() {
daemon::Daemon::new(daemon);
}
//TODO: cleanup CSZ support
fn daemon_with_context_size<const N: usize>(
daemon: daemon::Daemon,
@@ -185,8 +181,11 @@ fn daemon_with_context_size<const N: usize>(
}
}
fn daemon(daemon: daemon::Daemon) -> ! {
let mut pcid_handle = PciFunctionHandle::connect_default();
fn main() {
pcid_interface::pci_daemon(daemon);
}
fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
let cap = unsafe { &mut *(address as *mut xhci::CapabilityRegs) };
if cap.csz() {
+108 -110
View File
@@ -191,7 +191,10 @@ impl VboxGuestInfo {
}
fn main() {
let mut pcid_handle = PciFunctionHandle::connect_default();
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();
@@ -206,129 +209,124 @@ fn main() {
println!(" + VirtualBox {}", pci_config.func.display());
// Daemonize
daemon::Daemon::new(move |daemon| {
common::acquire_port_io_rights().expect("vboxd: failed to get I/O permission");
common::acquire_port_io_rights().expect("vboxd: failed to get I/O permission");
let mut width = 0;
let mut height = 0;
let mut display_opt = File::open("inputd:producer").ok();
if let Some(ref display) = display_opt {
let mut buf: [u8; 4096] = [0; 4096];
if let Ok(count) = libredox::call::fpath(display.as_raw_fd() as usize, &mut buf) {
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
let res = path.split(":").nth(1).unwrap_or("");
width = res
.split("/")
.nth(1)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
height = res
.split("/")
.nth(2)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
let mut width = 0;
let mut height = 0;
let mut display_opt = File::open("inputd:producer").ok();
if let Some(ref display) = display_opt {
let mut buf: [u8; 4096] = [0; 4096];
if let Ok(count) = libredox::call::fpath(display.as_raw_fd() as usize, &mut buf) {
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
let res = path.split(":").nth(1).unwrap_or("");
width = res
.split("/")
.nth(1)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
height = res
.split("/")
.nth(2)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
}
}
let mut irq_file = irq.irq_handle("vboxd");
let mut port = Pio::<u32>::new(bar0 as u16);
let address = unsafe { pcid_handle.map_bar(1) }.ptr.as_ptr();
{
let vmmdev = unsafe { &mut *(address as *mut VboxVmmDev) };
let mut guest_info = VboxGuestInfo::new().expect("vboxd: failed to map GuestInfo");
guest_info.version.write(VBOX_VMMDEV_VERSION);
guest_info.ostype.write(0x100);
port.write(guest_info.physical() as u32);
let mut guest_caps = VboxGuestCaps::new().expect("vboxd: failed to map GuestCaps");
guest_caps.caps.write(1 << 2);
port.write(guest_caps.physical() as u32);
let mut set_mouse = VboxSetMouse::new().expect("vboxd: failed to map SetMouse");
set_mouse.features.write(1 << 4 | 1);
port.write(set_mouse.physical() as u32);
vmmdev
.guest_events
.write(VBOX_EVENT_DISPLAY | VBOX_EVENT_MOUSE);
user_data! {
enum Source {
Irq,
}
}
let mut irq_file = irq.irq_handle("vboxd");
let event_queue =
EventQueue::<Source>::new().expect("vboxd: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
let mut port = Pio::<u32>::new(bar0 as u16);
let address = unsafe { pcid_handle.map_bar(1) }.ptr.as_ptr();
daemon.ready();
libredox::call::setrens(0, 0).expect("vboxd: failed to enter null namespace");
let mut bga = Bga::new();
let get_mouse = VboxGetMouse::new().expect("vboxd: failed to map GetMouse");
let display_change = VboxDisplayChange::new().expect("vboxd: failed to map DisplayChange");
let ack_events = VboxAckEvents::new().expect("vboxd: failed to map AckEvents");
for Source::Irq in iter::once(Source::Irq)
.chain(event_queue.map(|e| e.expect("vboxd: failed to get next event").user_data))
{
let vmmdev = unsafe { &mut *(address as *mut VboxVmmDev) };
let mut irq = [0; 8];
if irq_file.read(&mut irq).unwrap() >= irq.len() {
let host_events = vmmdev.host_events.read();
if host_events != 0 {
port.write(ack_events.physical() as u32);
irq_file.write(&irq).unwrap();
let mut guest_info = VboxGuestInfo::new().expect("vboxd: failed to map GuestInfo");
guest_info.version.write(VBOX_VMMDEV_VERSION);
guest_info.ostype.write(0x100);
port.write(guest_info.physical() as u32);
let mut guest_caps = VboxGuestCaps::new().expect("vboxd: failed to map GuestCaps");
guest_caps.caps.write(1 << 2);
port.write(guest_caps.physical() as u32);
let mut set_mouse = VboxSetMouse::new().expect("vboxd: failed to map SetMouse");
set_mouse.features.write(1 << 4 | 1);
port.write(set_mouse.physical() as u32);
vmmdev
.guest_events
.write(VBOX_EVENT_DISPLAY | VBOX_EVENT_MOUSE);
user_data! {
enum Source {
Irq,
}
}
let event_queue =
EventQueue::<Source>::new().expect("vboxd: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
daemon.ready();
libredox::call::setrens(0, 0).expect("vboxd: failed to enter null namespace");
let mut bga = Bga::new();
let get_mouse = VboxGetMouse::new().expect("vboxd: failed to map GetMouse");
let display_change =
VboxDisplayChange::new().expect("vboxd: failed to map DisplayChange");
let ack_events = VboxAckEvents::new().expect("vboxd: failed to map AckEvents");
for Source::Irq in iter::once(Source::Irq)
.chain(event_queue.map(|e| e.expect("vboxd: failed to get next event").user_data))
{
let mut irq = [0; 8];
if irq_file.read(&mut irq).unwrap() >= irq.len() {
let host_events = vmmdev.host_events.read();
if host_events != 0 {
port.write(ack_events.physical() as u32);
irq_file.write(&irq).unwrap();
if host_events & VBOX_EVENT_DISPLAY == VBOX_EVENT_DISPLAY {
port.write(display_change.physical() as u32);
if let Some(ref mut display) = display_opt {
let new_width = display_change.xres.read();
let new_height = display_change.yres.read();
if width != new_width || height != new_height {
width = new_width;
height = new_height;
println!("Display {}, {}", width, height);
bga.set_size(width as u16, height as u16);
let _ = display.write(
&orbclient::ResizeEvent { width, height }.to_event(),
);
}
if host_events & VBOX_EVENT_DISPLAY == VBOX_EVENT_DISPLAY {
port.write(display_change.physical() as u32);
if let Some(ref mut display) = display_opt {
let new_width = display_change.xres.read();
let new_height = display_change.yres.read();
if width != new_width || height != new_height {
width = new_width;
height = new_height;
println!("Display {}, {}", width, height);
bga.set_size(width as u16, height as u16);
let _ = display
.write(&orbclient::ResizeEvent { width, height }.to_event());
}
}
}
if host_events & VBOX_EVENT_MOUSE == VBOX_EVENT_MOUSE {
port.write(get_mouse.physical() as u32);
if let Some(ref mut display) = display_opt {
let x = get_mouse.x.read() * width / 0x10000;
let y = get_mouse.y.read() * height / 0x10000;
let _ = display.write(
&orbclient::MouseEvent {
x: x as i32,
y: y as i32,
}
.to_event(),
);
}
if host_events & VBOX_EVENT_MOUSE == VBOX_EVENT_MOUSE {
port.write(get_mouse.physical() as u32);
if let Some(ref mut display) = display_opt {
let x = get_mouse.x.read() * width / 0x10000;
let y = get_mouse.y.read() * height / 0x10000;
let _ = display.write(
&orbclient::MouseEvent {
x: x as i32,
y: y as i32,
}
.to_event(),
);
}
}
}
}
}
}
std::process::exit(0);
});
std::process::exit(0);
}
+1 -2
View File
@@ -1,6 +1,6 @@
# Various daemons that relibc needs to function as well as a bunch of env vars
# that should be set for every program.
export PATH /bin
export PATH /scheme/initfs/bin
export RUST_BACKTRACE 1
rtcd
nulld
@@ -34,7 +34,6 @@ redoxfs --uuid $REDOXFS_UUID file $REDOXFS_BLOCK
unset REDOXFS_UUID REDOXFS_BLOCK REDOXFS_PASSWORD_ADDR REDOXFS_PASSWORD_SIZE
# Exit initfs
set-default-scheme file
cd /
export PATH /usr/bin
run.d /usr/lib/init.d /etc/init.d
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "init"
version = "0.1.0"
edition = "2021"
edition = "2024"
license = "MIT"
[dependencies]
+160 -205
View File
@@ -1,33 +1,12 @@
use std::collections::BTreeMap;
use std::env;
use std::ffi::CString;
use std::fs::{read_dir, File};
use std::io::{BufRead, BufReader, Result};
use std::fs::read_dir;
use std::io::Result;
use std::path::Path;
use std::process::Command;
use libredox::error::Error as OsError;
use std::{env, fs};
use libredox::flag::{O_RDONLY, O_WRONLY};
fn set_default_scheme(scheme: &str) -> std::result::Result<(), OsError> {
use std::ffi::{c_char, c_int};
extern "C" {
fn set_default_scheme(scheme: *const c_char) -> c_int;
}
let cstr =
CString::new(scheme.as_bytes()).expect(&format!("init: invalid default scheme {}", scheme));
let res = unsafe { set_default_scheme(cstr.as_ptr()) };
match res {
0 => Ok(()),
error_code => Err(OsError::new(error_code)),
}
}
fn switch_stdio(stdio: &str) -> Result<()> {
let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?;
let stdout = libredox::Fd::open(stdio, O_WRONLY, 0)?;
@@ -41,194 +20,170 @@ fn switch_stdio(stdio: &str) -> Result<()> {
}
pub fn run(file: &Path) -> Result<()> {
let file = File::open(file)?;
let reader = BufReader::new(file);
for line_res in reader.lines() {
let line_raw = line_res?;
let line = line_raw.trim();
if !line.is_empty() && !line.starts_with('#') {
let mut args = line.split(' ').map(|arg| {
if arg.starts_with('$') {
env::var(&arg[1..]).unwrap_or(String::new())
} else {
arg.to_string()
}
});
if let Some(cmd) = args.next() {
match cmd.as_str() {
"cd" => {
if let Some(dir) = args.next() {
if let Err(err) = env::set_current_dir(&dir) {
println!("init: failed to cd to '{}': {}", dir, err);
}
} else {
println!("init: failed to cd: no argument");
}
}
"set-default-scheme" => {
if let Some(scheme) = args.next() {
if let Err(err) = set_default_scheme(&scheme) {
println!(
"init: failed to set default scheme to '{}': {}",
scheme, err
);
}
} else {
println!("init: failed to set default scheme: no argument");
}
}
"echo" => {
if let Some(arg) = args.next() {
print!("{}", arg);
}
for arg in args {
print!(" {}", arg);
}
print!("\n");
}
"export" => {
if let Some(var) = args.next() {
let mut value = String::new();
if let Some(arg) = args.next() {
value.push_str(&arg);
}
for arg in args {
value.push(' ');
value.push_str(&arg);
}
env::set_var(var, value);
} else {
println!("init: failed to export: no argument");
}
}
"run" => {
if let Some(new_file) = args.next() {
if let Err(err) = run(&Path::new(&new_file)) {
println!("init: failed to run '{}': {}", new_file, err);
}
} else {
println!("init: failed to run: no argument");
}
}
"run.d" => {
// This must be a BTreeMap to iterate in sorted order.
let mut entries = BTreeMap::new();
let mut missing_arg = true;
for new_dir in args {
if !Path::new(&new_dir).exists() {
// Skip non-existent dirs
continue;
}
missing_arg = false;
match read_dir(&new_dir) {
Ok(list) => {
for entry_res in list {
match entry_res {
Ok(entry) => {
// This intentionally overwrites older entries with
// the same filename to allow overriding entries in
// one search dir with those in a later search dir.
entries.insert(entry.file_name(), entry.path());
}
Err(err) => {
println!(
"init: failed to run.d: '{}': {}",
new_dir, err
);
}
}
}
}
Err(err) => {
println!("init: failed to run.d: '{}': {}", new_dir, err);
}
}
}
if missing_arg {
println!(
"init: failed to run.d: no argument or all dirs are non-existent"
);
} else {
// This takes advantage of BTreeMap iterating in sorted order.
for (_, entry_path) in entries {
if let Err(err) = run(&entry_path) {
println!(
"init: failed to run '{}': {}",
entry_path.display(),
err
);
}
}
}
}
"stdio" => {
if let Some(stdio) = args.next() {
if let Err(err) = switch_stdio(&stdio) {
println!("init: failed to switch stdio to '{}': {}", stdio, err);
}
} else {
println!("init: failed to set stdio: no argument");
}
}
"unset" => {
for arg in args {
env::remove_var(&arg);
}
}
"nowait" => {
if let Some(cmd) = args.next() {
let mut command = Command::new(cmd);
for arg in args {
command.arg(arg);
}
match command.spawn() {
Ok(_child) => {}
Err(err) => println!("init: failed to execute '{}': {}", line, err),
}
} else {
println!("init: failed to run nowait: no argument");
}
}
_ => {
let mut command = Command::new(cmd.clone());
for arg in args {
command.arg(arg);
}
match command.spawn() {
Ok(mut child) => match child.wait() {
Ok(exit_status) => {
if !exit_status.success() {
println!("{cmd} failed with {exit_status}");
}
}
Err(err) => {
println!("init: failed to wait for '{}': {}", line, err)
}
},
Err(err) => println!("init: failed to execute '{}': {}", line, err),
}
}
}
}
}
for line in fs::read_to_string(file)?.lines() {
run_command(line);
}
Ok(())
}
pub fn main() {
if let Err(err) = set_default_scheme("initfs") {
println!("init: failed to set default scheme: {}", err);
fn run_command(line_raw: &str) {
let line = line_raw.trim();
if line.is_empty() || line.starts_with('#') {
return;
}
let mut args = line.split(' ').map(|arg| {
if arg.starts_with('$') {
env::var(&arg[1..]).unwrap_or(String::new())
} else {
arg.to_string()
}
});
let config = "/etc/init.rc";
if let Some(cmd) = args.next() {
match cmd.as_str() {
"cd" => {
let Some(dir) = args.next() else {
println!("init: failed to cd: no argument");
return;
};
if let Err(err) = env::set_current_dir(&dir) {
println!("init: failed to cd to '{}': {}", dir, err);
}
}
"echo" => {
println!("{}", args.collect::<Vec<_>>().join(" "));
}
"export" => {
let Some(var) = args.next() else {
println!("init: failed to export: no argument");
return;
};
let mut value = String::new();
if let Some(arg) = args.next() {
value.push_str(&arg);
}
for arg in args {
value.push(' ');
value.push_str(&arg);
}
unsafe { env::set_var(var, value) };
}
"run" => {
let Some(new_file) = args.next() else {
println!("init: failed to run: no argument");
return;
};
if let Err(err) = run(&Path::new(&new_file)) {
println!("init: failed to run '{}': {}", new_file, err);
}
}
"run.d" => {
// This must be a BTreeMap to iterate in sorted order.
let mut entries = BTreeMap::new();
let mut missing_arg = true;
for new_dir in args {
if !Path::new(&new_dir).exists() {
// Skip non-existent dirs
continue;
}
missing_arg = false;
let list = match read_dir(&new_dir) {
Ok(list) => list,
Err(err) => {
println!("init: failed to run.d: '{}': {}", new_dir, err);
continue;
}
};
for entry_res in list {
match entry_res {
Ok(entry) => {
// This intentionally overwrites older entries with
// the same filename to allow overriding entries in
// one search dir with those in a later search dir.
entries.insert(entry.file_name(), entry.path());
}
Err(err) => {
println!("init: failed to run.d: '{}': {}", new_dir, err);
}
}
}
}
if missing_arg {
println!("init: failed to run.d: no argument or all dirs are non-existent");
return;
}
// This takes advantage of BTreeMap iterating in sorted order.
for (_, entry_path) in entries {
if let Err(err) = run(&entry_path) {
println!("init: failed to run '{}': {}", entry_path.display(), err);
}
}
}
"stdio" => {
let Some(stdio) = args.next() else {
println!("init: failed to set stdio: no argument");
return;
};
if let Err(err) = switch_stdio(&stdio) {
println!("init: failed to switch stdio to '{}': {}", stdio, err);
}
}
"unset" => {
for arg in args {
unsafe { env::remove_var(&arg) };
}
}
"nowait" => {
let Some(cmd) = args.next() else {
println!("init: failed to run nowait: no argument");
return;
};
let mut command = Command::new(cmd);
for arg in args {
command.arg(arg);
}
match command.spawn() {
Ok(_child) => {}
Err(err) => println!("init: failed to execute '{}': {}", line, err),
}
}
_ => {
let mut command = Command::new(cmd.clone());
for arg in args {
command.arg(arg);
}
let mut child = match command.spawn() {
Ok(child) => child,
Err(err) => {
println!("init: failed to execute '{}': {}", line, err);
return;
}
};
match child.wait() {
Ok(exit_status) => {
if !exit_status.success() {
println!("{cmd} failed with {exit_status}");
}
}
Err(err) => {
println!("init: failed to wait for '{}': {}", line, err)
}
}
}
}
}
}
pub fn main() {
let config = "/scheme/initfs/etc/init.rc";
if let Err(err) = run(&Path::new(config)) {
println!("init: failed to run {}: {}", config, err);
}
+1 -1
View File
@@ -1,3 +1,3 @@
ps2d us
hwd
pcid-spawner /etc/pcid/initfs.toml
pcid-spawner /scheme/initfs/etc/pcid/initfs.toml
+3 -1
View File
@@ -8,8 +8,10 @@ libredox = { version = "0.1.8", features = ["call"]}
daemon = { path = "../daemon" }
redox_syscall = "0.5.17"
redox-scheme = "0.8.0"
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false }
redox_event = "0.4.0"
anyhow = "1.0.97"
libc = "0.2"
rand = { version = "0.8", features = ["small_rng"] }
[target.'cfg(target_os = "redox")'.dependencies]
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc.git", default-features = false }
+11 -9
View File
@@ -14,16 +14,18 @@ use self::uds::dgram::UdsDgramScheme;
use self::uds::stream::UdsStreamScheme;
fn main() {
daemon::Daemon::new(move |daemon| {
// TODO: Better error handling
match inner(daemon) {
Ok(()) => std::process::exit(0),
Err(error) => {
println!("ipcd failed: {error}");
std::process::exit(1);
}
daemon::Daemon::new(daemon_runner);
}
fn daemon_runner(daemon: daemon::Daemon) -> ! {
// TODO: Better error handling
match inner(daemon) {
Ok(()) => std::process::exit(0),
Err(error) => {
println!("ipcd failed: {error}");
std::process::exit(1);
}
});
}
}
fn inner(daemon: daemon::Daemon) -> anyhow::Result<()> {
+3 -3
View File
@@ -737,9 +737,9 @@ impl<'sock> SchemeSync for UdsDgramScheme<'sock> {
}
}
fn fevent(&mut self, id: usize, flags: EventFlags, ctx: &CallerCtx) -> Result<EventFlags> {
fn fevent(&mut self, id: usize, flags: EventFlags, _ctx: &CallerCtx) -> Result<EventFlags> {
let socket_rc = self.get_socket(id)?;
let mut socket = socket_rc.borrow_mut();
let socket = socket_rc.borrow_mut();
let mut ready = EventFlags::empty();
if flags.contains(EVENT_READ) && !socket.messages.is_empty() {
@@ -752,7 +752,7 @@ impl<'sock> SchemeSync for UdsDgramScheme<'sock> {
Ok(ready)
}
fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> {
self.get_socket(id)?;
*stat = Stat {
+4 -4
View File
@@ -16,7 +16,7 @@ use std::{
cell::RefCell,
cmp,
collections::{HashMap, HashSet, VecDeque},
mem, ptr,
mem,
rc::Rc,
slice,
};
@@ -383,7 +383,7 @@ impl<'sock> UdsStreamScheme<'sock> {
})
}
fn post_fevent(&self, id: usize, mut flags: EventFlags) -> Result<()> {
fn post_fevent(&self, id: usize, flags: EventFlags) -> Result<()> {
/*TODO: filter out unnecessary flags?
if let Ok(socket_rc) = self.get_socket(id) {
let socket = socket_rc.borrow();
@@ -1324,13 +1324,13 @@ impl<'sock> SchemeSync for UdsStreamScheme<'sock> {
}
}
fn fevent(&mut self, id: usize, flags: EventFlags, ctx: &CallerCtx) -> Result<EventFlags> {
fn fevent(&mut self, id: usize, flags: EventFlags, _ctx: &CallerCtx) -> Result<EventFlags> {
let socket_rc = self.get_socket(id)?;
let socket = socket_rc.borrow();
Ok(socket.events() & flags)
}
fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
fn fstat(&mut self, id: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> {
self.get_socket(id)?;
*stat = Stat {
+11 -9
View File
@@ -164,13 +164,15 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
}
fn main() {
daemon::Daemon::new(move |daemon| {
logger::init_logger("smolnetd");
if let Err(err) = run(daemon) {
error!("smoltcpd: {}", err);
process::exit(1);
}
process::exit(0);
});
daemon::Daemon::new(daemon_runner);
}
fn daemon_runner(daemon: daemon::Daemon) -> ! {
logger::init_logger("smolnetd");
if let Err(err) = run(daemon) {
error!("smoltcpd: {}", err);
process::exit(1);
}
process::exit(0);
}
+60 -59
View File
@@ -19,71 +19,72 @@ mod winsize;
use scheme::PtyScheme;
fn main() {
daemon::Daemon::new(move |daemon| {
user_data! {
enum EventSource {
Socket,
Time,
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
user_data! {
enum EventSource {
Socket,
Time,
}
}
let event_queue = EventQueue::<EventSource>::new().expect("pty: failed to open event:");
let time_path = format!("/scheme/time/{}", flag::CLOCK_MONOTONIC);
let mut time_file =
Fd::open(&time_path, flag::O_NONBLOCK, 0).expect("pty: failed to open time:");
let socket = redox_scheme::Socket::nonblock("pty").expect("pty: failed to create pty scheme");
libredox::call::setrens(0, 0).expect("ptyd: failed to enter null namespace");
event_queue
.subscribe(socket.inner().raw(), EventSource::Socket, EventFlags::READ)
.expect("pty: failed to watch events on pty:");
event_queue
.subscribe(time_file.raw(), EventSource::Time, EventFlags::READ)
.expect("pty: failed to watch events on time:");
daemon.ready();
//TODO: do not set timeout if not necessary
timeout(&mut time_file).expect("pty: failed to set timeout");
let mut scheme = PtyScheme::new();
let mut todo = Vec::new();
let mut timeout_count = 0u64;
scan_requests(&socket, &mut scheme, &mut todo).expect("pty: could not scan requests");
do_todos(&socket, &mut scheme, &mut todo);
issue_events(&socket, &mut scheme);
for event_res in event_queue {
let event = event_res.expect("pty: failed to read from event queue");
match event.user_data {
EventSource::Socket => {
if scan_requests(&socket, &mut scheme, &mut todo).is_err() {
break;
}
}
EventSource::Time => {
timeout(&mut time_file).expect("pty: failed to set timeout");
timeout_count = timeout_count.wrapping_add(1);
for (_id, handle) in scheme.handles.iter_mut() {
handle.timeout(timeout_count);
}
}
}
let event_queue = EventQueue::<EventSource>::new().expect("pty: failed to open event:");
let time_path = format!("/scheme/time/{}", flag::CLOCK_MONOTONIC);
let mut time_file =
Fd::open(&time_path, flag::O_NONBLOCK, 0).expect("pty: failed to open time:");
let socket =
redox_scheme::Socket::nonblock("pty").expect("pty: failed to create pty scheme");
libredox::call::setrens(0, 0).expect("ptyd: failed to enter null namespace");
event_queue
.subscribe(socket.inner().raw(), EventSource::Socket, EventFlags::READ)
.expect("pty: failed to watch events on pty:");
event_queue
.subscribe(time_file.raw(), EventSource::Time, EventFlags::READ)
.expect("pty: failed to watch events on time:");
daemon.ready();
//TODO: do not set timeout if not necessary
timeout(&mut time_file).expect("pty: failed to set timeout");
let mut scheme = PtyScheme::new();
let mut todo = Vec::new();
let mut timeout_count = 0u64;
scan_requests(&socket, &mut scheme, &mut todo).expect("pty: could not scan requests");
do_todos(&socket, &mut scheme, &mut todo);
issue_events(&socket, &mut scheme);
}
for event_res in event_queue {
let event = event_res.expect("pty: failed to read from event queue");
match event.user_data {
EventSource::Socket => {
if scan_requests(&socket, &mut scheme, &mut todo).is_err() {
break;
}
}
EventSource::Time => {
timeout(&mut time_file).expect("pty: failed to set timeout");
timeout_count = timeout_count.wrapping_add(1);
for (_id, handle) in scheme.handles.iter_mut() {
handle.timeout(timeout_count);
}
}
}
do_todos(&socket, &mut scheme, &mut todo);
issue_events(&socket, &mut scheme);
}
std::process::exit(0);
});
std::process::exit(0);
}
struct Todo {
+28 -26
View File
@@ -8,40 +8,42 @@ use redox_scheme::{RequestKind, SignalBehavior};
use self::scheme::Scheme;
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let scheme_name = env::args().nth(1).expect("Usage:\n\tramfs SCHEME_NAME");
daemon::Daemon::new(move |daemon| {
let socket =
redox_scheme::Socket::create(&scheme_name).expect("ramfs: failed to create socket");
let socket =
redox_scheme::Socket::create(&scheme_name).expect("ramfs: failed to create socket");
let mut scheme = Scheme::new(scheme_name).expect("ramfs: failed to initialize scheme");
let mut scheme = Scheme::new(scheme_name).expect("ramfs: failed to initialize scheme");
libredox::call::setrens(0, 0).expect("ramfs: failed to enter null namespace");
libredox::call::setrens(0, 0).expect("ramfs: failed to enter null namespace");
daemon.ready();
daemon.ready();
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("ramfs: failed to get next scheme request")
else {
break;
};
match request.kind() {
RequestKind::Call(call) => {
let response = call.handle_sync(&mut scheme);
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("ramfs: failed to get next scheme request")
else {
break;
};
match request.kind() {
RequestKind::Call(call) => {
let response = call.handle_sync(&mut scheme);
socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("ramfs: failed to write next scheme response");
}
RequestKind::OnClose { id } => {
scheme.on_close(id);
}
_ => (),
socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("ramfs: failed to write next scheme response");
}
RequestKind::OnClose { id } => {
scheme.on_close(id);
}
_ => (),
}
}
process::exit(0);
});
process::exit(0);
}
+29 -27
View File
@@ -10,41 +10,43 @@ enum Ty {
}
fn main() {
daemon::Daemon::new(daemon);
}
fn daemon(daemon: daemon::Daemon) -> ! {
let ty = match &*std::env::args().next().unwrap() {
"nulld" => Ty::Null,
"zerod" => Ty::Zero,
_ => panic!("needs to be called as either nulld or zerod"),
};
daemon::Daemon::new(move |daemon| {
let name = match ty {
Ty::Null => "null",
Ty::Zero => "zero",
let name = match ty {
Ty::Null => "null",
Ty::Zero => "zero",
};
let socket = Socket::<V2>::create(name).expect("zerod: failed to create zero scheme");
let mut zero_scheme = ZeroScheme(ty);
libredox::call::setrens(0, 0).expect("zerod: failed to enter null namespace");
daemon.ready();
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("zerod: failed to read events from zero scheme")
else {
std::process::exit(0);
};
let socket = Socket::<V2>::create(name).expect("zerod: failed to create zero scheme");
let mut zero_scheme = ZeroScheme(ty);
match request.kind() {
RequestKind::Call(request) => {
let response = request.handle_scheme_mut(&mut zero_scheme);
libredox::call::setrens(0, 0).expect("zerod: failed to enter null namespace");
daemon.ready();
loop {
let Some(request) = socket
.next_request(SignalBehavior::Restart)
.expect("zerod: failed to read events from zero scheme")
else {
std::process::exit(0);
};
match request.kind() {
RequestKind::Call(request) => {
let response = request.handle_scheme_mut(&mut zero_scheme);
socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("zerod: failed to write responses to zero scheme");
}
_ => (),
socket
.write_responses(&[response], SignalBehavior::Restart)
.expect("zerod: failed to write responses to zero scheme");
}
_ => (),
}
});
}
}