From b9d0599bac57a9982f5a13780e6dcd2e15f69318 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 22 Oct 2025 16:27:32 +0700 Subject: [PATCH 1/4] Add scrollback into fbbootlogd --- graphics/console-draw/src/lib.rs | 34 ++++++++++ graphics/fbbootlogd/src/main.rs | 6 +- graphics/fbbootlogd/src/scheme.rs | 109 ++++++++++++++++++++++++++---- 3 files changed, 136 insertions(+), 13 deletions(-) diff --git a/graphics/console-draw/src/lib.rs b/graphics/console-draw/src/lib.rs index 390c5cc73a..93fa641cd1 100644 --- a/graphics/console-draw/src/lib.rs +++ b/graphics/console-draw/src/lib.rs @@ -260,3 +260,37 @@ impl TextScreen { } } } + +pub struct TextBuffer { + pub lines: VecDeque>, + pub lines_max: u32, +} + +impl TextBuffer { + pub fn new(max: u32) -> Self { + let mut lines = VecDeque::new(); + lines.push_back(Vec::new()); + Self { + lines, + lines_max: max, + } + } + pub fn write(&mut self, buf: &[u8]) { + if buf.is_empty() { + return; + } + + for &byte in buf { + self.lines.back_mut().unwrap().push(byte); + + if byte == b'\n' { + self.lines.push_back(Vec::new()); + } + } + + let max_len = self.lines_max as usize; + while self.lines.len() > max_len { + self.lines.pop_front(); + } + } +} diff --git a/graphics/fbbootlogd/src/main.rs b/graphics/fbbootlogd/src/main.rs index b2f723ba3f..bc3759c469 100644 --- a/graphics/fbbootlogd/src/main.rs +++ b/graphics/fbbootlogd/src/main.rs @@ -107,7 +107,11 @@ fn inner(daemon: redox_daemon::Daemon) -> ! { .expect("fbbootlogd: error while reading events") { ConsumerHandleEvent::Events(&[]) => break, - ConsumerHandleEvent::Events(_) => {} + ConsumerHandleEvent::Events(events) => { + for event in events { + scheme.handle_input(&event); + } + } ConsumerHandleEvent::Handoff => { eprintln!("fbbootlogd: handoff requested"); scheme.handle_handoff(); diff --git a/graphics/fbbootlogd/src/scheme.rs b/graphics/fbbootlogd/src/scheme.rs index f6180e280b..0b33312959 100644 --- a/graphics/fbbootlogd/src/scheme.rs +++ b/graphics/fbbootlogd/src/scheme.rs @@ -1,9 +1,10 @@ use std::collections::VecDeque; -use std::ptr; +use std::{cmp, ptr}; use console_draw::TextScreen; use graphics_ipc::v2::V2GraphicsHandle; use inputd::ConsumerHandle; +use orbclient::{Event, EventOption}; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult}; use syscall::schemev2::NewFdFlags; @@ -19,6 +20,9 @@ pub struct FbbootlogScheme { pub input_handle: ConsumerHandle, display_map: Option, text_screen: console_draw::TextScreen, + text_buffer: console_draw::TextBuffer, + is_scrollback: bool, + scrollback_offset: usize, } impl FbbootlogScheme { @@ -27,6 +31,9 @@ impl FbbootlogScheme { input_handle: ConsumerHandle::new_vt().expect("fbbootlogd: Failed to open vt"), display_map: None, text_screen: console_draw::TextScreen::new(), + text_buffer: console_draw::TextBuffer::new(1000), + is_scrollback: false, + scrollback_offset: 1000, }; scheme.handle_handoff(); @@ -64,6 +71,81 @@ impl FbbootlogScheme { } } + pub fn handle_input(&mut self, ev: &Event) { + match ev.to_option() { + EventOption::Key(key_event) => { + match key_event.scancode { + 0x48 => { + // Up + if self.scrollback_offset >= 1 { + self.scrollback_offset -= 1; + } + } + 0x49 => { + // Page up + if self.scrollback_offset >= 10 { + self.scrollback_offset -= 10; + } else { + self.scrollback_offset = 0; + } + } + 0x50 => { + // Down + self.scrollback_offset += 1; + } + 0x51 => { + // Page down + self.scrollback_offset += 10; + } + 0x47 => { + // Home + self.scrollback_offset = 0; + } + 0x4F => { + // End + self.scrollback_offset = 1000; + } + _ => return, + } + } + _ => return, + } + self.handle_scrollback_render(); + } + + fn handle_scrollback_render(&mut self) { + let Some(map) = &mut self.display_map else { + return; + }; + self.is_scrollback = true; + let buffer_len = self.text_buffer.lines.len(); + self.scrollback_offset = cmp::min(self.scrollback_offset, buffer_len - 10); + let mut i = self.scrollback_offset; + let dmap = &mut console_draw::DisplayMap { + offscreen: map.inner.ptr_mut(), + width: map.inner.width(), + height: map.inner.height(), + }; + self.text_screen + .write(dmap, b"\x1B[1;1H\x1B[2J", &mut VecDeque::new()); + while i < buffer_len { + let mut damage = + self.text_screen + .write(dmap, &self.text_buffer.lines[i][..], &mut VecDeque::new()); + i += 1; + let yd = damage.y + damage.height; + if i == buffer_len || yd + 48 >= dmap.height as u32 { + // render until end of screen + damage.height = (dmap.height as u32) - damage.y; + map.display_handle.update_plane(0, map.fb, damage).unwrap(); + self.is_scrollback = i < buffer_len; + break; + } else { + map.display_handle.update_plane(0, map.fb, damage).unwrap(); + } + } + } + fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { let (width, height) = match map.display_handle.display_size(0) { Ok((width, height)) => (width, height), @@ -163,19 +245,22 @@ impl SchemeSync for FbbootlogScheme { ) -> Result { if let Some(map) = &mut self.display_map { Self::handle_resize(map, &mut self.text_screen); + self.text_buffer.write(buf); - 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(), - ); + if !self.is_scrollback { + 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(), + ); - if let Some(map) = &self.display_map { - map.display_handle.update_plane(0, map.fb, damage).unwrap(); + if let Some(map) = &self.display_map { + map.display_handle.update_plane(0, map.fb, damage).unwrap(); + } } } From 306079c0918d74fd1c89bfab40d215bd1adbbd2e Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 22 Oct 2025 16:27:38 +0700 Subject: [PATCH 2/4] Fix fmt --- storage/ahcid/src/ahci/hba.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/storage/ahcid/src/ahci/hba.rs b/storage/ahcid/src/ahci/hba.rs index a9d51792b0..bf5dac6e3a 100644 --- a/storage/ahcid/src/ahci/hba.rs +++ b/storage/ahcid/src/ahci/hba.rs @@ -182,23 +182,24 @@ impl HbaPort { ) -> Result { let dest: Dma<[u16; 256]> = Dma::new([0; 256]).unwrap(); - let slot = self.ata_start(clb, ctbas, |cmdheader, cmdfis, prdt_entries, _acmd| { - cmdheader.prdtl.write(1); + let slot = self + .ata_start(clb, ctbas, |cmdheader, cmdfis, prdt_entries, _acmd| { + cmdheader.prdtl.write(1); - let prdt_entry = &mut prdt_entries[0]; - prdt_entry.dba_low.write(dest.physical() as u32); - prdt_entry - .dba_high - .write((dest.physical() as u64 >> 32) as u32); - prdt_entry.dbc.write(512 | 1); + let prdt_entry = &mut prdt_entries[0]; + prdt_entry.dba_low.write(dest.physical() as u32); + prdt_entry + .dba_high + .write((dest.physical() as u64 >> 32) as u32); + prdt_entry.dbc.write(512 | 1); - cmdfis.pm.write(1 << 7); - cmdfis.command.write(cmd); - cmdfis.device.write(0); - cmdfis.countl.write(1); - cmdfis.counth.write(0); - })? - .ok_or(Error::new(EIO))?; + cmdfis.pm.write(1 << 7); + cmdfis.command.write(cmd); + cmdfis.device.write(0); + cmdfis.countl.write(1); + cmdfis.counth.write(0); + })? + .ok_or(Error::new(EIO))?; self.ata_stop(slot)?; From 6c9822893e09a2b118caddbb7123657a46f89653 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 22 Oct 2025 17:02:03 +0700 Subject: [PATCH 3/4] Fix double key register on dbbootlogd --- graphics/console-draw/src/lib.rs | 6 +++--- graphics/fbbootlogd/src/scheme.rs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/graphics/console-draw/src/lib.rs b/graphics/console-draw/src/lib.rs index 93fa641cd1..20bc77b6e6 100644 --- a/graphics/console-draw/src/lib.rs +++ b/graphics/console-draw/src/lib.rs @@ -263,11 +263,11 @@ impl TextScreen { pub struct TextBuffer { pub lines: VecDeque>, - pub lines_max: u32, + pub lines_max: usize, } impl TextBuffer { - pub fn new(max: u32) -> Self { + pub fn new(max: usize) -> Self { let mut lines = VecDeque::new(); lines.push_back(Vec::new()); Self { @@ -288,7 +288,7 @@ impl TextBuffer { } } - let max_len = self.lines_max as usize; + let max_len = self.lines_max; while self.lines.len() > max_len { self.lines.pop_front(); } diff --git a/graphics/fbbootlogd/src/scheme.rs b/graphics/fbbootlogd/src/scheme.rs index 0b33312959..4bfc0570b0 100644 --- a/graphics/fbbootlogd/src/scheme.rs +++ b/graphics/fbbootlogd/src/scheme.rs @@ -74,6 +74,9 @@ impl FbbootlogScheme { pub fn handle_input(&mut self, ev: &Event) { match ev.to_option() { EventOption::Key(key_event) => { + if !key_event.pressed { + return; + } match key_event.scancode { 0x48 => { // Up @@ -103,7 +106,7 @@ impl FbbootlogScheme { } 0x4F => { // End - self.scrollback_offset = 1000; + self.scrollback_offset = self.text_buffer.lines_max; } _ => return, } From fa9127ca34da6e208ea57045938b0f9c7b82f8fa Mon Sep 17 00:00:00 2001 From: Wildan M Date: Thu, 23 Oct 2025 00:14:05 +0700 Subject: [PATCH 4/4] Require shift key for scrollback and have better limit --- graphics/fbbootlogd/src/scheme.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/graphics/fbbootlogd/src/scheme.rs b/graphics/fbbootlogd/src/scheme.rs index 4bfc0570b0..58166f906c 100644 --- a/graphics/fbbootlogd/src/scheme.rs +++ b/graphics/fbbootlogd/src/scheme.rs @@ -23,6 +23,7 @@ pub struct FbbootlogScheme { text_buffer: console_draw::TextBuffer, is_scrollback: bool, scrollback_offset: usize, + shift: bool, } impl FbbootlogScheme { @@ -34,6 +35,7 @@ impl FbbootlogScheme { text_buffer: console_draw::TextBuffer::new(1000), is_scrollback: false, scrollback_offset: 1000, + shift: false, }; scheme.handle_handoff(); @@ -74,7 +76,9 @@ impl FbbootlogScheme { pub fn handle_input(&mut self, ev: &Event) { match ev.to_option() { EventOption::Key(key_event) => { - if !key_event.pressed { + if key_event.scancode == 0x2A || key_event.scancode == 0x36 { + self.shift = key_event.pressed; + } else if !key_event.pressed || !self.shift { return; } match key_event.scancode { @@ -120,15 +124,20 @@ impl FbbootlogScheme { let Some(map) = &mut self.display_map else { return; }; - self.is_scrollback = true; let buffer_len = self.text_buffer.lines.len(); - self.scrollback_offset = cmp::min(self.scrollback_offset, buffer_len - 10); - let mut i = self.scrollback_offset; let dmap = &mut console_draw::DisplayMap { offscreen: map.inner.ptr_mut(), width: map.inner.width(), height: map.inner.height(), }; + // for both extra space on wrapping text and a scrollback indicator + let spare_lines = 3; + self.is_scrollback = true; + self.scrollback_offset = cmp::min( + self.scrollback_offset, + buffer_len - dmap.height / 16 + spare_lines, + ); + let mut i = self.scrollback_offset; self.text_screen .write(dmap, b"\x1B[1;1H\x1B[2J", &mut VecDeque::new()); while i < buffer_len { @@ -136,8 +145,8 @@ impl FbbootlogScheme { self.text_screen .write(dmap, &self.text_buffer.lines[i][..], &mut VecDeque::new()); i += 1; - let yd = damage.y + damage.height; - if i == buffer_len || yd + 48 >= dmap.height as u32 { + let yd = (damage.y + damage.height) as usize; + if i == buffer_len || yd + spare_lines * 16 > dmap.height { // render until end of screen damage.height = (dmap.height as u32) - damage.y; map.display_handle.update_plane(0, map.fb, damage).unwrap();