Merge branch 'init_rework4' into 'main'

Convert 10_logging, 20_graphics and 30_live to services

See merge request redox-os/base!136
This commit is contained in:
Jeremy Soller
2026-02-26 08:50:52 -07:00
26 changed files with 155 additions and 68 deletions
-1
View File
@@ -1,6 +1,5 @@
//! <https://www.qemu.org/docs/master/specs/standard-vga.html>
use common::acquire_port_io_rights;
use inputd::ProducerHandle;
use pcid_interface::PciFunctionHandle;
use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior, Socket};
+1 -3
View File
@@ -22,9 +22,7 @@ use libredox::Fd;
use redox_scheme::scheme::{register_scheme_inner, SchemeSync};
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
use syscall::schemev2::NewFdFlags;
use syscall::{
CallFlags, Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP,
};
use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP};
use crate::objects::{DrmObjectId, DrmObjects};
use crate::properties::DrmPropertyKind;
+2 -2
View File
@@ -25,7 +25,7 @@ pub struct FbbootlogScheme {
impl FbbootlogScheme {
pub fn new() -> FbbootlogScheme {
let mut scheme = FbbootlogScheme {
input_handle: ConsumerHandle::new_vt().expect("fbbootlogd: Failed to open vt"),
input_handle: ConsumerHandle::bootlog_vt().expect("fbbootlogd: Failed to open vt"),
display_map: None,
text_screen: console_draw::TextScreen::new(),
text_buffer: console_draw::TextBuffer::new(1000),
@@ -184,7 +184,7 @@ impl SchemeSync for FbbootlogScheme {
&mut self,
dirfd: usize,
path_str: &str,
flags: usize,
_flags: usize,
_fcntl_flags: u32,
_ctx: &CallerCtx,
) -> Result<OpenResult> {
+7 -22
View File
@@ -130,11 +130,7 @@ impl SchemeSync for FbconScheme {
flags: syscall::EventFlags,
_ctx: &CallerCtx,
) -> Result<syscall::EventFlags> {
let handle = match self.handles.get_mut(&id) {
Some(Handle::Vt(handle)) => Ok(handle),
Some(Handle::SchemeRoot) => Err(Error::new(EBADF)),
None => Err(Error::new(EBADF)),
}?;
let handle = self.get_vt_handle_mut(id)?;
handle.notified_read = false;
handle.events = flags;
@@ -143,11 +139,7 @@ impl SchemeSync for FbconScheme {
}
fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
let handle = match self.handles.get(&id) {
Some(Handle::Vt(handle)) => Ok(handle),
Some(Handle::SchemeRoot) => Err(Error::new(EBADF)),
None => Err(Error::new(EBADF)),
}?;
let handle = self.get_vt_handle_mut(id)?;
let path_str = format!("fbcon:{}", handle.vt_i.0);
let path = path_str.as_bytes();
@@ -162,14 +154,11 @@ impl SchemeSync for FbconScheme {
}
fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> {
match self.handles.get(&id) {
Some(Handle::Vt(_)) => Ok(()),
Some(Handle::SchemeRoot) => Err(Error::new(EBADF)),
None => Err(Error::new(EBADF)),
}
let _handle = self.get_vt_handle_mut(id)?;
Ok(())
}
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result<usize> {
fn fcntl(&mut self, id: usize, _cmd: usize, _arg: usize, _ctx: &CallerCtx) -> Result<usize> {
if !self.handles.get(&id).is_some() {
return Err(Error::new(EBADF));
};
@@ -213,13 +202,9 @@ impl SchemeSync for FbconScheme {
_fcntl_flags: u32,
_ctx: &CallerCtx,
) -> Result<usize> {
let handle = match self.handles.get(&id) {
Some(Handle::Vt(handle)) => Ok(handle),
Some(Handle::SchemeRoot) => Err(Error::new(EBADF)),
None => Err(Error::new(EBADF)),
}?;
let vt_i = self.get_vt_handle_mut(id)?.vt_i;
if let Some(console) = self.vts.get_mut(&handle.vt_i) {
if let Some(console) = self.vts.get_mut(&vt_i) {
console.write(buf)
} else {
Err(Error::new(EBADF))
+8
View File
@@ -47,6 +47,14 @@ impl ConsumerHandle {
Ok(Self(file))
}
pub fn bootlog_vt() -> io::Result<Self> {
let file = OpenOptions::new()
.read(true)
.custom_flags(O_NONBLOCK as i32)
.open(format!("/scheme/input/consumer_bootlog"))?;
Ok(Self(file))
}
pub fn event_handle(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
+16 -2
View File
@@ -25,7 +25,7 @@ use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior,
use orbclient::{Event, EventOption};
use syscall::schemev2::NewFdFlags;
use syscall::{Error as SysError, EventFlags, EACCES, EBADF, EINVAL};
use syscall::{Error as SysError, EventFlags, EACCES, EBADF, EEXIST, EINVAL};
pub mod keymap;
@@ -79,7 +79,7 @@ impl InputScheme {
handles: BTreeMap::new(),
next_id: AtomicUsize::new(0),
next_vt_id: AtomicUsize::new(1),
next_vt_id: AtomicUsize::new(2), // VT 1 is reserved for the bootlog
display: None,
vts: BTreeSet::new(),
@@ -195,6 +195,20 @@ impl SchemeSync for InputScheme {
vt,
}
}
"consumer_bootlog" => {
if !self.vts.insert(1) {
return Err(SysError::new(EEXIST));
}
self.switch_vt(1);
Handle::Consumer {
events: EventFlags::empty(),
pending: Vec::new(),
needs_handoff: false,
notified: false,
vt: 1,
}
}
"handle" | "handle_early" => {
let display = path_parts.collect::<Vec<_>>().join(".");
+1 -2
View File
@@ -1,4 +1,3 @@
requires_weak 30_live
notify hwd
requires_weak 10_lived.service 20_graphics.target
notify RSDP_ADDR=$ RSDP_SIZE=$ hwd
pcid-spawner --initfs
@@ -1,3 +1,2 @@
requires_weak 30_live
unset RSDP_ADDR RSDP_SIZE
requires_weak 10_lived.service 20_graphics.target
notify bcm2835-sdhcid
+13
View File
@@ -0,0 +1,13 @@
{
"unit": {
"default_dependencies": false,
"requires_weak": ["00_randd.service"]
},
"service": {
"cmd": "ramfs",
"args": ["logging"],
"type": {
"scheme": "logging"
}
}
}
+1
View File
@@ -1,5 +1,6 @@
{
"unit": {
"description": "/dev/null",
"default_dependencies": false
},
"service": {
+1
View File
@@ -1,5 +1,6 @@
{
"unit": {
"description": "/dev/rand",
"default_dependencies": false
},
"service": {
+3 -2
View File
@@ -1,12 +1,13 @@
{
"unit": {
"description": "Various daemons that relibc needs to function.",
"description": "Services that relibc needs to function",
"default_dependencies": false,
"requires_weak": [
"00_nulld.service",
"00_randd.service",
"00_rtcd.service",
"00_zerod.service"
"00_zerod.service",
"00_logging_ramfs.service"
]
}
}
+1
View File
@@ -1,5 +1,6 @@
{
"unit": {
"description": "/dev/zero",
"default_dependencies": false
},
"service": {
+11
View File
@@ -0,0 +1,11 @@
{
"unit": {
"description": "VT input and graphics multiplexer"
},
"service": {
"cmd": "inputd",
"type": {
"scheme": "input"
}
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"_comment": "Needs to start before drivers to ensure it gets priority when redoxfs searches for disks",
"unit": {
"description": "Live disk"
},
"service": {
"cmd": "lived",
"type": "notify"
}
}
-4
View File
@@ -1,4 +0,0 @@
requires_weak 00_runtime.target
scheme log logd
stdio /scheme/log
scheme logging ramfs logging
+12
View File
@@ -0,0 +1,12 @@
{
"unit": {
"description": "Graphical bootlog",
"requires_weak": ["10_inputd.service"]
},
"service": {
"cmd": "fbbootlogd",
"type": {
"scheme": "fbbootlog"
}
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"unit": {
"description": "Framebuffer text console",
"requires_weak": ["10_inputd.service", "20_vesad.service"]
},
"service": {
"cmd": "fbcond",
"args": ["2"],
"type": {
"scheme": "fbcon"
}
}
}
-7
View File
@@ -1,7 +0,0 @@
requires_weak 10_logging
scheme input inputd
notify FRAMEBUFFER_ADDR=$ FRAMEBUFFER_VIRT=$ FRAMEBUFFER_WIDTH=$ FRAMEBUFFER_HEIGHT=$ FRAMEBUFFER_STRIDE=$ vesad
scheme fbbootlog fbbootlogd
# Activate framebuffer log VT, which disables kernel graphical debug
inputd -A 1
scheme fbcon fbcond 2
+11
View File
@@ -0,0 +1,11 @@
{
"unit": {
"description": "Graphics subsystem",
"requires_weak": [
"10_inputd.service",
"20_vesad.service",
"20_fbbootlogd.service",
"20_fbcond.service"
]
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"unit": {
"description": "Bootloader framebuffer handler",
"requires_weak": [
"10_inputd.service"
]
},
"service": {
"cmd": "vesad",
"inherit_envs": [
"FRAMEBUFFER_ADDR",
"FRAMEBUFFER_VIRT",
"FRAMEBUFFER_WIDTH",
"FRAMEBUFFER_HEIGHT",
"FRAMEBUFFER_STRIDE"
],
"type": "notify"
}
}
-3
View File
@@ -1,3 +0,0 @@
requires_weak 20_graphics
# Note: Needs to start before drivers to ensure it gets priority when redoxfs searches for disks
notify lived
+1 -1
View File
@@ -1,4 +1,4 @@
requires_weak 30_live
requires_weak 10_lived.service 20_graphics.target
notify ps2d
notify RSDP_ADDR=$ RSDP_SIZE=$ hwd
pcid-spawner --initfs
+7 -5
View File
@@ -135,11 +135,6 @@ fn run_command(cmd: Command, config: &mut InitConfig) {
Command::RequiresWeak(_) => {} // handled by unit parsing code
Command::Nothing => {}
Command::Echo(text) => println!("{text}"),
Command::Stdio(stdio) => {
if let Err(err) = switch_stdio(&stdio) {
eprintln!("init: failed to switch stdio to '{}': {}", stdio, err);
}
}
Command::Service(service) => {
if config.skip_cmd.contains(&service.cmd) {
eprintln!(
@@ -166,6 +161,13 @@ fn main() {
}
.apply(&mut pending_units, &mut unit_store, &mut init_config);
let mut command = std::process::Command::new("logd");
command.env_clear().envs(&init_config.envs);
daemon::SchemeDaemon::spawn(command, "log");
if let Err(err) = switch_stdio("/scheme/log") {
eprintln!("init: failed to switch stdio to '/scheme/log': {err}");
}
let runtime_target = UnitId("00_runtime.target".to_owned());
'a: while let Some(unit) = pending_units.pop_front() {
+5 -10
View File
@@ -1,4 +1,4 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use std::{env, io, iter};
use crate::service::{Service, ServiceType};
@@ -45,9 +45,6 @@ pub enum Command {
// Service
Service(Service),
// Modify env
Stdio(String),
// Misc
Echo(String),
Nothing,
@@ -62,12 +59,6 @@ impl Command {
match cmd.as_str() {
"requires_weak" => Ok(Command::RequiresWeak(args.map(UnitId).collect::<Vec<_>>())),
"echo" => Ok(Command::Echo(args.collect::<Vec<_>>().join(" "))),
"stdio" => {
let Some(stdio) = args.next() else {
return Err("init: failed to set stdio: no argument".to_owned());
};
Ok(Command::Stdio(stdio))
}
"notify" => {
let process = Process::parse(args)?;
@@ -75,6 +66,7 @@ impl Command {
cmd: process.cmd,
args: process.args,
envs: process.envs,
inherit_envs: BTreeSet::new(),
type_: ServiceType::Notify,
}))
}
@@ -89,6 +81,7 @@ impl Command {
cmd: process.cmd,
args: process.args,
envs: process.envs,
inherit_envs: BTreeSet::new(),
type_: ServiceType::Scheme(scheme),
}))
}
@@ -99,6 +92,7 @@ impl Command {
cmd: process.cmd,
args: process.args,
envs: process.envs,
inherit_envs: BTreeSet::new(),
type_: ServiceType::OneshotAsync,
}))
}
@@ -109,6 +103,7 @@ impl Command {
cmd: process.cmd,
args: process.args,
envs: process.envs,
inherit_envs: BTreeSet::new(),
type_: ServiceType::Oneshot,
}))
}
+11 -2
View File
@@ -1,4 +1,5 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use std::env;
use std::ffi::OsString;
use std::process::Command;
@@ -11,6 +12,8 @@ pub struct Service {
pub args: Vec<String>,
#[serde(default)]
pub envs: BTreeMap<String, String>,
#[serde(default)]
pub inherit_envs: BTreeSet<String>,
#[serde(rename = "type")]
pub type_: ServiceType,
}
@@ -29,7 +32,13 @@ impl Service {
pub fn spawn(&self, base_envs: &BTreeMap<String, OsString>) {
let mut command = Command::new(&self.cmd);
command.args(&self.args);
command.env_clear().envs(base_envs).envs(&self.envs);
command.env_clear();
for env in &self.inherit_envs {
if let Some(value) = env::var_os(env) {
command.env(env, value);
}
}
command.envs(base_envs).envs(&self.envs);
match &self.type_ {
ServiceType::Notify => {