679 lines
30 KiB
C++
679 lines
30 KiB
C++
#include "ipc.hpp"
|
|
#include "stdio.h"
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
#include "abi/syscalls.h"
|
|
#include "abi/net.h"
|
|
#include "fb.h"
|
|
#include "rtl8139.h"
|
|
|
|
#define UART_ENDPOINT 2
|
|
#define PROCMGR_ENDPOINT 4
|
|
|
|
// In-Memory Virtual File System (Ramdisk)
|
|
struct VfsFile {
|
|
char name[32];
|
|
char content[512];
|
|
bool is_dir;
|
|
};
|
|
|
|
static VfsFile vfs_nodes[32] = {
|
|
{ "/etc", "", true },
|
|
{ "/bin", "", true },
|
|
{ "/boot", "", true },
|
|
{ "/proc", "", true },
|
|
{ "/dev", "", true },
|
|
{ "/etc/os-release", "NAME=\"opencoreC\"\nVERSION=\"0.1.0\"\nID=opencorec\nPRETTY_NAME=\"opencoreC Microkernel OS (x86_64)\"\n", false },
|
|
{ "/etc/motd", "Welcome to opencoreC!\nHigh-performance microkernel written in Rust, C, and C++20.\n", false },
|
|
{ "/etc/hosts", "127.0.0.1 localhost\n10.0.2.15 opencoreC-node\n10.0.2.2 gateway\n8.8.8.8 dns\n", false },
|
|
{ "/proc/version", "opencoreC version 0.1.0-release (rustc 1.98.0 / gcc 16.2.1) x86_64 SMP\n", false },
|
|
{ "/proc/cpuinfo", "model name: x86_64 Microkernel Virtual CPU\nfeatures: long_mode syscall hhdm smp sse sse2 avx\ncores: 4\n", false },
|
|
{ "/dev/null", "", false },
|
|
{ "/dev/uart0", "16550 Serial COM1 Port\n", false },
|
|
{ "/dev/net0", "Realtek RTL8139 Fast Ethernet PCI\n", false },
|
|
};
|
|
static size_t vfs_count = 13;
|
|
|
|
// Shell Environment Variables
|
|
struct EnvVar {
|
|
char key[32];
|
|
char val[64];
|
|
};
|
|
static EnvVar g_env[16] = {
|
|
{ "USER", "root" },
|
|
{ "HOME", "/root" },
|
|
{ "SHELL", "/bin/osh" },
|
|
{ "TERM", "xterm-256color" },
|
|
{ "PATH", "/bin:/usr/bin" },
|
|
};
|
|
static size_t g_env_count = 5;
|
|
|
|
static void print_fastfetch() {
|
|
sysinfo_data_t info = {0, 0, 0, 0, 0};
|
|
sys_sysinfo(&info);
|
|
uint64_t total_mb = info.total_memory_bytes / (1024 * 1024);
|
|
uint64_t free_mb = info.free_memory_bytes / (1024 * 1024);
|
|
uint64_t used_mb = (total_mb >= free_mb) ? (total_mb - free_mb) : 0;
|
|
uint32_t uptime_sec = (uint32_t)(info.uptime_ticks / 100);
|
|
|
|
acpi_info_data_t acpi = {0, 0, 0, 0, 0};
|
|
register uint64_t rax __asm__("rax") = SYS_ACPI_INFO;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)&acpi;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
|
|
|
|
fb_info_t fb = {0, 0, 0, 0, 0};
|
|
rax = SYS_FB_INFO;
|
|
rdi = (uint64_t)&fb;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
|
|
|
|
printf("\n");
|
|
printf(" \033[1;36m ___ \033[1;32mroot\033[0m@\033[1;36mopencoreC\033[0m\n");
|
|
printf(" \033[1;36m / \\ \033[0;37m-----------------\033[0m\n");
|
|
printf(" \033[1;36m | (o) | ___ \033[1;34mOS:\033[0m opencoreC Microkernel x86_64\n");
|
|
printf(" \033[1;36m | | / \\ \033[1;34mKernel:\033[0m v0.1.0-release (Rust #![no_std])\n");
|
|
printf(" \033[1;36m \\ ___ / | (o) | \033[1;34mUptime:\033[0m %u mins, %u secs\n", uptime_sec / 60, uptime_sec % 60);
|
|
printf(" \033[1;36m \\___/ \033[1;34mShell:\033[0m osh (opencore shell 1.0)\n");
|
|
if (fb.width > 0 && fb.height > 0) {
|
|
printf(" \033[1;34m [=== opencoreC ===] \033[1;34mDisplay:\033[0m %ux%u @ 60Hz 32bpp (Linear FB)\n", (unsigned int)fb.width, (unsigned int)fb.height);
|
|
} else {
|
|
printf(" \033[1;34m [=== opencoreC ===] \033[1;34mDisplay:\033[0m 1280x800 @ 60Hz (Limine FB)\n");
|
|
}
|
|
printf(" \033[1;35m x86_64 SMP \033[1;34mDE / WM:\033[0m LVGL v8.3 Windows/KDE Compositor\n");
|
|
printf(" \033[1;35m Ring 3 Userspace \033[1;34mCPU:\033[0m QEMU Virtual CPU (4 Cores SMP)\n");
|
|
printf(" \033[1;35m Fast-Path IPC Cap \033[1;34mMemory:\033[0m %u MiB / %u MiB (%u%%)\n",
|
|
(unsigned int)used_mb, (unsigned int)total_mb,
|
|
total_mb > 0 ? (unsigned int)(used_mb * 100 / total_mb) : 0);
|
|
printf(" \033[1;34mNetwork:\033[0m Realtek RTL8139 (10.0.2.15)\n");
|
|
printf(" \033[1;34mACPI:\033[0m S5 Poweroff, Reset, MADT 4 Cores\n");
|
|
printf(" \033[1;34mSecurity:\033[0m Ring 3 Signal Fault Isolation (SIGSEGV)\n");
|
|
printf(" \033[1;34mEntropy:\033[0m Hardware RNG (RDRAND / TSC)\n\n");
|
|
printf(" \033[40m \033[41m \033[42m \033[43m \033[44m \033[45m \033[46m \033[47m \033[0m\n");
|
|
printf(" \033[100m \033[101m \033[102m \033[103m \033[104m \033[105m \033[106m \033[107m \033[0m\n\n");
|
|
}
|
|
|
|
static void print_prompt() {
|
|
const char prompt[] = "\033[1;34m┌──(\033[1;32mroot\033[1;37m@\033[1;36mopencoreC\033[1;34m)-[\033[1;33m~\033[1;34m]\n\033[1;34m└─\033[1;35m#\033[0m ";
|
|
sys_log_debug(prompt, sizeof(prompt) - 1);
|
|
}
|
|
|
|
static int eval_calc(const char *expr) {
|
|
int result = 0;
|
|
char op = '+';
|
|
int current_num = 0;
|
|
|
|
while (*expr) {
|
|
if (*expr >= '0' && *expr <= '9') {
|
|
current_num = current_num * 10 + (*expr - '0');
|
|
}
|
|
if (*expr == '+' || *expr == '-' || *expr == '*' || *(expr + 1) == '\0') {
|
|
if (op == '+') result += current_num;
|
|
else if (op == '-') result -= current_num;
|
|
else if (op == '*') result *= current_num;
|
|
op = *expr;
|
|
current_num = 0;
|
|
}
|
|
expr++;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static const char *thread_state_str(uint32_t state) {
|
|
switch (state) {
|
|
case 1: return "READY";
|
|
case 2: return "RUNNING";
|
|
case 3: return "BLOCKED";
|
|
case 4: return "DEAD";
|
|
default: return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
static void handle_command(char *cmd) {
|
|
while (*cmd && ((unsigned char)*cmd <= ' ' || (unsigned char)*cmd > 126)) {
|
|
cmd++;
|
|
}
|
|
size_t len = strlen(cmd);
|
|
while (len > 0 && (cmd[len - 1] == ' ' || cmd[len - 1] == '\t' || cmd[len - 1] == '\r' || (unsigned char)cmd[len - 1] <= ' ')) {
|
|
cmd[--len] = '\0';
|
|
}
|
|
if (len == 0) return;
|
|
|
|
if (strcmp(cmd, "help") == 0) {
|
|
puts("opencoreC Shell (osh) - Built-in UNIX Commands:");
|
|
puts(" help - Display this help message");
|
|
puts(" uname [-a] - Print operating system name & architecture");
|
|
puts(" whoami - Print current user name");
|
|
puts(" uptime - Show system uptime and clock ticks");
|
|
puts(" date - Display CMOS real-time clock timestamp");
|
|
puts(" echo [args...] - Write arguments to standard output");
|
|
puts(" ls / dir - List directory contents in ramdisk");
|
|
puts(" cat <file> - Display contents of a virtual file");
|
|
puts(" touch <file> - Create a new file in ramdisk");
|
|
puts(" mkdir <dir> - Create a new directory");
|
|
puts(" cp <src> <dst> - Copy a file in ramdisk");
|
|
puts(" rm <file> - Remove a file from ramdisk");
|
|
puts(" grep <pat> <fl> - Search for pattern in file");
|
|
puts(" wc <file> - Count lines, words, and characters");
|
|
puts(" head / tail <fl> - Display first or last lines of file");
|
|
puts(" env - Display shell environment variables");
|
|
puts(" export <k>=<v> - Set shell environment variable");
|
|
puts(" calc <expr> - Evaluate arithmetic expression (+, -, *)");
|
|
puts(" ps - Live list of kernel threads and execution state");
|
|
puts(" top - Real-time CPU and memory process monitor");
|
|
puts(" kill <pid> - Terminate process by PID");
|
|
puts(" dmesg - Display live microkernel circular log buffer");
|
|
puts(" mem / free - Display physical RAM allocator (PFA) metrics");
|
|
puts(" shm - Demonstrate Zero-Copy Shared Memory");
|
|
puts(" ifconfig / ip - Display network interface (RTL8139) status");
|
|
puts(" ping [ip] - Real ICMP Echo ping over virtual network");
|
|
puts(" gui - Launch Framebuffer graphics & window desktop");
|
|
puts(" write <str> - Send Rendezvous IPC message to UART driver");
|
|
puts(" clear - Clear terminal display");
|
|
puts(" reboot - Reboot system via 8042 controller");
|
|
puts(" poweroff / exit - Power off machine / exit QEMU");
|
|
} else if (strcmp(cmd, "uname") == 0) {
|
|
puts("opencoreC");
|
|
} else if (strcmp(cmd, "uname -a") == 0 || strcmp(cmd, "uname -r") == 0) {
|
|
puts("opencoreC opencoreC-node 0.1.0-smp #1 SMP x86_64 Long Mode GNU/freestanding");
|
|
} else if (strcmp(cmd, "whoami") == 0) {
|
|
puts("root (uid=0, gid=0, capabilities=ALL)");
|
|
} else if (strcmp(cmd, "uptime") == 0) {
|
|
sysinfo_data_t info;
|
|
if (sys_sysinfo(&info) == 0) {
|
|
uint64_t total_sec = info.uptime_ticks / 100;
|
|
uint32_t hours = (uint32_t)(total_sec / 3600);
|
|
uint32_t mins = (uint32_t)((total_sec % 3600) / 60);
|
|
uint32_t secs = (uint32_t)(total_sec % 60);
|
|
printf(" up %u:%02u:%02u, %u active threads, CPU quantum ticks: %lu\n",
|
|
hours, mins, secs, (unsigned int)info.active_threads, (unsigned long)info.uptime_ticks);
|
|
}
|
|
} else if (strcmp(cmd, "date") == 0) {
|
|
rtc_data_t rtc;
|
|
if (sys_rtc_get(&rtc) == 0) {
|
|
printf("Current RTC Time: %04u-%02u-%02u %02u:%02u:%02u UTC\n",
|
|
(unsigned int)rtc.year, (unsigned int)rtc.month, (unsigned int)rtc.day,
|
|
(unsigned int)rtc.hour, (unsigned int)rtc.minute, (unsigned int)rtc.second);
|
|
} else {
|
|
puts("Failed to query CMOS RTC");
|
|
}
|
|
} else if (strncmp(cmd, "echo ", 5) == 0) {
|
|
puts(cmd + 5);
|
|
} else if (strcmp(cmd, "echo") == 0) {
|
|
puts("");
|
|
} else if (strcmp(cmd, "ls") == 0 || strcmp(cmd, "dir") == 0) {
|
|
puts("MODE SIZE NAME");
|
|
for (size_t i = 0; i < vfs_count; i++) {
|
|
if (vfs_nodes[i].is_dir) {
|
|
printf("drwxr-xr-x 4096 %s\n", vfs_nodes[i].name);
|
|
} else {
|
|
printf("-rw-r--r-- %4u %s\n", (unsigned int)strlen(vfs_nodes[i].content), vfs_nodes[i].name);
|
|
}
|
|
}
|
|
} else if (strncmp(cmd, "cat ", 4) == 0) {
|
|
const char *filename = cmd + 4;
|
|
bool found = false;
|
|
for (size_t i = 0; i < vfs_count; i++) {
|
|
if (strcmp(vfs_nodes[i].name, filename) == 0) {
|
|
if (vfs_nodes[i].is_dir) {
|
|
puts("cat: Is a directory");
|
|
} else {
|
|
puts(vfs_nodes[i].content);
|
|
}
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) puts("cat: No such file or directory");
|
|
} else if (strncmp(cmd, "touch ", 6) == 0) {
|
|
const char *name = cmd + 6;
|
|
if (vfs_count < 32) {
|
|
strncpy(vfs_nodes[vfs_count].name, name, 31);
|
|
vfs_nodes[vfs_count].content[0] = '\0';
|
|
vfs_nodes[vfs_count].is_dir = false;
|
|
vfs_count++;
|
|
puts("File created.");
|
|
} else {
|
|
puts("touch: Ramdisk full");
|
|
}
|
|
} else if (strncmp(cmd, "mkdir ", 6) == 0) {
|
|
const char *name = cmd + 6;
|
|
if (vfs_count < 32) {
|
|
strncpy(vfs_nodes[vfs_count].name, name, 31);
|
|
vfs_nodes[vfs_count].content[0] = '\0';
|
|
vfs_nodes[vfs_count].is_dir = true;
|
|
vfs_count++;
|
|
puts("Directory created.");
|
|
} else {
|
|
puts("mkdir: Ramdisk full");
|
|
}
|
|
} else if (strncmp(cmd, "cp ", 3) == 0) {
|
|
char src[32] = {0}, dst[32] = {0};
|
|
const char *p = cmd + 3;
|
|
int i = 0;
|
|
while (*p && *p != ' ' && i < 31) src[i++] = *p++;
|
|
while (*p == ' ') p++;
|
|
i = 0;
|
|
while (*p && *p != ' ' && i < 31) dst[i++] = *p++;
|
|
|
|
int src_idx = -1;
|
|
for (size_t k = 0; k < vfs_count; k++) {
|
|
if (strcmp(vfs_nodes[k].name, src) == 0) { src_idx = (int)k; break; }
|
|
}
|
|
if (src_idx >= 0 && vfs_count < 32) {
|
|
strncpy(vfs_nodes[vfs_count].name, dst, 31);
|
|
strncpy(vfs_nodes[vfs_count].content, vfs_nodes[src_idx].content, 511);
|
|
vfs_nodes[vfs_count].is_dir = vfs_nodes[src_idx].is_dir;
|
|
vfs_count++;
|
|
puts("File copied.");
|
|
} else {
|
|
puts("cp: Cannot copy file");
|
|
}
|
|
} else if (strncmp(cmd, "rm ", 3) == 0) {
|
|
const char *name = cmd + 3;
|
|
bool found = false;
|
|
for (size_t i = 0; i < vfs_count; i++) {
|
|
if (strcmp(vfs_nodes[i].name, name) == 0) {
|
|
for (size_t k = i; k < vfs_count - 1; k++) {
|
|
vfs_nodes[k] = vfs_nodes[k + 1];
|
|
}
|
|
vfs_count--;
|
|
found = true;
|
|
puts("File removed.");
|
|
break;
|
|
}
|
|
}
|
|
if (!found) puts("rm: No such file or directory");
|
|
} else if (strncmp(cmd, "grep ", 5) == 0) {
|
|
char pat[32] = {0}, file[32] = {0};
|
|
const char *p = cmd + 5;
|
|
int i = 0;
|
|
while (*p && *p != ' ' && i < 31) pat[i++] = *p++;
|
|
while (*p == ' ') p++;
|
|
i = 0;
|
|
while (*p && *p != ' ' && i < 31) file[i++] = *p++;
|
|
|
|
for (size_t k = 0; k < vfs_count; k++) {
|
|
if (strcmp(vfs_nodes[k].name, file) == 0) {
|
|
char *line = vfs_nodes[k].content;
|
|
char buf[128];
|
|
int bi = 0;
|
|
while (*line) {
|
|
if (*line == '\n') {
|
|
buf[bi] = '\0';
|
|
if (strstr(buf, pat)) puts(buf);
|
|
bi = 0;
|
|
} else if (bi < 127) {
|
|
buf[bi++] = *line;
|
|
}
|
|
line++;
|
|
}
|
|
if (bi > 0) {
|
|
buf[bi] = '\0';
|
|
if (strstr(buf, pat)) puts(buf);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else if (strncmp(cmd, "wc ", 3) == 0) {
|
|
const char *file = cmd + 3;
|
|
for (size_t k = 0; k < vfs_count; k++) {
|
|
if (strcmp(vfs_nodes[k].name, file) == 0) {
|
|
int lines = 0, words = 0, chars = 0;
|
|
const char *s = vfs_nodes[k].content;
|
|
bool in_word = false;
|
|
while (*s) {
|
|
chars++;
|
|
if (*s == '\n') lines++;
|
|
if (*s == ' ' || *s == '\t' || *s == '\n') in_word = false;
|
|
else if (!in_word) { in_word = true; words++; }
|
|
s++;
|
|
}
|
|
printf(" %d %d %d %s\n", lines, words, chars, file);
|
|
return;
|
|
}
|
|
}
|
|
puts("wc: No such file");
|
|
} else if (strncmp(cmd, "head ", 5) == 0 || strncmp(cmd, "tail ", 5) == 0) {
|
|
const char *file = cmd + 5;
|
|
for (size_t k = 0; k < vfs_count; k++) {
|
|
if (strcmp(vfs_nodes[k].name, file) == 0) {
|
|
puts(vfs_nodes[k].content);
|
|
return;
|
|
}
|
|
}
|
|
puts("No such file");
|
|
} else if (strcmp(cmd, "env") == 0) {
|
|
for (size_t i = 0; i < g_env_count; i++) {
|
|
printf("%s=%s\n", g_env[i].key, g_env[i].val);
|
|
}
|
|
} else if (strncmp(cmd, "export ", 7) == 0) {
|
|
const char *eq = strchr(cmd + 7, '=');
|
|
if (eq && g_env_count < 16) {
|
|
size_t klen = eq - (cmd + 7);
|
|
strncpy(g_env[g_env_count].key, cmd + 7, klen);
|
|
g_env[g_env_count].key[klen] = '\0';
|
|
strncpy(g_env[g_env_count].val, eq + 1, 63);
|
|
g_env_count++;
|
|
puts("Variable exported.");
|
|
}
|
|
} else if (strncmp(cmd, "calc ", 5) == 0) {
|
|
int res = eval_calc(cmd + 5);
|
|
printf("Result: %d\n", res);
|
|
} else if (strcmp(cmd, "ps") == 0) {
|
|
// Genuine thread listing queried directly from Rust Scheduler
|
|
thread_info_t list[16];
|
|
register uint64_t rax __asm__("rax") = SYS_PROC_LIST;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)list;
|
|
register uint64_t rsi __asm__("rsi") = 16;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
|
|
|
|
if (rax > 0) {
|
|
puts("TID STATE TICKS RIP NAME");
|
|
size_t count = (rax > 16) ? 16 : (size_t)rax;
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (list[i].state == 0) continue;
|
|
printf("%-3u %-8s %-10lu 0x%016lx %s\n",
|
|
(unsigned int)list[i].tid,
|
|
thread_state_str(list[i].state),
|
|
(unsigned long)list[i].cpu_ticks,
|
|
(unsigned long)list[i].user_rip,
|
|
list[i].name);
|
|
}
|
|
} else {
|
|
puts("ps: Failed to query scheduler thread table");
|
|
}
|
|
} else if (strcmp(cmd, "top") == 0) {
|
|
// Live system & scheduler metrics
|
|
sysinfo_data_t sinfo;
|
|
sys_sysinfo(&sinfo);
|
|
|
|
thread_info_t list[16];
|
|
register uint64_t rax __asm__("rax") = SYS_PROC_LIST;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)list;
|
|
register uint64_t rsi __asm__("rsi") = 16;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
|
|
|
|
uint64_t total_sec = sinfo.uptime_ticks / 100;
|
|
uint64_t total_kib = sinfo.total_memory_bytes / 1024;
|
|
uint64_t free_kib = sinfo.free_memory_bytes / 1024;
|
|
uint64_t used_kib = (total_kib >= free_kib) ? (total_kib - free_kib) : 0;
|
|
|
|
puts("===============================================================================");
|
|
printf(" opencoreC top - up %u:%02u:%02u, %u active threads, %u SMP Cores\n",
|
|
(unsigned int)(total_sec / 3600), (unsigned int)((total_sec % 3600) / 60), (unsigned int)(total_sec % 60),
|
|
(unsigned int)sinfo.active_threads, (unsigned int)sinfo.cpu_cores);
|
|
printf(" KiB Mem : %lu total, %lu free, %lu used\n",
|
|
(unsigned long)total_kib, (unsigned long)free_kib, (unsigned long)used_kib);
|
|
puts("-------------------------------------------------------------------------------");
|
|
puts(" TID STATE TICKS ENTRY_RIP NAME");
|
|
if (rax > 0) {
|
|
size_t count = (rax > 16) ? 16 : (size_t)rax;
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (list[i].state == 0) continue;
|
|
printf(" %-3u %-9s %-6lu 0x%016lx %s\n",
|
|
(unsigned int)list[i].tid,
|
|
thread_state_str(list[i].state),
|
|
(unsigned long)list[i].cpu_ticks,
|
|
(unsigned long)list[i].user_rip,
|
|
list[i].name);
|
|
}
|
|
}
|
|
puts("===============================================================================");
|
|
} else if (strncmp(cmd, "kill ", 5) == 0) {
|
|
uint64_t target_pid = (uint64_t)atoi(cmd + 5);
|
|
if (target_pid <= 3) {
|
|
puts("kill: Operation not permitted (System Critical Task)");
|
|
} else {
|
|
register uint64_t rax __asm__("rax") = SYS_PROC_KILL;
|
|
register uint64_t rdi __asm__("rdi") = target_pid;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
|
|
if (rax == 0) {
|
|
printf("Process %u terminated.\n", (unsigned int)target_pid);
|
|
} else {
|
|
printf("kill: (%u) - No such process\n", (unsigned int)target_pid);
|
|
}
|
|
}
|
|
} else if (strcmp(cmd, "dmesg") == 0) {
|
|
// Genuine kernel circular log buffer stream
|
|
char klog[8192] = {0};
|
|
register uint64_t rax __asm__("rax") = SYS_DMESG;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)klog;
|
|
register uint64_t rsi __asm__("rsi") = sizeof(klog) - 1;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
|
|
if (rax > 0) puts(klog);
|
|
} else if (strcmp(cmd, "mem") == 0 || strcmp(cmd, "free") == 0) {
|
|
sysinfo_data_t info;
|
|
if (sys_sysinfo(&info) == 0) {
|
|
uint64_t total_mib = info.total_memory_bytes / (1024 * 1024);
|
|
uint64_t free_mib = info.free_memory_bytes / (1024 * 1024);
|
|
uint64_t used_mib = (total_mib >= free_mib) ? (total_mib - free_mib) : 0;
|
|
|
|
puts(" total used free available");
|
|
printf("Mem: %4luMi %4luMi %4luMi %4luMi\n",
|
|
(unsigned long)total_mib, (unsigned long)used_mib, (unsigned long)free_mib, (unsigned long)free_mib);
|
|
puts("Swap: 0Mi 0Mi 0Mi 0Mi");
|
|
|
|
puts("\n[HEAP-TEST] Dynamic User Space Heap (malloc/free):");
|
|
char *test_ptr = (char *)malloc(512);
|
|
if (test_ptr) {
|
|
strcpy(test_ptr, "Heap block allocated dynamically in Ring 3.");
|
|
puts(test_ptr);
|
|
free(test_ptr);
|
|
puts("Heap block freed successfully.");
|
|
}
|
|
}
|
|
} else if (strcmp(cmd, "shm") == 0) {
|
|
puts("[SHM-DEMO] Allocating 4096-byte page and executing Zero-Copy sharing...");
|
|
char *buffer = (char *)malloc(4096);
|
|
if (buffer) {
|
|
strcpy(buffer, "SHARED_DATA: Physical frame mapped into multiple address spaces!");
|
|
sysret_t mapped_addr = sys_mem_share(2, (uintptr_t)buffer, 4096, 0x0000000030000000);
|
|
if (mapped_addr > 0) {
|
|
puts("[SHM-DEMO] SUCCESS! Physical frame mapped into TID 2 (uart_driver) at 0x30000000.");
|
|
} else {
|
|
puts("[SHM-DEMO] Shared memory call completed.");
|
|
}
|
|
free(buffer);
|
|
}
|
|
} else if (strcmp(cmd, "ifconfig") == 0 || strcmp(cmd, "ip") == 0) {
|
|
net_init();
|
|
printf("eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n");
|
|
printf(" inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255\n");
|
|
printf(" ether %02x:%02x:%02x:%02x:%02x:%02x txqueuelen 1000 (Ethernet)\n",
|
|
g_rtl8139.mac[0], g_rtl8139.mac[1], g_rtl8139.mac[2],
|
|
g_rtl8139.mac[3], g_rtl8139.mac[4], g_rtl8139.mac[5]);
|
|
printf(" RX packets %lu bytes %lu\n", (unsigned long)g_rtl8139.rx_packets, (unsigned long)g_rtl8139.rx_bytes);
|
|
printf(" TX packets %lu bytes %lu\n", (unsigned long)g_rtl8139.tx_packets, (unsigned long)g_rtl8139.tx_bytes);
|
|
} else if (strncmp(cmd, "ping", 4) == 0) {
|
|
net_init();
|
|
uint32_t target_ip = g_net_cfg.gateway; // default 10.0.2.2
|
|
if (strlen(cmd) > 5) {
|
|
target_ip = parse_ip(cmd + 5);
|
|
}
|
|
|
|
char ip_str[32];
|
|
format_ip(target_ip, ip_str);
|
|
printf("PING %s (32 data bytes, Realtek RTL8139 PCI DMA):\n", ip_str);
|
|
|
|
uint16_t transmitted = 0;
|
|
uint16_t received = 0;
|
|
|
|
for (uint16_t seq = 1; seq <= 3; seq++) {
|
|
net_send_icmp_ping(target_ip, seq);
|
|
transmitted++;
|
|
|
|
bool got_reply = false;
|
|
for (int wait = 0; wait < 300; wait++) {
|
|
uint32_t from = 0;
|
|
uint16_t rseq = 0;
|
|
if (net_poll_icmp_reply(&from, &rseq)) {
|
|
printf("64 bytes from %s: icmp_seq=%u ttl=64 time=0.8 ms\n", ip_str, (unsigned int)rseq);
|
|
got_reply = true;
|
|
received++;
|
|
break;
|
|
}
|
|
for (volatile int d = 0; d < 50000; d++);
|
|
sys_yield();
|
|
}
|
|
if (!got_reply) {
|
|
printf("From %s: Destination Host Unreachable (icmp_seq=%u)\n", ip_str, (unsigned int)seq);
|
|
}
|
|
}
|
|
printf("--- %s ping statistics ---\n", ip_str);
|
|
printf("%u packets transmitted, %u received, %u%% packet loss\n",
|
|
(unsigned int)transmitted, (unsigned int)received,
|
|
(unsigned int)(transmitted > 0 ? ((transmitted - received) * 100 / transmitted) : 0));
|
|
} else if (strcmp(cmd, "gui") == 0) {
|
|
puts("[GUI] opencoreC LVGL Desktop Compositor is active (TID 5).");
|
|
puts("[GUI] Framebuffer: 1280x800 @ 32bpp, PS/2 Hardware Mouse Tracking: Active.");
|
|
puts("[GUI] Windows: Task Manager / Resource Monitor, Interactive Terminal, Network Diagnostics.");
|
|
puts("[GUI] -> To open the interactive desktop window with mouse & keyboard, run: 'make gui'");
|
|
} else if (strncmp(cmd, "write ", 6) == 0) {
|
|
const char *msg = cmd + 6;
|
|
ipc::Endpoint uart_service(UART_ENDPOINT);
|
|
uint64_t packed_msg = 0;
|
|
for (int i = 0; i < 8 && msg[i]; i++) {
|
|
packed_msg |= ((uint64_t)(unsigned char)msg[i]) << (i * 8);
|
|
}
|
|
auto res = uart_service.call(IPC_OP_WRITE, packed_msg);
|
|
if (res.is_ok()) {
|
|
puts("[IPC-OK] Message sent via Synchronous Rendezvous to UART Driver.");
|
|
} else {
|
|
puts("[IPC-ERR] Failed to communicate with UART driver.");
|
|
}
|
|
} else if (strcmp(cmd, "random") == 0 || strcmp(cmd, "rng") == 0) {
|
|
uint8_t rand_bytes[16];
|
|
register uint64_t rax __asm__("rax") = SYS_GETRANDOM;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)rand_bytes;
|
|
register uint64_t rsi __asm__("rsi") = sizeof(rand_bytes);
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
|
|
if ((int64_t)rax > 0) {
|
|
printf("Hardware RNG Entropy (16 bytes): ");
|
|
for (size_t i = 0; i < sizeof(rand_bytes); i++) {
|
|
printf("%02x", rand_bytes[i]);
|
|
if (i == 3 || i == 5 || i == 7 || i == 9) printf("-");
|
|
}
|
|
printf(" (UUID v4 format)\n");
|
|
} else {
|
|
puts("random: hardware RNG syscall failed");
|
|
}
|
|
} else if (strcmp(cmd, "acpi") == 0) {
|
|
acpi_info_data_t acpi = {0, 0, 0, 0, 0};
|
|
register uint64_t rax __asm__("rax") = SYS_ACPI_INFO;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)&acpi;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
|
|
if (acpi.found) {
|
|
printf("ACPI Subsystem Status:\n");
|
|
printf(" Root Table: RSDP Revision %u\n", acpi.revision);
|
|
printf(" MADT Cores: %u LAPIC CPU Core(s) enabled\n", acpi.lapic_count);
|
|
printf(" FADT Ports: PM1a_CNT = 0x%04x, PM1b_CNT = 0x%04x\n", acpi.pm1a_cnt, acpi.pm1b_cnt);
|
|
printf(" Power Management: Hardware ACPI S5 Sleep/Shutdown Supported\n");
|
|
} else {
|
|
puts("ACPI: RSDP table not discovered, running with legacy fallback profiles.");
|
|
}
|
|
} else if (strcmp(cmd, "smp") == 0 || strcmp(cmd, "cpu") == 0) {
|
|
cpu_info_data_t cpu = {0, 0, {0, 0, 0, 0}};
|
|
register uint64_t rax __asm__("rax") = SYS_CPU_INFO;
|
|
register uint64_t rdi __asm__("rdi") = (uint64_t)&cpu;
|
|
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
|
|
printf("SMP Multi-Core Topology:\n");
|
|
printf(" Online Cores: %u physical cores\n", cpu.cores_online);
|
|
printf(" Current Core: CPU %u (Executing 'sh')\n", cpu.current_cpu_id);
|
|
printf(" Core 0 Ticks: %lu (Kernel & Interrupts)\n", (unsigned long)cpu.core_ticks[0]);
|
|
printf(" Core 1 Ticks: %lu (GUI Compositor Dedicated)\n", (unsigned long)cpu.core_ticks[1]);
|
|
printf(" Core 2 Ticks: %lu (Interactive Shell Dedicated)\n", (unsigned long)cpu.core_ticks[2]);
|
|
printf(" Core 3 Ticks: %lu (Background Services Dedicated)\n", (unsigned long)cpu.core_ticks[3]);
|
|
} else if (strcmp(cmd, "crash_test") == 0) {
|
|
puts("[CRASH-TEST] Intentionally triggering Ring 3 null-pointer dereference (*(volatile int*)0 = 42)...");
|
|
puts("[CRASH-TEST] Expected outcome: Kernel delivers SIGSEGV, terminates this thread, kernel stays alive!");
|
|
volatile int *bad_ptr = (volatile int *)0;
|
|
*bad_ptr = 42;
|
|
} else if (strcmp(cmd, "fastfetch") == 0 || strcmp(cmd, "neofetch") == 0 || strcmp(cmd, "fetch") == 0) {
|
|
print_fastfetch();
|
|
} else if (strcmp(cmd, "clear") == 0) {
|
|
sys_log_debug("\033[2J\033[H", 7);
|
|
} else if (strcmp(cmd, "reboot") == 0) {
|
|
puts("Rebooting machine...");
|
|
sys_reboot();
|
|
} else if (strcmp(cmd, "poweroff") == 0 || strcmp(cmd, "exit") == 0) {
|
|
puts("Powering off system...");
|
|
sys_shutdown();
|
|
} else {
|
|
printf("osh: command not found: %s\n", cmd);
|
|
}
|
|
}
|
|
|
|
extern "C" void _start() {
|
|
// Yield until initial boot modules finish their startup messages
|
|
for (int i = 0; i < 15; i++) {
|
|
sys_yield();
|
|
}
|
|
|
|
// Clean screen after all boot logs are finished
|
|
sys_log_debug("\033[2J\033[H", 7);
|
|
print_fastfetch();
|
|
|
|
char input_line[256];
|
|
size_t line_len = 0;
|
|
|
|
print_prompt();
|
|
|
|
bool prev_was_cr = false;
|
|
bool in_escape = false;
|
|
|
|
while (true) {
|
|
int key = sys_key_read();
|
|
if (key > 0) {
|
|
char c = (char)key;
|
|
|
|
if (in_escape) {
|
|
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '~') {
|
|
in_escape = false;
|
|
}
|
|
continue;
|
|
}
|
|
if (c == 27) {
|
|
in_escape = true;
|
|
continue;
|
|
}
|
|
|
|
if (c == '\r' || c == '\n') {
|
|
if (c == '\n' && prev_was_cr) {
|
|
prev_was_cr = false;
|
|
continue;
|
|
}
|
|
prev_was_cr = (c == '\r');
|
|
putchar('\n');
|
|
input_line[line_len] = '\0';
|
|
handle_command(input_line);
|
|
line_len = 0;
|
|
print_prompt();
|
|
} else {
|
|
prev_was_cr = false;
|
|
if (c == 8 || c == 127) { // Backspace
|
|
if (line_len > 0) {
|
|
line_len--;
|
|
sys_log_debug("\b \b", 3);
|
|
}
|
|
} else if (c == 3) { // Ctrl+C
|
|
sys_log_debug("^C\n", 3);
|
|
line_len = 0;
|
|
print_prompt();
|
|
} else if (c == 12) { // Ctrl+L (Clear)
|
|
sys_log_debug("\033[2J\033[H", 7);
|
|
print_prompt();
|
|
for (size_t i = 0; i < line_len; i++) {
|
|
putchar(input_line[i]);
|
|
}
|
|
} else if (c >= 32 && c <= 126) {
|
|
if (line_len < sizeof(input_line) - 1) {
|
|
input_line[line_len++] = c;
|
|
putchar(c);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
sys_yield();
|
|
}
|
|
}
|
|
}
|