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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user