base: P25-P32 patch chain — fbcond VESA fallback, driver-manager initfs, init conditions, acpid graceful boot, xhcid interrupts
This commit is contained in:
@@ -0,0 +1,519 @@
|
||||
diff --git a/drivers/graphics/fbcond/src/display.rs b/drivers/graphics/fbcond/src/display.rs
|
||||
index 9bc6000f..c315bbe9 100644
|
||||
--- a/drivers/graphics/fbcond/src/display.rs
|
||||
+++ b/drivers/graphics/fbcond/src/display.rs
|
||||
@@ -5,9 +5,94 @@ use graphics_ipc::V2GraphicsHandle;
|
||||
use inputd::ConsumerHandle;
|
||||
use std::io;
|
||||
|
||||
+use common::{MemoryType, PhysBorrowed, Prot};
|
||||
+
|
||||
+pub struct DirectFbMap {
|
||||
+ fb_mem: PhysBorrowed,
|
||||
+ width: usize,
|
||||
+ height: usize,
|
||||
+ stride: usize,
|
||||
+}
|
||||
+
|
||||
+impl DirectFbMap {
|
||||
+ pub fn try_new() -> Option<Self> {
|
||||
+ let addr = std::env::var("FRAMEBUFFER_ADDR").ok()?;
|
||||
+ let width_str = std::env::var("FRAMEBUFFER_WIDTH").ok()?;
|
||||
+ let height_str = std::env::var("FRAMEBUFFER_HEIGHT").ok()?;
|
||||
+ let stride_str = std::env::var("FRAMEBUFFER_STRIDE").ok()?;
|
||||
+
|
||||
+ let phys = usize::from_str_radix(&addr, 16).ok()?;
|
||||
+ let width = usize::from_str_radix(&width_str, 16).ok()?;
|
||||
+ let height = usize::from_str_radix(&height_str, 16).ok()?;
|
||||
+ let stride = usize::from_str_radix(&stride_str, 16).ok()?;
|
||||
+
|
||||
+ if phys == 0 || width == 0 || height == 0 || stride == 0 {
|
||||
+ log::warn!("fbcond: FRAMEBUFFER_* env vars present but contain zero values");
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let size = stride * height * 4;
|
||||
+
|
||||
+ let fb_mem = match PhysBorrowed::map(
|
||||
+ phys,
|
||||
+ size,
|
||||
+ Prot {
|
||||
+ read: true,
|
||||
+ write: true,
|
||||
+ },
|
||||
+ MemoryType::WriteCombining,
|
||||
+ ) {
|
||||
+ Ok(m) => m,
|
||||
+ Err(e) => {
|
||||
+ log::warn!("fbcond: failed to map physical framebuffer at 0x{phys:X}: {e}");
|
||||
+ return None;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ log::info!(
|
||||
+ "fbcond: Direct framebuffer mapped: {}x{} stride {} at 0x{phys:X}",
|
||||
+ width,
|
||||
+ height,
|
||||
+ stride
|
||||
+ );
|
||||
+
|
||||
+ Some(DirectFbMap {
|
||||
+ fb_mem,
|
||||
+ width,
|
||||
+ height,
|
||||
+ stride,
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ pub fn width(&self) -> usize {
|
||||
+ self.width
|
||||
+ }
|
||||
+
|
||||
+ pub fn height(&self) -> usize {
|
||||
+ self.height
|
||||
+ }
|
||||
+
|
||||
+ pub(crate) fn pixel_slice(&mut self) -> &mut [u32] {
|
||||
+ unsafe {
|
||||
+ let ptr = self.fb_mem.as_ptr() as *mut u32;
|
||||
+ let len = self.stride * self.height;
|
||||
+ std::slice::from_raw_parts_mut(ptr, len)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn sync_rect(&mut self, _damage: Damage) {
|
||||
+ // Direct framebuffer writes are immediately visible
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+pub enum DisplayMap {
|
||||
+ Drm(V2DisplayMap),
|
||||
+ Direct(DirectFbMap),
|
||||
+}
|
||||
+
|
||||
pub struct Display {
|
||||
pub input_handle: ConsumerHandle,
|
||||
- pub map: Option<V2DisplayMap>,
|
||||
+ pub map: Option<DisplayMap>,
|
||||
}
|
||||
|
||||
impl Display {
|
||||
@@ -22,19 +107,29 @@ impl Display {
|
||||
Ok(display)
|
||||
}
|
||||
|
||||
- /// Re-open the display after a handoff.
|
||||
+ /// Re-open the display after a handoff. Tries DRM first, then falls back
|
||||
+ /// to direct physical framebuffer via FRAMEBUFFER_* env vars.
|
||||
pub fn reopen_for_handoff(&mut self) {
|
||||
let display_file = match self.input_handle.open_display_v2() {
|
||||
Ok(display_file) => display_file,
|
||||
Err(err) => {
|
||||
log::error!("fbcond: No display present yet: {err}");
|
||||
+ if let Some(direct) = DirectFbMap::try_new() {
|
||||
+ log::info!("fbcond: Falling back to direct framebuffer (no display handle)");
|
||||
+ self.map = Some(DisplayMap::Direct(direct));
|
||||
+ }
|
||||
return;
|
||||
}
|
||||
};
|
||||
+
|
||||
let new_display_handle = match V2GraphicsHandle::from_file(display_file) {
|
||||
Ok(handle) => handle,
|
||||
Err(err) => {
|
||||
- log::error!("fbcond: failed to create graphics handle (DRM ioctl unsupported): {err}");
|
||||
+ log::warn!("fbcond: DRM ioctl unsupported, trying direct framebuffer: {err}");
|
||||
+ if let Some(direct) = DirectFbMap::try_new() {
|
||||
+ log::info!("fbcond: Using direct framebuffer fallback");
|
||||
+ self.map = Some(DisplayMap::Direct(direct));
|
||||
+ }
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -48,43 +143,64 @@ impl Display {
|
||||
map.buffer.buffer().size().0,
|
||||
map.buffer.buffer().size().1,
|
||||
);
|
||||
- self.map = Some(map)
|
||||
+ self.map = Some(DisplayMap::Drm(map))
|
||||
}
|
||||
Err(err) => {
|
||||
- log::error!("fbcond: failed to map new display: {err}");
|
||||
- return;
|
||||
+ log::warn!("fbcond: failed to map DRM display, trying direct framebuffer: {err}");
|
||||
+ if let Some(direct) = DirectFbMap::try_new() {
|
||||
+ log::info!("fbcond: Using direct framebuffer fallback");
|
||||
+ self.map = Some(DisplayMap::Direct(direct));
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- pub fn handle_resize(map: &mut V2DisplayMap, text_screen: &mut TextScreen) {
|
||||
- let mode = match map
|
||||
- .display_handle
|
||||
- .first_display()
|
||||
- .and_then(|handle| Ok(map.display_handle.get_connector(handle, true)?.modes()[0]))
|
||||
- {
|
||||
- Ok(mode) => mode,
|
||||
- Err(err) => {
|
||||
- eprintln!("fbcond: failed to get display size: {}", err);
|
||||
- return;
|
||||
- }
|
||||
- };
|
||||
+ pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) {
|
||||
+ match map {
|
||||
+ DisplayMap::Drm(drm_map) => {
|
||||
+ let mode = match drm_map
|
||||
+ .display_handle
|
||||
+ .first_display()
|
||||
+ .and_then(|handle| {
|
||||
+ Ok(drm_map.display_handle.get_connector(handle, true)?.modes()[0])
|
||||
+ }) {
|
||||
+ Ok(mode) => mode,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("fbcond: failed to get display size: {}", err);
|
||||
+ return;
|
||||
+ }
|
||||
+ };
|
||||
|
||||
- if (u32::from(mode.size().0), u32::from(mode.size().1)) != map.buffer.buffer().size() {
|
||||
- match text_screen.resize(map, mode) {
|
||||
- Ok(()) => eprintln!("fbcond: mapped display"),
|
||||
- Err(err) => {
|
||||
- eprintln!("fbcond: failed to create or map framebuffer: {}", err);
|
||||
- return;
|
||||
+ if (u32::from(mode.size().0), u32::from(mode.size().1))
|
||||
+ != drm_map.buffer.buffer().size()
|
||||
+ {
|
||||
+ match text_screen.resize(drm_map, mode) {
|
||||
+ Ok(()) => eprintln!("fbcond: mapped display"),
|
||||
+ Err(err) => {
|
||||
+ eprintln!(
|
||||
+ "fbcond: failed to create or map framebuffer: {}",
|
||||
+ err
|
||||
+ );
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ DisplayMap::Direct(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sync_rect(&mut self, damage: Damage) {
|
||||
if let Some(map) = &mut self.map {
|
||||
- if let Err(e) = map.dirty_fb(damage) {
|
||||
- log::error!("fbcond: failed to sync framebuffer: {}", e);
|
||||
+ match map {
|
||||
+ DisplayMap::Drm(drm_map) => {
|
||||
+ if let Err(e) = drm_map.dirty_fb(damage) {
|
||||
+ log::error!("fbcond: failed to sync framebuffer: {}", e);
|
||||
+ }
|
||||
+ }
|
||||
+ DisplayMap::Direct(direct_map) => {
|
||||
+ direct_map.sync_rect(damage);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/drivers/graphics/fbcond/src/text.rs b/drivers/graphics/fbcond/src/text.rs
|
||||
index f9992d2b..4130b05f 100644
|
||||
--- a/drivers/graphics/fbcond/src/text.rs
|
||||
+++ b/drivers/graphics/fbcond/src/text.rs
|
||||
@@ -3,9 +3,11 @@ use std::collections::VecDeque;
|
||||
use orbclient::{Event, EventOption};
|
||||
use syscall::error::*;
|
||||
|
||||
-use crate::display::Display;
|
||||
+use crate::display::{DirectFbMap, Display, DisplayMap};
|
||||
|
||||
const SCROLLBACK_LINES: usize = 1000;
|
||||
+const CHAR_WIDTH: usize = 8;
|
||||
+const CHAR_HEIGHT: usize = 16;
|
||||
|
||||
pub struct TextScreen {
|
||||
pub display: Display,
|
||||
@@ -14,6 +16,8 @@ pub struct TextScreen {
|
||||
input: VecDeque<u8>,
|
||||
scrollback: VecDeque<Vec<u8>>,
|
||||
scroll_pos: usize,
|
||||
+ direct_console: ransid::Console,
|
||||
+ direct_initialized: bool,
|
||||
}
|
||||
|
||||
impl TextScreen {
|
||||
@@ -22,9 +26,11 @@ impl TextScreen {
|
||||
display,
|
||||
inner: console_draw::TextScreen::new(),
|
||||
ctrl: false,
|
||||
- input: VecDeque::new(),
|
||||
+ input: VecDeque::with_capacity(SCROLLBACK_LINES),
|
||||
scrollback: VecDeque::with_capacity(SCROLLBACK_LINES),
|
||||
scroll_pos: 0,
|
||||
+ direct_console: ransid::Console::new(0, 0),
|
||||
+ direct_initialized: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,47 +49,36 @@ impl TextScreen {
|
||||
} else if key_event.pressed {
|
||||
match key_event.scancode {
|
||||
0x0E => {
|
||||
- // Backspace
|
||||
buf.extend_from_slice(b"\x7F");
|
||||
}
|
||||
0x47 => {
|
||||
- // Home
|
||||
buf.extend_from_slice(b"\x1B[H");
|
||||
}
|
||||
0x48 => {
|
||||
- // Up
|
||||
buf.extend_from_slice(b"\x1B[A");
|
||||
}
|
||||
0x49 => {
|
||||
- // Page up
|
||||
buf.extend_from_slice(b"\x1B[5~");
|
||||
}
|
||||
0x4B => {
|
||||
- // Left
|
||||
buf.extend_from_slice(b"\x1B[D");
|
||||
}
|
||||
0x4D => {
|
||||
- // Right
|
||||
buf.extend_from_slice(b"\x1B[C");
|
||||
}
|
||||
0x4F => {
|
||||
- // End
|
||||
buf.extend_from_slice(b"\x1B[F");
|
||||
}
|
||||
0x50 => {
|
||||
- // Down
|
||||
buf.extend_from_slice(b"\x1B[B");
|
||||
}
|
||||
0x51 => {
|
||||
- // Page down
|
||||
buf.extend_from_slice(b"\x1B[6~");
|
||||
}
|
||||
0x52 => {
|
||||
- // Insert
|
||||
buf.extend_from_slice(b"\x1B[2~");
|
||||
}
|
||||
0x53 => {
|
||||
- // Delete
|
||||
buf.extend_from_slice(b"\x1B[3~");
|
||||
}
|
||||
_ => {
|
||||
@@ -101,7 +96,7 @@ impl TextScreen {
|
||||
}
|
||||
}
|
||||
}
|
||||
- _ => (), //TODO: Mouse in terminal
|
||||
+ _ => (),
|
||||
}
|
||||
|
||||
for &b in buf.iter() {
|
||||
@@ -130,21 +125,27 @@ impl TextScreen {
|
||||
}
|
||||
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
- if let Some(map) = &mut self.display.map {
|
||||
- Display::handle_resize(map, &mut self.inner);
|
||||
+ match &mut self.display.map {
|
||||
+ Some(DisplayMap::Drm(map)) => {
|
||||
+ Display::handle_resize(map, &mut self.inner);
|
||||
|
||||
- let damage = self.inner.write(map, buf, &mut self.input);
|
||||
+ let damage = self.inner.write(map, buf, &mut self.input);
|
||||
|
||||
- for line in buf.split(|&b| b == b'\n') {
|
||||
- let mut v = line.to_vec();
|
||||
- v.push(b'\n');
|
||||
- self.scrollback.push_back(v);
|
||||
+ for line in buf.split(|&b| b == b'\n') {
|
||||
+ let mut v = line.to_vec();
|
||||
+ v.push(b'\n');
|
||||
+ self.scrollback.push_back(v);
|
||||
+ }
|
||||
+ while self.scrollback.len() > SCROLLBACK_LINES {
|
||||
+ self.scrollback.pop_front();
|
||||
+ }
|
||||
+
|
||||
+ self.display.sync_rect(damage);
|
||||
}
|
||||
- while self.scrollback.len() > SCROLLBACK_LINES {
|
||||
- self.scrollback.pop_front();
|
||||
+ Some(DisplayMap::Direct(direct_map)) => {
|
||||
+ self.write_direct(direct_map, buf);
|
||||
}
|
||||
-
|
||||
- self.display.sync_rect(damage);
|
||||
+ None => {}
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
@@ -158,3 +159,163 @@ impl TextScreen {
|
||||
result
|
||||
}
|
||||
}
|
||||
+
|
||||
+impl TextScreen {
|
||||
+ fn write_direct(&mut self, direct_map: &mut DirectFbMap, buf: &[u8]) {
|
||||
+ let width = direct_map.width();
|
||||
+ let height = direct_map.height();
|
||||
+
|
||||
+ if width < CHAR_WIDTH || height < CHAR_HEIGHT {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if !self.direct_initialized {
|
||||
+ self.direct_console.resize(width / CHAR_WIDTH, height / CHAR_HEIGHT);
|
||||
+ self.direct_initialized = true;
|
||||
+ }
|
||||
+
|
||||
+ let console = &mut self.direct_console;
|
||||
+
|
||||
+ if console.state.cursor
|
||||
+ && console.state.x < console.state.w
|
||||
+ && console.state.y < console.state.h
|
||||
+ {
|
||||
+ let x = console.state.x;
|
||||
+ let y = console.state.y;
|
||||
+ Self::invert_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, CHAR_WIDTH, CHAR_HEIGHT);
|
||||
+ }
|
||||
+
|
||||
+ let pixels = direct_map.pixel_slice();
|
||||
+ let stride = direct_map.width();
|
||||
+
|
||||
+ console.write(buf, |event| match event {
|
||||
+ ransid::Event::Char {
|
||||
+ x,
|
||||
+ y,
|
||||
+ c,
|
||||
+ color,
|
||||
+ bold,
|
||||
+ ..
|
||||
+ } => {
|
||||
+ Self::char_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, c, color.as_rgb(), bold);
|
||||
+ }
|
||||
+ ransid::Event::Input { data } => self.input.extend(data),
|
||||
+ ransid::Event::Rect { x, y, w, h, color } => {
|
||||
+ Self::rect_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, w * CHAR_WIDTH, h * CHAR_HEIGHT, color.as_rgb());
|
||||
+ }
|
||||
+ ransid::Event::ScreenBuffer { .. } => (),
|
||||
+ ransid::Event::Move {
|
||||
+ from_x,
|
||||
+ from_y,
|
||||
+ to_x,
|
||||
+ to_y,
|
||||
+ w,
|
||||
+ h,
|
||||
+ } => {
|
||||
+ for row in 0..h {
|
||||
+ let src_y = if from_y > to_y { row } else { h - row - 1 };
|
||||
+ for pixel_y in 0..CHAR_HEIGHT {
|
||||
+ let off_from = ((from_y + src_y) * CHAR_HEIGHT + pixel_y) * stride + from_x * CHAR_WIDTH;
|
||||
+ let off_to = ((to_y + src_y) * CHAR_HEIGHT + pixel_y) * stride + to_x * CHAR_WIDTH;
|
||||
+ let len = w * CHAR_WIDTH;
|
||||
+
|
||||
+ if off_from + len <= pixels.len() && off_to + len <= pixels.len() {
|
||||
+ unsafe {
|
||||
+ let data_ptr = pixels.as_mut_ptr();
|
||||
+ std::ptr::copy(
|
||||
+ data_ptr.add(off_from),
|
||||
+ data_ptr.add(off_to),
|
||||
+ len,
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ ransid::Event::Resize { .. } => (),
|
||||
+ ransid::Event::Title { .. } => (),
|
||||
+ });
|
||||
+
|
||||
+ if console.state.cursor
|
||||
+ && console.state.x < console.state.w
|
||||
+ && console.state.y < console.state.h
|
||||
+ {
|
||||
+ let x = console.state.x;
|
||||
+ let y = console.state.y;
|
||||
+ Self::invert_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, CHAR_WIDTH, CHAR_HEIGHT);
|
||||
+ }
|
||||
+
|
||||
+ for line in buf.split(|&b| b == b'\n') {
|
||||
+ let mut v = line.to_vec();
|
||||
+ v.push(b'\n');
|
||||
+ self.scrollback.push_back(v);
|
||||
+ }
|
||||
+ while self.scrollback.len() > SCROLLBACK_LINES {
|
||||
+ self.scrollback.pop_front();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn rect_direct(map: &mut DirectFbMap, x: usize, y: usize, w: usize, h: usize, color: u32) {
|
||||
+ let width = map.width();
|
||||
+ let height = map.height();
|
||||
+ let pixels = map.pixel_slice();
|
||||
+ let stride = width;
|
||||
+
|
||||
+ let start_y = y.min(height);
|
||||
+ let end_y = (y + h).min(height);
|
||||
+ let start_x = x.min(width);
|
||||
+ let len = (x + w).min(width) - start_x;
|
||||
+
|
||||
+ for row in start_y..end_y {
|
||||
+ let offset = row * stride + start_x;
|
||||
+ for i in 0..len {
|
||||
+ pixels[offset + i] = color;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn char_direct(map: &mut DirectFbMap, x: usize, y: usize, character: char, color: u32, _bold: bool) {
|
||||
+ let width = map.width();
|
||||
+ let height = map.height();
|
||||
+
|
||||
+ if x + CHAR_WIDTH > width || y + CHAR_HEIGHT > height {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ let pixels = map.pixel_slice();
|
||||
+ let stride = width;
|
||||
+ let font_i = CHAR_HEIGHT * (character as usize);
|
||||
+ if font_i + CHAR_HEIGHT > orbclient::FONT.len() {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for row in 0..CHAR_HEIGHT {
|
||||
+ let row_data = orbclient::FONT[font_i + row];
|
||||
+ let offset = (y + row) * stride + x;
|
||||
+ for col in 0..CHAR_WIDTH {
|
||||
+ if (row_data >> (7 - col)) & 1 == 1 {
|
||||
+ pixels[offset + col] = color;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn invert_direct(map: &mut DirectFbMap, x: usize, y: usize, w: usize, h: usize) {
|
||||
+ let width = map.width();
|
||||
+ let height = map.height();
|
||||
+ let pixels = map.pixel_slice();
|
||||
+ let stride = width;
|
||||
+
|
||||
+ let start_y = y.min(height);
|
||||
+ let end_y = (y + h).min(height);
|
||||
+ let start_x = x.min(width);
|
||||
+ let len = (x + w).min(width) - start_x;
|
||||
+
|
||||
+ for row in start_y..end_y {
|
||||
+ let offset = row * stride + start_x;
|
||||
+ for i in 0..len {
|
||||
+ pixels[offset + i] = !pixels[offset + i];
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1,147 @@
|
||||
diff --git a/drivers/initfs-storage.toml b/drivers/initfs-storage.toml
|
||||
new file mode 100644
|
||||
index 00000000..4a9a603a
|
||||
--- /dev/null
|
||||
+++ b/drivers/initfs-storage.toml
|
||||
@@ -0,0 +1,51 @@
|
||||
+## Initfs driver configs for driver-manager
|
||||
+## Read by driver-manager --initfs from /scheme/initfs/lib/drivers.d/
|
||||
+##
|
||||
+## Storage drivers essential for early boot (mounting rootfs).
|
||||
+## GPU/display drivers are NOT probed in initfs.
|
||||
+
|
||||
+[[driver]]
|
||||
+name = "ahcid"
|
||||
+description = "AHCI SATA storage driver"
|
||||
+priority = 100
|
||||
+command = ["/scheme/initfs/lib/drivers/ahcid"]
|
||||
+
|
||||
+[[driver.match]]
|
||||
+bus = "pci"
|
||||
+class = 1
|
||||
+subclass = 6
|
||||
+
|
||||
+[[driver]]
|
||||
+name = "ided"
|
||||
+description = "PATA IDE storage driver"
|
||||
+priority = 100
|
||||
+command = ["/scheme/initfs/lib/drivers/ided"]
|
||||
+
|
||||
+[[driver.match]]
|
||||
+bus = "pci"
|
||||
+class = 1
|
||||
+subclass = 1
|
||||
+
|
||||
+[[driver]]
|
||||
+name = "nvmed"
|
||||
+description = "NVMe storage driver"
|
||||
+priority = 100
|
||||
+command = ["/scheme/initfs/lib/drivers/nvmed"]
|
||||
+
|
||||
+[[driver.match]]
|
||||
+bus = "pci"
|
||||
+class = 1
|
||||
+subclass = 8
|
||||
+
|
||||
+[[driver]]
|
||||
+name = "virtio-blkd"
|
||||
+description = "VirtIO block device driver"
|
||||
+priority = 100
|
||||
+command = ["/scheme/initfs/lib/drivers/virtio-blkd"]
|
||||
+
|
||||
+[[driver.match]]
|
||||
+bus = "pci"
|
||||
+vendor = 0x1AF4
|
||||
+device = 0x1001
|
||||
+class = 1
|
||||
+subclass = 0
|
||||
diff --git a/init.d/00_base.target b/init.d/00_base.target
|
||||
index 03c25798..9411cc88 100644
|
||||
--- a/init.d/00_base.target
|
||||
+++ b/init.d/00_base.target
|
||||
@@ -7 +7 @@ requires_weak = [
|
||||
- "00_pcid-spawner.service",
|
||||
+ "00_driver-manager.service",
|
||||
diff --git a/init.d/00_pcid-spawner.service b/init.d/00_pcid-spawner.service
|
||||
deleted file mode 100644
|
||||
index 8ba6fc6c..00000000
|
||||
--- a/init.d/00_pcid-spawner.service
|
||||
+++ /dev/null
|
||||
@@ -1,6 +0,0 @@
|
||||
-[unit]
|
||||
-description = "PCI driver spawner"
|
||||
-
|
||||
-[service]
|
||||
-cmd = "pcid-spawner"
|
||||
-type = "oneshot"
|
||||
diff --git a/init.d/10_smolnetd.service b/init.d/10_smolnetd.service
|
||||
index 1ee54ad0..29563e65 100644
|
||||
--- a/init.d/10_smolnetd.service
|
||||
+++ b/init.d/10_smolnetd.service
|
||||
@@ -6 +6 @@ requires_weak = [
|
||||
- "00_pcid-spawner.service",
|
||||
+ "00_driver-manager.service",
|
||||
diff --git a/init.initfs.d/00_driver-manager-initfs.service b/init.initfs.d/00_driver-manager-initfs.service
|
||||
new file mode 100644
|
||||
index 00000000..39613261
|
||||
--- /dev/null
|
||||
+++ b/init.initfs.d/00_driver-manager-initfs.service
|
||||
@@ -0,0 +1,8 @@
|
||||
+[unit]
|
||||
+description = "Red Bear driver manager (initfs)"
|
||||
+requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target", "40_hwd.service"]
|
||||
+
|
||||
+[service]
|
||||
+cmd = "driver-manager"
|
||||
+args = ["--initfs"]
|
||||
+type = "oneshot_async"
|
||||
diff --git a/init.initfs.d/30_redox-drm.service b/init.initfs.d/30_redox-drm.service
|
||||
index ba380bf2..3e051003 100644
|
||||
--- a/init.initfs.d/30_redox-drm.service
|
||||
+++ b/init.initfs.d/30_redox-drm.service
|
||||
@@ -3 +3 @@ description = "DRM/KMS Display Driver"
|
||||
-requires_weak = ["20_graphics.target", "40_hwd.service", "40_pcid-spawner-initfs.service"]
|
||||
+requires_weak = ["20_graphics.target", "40_hwd.service", "00_driver-manager-initfs.service"]
|
||||
diff --git a/init.initfs.d/40_drivers.target b/init.initfs.d/40_drivers.target
|
||||
index 061c2bed..2a91d2d4 100644
|
||||
--- a/init.initfs.d/40_drivers.target
|
||||
+++ b/init.initfs.d/40_drivers.target
|
||||
@@ -6 +5,0 @@ requires_weak = [
|
||||
- "40_pcid.service",
|
||||
@@ -10 +9 @@ requires_weak = [
|
||||
- "40_pcid-spawner-initfs.service",
|
||||
+ "00_driver-manager-initfs.service",
|
||||
diff --git a/init.initfs.d/40_hwd.service b/init.initfs.d/40_hwd.service
|
||||
index ff0e76dc..d4625542 100644
|
||||
--- a/init.initfs.d/40_hwd.service
|
||||
+++ b/init.initfs.d/40_hwd.service
|
||||
@@ -3 +3 @@ description = "Hardware manager"
|
||||
-requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target", "40_pcid.service", "41_acpid.service"]
|
||||
+requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target", "00_driver-manager-initfs.service", "41_acpid.service"]
|
||||
diff --git a/init.initfs.d/40_pcid-spawner-initfs.service b/init.initfs.d/40_pcid-spawner-initfs.service
|
||||
deleted file mode 100644
|
||||
index 2d36c9d5..00000000
|
||||
--- a/init.initfs.d/40_pcid-spawner-initfs.service
|
||||
+++ /dev/null
|
||||
@@ -1,8 +0,0 @@
|
||||
-[unit]
|
||||
-description = "PCI driver spawner"
|
||||
-requires_weak = ["10_inputd.service", "20_graphics.target", "40_pcid.service"]
|
||||
-
|
||||
-[service]
|
||||
-cmd = "pcid-spawner"
|
||||
-args = ["--initfs"]
|
||||
-type = "oneshot"
|
||||
diff --git a/init.initfs.d/40_pcid.service b/init.initfs.d/40_pcid.service
|
||||
deleted file mode 100644
|
||||
index 6c3a83d8..00000000
|
||||
--- a/init.initfs.d/40_pcid.service
|
||||
+++ /dev/null
|
||||
@@ -1,7 +0,0 @@
|
||||
-[unit]
|
||||
-description = "PCI daemon"
|
||||
-requires_weak = ["41_acpid.service"]
|
||||
-
|
||||
-[service]
|
||||
-cmd = "pcid"
|
||||
-type = "notify"
|
||||
@@ -0,0 +1,127 @@
|
||||
diff --git a/drivers/graphics/fbcond/src/text.rs b/drivers/graphics/fbcond/src/text.rs
|
||||
index 4130b05f..a71a9f51 100644
|
||||
--- a/drivers/graphics/fbcond/src/text.rs
|
||||
+++ b/drivers/graphics/fbcond/src/text.rs
|
||||
@@ -128,2 +128 @@ impl TextScreen {
|
||||
- match &mut self.display.map {
|
||||
- Some(DisplayMap::Drm(map)) => {
|
||||
+ if let Some(map) = &mut self.display.map {
|
||||
@@ -130,0 +130 @@ impl TextScreen {
|
||||
+ }
|
||||
@@ -131,0 +132,2 @@ impl TextScreen {
|
||||
+ match &mut self.display.map {
|
||||
+ Some(DisplayMap::Drm(map)) => {
|
||||
@@ -146 +148,7 @@ impl TextScreen {
|
||||
- self.write_direct(direct_map, buf);
|
||||
+ Self::write_direct(
|
||||
+ direct_map,
|
||||
+ buf,
|
||||
+ &mut self.direct_console,
|
||||
+ &mut self.direct_initialized,
|
||||
+ &mut self.scrollback,
|
||||
+ );
|
||||
@@ -164 +172,7 @@ impl TextScreen {
|
||||
- fn write_direct(&mut self, direct_map: &mut DirectFbMap, buf: &[u8]) {
|
||||
+ fn write_direct(
|
||||
+ direct_map: &mut DirectFbMap,
|
||||
+ buf: &[u8],
|
||||
+ direct_console: &mut ransid::Console,
|
||||
+ direct_initialized: &mut bool,
|
||||
+ scrollback: &mut VecDeque<Vec<u8>>,
|
||||
+ ) {
|
||||
@@ -172,3 +186,3 @@ impl TextScreen {
|
||||
- if !self.direct_initialized {
|
||||
- self.direct_console.resize(width / CHAR_WIDTH, height / CHAR_HEIGHT);
|
||||
- self.direct_initialized = true;
|
||||
+ if !*direct_initialized {
|
||||
+ direct_console.resize(width / CHAR_WIDTH, height / CHAR_HEIGHT);
|
||||
+ *direct_initialized = true;
|
||||
@@ -177,5 +191,3 @@ impl TextScreen {
|
||||
- let console = &mut self.direct_console;
|
||||
-
|
||||
- if console.state.cursor
|
||||
- && console.state.x < console.state.w
|
||||
- && console.state.y < console.state.h
|
||||
+ if direct_console.state.cursor
|
||||
+ && direct_console.state.x < direct_console.state.w
|
||||
+ && direct_console.state.y < direct_console.state.h
|
||||
@@ -183,2 +195,2 @@ impl TextScreen {
|
||||
- let x = console.state.x;
|
||||
- let y = console.state.y;
|
||||
+ let x = direct_console.state.x;
|
||||
+ let y = direct_console.state.y;
|
||||
@@ -188 +200,2 @@ impl TextScreen {
|
||||
- let pixels = direct_map.pixel_slice();
|
||||
+ // Extract stride before pixel_slice: borrow sequence must be
|
||||
+ // width/height → stride → pixel_slice to avoid E0502/E0500.
|
||||
@@ -189,0 +203,3 @@ impl TextScreen {
|
||||
+ let pixels = direct_map.pixel_slice();
|
||||
+ let fb_width = width;
|
||||
+ let fb_height = height;
|
||||
@@ -191 +207,4 @@ impl TextScreen {
|
||||
- console.write(buf, |event| match event {
|
||||
+ // Use pixels/stride inside the closure — direct_map is already mutably
|
||||
+ // borrowed via pixel_slice, so we cannot call Self::char_direct etc.
|
||||
+ // which would re-borrow direct_map.
|
||||
+ direct_console.write(buf, |event| match event {
|
||||
@@ -197 +216 @@ impl TextScreen {
|
||||
- bold,
|
||||
+ bold: _,
|
||||
@@ -200 +219,13 @@ impl TextScreen {
|
||||
- Self::char_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, c, color.as_rgb(), bold);
|
||||
+ let cx = x * CHAR_WIDTH;
|
||||
+ let cy = y * CHAR_HEIGHT;
|
||||
+ if cx + CHAR_WIDTH <= fb_width && cy + CHAR_HEIGHT <= fb_height {
|
||||
+ let font_i = CHAR_HEIGHT * (c as usize);
|
||||
+ if font_i + CHAR_HEIGHT <= orbclient::FONT.len() {
|
||||
+ for row in 0..CHAR_HEIGHT {
|
||||
+ let row_data = orbclient::FONT[font_i + row];
|
||||
+ let offset = (cy + row) * stride + cx;
|
||||
+ for col in 0..CHAR_WIDTH {
|
||||
+ if (row_data >> (7 - col)) & 1 == 1 {
|
||||
+ pixels[offset + col] = color.as_rgb();
|
||||
+ }
|
||||
+ }
|
||||
@@ -202 +233,4 @@ impl TextScreen {
|
||||
- ransid::Event::Input { data } => self.input.extend(data),
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ ransid::Event::Input { .. } => (),
|
||||
@@ -204 +238,15 @@ impl TextScreen {
|
||||
- Self::rect_direct(direct_map, x * CHAR_WIDTH, y * CHAR_HEIGHT, w * CHAR_WIDTH, h * CHAR_HEIGHT, color.as_rgb());
|
||||
+ let rx = x * CHAR_WIDTH;
|
||||
+ let ry = y * CHAR_HEIGHT;
|
||||
+ let rw = w * CHAR_WIDTH;
|
||||
+ let rh = h * CHAR_HEIGHT;
|
||||
+ let start_y = ry.min(fb_height);
|
||||
+ let end_y = (ry + rh).min(fb_height);
|
||||
+ let start_x = rx.min(fb_width);
|
||||
+ let len = (rx + rw).min(fb_width) - start_x;
|
||||
+ let rgb = color.as_rgb();
|
||||
+ for row in start_y..end_y {
|
||||
+ let offset = row * stride + start_x;
|
||||
+ for i in 0..len {
|
||||
+ pixels[offset + i] = rgb;
|
||||
+ }
|
||||
+ }
|
||||
@@ -239,3 +287,3 @@ impl TextScreen {
|
||||
- if console.state.cursor
|
||||
- && console.state.x < console.state.w
|
||||
- && console.state.y < console.state.h
|
||||
+ if direct_console.state.cursor
|
||||
+ && direct_console.state.x < direct_console.state.w
|
||||
+ && direct_console.state.y < direct_console.state.h
|
||||
@@ -243,2 +291,2 @@ impl TextScreen {
|
||||
- let x = console.state.x;
|
||||
- let y = console.state.y;
|
||||
+ let x = direct_console.state.x;
|
||||
+ let y = direct_console.state.y;
|
||||
@@ -251 +299 @@ impl TextScreen {
|
||||
- self.scrollback.push_back(v);
|
||||
+ scrollback.push_back(v);
|
||||
@@ -253,2 +301,2 @@ impl TextScreen {
|
||||
- while self.scrollback.len() > SCROLLBACK_LINES {
|
||||
- self.scrollback.pop_front();
|
||||
+ while scrollback.len() > SCROLLBACK_LINES {
|
||||
+ scrollback.pop_front();
|
||||
@@ -0,0 +1,9 @@
|
||||
diff --git a/init/src/unit.rs b/init/src/unit.rs
|
||||
index 98053cb2..eabb031b 100644
|
||||
--- a/init/src/unit.rs
|
||||
+++ b/init/src/unit.rs
|
||||
@@ -60,0 +61,4 @@ impl UnitStore {
|
||||
+ if !unit.conditions_met() {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
@@ -0,0 +1,15 @@
|
||||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||||
index 059254b3..a43bab83 100644
|
||||
--- a/drivers/acpid/src/main.rs
|
||||
+++ b/drivers/acpid/src/main.rs
|
||||
@@ -96,2 +96,8 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- register_sync_scheme(&socket, "acpi", &mut scheme)
|
||||
- .expect("acpid: failed to register acpi scheme to namespace");
|
||||
+ if let Err(err) = register_sync_scheme(&socket, "acpi", &mut scheme) {
|
||||
+ log::warn!(
|
||||
+ "acpid: failed to register acpi scheme (error: {}). Another acpid instance may already own it.",
|
||||
+ err
|
||||
+ );
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
@@ -0,0 +1,30 @@
|
||||
diff --git a/drivers/usb/xhcid/src/main.rs b/drivers/usb/xhcid/src/main.rs
|
||||
index da9cabe1..042173d6 100644
|
||||
--- a/drivers/usb/xhcid/src/main.rs
|
||||
+++ b/drivers/usb/xhcid/src/main.rs
|
||||
@@ -65 +64,0 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
|
||||
- PciFeatureInfo::Msi(_) => panic!(),
|
||||
@@ -66,0 +66,4 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
|
||||
+ other => {
|
||||
+ log::error!("xhcid: unexpected MSI-X feature info response: {:?}", other);
|
||||
+ return (None, InterruptMethod::Polling);
|
||||
+ }
|
||||
@@ -78 +81,7 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
|
||||
- let destination_id = read_bsp_apic_id().expect("xhcid: failed to read BSP apic id");
|
||||
+ let destination_id = match read_bsp_apic_id() {
|
||||
+ Ok(id) => id,
|
||||
+ Err(err) => {
|
||||
+ log::error!("xhcid: failed to read BSP APIC ID: {}", err);
|
||||
+ return (None, InterruptMethod::Polling);
|
||||
+ }
|
||||
+ };
|
||||
@@ -150,2 +159,7 @@ fn daemon_with_context_size<const N: usize>(
|
||||
- let (irq_file, interrupt_method) = (None, InterruptMethod::Polling); //get_int_method(&mut pcid_handle);
|
||||
- //TODO: Fix interrupts.
|
||||
+ let (irq_file, interrupt_method) = get_int_method(&mut pcid_handle);
|
||||
+
|
||||
+ match interrupt_method {
|
||||
+ InterruptMethod::Msi => log::info!("xhcid: using MSI/MSI-X interrupt delivery"),
|
||||
+ InterruptMethod::Intx => log::info!("xhcid: using legacy INTx interrupt delivery"),
|
||||
+ InterruptMethod::Polling => log::warn!("xhcid: falling back to polling mode"),
|
||||
+ }
|
||||
@@ -0,0 +1,70 @@
|
||||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||||
index 5528ad0a..b05102f6 100644
|
||||
--- a/drivers/acpid/src/main.rs
|
||||
+++ b/drivers/acpid/src/main.rs
|
||||
@@ -50,2 +50,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- log::error!("acpid: failed to parse [RX]SDT: {}", e);
|
||||
- std::process::exit(1);
|
||||
+ log::warn!("acpid: failed to parse [RX]SDT: {} — booting without ACPI", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
@@ -80,2 +81,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- log::error!("acpid: expected [RX]SDT from kernel to be RSDT or XSDT, got {:?}", String::from_utf8_lossy(&sdt.signature));
|
||||
- std::process::exit(1);
|
||||
+ log::warn!("acpid: expected [RX]SDT from kernel to be RSDT or XSDT, got {:?} — booting without ACPI", String::from_utf8_lossy(&sdt.signature));
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
@@ -102,2 +104 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- log::error!("acpid: failed to set I/O privilege level to Ring 3: {}", e);
|
||||
- std::process::exit(1);
|
||||
+ log::warn!("acpid: failed to set I/O privilege level to Ring 3: {} — continuing without port I/O", e);
|
||||
@@ -106,2 +107,17 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- let shutdown_pipe = File::open("/scheme/kernel.acpi/kstop")
|
||||
- .expect("acpid: failed to open `/scheme/kernel.acpi/kstop`");
|
||||
+ let shutdown_pipe = match File::open("/scheme/kernel.acpi/kstop") {
|
||||
+ Ok(f) => f,
|
||||
+ Err(e) => {
|
||||
+ log::warn!("acpid: failed to open `/scheme/kernel.acpi/kstop`: {} — booting without ACPI shutdown", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ let mut event_queue = match RawEventQueue::new() {
|
||||
+ Ok(q) => q,
|
||||
+ Err(e) => {
|
||||
+ log::warn!("acpid: failed to create event queue: {} — booting without ACPI", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
+ };
|
||||
@@ -109,2 +125,8 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue");
|
||||
- let socket = Socket::nonblock().expect("acpid: failed to create disk scheme");
|
||||
+ let socket = match Socket::nonblock() {
|
||||
+ Ok(s) => s,
|
||||
+ Err(e) => {
|
||||
+ log::warn!("acpid: failed to create scheme socket: {} — booting without ACPI", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
+ };
|
||||
@@ -115,6 +137,12 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- event_queue
|
||||
- .subscribe(shutdown_pipe.as_raw_fd() as usize, 0, EventFlags::READ)
|
||||
- .expect("acpid: failed to register shutdown pipe for event queue");
|
||||
- event_queue
|
||||
- .subscribe(socket.inner().raw(), 1, EventFlags::READ)
|
||||
- .expect("acpid: failed to register scheme socket for event queue");
|
||||
+ if let Err(e) = event_queue
|
||||
+ .subscribe(shutdown_pipe.as_raw_fd() as usize, 0, EventFlags::READ) {
|
||||
+ log::warn!("acpid: failed to register shutdown pipe for event queue: {} — booting without ACPI", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
+ if let Err(e) = event_queue
|
||||
+ .subscribe(socket.inner().raw(), 1, EventFlags::READ) {
|
||||
+ log::warn!("acpid: failed to register scheme socket for event queue: {} — booting without ACPI", e);
|
||||
+ daemon.ready();
|
||||
+ std::process::exit(0);
|
||||
+ }
|
||||
@@ -70,6 +70,13 @@ patches = [
|
||||
"P21-boot-daemon-graceful-panic.patch",
|
||||
"P23-rootfs-hard-dep-on-drivers.patch",
|
||||
"P24-acpi-s5-derivation-shutdown-semantics.patch",
|
||||
"P25-fbcond-vesa-fallback.patch",
|
||||
"P26-driver-manager-initfs-conversion.patch",
|
||||
"P27-fbcond-borrow-fix.patch",
|
||||
"P28-init-skip-unmet-conditions.patch",
|
||||
"P30-acpid-graceful-scheme-exists.patch",
|
||||
"P31-xhcid-restore-interrupts.patch",
|
||||
"P32-acpid-graceful-boot.patch",
|
||||
]
|
||||
|
||||
[package]
|
||||
|
||||
Reference in New Issue
Block a user