Archived
test: direct zero-overhead echo console for Ring 3 sh
This commit is contained in:
+19
-219
@@ -1,240 +1,40 @@
|
|||||||
//! # sh — Userspace Interactive Shell (Ring 3, PID 3).
|
//! # sh — Direct Interactive Console (Ring 3, PID 3).
|
||||||
//!
|
//!
|
||||||
//! Полноценный пользовательский командный процессор, работающий полностью в Ring 3
|
//! Максимально простая консоль без сложной логики: читает символ и сразу выводит его.
|
||||||
//! поверх VFS и системных вызовов opencoreRS.
|
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
const PROMPT: &str = "\x1b[1;32muser\x1b[0m@\x1b[1;36mopencoreRS\x1b[0m\x1b[33m:~\x1b[0m$ ";
|
|
||||||
const MAX_LINE: usize = 256;
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
ipc_client::log("[sh] Userspace Interactive Shell started (Ring 3, PID 3)");
|
ipc_client::print_str("\r\n");
|
||||||
ipc_client::log("[sh] Connected to TTY terminal");
|
ipc_client::print_str("==============================================\r\n");
|
||||||
|
ipc_client::print_str(" opencoreRS Simple Direct Console (Ring 3)\r\n");
|
||||||
ipc_client::println("");
|
ipc_client::print_str(" Type characters on your keyboard:\r\n");
|
||||||
ipc_client::println("\x1b[1;36m╔═══════════════════════════════════════════════════════╗\x1b[0m");
|
ipc_client::print_str("==============================================\r\n\r\n> ");
|
||||||
ipc_client::println("\x1b[1;36m║ opencoreRS v0.1.0 — Userspace Unix Shell (Ring 3) ║\x1b[0m");
|
|
||||||
ipc_client::println("\x1b[1;36m╚═══════════════════════════════════════════════════════╝\x1b[0m");
|
|
||||||
ipc_client::println(" Running in \x1b[1;32mRing 3 (Userspace PID 3)\x1b[0m with VFS & IPC");
|
|
||||||
ipc_client::println(" Type \x1b[1m'help'\x1b[0m to see available commands.\r\n");
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
ipc_client::print_str(PROMPT);
|
if let Some(ch) = ipc_client::read_char() {
|
||||||
|
if ch == b'\r' || ch == b'\n' {
|
||||||
let mut buf = [0u8; MAX_LINE];
|
ipc_client::print_str("\r\n> ");
|
||||||
let len = read_line(&mut buf);
|
} else if ch == 0x08 || ch == 0x7F {
|
||||||
|
ipc_client::print_str("\x08 \x08");
|
||||||
if len == 0 {
|
} else {
|
||||||
continue;
|
let slice = [ch];
|
||||||
}
|
if let Ok(s) = core::str::from_utf8(&slice) {
|
||||||
|
ipc_client::print_str(s);
|
||||||
let line = match core::str::from_utf8(&buf[..len]) {
|
|
||||||
Ok(s) => s.trim(),
|
|
||||||
Err(_) => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
if line.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch_command(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Чтение строки из терминала в Ring 3 с поддержкой Backspace, Enter, Ctrl-L.
|
|
||||||
fn read_line(buf: &mut [u8]) -> usize {
|
|
||||||
let mut len = 0usize;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Опрашиваем символы пакетами перед уступкой кванта времени
|
|
||||||
for _ in 0..200 {
|
|
||||||
match ipc_client::read_char() {
|
|
||||||
Some(b'\r') | Some(b'\n') => {
|
|
||||||
ipc_client::print_str("\r\n");
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
Some(0x08) | Some(0x7F) => {
|
|
||||||
if len > 0 {
|
|
||||||
len -= 1;
|
|
||||||
ipc_client::print_str("\x08 \x08");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(0x0C) => {
|
|
||||||
// Ctrl-L: Clear screen
|
|
||||||
ipc_client::print_str("\x1b[2J\x1b[H");
|
|
||||||
ipc_client::print_str(PROMPT);
|
|
||||||
if let Ok(s) = core::str::from_utf8(&buf[..len]) {
|
|
||||||
ipc_client::print_str(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(b) if b >= 0x20 && b < 0x7F => {
|
|
||||||
if len < buf.len() - 1 {
|
|
||||||
buf[len] = b;
|
|
||||||
len += 1;
|
|
||||||
let slice = [b];
|
|
||||||
if let Ok(s) = core::str::from_utf8(&slice) {
|
|
||||||
ipc_client::print_str(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc_client::yield_cpu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Диспетчер команд Userspace Shell (Ring 3).
|
|
||||||
fn dispatch_command(cmdline: &str) {
|
|
||||||
let mut parts = cmdline.split_ascii_whitespace();
|
|
||||||
let cmd = match parts.next() {
|
|
||||||
Some(c) => c,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
let args: &[&str] = &[];
|
|
||||||
let arg1 = parts.next().unwrap_or("");
|
|
||||||
|
|
||||||
match cmd {
|
|
||||||
"help" | "?" => {
|
|
||||||
ipc_client::println("\x1b[1;36mopencoreRS Ring 3 Shell — Built-in Commands\x1b[0m");
|
|
||||||
ipc_client::println("\x1b[90m─────────────────────────────────────────────\x1b[0m");
|
|
||||||
ipc_client::println(" \x1b[1;33mhelp, ?\x1b[0m Show this help menu");
|
|
||||||
ipc_client::println(" \x1b[1;33muname [-a]\x1b[0m Display OS, kernel and architecture");
|
|
||||||
ipc_client::println(" \x1b[1;33mls [path]\x1b[0m List VFS directory (/proc, /dev, /etc)");
|
|
||||||
ipc_client::println(" \x1b[1;33mcat <file>\x1b[0m Display contents of a file");
|
|
||||||
ipc_client::println(" \x1b[1;33mecho <text>\x1b[0m Print text to terminal");
|
|
||||||
ipc_client::println(" \x1b[1;33mcpuinfo\x1b[0m Display CPUID vendor, model & features");
|
|
||||||
ipc_client::println(" \x1b[1;33mlspci\x1b[0m Scan and list PCI hardware devices");
|
|
||||||
ipc_client::println(" \x1b[1;33mifconfig, net\x1b[0m Network interface configuration & stats");
|
|
||||||
ipc_client::println(" \x1b[1;33mping [ip]\x1b[0m Send ICMP Echo Request");
|
|
||||||
ipc_client::println(" \x1b[1;33mclear, cls\x1b[0m Clear terminal screen");
|
|
||||||
ipc_client::println(" \x1b[1;33mexit\x1b[0m Exit userspace shell");
|
|
||||||
ipc_client::println("");
|
|
||||||
}
|
|
||||||
"uname" => {
|
|
||||||
ipc_client::println("opencoreRS 0.1.0 x86_64 microkernel SMP (Ring 3 Shell)");
|
|
||||||
}
|
|
||||||
"echo" => {
|
|
||||||
let mut first = true;
|
|
||||||
for p in cmdline.split_ascii_whitespace().skip(1) {
|
|
||||||
if !first {
|
|
||||||
ipc_client::print_str(" ");
|
|
||||||
}
|
|
||||||
ipc_client::print_str(p);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
ipc_client::println("");
|
|
||||||
}
|
|
||||||
"ls" => {
|
|
||||||
let path = if arg1.is_empty() { "/" } else { arg1 };
|
|
||||||
match path {
|
|
||||||
"/" => {
|
|
||||||
ipc_client::println("\x1b[1;34mbin dev etc proc sys\x1b[0m");
|
|
||||||
}
|
|
||||||
"/proc" => {
|
|
||||||
ipc_client::println("\x1b[32mcpuinfo version meminfo tasks\x1b[0m");
|
|
||||||
}
|
|
||||||
"/etc" => {
|
|
||||||
ipc_client::println("\x1b[32mhostname os-release resolv.conf\x1b[0m");
|
|
||||||
}
|
|
||||||
"/dev" => {
|
|
||||||
ipc_client::println("\x1b[33mnull zero tty eth0 sda\x1b[0m");
|
|
||||||
}
|
|
||||||
"/bin" => {
|
|
||||||
ipc_client::println("\x1b[1;32minit vfs sh ls cat echo ping\x1b[0m");
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ipc_client::print_str("ls: cannot access '");
|
|
||||||
ipc_client::print_str(path);
|
|
||||||
ipc_client::println("': No such file or directory");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
"cat" => {
|
ipc_client::yield_cpu();
|
||||||
if arg1.is_empty() {
|
|
||||||
ipc_client::println("cat: missing file operand");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
match arg1 {
|
|
||||||
"/proc/version" => {
|
|
||||||
ipc_client::println("opencoreRS kernel v0.1.0 (x86_64-unknown-none) Rust Microkernel");
|
|
||||||
}
|
|
||||||
"/proc/cpuinfo" => {
|
|
||||||
ipc_client::println("vendor_id\t: Intel / AMD (Detected via CPUID)");
|
|
||||||
ipc_client::println("model name\t: x86_64 Microkernel Core");
|
|
||||||
ipc_client::println("flags\t\t: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge sse sse2 avx");
|
|
||||||
}
|
|
||||||
"/proc/meminfo" => {
|
|
||||||
ipc_client::println("MemTotal:\t248832 kB");
|
|
||||||
ipc_client::println("MemFree:\t245760 kB");
|
|
||||||
ipc_client::println("Buffers:\t 1024 kB");
|
|
||||||
}
|
|
||||||
"/etc/hostname" => {
|
|
||||||
ipc_client::println("opencoreRS");
|
|
||||||
}
|
|
||||||
"/etc/os-release" => {
|
|
||||||
ipc_client::println("NAME=\"opencoreRS\"");
|
|
||||||
ipc_client::println("VERSION=\"0.1.0-microkernel\"");
|
|
||||||
ipc_client::println("ID=opencore");
|
|
||||||
ipc_client::println("PRETTY_NAME=\"opencoreRS Microkernel OS\"");
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ipc_client::print_str("cat: ");
|
|
||||||
ipc_client::print_str(arg1);
|
|
||||||
ipc_client::println(": No such file or directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"cpuinfo" => {
|
|
||||||
ipc_client::println("\x1b[1;36mHardware CPU Information (Ring 3 query)\x1b[0m");
|
|
||||||
ipc_client::println("\x1b[90m─────────────────────────────────────────────\x1b[0m");
|
|
||||||
ipc_client::println(" \x1b[1;33mVendor :\x1b[0m Intel / AMD Processor");
|
|
||||||
ipc_client::println(" \x1b[1;33mArchitecture:\x1b[0m x86_64 (64-bit Long Mode)");
|
|
||||||
ipc_client::println(" \x1b[1;33mFeatures :\x1b[0m APIC, SSE, AVX, RDRAND, SMP Multi-Core\r\n");
|
|
||||||
}
|
|
||||||
"lspci" => {
|
|
||||||
ipc_client::println("\x1b[1;36mPCI Bus Device Enumeration (Ring 3 query)\x1b[0m");
|
|
||||||
ipc_client::println("\x1b[90m─────────────────────────────────────────────\x1b[0m");
|
|
||||||
ipc_client::println(" \x1b[1;33m00:00.0\x1b[0m [8086:29c0] \x1b[1mHost Bridge\x1b[0m (Intel Corporation)");
|
|
||||||
ipc_client::println(" \x1b[1;33m00:01.0\x1b[0m [1234:1111] \x1b[1mVGA Controller\x1b[0m (QEMU / Bochs Device)");
|
|
||||||
ipc_client::println(" \x1b[1;33m00:02.0\x1b[0m [8086:100e] \x1b[1mEthernet Controller\x1b[0m (Intel E1000 Gigabit)");
|
|
||||||
ipc_client::println(" \x1b[1;33m00:03.0\x1b[0m [8086:2922] \x1b[1mSATA / AHCI Controller\x1b[0m (Intel Corporation)");
|
|
||||||
ipc_client::println(" \x1b[1;33m00:1f.0\x1b[0m [8086:2918] \x1b[1mISA Bridge\x1b[0m (Intel Corporation)\r\n");
|
|
||||||
}
|
|
||||||
"ifconfig" | "net" => {
|
|
||||||
ipc_client::println("\x1b[1;36mNetwork Interface Configuration (eth0)\x1b[0m");
|
|
||||||
ipc_client::println("\x1b[90m─────────────────────────────────────────────\x1b[0m");
|
|
||||||
ipc_client::println(" \x1b[1;33mInterface :\x1b[0m eth0 (Intel E1000 Gigabit)");
|
|
||||||
ipc_client::println(" \x1b[1;33mMAC Address:\x1b[0m 52:54:00:12:34:56");
|
|
||||||
ipc_client::println(" \x1b[1;33mIPv4 :\x1b[0m 10.0.2.15 / 24");
|
|
||||||
ipc_client::println(" \x1b[1;33mGateway :\x1b[0m 10.0.2.2\r\n");
|
|
||||||
}
|
|
||||||
"ping" => {
|
|
||||||
ipc_client::println("PING 10.0.2.2 (10.0.2.2): 64 data bytes (ICMP Echo sent via kernel netstack)");
|
|
||||||
ipc_client::println("64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.42 ms");
|
|
||||||
}
|
|
||||||
"clear" | "cls" => {
|
|
||||||
ipc_client::print_str("\x1b[2J\x1b[H");
|
|
||||||
}
|
|
||||||
"exit" => {
|
|
||||||
ipc_client::println("[sh] Exiting userspace shell...");
|
|
||||||
ipc_client::exit(0);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ipc_client::print_str("\x1b[31msh: command not found: \x1b[0m");
|
|
||||||
ipc_client::println(cmd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
ipc_client::log("[sh] Panic in userspace shell!");
|
ipc_client::log("[sh] Panic in simple shell!");
|
||||||
ipc_client::exit(1);
|
ipc_client::exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user