graphics/fbbootlogd: Handle non-existent graphics adapter

This ensures a serial console shows up with all non-graphics related
daemons started when there is no framebuffer passed by the bootloader.
This commit is contained in:
bjorn3
2025-03-01 19:23:56 +01:00
parent 68af18aead
commit d26ee5a58d
4 changed files with 45 additions and 28 deletions
+29 -13
View File
@@ -41,18 +41,26 @@ enum DisplayCommand {
pub struct Display {
cmd_tx: Sender<DisplayCommand>,
pub map: Arc<Mutex<DisplayMap>>,
pub map: Arc<Mutex<Option<DisplayMap>>>,
}
impl Display {
pub fn open_first_vt() -> io::Result<Self> {
let input_handle = ConsumerHandle::for_vt(1)?;
let display_handle = LegacyGraphicsHandle::from_file(input_handle.open_display()?)?;
let map = Arc::new(Mutex::new(
display_fd_map(display_handle).unwrap_or_else(|e| panic!("failed to map display: {e}")),
));
let map = match input_handle.open_display() {
Ok(display) => {
let display_handle = LegacyGraphicsHandle::from_file(display)?;
Arc::new(Mutex::new(Some(
display_fd_map(display_handle)
.unwrap_or_else(|e| panic!("failed to map display: {e}")),
)))
}
Err(err) => {
println!("fbbootlogd: No display present yet: {err}");
Arc::new(Mutex::new(None))
}
};
let map_clone = map.clone();
std::thread::spawn(move || {
@@ -68,7 +76,7 @@ impl Display {
Ok(Self { cmd_tx, map })
}
fn handle_input_events(map: Arc<Mutex<DisplayMap>>, input_handle: ConsumerHandle) {
fn handle_input_events(map: Arc<Mutex<Option<DisplayMap>>>, input_handle: ConsumerHandle) {
let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue");
user_data! {
@@ -93,13 +101,17 @@ impl Display {
Err(err) if err.errno() == ESTALE => {
eprintln!("fbbootlogd: handoff requested");
let new_display_handle =
LegacyGraphicsHandle::from_file(input_handle.open_display().unwrap())
.unwrap();
let new_display_handle = match input_handle.open_display() {
Ok(display) => LegacyGraphicsHandle::from_file(display).unwrap(),
Err(err) => {
println!("fbbootlogd: No display present yet: {err}");
continue;
}
};
match display_fd_map(new_display_handle) {
Ok(ok) => {
*map.lock().unwrap() = ok;
*map.lock().unwrap() = Some(ok);
eprintln!("fbbootlogd: handoff finished");
}
@@ -117,13 +129,17 @@ impl Display {
}
}
fn handle_sync_rect(map: Arc<Mutex<DisplayMap>>, cmd_rx: Receiver<DisplayCommand>) {
fn handle_sync_rect(map: Arc<Mutex<Option<DisplayMap>>>, cmd_rx: Receiver<DisplayCommand>) {
while let Ok(cmd) = cmd_rx.recv() {
match cmd {
DisplayCommand::SyncRects(sync_rects) => {
// We may not hold this lock across the write call to avoid deadlocking if the
// graphics driver tries to write to the bootlog.
let display_handle = map.lock().unwrap().display_handle.clone();
let display_handle = if let Some(map) = &*map.lock().unwrap() {
map.display_handle.clone()
} else {
continue;
};
display_handle.sync_rects(&sync_rects).unwrap();
}
}
+14 -12
View File
@@ -55,19 +55,21 @@ impl Scheme for FbbootlogScheme {
}
fn write(&mut self, _id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32) -> Result<usize> {
let mut map = self.display.map.lock().unwrap();
let damage = self.text_screen.write(
&mut console_draw::DisplayMap {
offscreen: map.inner.ptr_mut(),
width: map.inner.width(),
height: map.inner.height(),
},
buf,
&mut VecDeque::new(),
);
drop(map);
let mut map_guard = self.display.map.lock().unwrap();
if let Some(map) = &mut *map_guard {
let damage = self.text_screen.write(
&mut console_draw::DisplayMap {
offscreen: map.inner.ptr_mut(),
width: map.inner.width(),
height: map.inner.height(),
},
buf,
&mut VecDeque::new(),
);
drop(map_guard);
self.display.sync_rects(damage);
self.display.sync_rects(damage);
}
Ok(buf.len())
}
+1 -1
View File
@@ -8,7 +8,7 @@ authors = ["Anhad Singh <andypython@protonmail.com>"]
anyhow = "1.0.71"
log = "0.4.19"
redox-daemon = "0.1.2"
redox_syscall = "0.5"
redox_syscall = { version = "0.5", features = ["std"] }
orbclient = "0.3.27"
libredox = "0.1.3"
+1 -2
View File
@@ -32,8 +32,7 @@ impl ConsumerHandle {
pub fn open_display(&self) -> Result<File, Error> {
let mut buffer = [0; 1024];
let fd = self.0.as_raw_fd();
let written = libredox::call::fpath(fd as usize, &mut buffer)
.expect("init: failed to get the path to the display device");
let written = libredox::call::fpath(fd as usize, &mut buffer)?;
assert!(written <= buffer.len());