summaryrefslogtreecommitdiffstats
path: root/rsdos
diff options
context:
space:
mode:
Diffstat (limited to 'rsdos')
-rw-r--r--rsdos/src/main.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs
index 6d2fa4a..e5fb6dd 100644
--- a/rsdos/src/main.rs
+++ b/rsdos/src/main.rs
@@ -420,10 +420,79 @@ pub unsafe extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut
420 t.set_window(id); 420 t.set_window(id);
421 } 421 }
422 rsnix::wm::spawn_input_pump(); 422 rsnix::wm::spawn_input_pump();
423 // Register the terminal-spawn callback so F1 in the WM creates a
424 // windowed shell. The task lives here in rsdos (which depends on
425 // both rsnix and shell).
426 unsafe {
427 rsnix::wm::SPAWN_TERMINAL_CB = Some(terminal_task);
428 }
423 429
424 shell::run(); 430 shell::run();
425} 431}
426 432
433/// Callback registered with the WM for F1. Stores the spawn arguments
434/// and spawns the terminal task (can't block the input pump).
435static mut TERM_TITLE_BUF: [u8; 64] = [0u8; 64];
436static mut TERM_TITLE_LEN: usize = 0;
437static mut TERM_W: usize = 0;
438static mut TERM_H: usize = 0;
439
440fn terminal_task(title: &str, w: usize, h: usize) {
441 rsnix::serial_println!("term: callback invoked title='{}' {}x{}", title, w, h);
442 // Copy title into static buffer so the spawned task can see it.
443 let bytes = title.as_bytes();
444 let n = bytes.len().min(63);
445 unsafe {
446 TERM_TITLE_BUF[..n].copy_from_slice(&bytes[..n]);
447 TERM_TITLE_BUF[n] = 0;
448 TERM_TITLE_LEN = n;
449 TERM_W = w;
450 TERM_H = h;
451 }
452 match rsnix::sched::spawn(terminal_entry, "term") {
453 Some(id) => rsnix::serial_println!("term: spawned task {}", id),
454 None => rsnix::serial_println!("term: spawn FAILED"),
455 }
456}
457
458/// The actual terminal task — reads args from statics, creates a window,
459/// and runs the shell.
460fn terminal_entry() {
461 use rsnix::vt::Terminal;
462 let (w, h) = unsafe { (TERM_W, TERM_H) };
463 let title = unsafe { core::str::from_utf8_unchecked(&TERM_TITLE_BUF[..TERM_TITLE_LEN]) };
464 rsnix::serial_println!("term: entry title='{}' {}x{}", title, w, h);
465 let Some(win_id) = rsnix::wm::create_window(title, w, h) else {
466 rsnix::serial_println!("term: create_window FAILED");
467 return;
468 };
469 rsnix::serial_println!("term: win_id={}", win_id);
470 let Some((buf, ww, hh)) = rsnix::wm::buffer(win_id) else {
471 rsnix::serial_println!("term: buffer FAILED");
472 rsnix::wm::destroy(win_id);
473 return;
474 };
475 rsnix::serial_println!("term: buffer {:?} {}x{}", buf as *mut u32, ww, hh);
476
477 // Build a Terminal that renders into the WM-allocated buffer.
478 let mut term = Terminal::from_buffer(buf as *mut u32, ww, hh);
479 term.set_window(win_id);
480 rsnix::serial_println!("term: terminal created, entering shell");
481
482 // Redirect all vt output (gop_print!, put_char, …) to this terminal.
483 rsnix::vt::set_active(&mut term as *mut Terminal);
484
485 // Run the shell — it owns input, line editing, and command execution.
486 shell::run_windowed();
487
488 // Shell exited (^D or window close). Clean up.
489 rsnix::serial_println!("term: shell exited, cleaning up");
490 rsnix::vt::set_active(core::ptr::null_mut());
491 drop(term);
492 rsnix::wm::destroy(win_id);
493 rsnix::serial_println!("term: done");
494}
495
427// --------------------------------------------------------------------------- 496// ---------------------------------------------------------------------------
428// Print a memory summary from the stashed memory map 497// Print a memory summary from the stashed memory map
429// --------------------------------------------------------------------------- 498// ---------------------------------------------------------------------------