diff options
Diffstat (limited to '')
| -rw-r--r-- | rsnix/src/gop.rs | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/rsnix/src/gop.rs b/rsnix/src/gop.rs index 8e804e5..012a9d0 100644 --- a/rsnix/src/gop.rs +++ b/rsnix/src/gop.rs | |||
| @@ -293,13 +293,16 @@ pub fn init(gop: &mut GraphicsOutputProtocol) { | |||
| 293 | .map(|c| core::str::from_utf8(c).unwrap_or("?")) | 293 | .map(|c| core::str::from_utf8(c).unwrap_or("?")) |
| 294 | .collect(); | 294 | .collect(); |
| 295 | dump_lines(&lines); | 295 | dump_lines(&lines); |
| 296 | crate::gop::boot_marker("gop: NO-SHADOW (fallback mode)"); | 296 | crate::gop::boot_marker_at("gop: NO-SHADOW (fallback)", bottom_row(0)); |
| 297 | } else { | 297 | } else { |
| 298 | crate::gop::boot_marker(&alloc::format!( | 298 | crate::gop::boot_marker_at( |
| 299 | "gop: shadow {:#x} {:.2} MiB", | 299 | &alloc::format!( |
| 300 | SHADOW as usize, | 300 | "gop: shadow {:#x} {:.2} MiB", |
| 301 | swords as f64 * 4.0 / 1048576.0 | 301 | SHADOW as usize, |
| 302 | )); | 302 | swords as f64 * 4.0 / 1048576.0 |
| 303 | ), | ||
| 304 | bottom_row(0), | ||
| 305 | ); | ||
| 303 | } | 306 | } |
| 304 | } | 307 | } |
| 305 | } | 308 | } |
| @@ -313,6 +316,16 @@ pub fn init(gop: &mut GraphicsOutputProtocol) { | |||
| 313 | /// direct-display glyph path (the shadow may not exist yet in early | 316 | /// direct-display glyph path (the shadow may not exist yet in early |
| 314 | /// boot); the shell banner overwrites row 0 at first paint. | 317 | /// boot); the shell banner overwrites row 0 at first paint. |
| 315 | pub fn boot_marker(msg: &str) { | 318 | pub fn boot_marker(msg: &str) { |
| 319 | boot_marker_at(msg, 0); | ||
| 320 | } | ||
| 321 | |||
| 322 | /// boot_marker at an explicit text row. The shell's first paint | ||
| 323 | /// occupies grid rows 0 (motd) and 1 (=== banner) and the prompt sits | ||
| 324 | /// at row 2 — markers whose *values* matter after boot (shadow state, | ||
| 325 | /// vt grid pointers) are anchored to the bottom of the screen via | ||
| 326 | /// `bottom_row`, which also survives a stale crash.log replay (the | ||
| 327 | /// fault band is ~20 lines starting at grid row 2). | ||
| 328 | pub fn boot_marker_at(msg: &str, row: usize) { | ||
| 316 | // Record the stage so a later panic band can show how far boot got. | 329 | // Record the stage so a later panic band can show how far boot got. |
| 317 | unsafe { | 330 | unsafe { |
| 318 | let n = msg.len().min(STAGE_MAX); | 331 | let n = msg.len().min(STAGE_MAX); |
| @@ -323,24 +336,39 @@ pub fn boot_marker(msg: &str) { | |||
| 323 | let Some(fb) = fb().as_ref() else { | 336 | let Some(fb) = fb().as_ref() else { |
| 324 | return; | 337 | return; |
| 325 | }; | 338 | }; |
| 339 | if row >= fb.height / 16 { | ||
| 340 | return; | ||
| 341 | } | ||
| 326 | let cols = fb.width / 8; | 342 | let cols = fb.width / 8; |
| 327 | let white = (0xFFu8, 0xFFu8, 0xFFu8); | 343 | let white = (0xFFu8, 0xFFu8, 0xFFu8); |
| 328 | let black = (0x00u8, 0x00u8, 0x00u8); | 344 | let black = (0x00u8, 0x00u8, 0x00u8); |
| 329 | let mut c = 0usize; | 345 | let mut c = 0usize; |
| 330 | for &b in msg.as_bytes().iter().take(cols) { | 346 | for &b in msg.as_bytes().iter().take(cols) { |
| 331 | if b < 0x80 { | 347 | if b < 0x80 { |
| 332 | blit_glyph(c, 0, b as u16, white, black); | 348 | blit_glyph(c, row, b as u16, white, black); |
| 333 | c += 1; | 349 | c += 1; |
| 334 | } | 350 | } |
| 335 | } | 351 | } |
| 336 | // Blank the rest of the row so a shorter message can't leave stale | 352 | // Blank the rest of the row so a shorter message can't leave stale |
| 337 | // glyphs behind. | 353 | // glyphs behind. |
| 338 | while c < cols { | 354 | while c < cols { |
| 339 | blit_glyph(c, 0, b' ' as u16, white, black); | 355 | blit_glyph(c, row, b' ' as u16, white, black); |
| 340 | c += 1; | 356 | c += 1; |
| 341 | } | 357 | } |
| 342 | } | 358 | } |
| 343 | 359 | ||
| 360 | /// Text-row count of the active framebuffer (each row is 16 px tall). | ||
| 361 | pub fn text_rows() -> usize { | ||
| 362 | fb().as_ref().map(|f| f.height / 16).unwrap_or(0) | ||
| 363 | } | ||
| 364 | |||
| 365 | /// Row index of the `off`-th text row from the bottom (0 = last row). | ||
| 366 | /// Bottom-anchored markers survive the shell banner + prompt at the top | ||
| 367 | /// and a stale crash.log replay below it. | ||
| 368 | pub fn bottom_row(off: usize) -> usize { | ||
| 369 | text_rows().saturating_sub(1 + off) | ||
| 370 | } | ||
| 371 | |||
| 344 | // --------------------------------------------------------------------------- | 372 | // --------------------------------------------------------------------------- |
| 345 | // Public text API — the text surface now lives in `crate::vt`; these wrappers | 373 | // Public text API — the text surface now lives in `crate::vt`; these wrappers |
| 346 | // keep callers (shell, macros) unchanged. | 374 | // keep callers (shell, macros) unchanged. |
