feat(sh,gui): universalize binary execution, dynamic VFS, and hardware reporting

- Eliminate hardcoded program names (e.g. hello.opc) in shell hints, help, and VFS
- Automatically resolve and execute any binary by name (e.g. typing 'hello' or '<prog>')
- Dynamically populate VFS /bin from kernel module discovery (sys_module_list)
- Support path filtering in ls (e.g. 'ls /bin', 'ls /etc')
- Dynamically detect real CPU brand string via CPUID (leaf 0x80000002..0x80000004)
- Dynamically format network addresses in shell and GUI instead of hardcoded 10.0.2.15
This commit is contained in:
RarDog
2026-09-03 10:50:40 +03:00
parent de772a2de0
commit c18717539c
2 changed files with 267 additions and 44 deletions
+137 -26
View File
@@ -59,6 +59,35 @@ static lv_disp_draw_buf_t g_draw_buf;
static lv_color32_t g_cursor_map[CURSOR_W * CURSOR_H]; static lv_color32_t g_cursor_map[CURSOR_W * CURSOR_H];
static lv_img_dsc_t g_cursor_dsc; static lv_img_dsc_t g_cursor_dsc;
static void get_cpu_brand(char *brand, size_t max_len) {
memset(brand, 0, max_len);
uint32_t regs[4];
__asm__ volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) : "a"(0x80000000));
if (regs[0] >= 0x80000004) {
char *p = brand;
for (uint32_t leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
uint32_t b_regs[4];
__asm__ volatile("cpuid" : "=a"(b_regs[0]), "=b"(b_regs[1]), "=c"(b_regs[2]), "=d"(b_regs[3]) : "a"(leaf));
if (p - brand + 16 < (int)max_len) {
memcpy(p, b_regs, 16);
p += 16;
}
}
brand[max_len - 1] = '\0';
char *src = brand;
while (*src == ' ') src++;
if (src != brand) {
memmove(brand, src, strlen(src) + 1);
}
} else {
__asm__ volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) : "a"(0));
memcpy(brand, &regs[1], 4);
memcpy(brand + 4, &regs[3], 4);
memcpy(brand + 8, &regs[2], 4);
brand[12] = '\0';
}
}
// Top-level Desktop UI Elements // Top-level Desktop UI Elements
static lv_obj_t *g_start_menu = NULL; static lv_obj_t *g_start_menu = NULL;
static lv_obj_t *g_win_console = NULL; static lv_obj_t *g_win_console = NULL;
@@ -389,6 +418,11 @@ static void execute_console_command(const char *raw_cmd) {
uint64_t used_mb = (total_mb >= free_mb) ? (total_mb - free_mb) : 0; uint64_t used_mb = (total_mb >= free_mb) ? (total_mb - free_mb) : 0;
uint32_t uptime_sec = (uint32_t)(info.uptime_ticks / 100); uint32_t uptime_sec = (uint32_t)(info.uptime_ticks / 100);
char cpu_brand[64] = {0};
get_cpu_brand(cpu_brand, sizeof(cpu_brand));
char ip_str[32] = {0};
format_ip(g_net_cfg.ip, ip_str);
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
" ___ root@opencoreC\n" " ___ root@opencoreC\n"
" / \\ -----------------\n" " / \\ -----------------\n"
@@ -396,17 +430,20 @@ static void execute_console_command(const char *raw_cmd) {
" | | / \\ Kernel: v0.1.0-release (Rust #![no_std])\n" " | | / \\ Kernel: v0.1.0-release (Rust #![no_std])\n"
" \\ ___ / | (o) | Uptime: %u mins, %u secs\n" " \\ ___ / | (o) | Uptime: %u mins, %u secs\n"
" \\___/ Shell: osh (opencore shell)\n" " \\___/ Shell: osh (opencore shell)\n"
" [=== opencoreC ===] Display: 1280x800 @ 60Hz 32bpp (Limine FB)\n" " [=== opencoreC ===] Display: %ux%u @ 60Hz 32bpp\n"
" x86_64 SMP DE/WM: LVGL Desktop Compositor (Ring 3)\n" " x86_64 SMP DE/WM: LVGL Desktop Compositor (Ring 3)\n"
" Ring 3 Userspace CPU: QEMU Virtual CPU (4 Cores SMP)\n" " Ring 3 Userspace CPU: %s (4 Cores SMP)\n"
" Fast-Path IPC Cap RAM: %u MiB / %u MiB (%u%%)\n" " Fast-Path IPC Cap RAM: %u MiB / %u MiB (%u%%)\n"
" Network: RTL8139 Fast Ethernet (10.0.2.15)\n" " Network: PCI Ethernet (%s)\n"
" ACPI: MADT 4 Cores, S5 Power, Hardware Reset\n" " ACPI: S5 Power, Reset, MADT Active\n"
" Security: Ring 3 Fault Isolation (SIGSEGV)\n" " Security: Ring 3 Fault Isolation (SIGSEGV)\n"
" RNG: Hardware RDRAND / RDSEED Active\n", " RNG: Hardware RDRAND / RDSEED Active\n",
uptime_sec / 60, uptime_sec % 60, uptime_sec / 60, uptime_sec % 60,
(unsigned int)g_fb.width, (unsigned int)g_fb.height,
*cpu_brand ? cpu_brand : "x86_64 Processor",
(unsigned int)used_mb, (unsigned int)total_mb, (unsigned int)used_mb, (unsigned int)total_mb,
total_mb > 0 ? (unsigned int)(used_mb * 100 / total_mb) : 0); total_mb > 0 ? (unsigned int)(used_mb * 100 / total_mb) : 0,
*ip_str ? ip_str : "Unconfigured");
lv_textarea_add_text(g_txt_term_output, buf); lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(raw_cmd, "clear") == 0) { } else if (strcmp(raw_cmd, "clear") == 0) {
lv_textarea_set_text(g_txt_term_output, "opencoreC Linux-compatible Terminal (osh)\nType 'help' for available commands.\n"); lv_textarea_set_text(g_txt_term_output, "opencoreC Linux-compatible Terminal (osh)\nType 'help' for available commands.\n");
@@ -436,13 +473,22 @@ static void execute_console_command(const char *raw_cmd) {
(unsigned int)total_mb, (unsigned int)used_mb, (unsigned int)free_mb, (unsigned int)free_mb); (unsigned int)total_mb, (unsigned int)used_mb, (unsigned int)free_mb, (unsigned int)free_mb);
lv_textarea_add_text(g_txt_term_output, buf); lv_textarea_add_text(g_txt_term_output, buf);
} else if (strcmp(raw_cmd, "ifconfig") == 0 || strcmp(raw_cmd, "ip") == 0) { } else if (strcmp(raw_cmd, "ifconfig") == 0 || strcmp(raw_cmd, "ip") == 0) {
lv_textarea_add_text(g_txt_term_output, char ip_str[32], mask_str[32], gw_str[32];
format_ip(g_net_cfg.ip, ip_str);
format_ip(g_net_cfg.netmask, mask_str);
format_ip(g_net_cfg.gateway, gw_str);
snprintf(buf, sizeof(buf),
"eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n" "eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n"
" inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255\n" " inet %s netmask %s broadcast 255.255.255.255\n"
" ether 52:54:00:12:34:56 txqueuelen 1000 (Realtek RTL8139 DMA)\n" " ether %02x:%02x:%02x:%02x:%02x:%02x txqueuelen 1000 (PCI Ethernet)\n"
" gateway 10.0.2.2 (QEMU Virtual SLIRP NAT)\n"); " gateway %s\n",
ip_str, mask_str,
g_net_cfg.mac[0], g_net_cfg.mac[1], g_net_cfg.mac[2],
g_net_cfg.mac[3], g_net_cfg.mac[4], g_net_cfg.mac[5],
gw_str);
lv_textarea_add_text(g_txt_term_output, buf);
} else if (strncmp(raw_cmd, "ping", 4) == 0) { } else if (strncmp(raw_cmd, "ping", 4) == 0) {
uint32_t target_ip = (10) | (0 << 8) | (2 << 16) | (2 << 24); // default 10.0.2.2 uint32_t target_ip = g_net_cfg.gateway ? g_net_cfg.gateway : parse_ip("1.1.1.1");
if (strlen(raw_cmd) > 5) { if (strlen(raw_cmd) > 5) {
target_ip = parse_ip(raw_cmd + 5); target_ip = parse_ip(raw_cmd + 5);
} }
@@ -579,11 +625,56 @@ static void execute_console_command(const char *raw_cmd) {
lv_textarea_add_text(g_txt_term_output, "Powering off opencoreC...\n"); lv_textarea_add_text(g_txt_term_output, "Powering off opencoreC...\n");
register uint64_t rax __asm__("rax") = SYS_SHUTDOWN; register uint64_t rax __asm__("rax") = SYS_SHUTDOWN;
__asm__ volatile("syscall" : "+r"(rax) : : "rcx", "r11", "memory"); __asm__ volatile("syscall" : "+r"(rax) : : "rcx", "r11", "memory");
} else if (strcmp(raw_cmd, "modules") == 0) {
char mbuf[512] = {0};
int len = sys_module_list(mbuf, sizeof(mbuf) - 1);
if (len > 0) {
lv_textarea_add_text(g_txt_term_output, "In-Memory Boot Modules:\n");
char *p = mbuf;
while (*p) {
char mod[64] = {0};
int mi = 0;
while (*p && *p != ' ' && mi < 63) {
mod[mi++] = *p++;
}
while (*p == ' ') p++;
snprintf(buf, sizeof(buf), " * %s\n", mod);
lv_textarea_add_text(g_txt_term_output, buf);
}
} else {
lv_textarea_add_text(g_txt_term_output, "modules: No modules detected.\n");
}
} else {
char prog_name[64];
strncpy(prog_name, raw_cmd, sizeof(prog_name) - 1);
prog_name[sizeof(prog_name) - 1] = '\0';
const char *exec_target = prog_name;
while (*exec_target == '.' || *exec_target == '/') {
exec_target++;
}
int64_t tid = sys_module_exec(exec_target);
if (tid < 0 && !strstr(exec_target, ".")) {
char opc_name[70];
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
tid = sys_module_exec(opc_name);
if (tid < 0) {
char elf_name[70];
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
tid = sys_module_exec(elf_name);
}
}
if (tid >= 0) {
snprintf(buf, sizeof(buf), "[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
lv_textarea_add_text(g_txt_term_output, buf);
} else { } else {
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd); snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
lv_textarea_add_text(g_txt_term_output, buf); lv_textarea_add_text(g_txt_term_output, buf);
} }
} }
}
// Console input submit callback (Enter key) // Console input submit callback (Enter key)
static void console_submit_event_cb(lv_event_t *e) { static void console_submit_event_cb(lv_event_t *e) {
@@ -607,15 +698,20 @@ static void start_item_event_cb(lv_event_t *e) {
// Ping button inside Network window // Ping button inside Network window
static void ping_btn_event_cb(lv_event_t *e) { static void ping_btn_event_cb(lv_event_t *e) {
(void)e; (void)e;
uint32_t target_ip = (10) | (0 << 8) | (2 << 16) | (2 << 24); uint32_t target_ip = g_net_cfg.gateway ? g_net_cfg.gateway : parse_ip("1.1.1.1");
int res = net_send_icmp_ping(target_ip, 1); int res = net_send_icmp_ping(target_ip, 1);
char ip_str[32];
format_ip(target_ip, ip_str);
char res_buf[128];
if (g_lbl_net_ping_res) { if (g_lbl_net_ping_res) {
if (res == 0) { if (res == 0) {
lv_label_set_text(g_lbl_net_ping_res, "Ping: 10.0.2.2 OK! RTT=0.45ms | 0% Loss (RTL8139 DMA)"); snprintf(res_buf, sizeof(res_buf), "Ping: %s OK! 0%% Loss (PCI DMA)", ip_str);
lv_label_set_text(g_lbl_net_ping_res, res_buf);
lv_obj_set_style_text_color(g_lbl_net_ping_res, lv_color_hex(0x22c55e), 0); lv_obj_set_style_text_color(g_lbl_net_ping_res, lv_color_hex(0x22c55e), 0);
} else { } else {
lv_label_set_text(g_lbl_net_ping_res, "Ping: Transmit error."); snprintf(res_buf, sizeof(res_buf), "Ping: %s Timeout / Unreachable", ip_str);
lv_label_set_text(g_lbl_net_ping_res, res_buf);
lv_obj_set_style_text_color(g_lbl_net_ping_res, lv_color_hex(0xef4444), 0); lv_obj_set_style_text_color(g_lbl_net_ping_res, lv_color_hex(0xef4444), 0);
} }
} }
@@ -624,7 +720,7 @@ static void ping_btn_event_cb(lv_event_t *e) {
static void browser_go_event_cb(lv_event_t *e) { static void browser_go_event_cb(lv_event_t *e) {
(void)e; (void)e;
const char *url = lv_textarea_get_text(g_ta_browser_url); const char *url = lv_textarea_get_text(g_ta_browser_url);
if (!url || !*url) url = "http://10.0.2.2/index.html"; if (!url || !*url) url = "http://neverssl.com/";
char buf[128]; char buf[128];
snprintf(buf, sizeof(buf), "Connecting to %s...", url); snprintf(buf, sizeof(buf), "Connecting to %s...", url);
@@ -839,13 +935,24 @@ static void create_desktop_environment() {
lv_obj_set_style_pad_all(net_content, 12, 0); lv_obj_set_style_pad_all(net_content, 12, 0);
lv_obj_t *lbl_net_info = lv_label_create(net_content); lv_obj_t *lbl_net_info = lv_label_create(net_content);
lv_label_set_text(lbl_net_info, char net_info[256];
"Adapter: Realtek RTL8139 Fast Ethernet PCI\n" char ip_str[32], mask_str[32], gw_str[32];
"Mode: PCI Bus Master DMA (CMD: 0x107)\n" format_ip(g_net_cfg.ip, ip_str);
"MAC: 52:54:00:12:34:56\n" format_ip(g_net_cfg.netmask, mask_str);
"IP: 10.0.2.15 / 255.255.255.0\n" format_ip(g_net_cfg.gateway, gw_str);
"Gateway: 10.0.2.2 (QEMU Virtual NAT)\n" snprintf(net_info, sizeof(net_info),
"DMA RX: 0x2176000 | DMA TX: 0x217a000"); "Adapter: PCI Fast Ethernet Network Adapter\n"
"Mode: PCI Bus Master DMA Link Active\n"
"MAC: %02x:%02x:%02x:%02x:%02x:%02x\n"
"IP: %s / %s\n"
"Gateway: %s\n"
"Status: Network Stack TCP/IPv4 Ready",
g_net_cfg.mac[0], g_net_cfg.mac[1], g_net_cfg.mac[2],
g_net_cfg.mac[3], g_net_cfg.mac[4], g_net_cfg.mac[5],
*ip_str ? ip_str : "0.0.0.0",
*mask_str ? mask_str : "0.0.0.0",
*gw_str ? gw_str : "None");
lv_label_set_text(lbl_net_info, net_info);
lv_obj_align(lbl_net_info, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_align(lbl_net_info, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_set_style_text_color(lbl_net_info, lv_color_hex(0xe2e8f0), 0); lv_obj_set_style_text_color(lbl_net_info, lv_color_hex(0xe2e8f0), 0);
@@ -854,7 +961,7 @@ static void create_desktop_environment() {
lv_obj_align(btn_ping, LV_ALIGN_TOP_LEFT, 0, 150); lv_obj_align(btn_ping, LV_ALIGN_TOP_LEFT, 0, 150);
lv_obj_set_style_bg_color(btn_ping, lv_color_hex(0x0284c7), 0); lv_obj_set_style_bg_color(btn_ping, lv_color_hex(0x0284c7), 0);
lv_obj_t *lbl_ping_text = lv_label_create(btn_ping); lv_obj_t *lbl_ping_text = lv_label_create(btn_ping);
lv_label_set_text(lbl_ping_text, "Ping Gateway (10.0.2.2)"); lv_label_set_text(lbl_ping_text, "Ping Default Gateway");
lv_obj_center(lbl_ping_text); lv_obj_center(lbl_ping_text);
lv_obj_add_event_cb(btn_ping, ping_btn_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(btn_ping, ping_btn_event_cb, LV_EVENT_CLICKED, NULL);
@@ -912,7 +1019,7 @@ static void create_desktop_environment() {
lv_obj_set_size(g_ta_browser_url, 500, 32); lv_obj_set_size(g_ta_browser_url, 500, 32);
lv_obj_align(g_ta_browser_url, LV_ALIGN_LEFT_MID, 2, 0); lv_obj_align(g_ta_browser_url, LV_ALIGN_LEFT_MID, 2, 0);
lv_textarea_set_one_line(g_ta_browser_url, true); lv_textarea_set_one_line(g_ta_browser_url, true);
lv_textarea_set_text(g_ta_browser_url, "http://10.0.2.2/index.html"); lv_textarea_set_text(g_ta_browser_url, "http://neverssl.com/");
lv_obj_set_style_bg_color(g_ta_browser_url, lv_color_hex(0x0f141f), 0); lv_obj_set_style_bg_color(g_ta_browser_url, lv_color_hex(0x0f141f), 0);
lv_obj_set_style_text_color(g_ta_browser_url, lv_color_hex(0xe2e8f0), 0); lv_obj_set_style_text_color(g_ta_browser_url, lv_color_hex(0xe2e8f0), 0);
lv_obj_set_style_border_color(g_ta_browser_url, lv_color_hex(0x38bdf8), 0); lv_obj_set_style_border_color(g_ta_browser_url, lv_color_hex(0x38bdf8), 0);
@@ -932,7 +1039,7 @@ static void create_desktop_environment() {
// Status / HTTP Header Bar // Status / HTTP Header Bar
g_lbl_browser_status = lv_label_create(b_content); g_lbl_browser_status = lv_label_create(b_content);
lv_label_set_text(g_lbl_browser_status, "Ready | Protocol: TCP/IPv4 | Gateway: 10.0.2.2"); lv_label_set_text(g_lbl_browser_status, "Ready | Protocol: TCP/IPv4");
lv_obj_align(g_lbl_browser_status, LV_ALIGN_TOP_LEFT, 0, 48); lv_obj_align(g_lbl_browser_status, LV_ALIGN_TOP_LEFT, 0, 48);
lv_obj_set_style_text_color(g_lbl_browser_status, lv_color_hex(0x94a3b8), 0); lv_obj_set_style_text_color(g_lbl_browser_status, lv_color_hex(0x94a3b8), 0);
@@ -953,7 +1060,7 @@ static void create_desktop_environment() {
" <p>Network: Realtek RTL8139 Fast Ethernet PCI Bus Master</p>\n" " <p>Network: Realtek RTL8139 Fast Ethernet PCI Bus Master</p>\n"
" <p>Stack: TCP/IPv4, ARP, ICMP, HTTP/1.1</p>\n" " <p>Stack: TCP/IPv4, ARP, ICMP, HTTP/1.1</p>\n"
" <hr/>\n" " <hr/>\n"
" <h3>Click 'Go ->' to connect to gateway (10.0.2.2) via TCP!</h3>\n" " <h3>Enter a URL or domain and click 'Go ->' to navigate via TCP/IPv4</h3>\n"
"</body>\n" "</body>\n"
"</html>\n"); "</html>\n");
@@ -1046,8 +1153,12 @@ static void create_desktop_environment() {
lv_obj_set_flex_flow(tray, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(tray, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(tray, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(tray, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
char tray_lan_buf[32];
char lan_ip[32];
format_ip(g_net_cfg.ip, lan_ip);
snprintf(tray_lan_buf, sizeof(tray_lan_buf), "LAN: %s", *lan_ip ? lan_ip : "0.0.0.0");
g_lbl_tray_net = lv_label_create(tray); g_lbl_tray_net = lv_label_create(tray);
lv_label_set_text(g_lbl_tray_net, "LAN: 10.0.2.15"); lv_label_set_text(g_lbl_tray_net, tray_lan_buf);
lv_obj_set_style_text_color(g_lbl_tray_net, lv_color_hex(0x38bdf8), 0); lv_obj_set_style_text_color(g_lbl_tray_net, lv_color_hex(0x38bdf8), 0);
lv_obj_set_style_pad_hor(g_lbl_tray_net, 8, 0); lv_obj_set_style_pad_hor(g_lbl_tray_net, 8, 0);
+127 -15
View File
@@ -26,15 +26,36 @@ static VfsFile vfs_nodes[64] = {
{ "/dev", "", true }, { "/dev", "", true },
{ "/etc/os-release", "NAME=\"opencoreC\"\nVERSION=\"0.1.0\"\nID=opencorec\nPRETTY_NAME=\"opencoreC Microkernel OS (x86_64)\"\n", false }, { "/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/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 }, { "/etc/hosts", "127.0.0.1 localhost\n", false },
{ "/proc/version", "opencoreC version 0.1.0-release (rustc 1.98.0 / gcc 16.2.1) x86_64 SMP\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 }, { "/proc/cpuinfo", "model name: x86_64 Microkernel Virtual CPU\nfeatures: long_mode syscall hhdm smp sse sse2 avx\n", false },
{ "/dev/null", "", false }, { "/dev/null", "", false },
{ "/dev/uart0", "16550 Serial COM1 Port\n", false }, { "/dev/uart0", "16550 Serial COM1 Port\n", false },
{ "/dev/net0", "Realtek RTL8139 Fast Ethernet PCI\n", false }, { "/dev/net0", "PCI Fast Ethernet Network Adapter\n", false },
{ "/boot/hello.opc", "OpenCore Native Executable Binary (.OPC v1.0)\n", false },
}; };
static size_t vfs_count = 14; static size_t vfs_count = 13;
static void vfs_init_modules() {
char buf[512] = {0};
int len = sys_module_list(buf, sizeof(buf) - 1);
if (len > 0) {
char *p = buf;
while (*p && vfs_count < 60) {
char mod[64] = {0};
int mi = 0;
while (*p && *p != ' ' && mi < 63) {
mod[mi++] = *p++;
}
while (*p == ' ') p++;
if (mi > 0) {
snprintf(vfs_nodes[vfs_count].name, sizeof(vfs_nodes[vfs_count].name), "/bin/%s", mod);
snprintf(vfs_nodes[vfs_count].content, sizeof(vfs_nodes[vfs_count].content), "Executable binary: %s\n", mod);
vfs_nodes[vfs_count].is_dir = false;
vfs_count++;
}
}
}
}
// Shell Environment Variables // Shell Environment Variables
struct EnvVar { struct EnvVar {
@@ -50,6 +71,35 @@ static EnvVar g_env[16] = {
}; };
static size_t g_env_count = 5; static size_t g_env_count = 5;
static void get_cpu_brand(char *brand, size_t max_len) {
memset(brand, 0, max_len);
uint32_t regs[4];
__asm__ volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) : "a"(0x80000000));
if (regs[0] >= 0x80000004) {
char *p = brand;
for (uint32_t leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
uint32_t b_regs[4];
__asm__ volatile("cpuid" : "=a"(b_regs[0]), "=b"(b_regs[1]), "=c"(b_regs[2]), "=d"(b_regs[3]) : "a"(leaf));
if (p - brand + 16 < (int)max_len) {
memcpy(p, b_regs, 16);
p += 16;
}
}
brand[max_len - 1] = '\0';
char *src = brand;
while (*src == ' ') src++;
if (src != brand) {
memmove(brand, src, strlen(src) + 1);
}
} else {
__asm__ volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) : "a"(0));
memcpy(brand, &regs[1], 4);
memcpy(brand + 4, &regs[3], 4);
memcpy(brand + 8, &regs[2], 4);
brand[12] = '\0';
}
}
static void print_fastfetch() { static void print_fastfetch() {
sysinfo_data_t info = {0, 0, 0, 0, 0}; sysinfo_data_t info = {0, 0, 0, 0, 0};
sys_sysinfo(&info); sys_sysinfo(&info);
@@ -71,6 +121,9 @@ static void print_fastfetch() {
gpu_info_t gpu; gpu_info_t gpu;
bool has_gpu = (pci_detect_gpu(&gpu) == 0); bool has_gpu = (pci_detect_gpu(&gpu) == 0);
char cpu_brand[64] = {0};
get_cpu_brand(cpu_brand, sizeof(cpu_brand));
printf("\n"); printf("\n");
printf(" \033[1;36m ___ \033[1;32mroot\033[0m@\033[1;36mopencoreC\033[0m\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 / \\ \033[0;37m-----------------\033[0m\n");
@@ -84,7 +137,9 @@ static void print_fastfetch() {
printf(" \033[1;34m [=== opencoreC ===] \033[1;34mDisplay:\033[0m 1280x800 @ 60Hz (Limine FB)\n"); 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 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 Ring 3 Userspace \033[1;34mCPU:\033[0m %s (%u Cores SMP)\n",
*cpu_brand ? cpu_brand : "x86_64 Processor",
acpi.lapic_count > 0 ? (unsigned int)acpi.lapic_count : 4);
if (has_gpu) { if (has_gpu) {
if (gpu.vram_mb > 0) { if (gpu.vram_mb > 0) {
printf(" \033[1;35m Fast-Path IPC Cap \033[1;34mGPU:\033[0m %s (%u MiB VRAM)\n", gpu.model_name, (unsigned int)gpu.vram_mb); printf(" \033[1;35m Fast-Path IPC Cap \033[1;34mGPU:\033[0m %s (%u MiB VRAM)\n", gpu.model_name, (unsigned int)gpu.vram_mb);
@@ -97,8 +152,16 @@ static void print_fastfetch() {
printf(" \033[1;34mMemory:\033[0m %u MiB / %u MiB (%u%%)\n", printf(" \033[1;34mMemory:\033[0m %u MiB / %u MiB (%u%%)\n",
(unsigned int)used_mb, (unsigned int)total_mb, (unsigned int)used_mb, (unsigned int)total_mb,
total_mb > 0 ? (unsigned int)(used_mb * 100 / total_mb) : 0); 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"); char ip_str[32] = {0};
format_ip(g_net_cfg.ip, ip_str);
if (g_net_cfg.ip != 0) {
printf(" \033[1;34mNetwork:\033[0m PCI Ethernet (%s)\n", ip_str);
} else {
printf(" \033[1;34mNetwork:\033[0m PCI Ethernet (Unconfigured)\n");
}
printf(" \033[1;34mACPI:\033[0m S5 Poweroff, Reset, MADT %u Cores\n",
acpi.lapic_count > 0 ? (unsigned int)acpi.lapic_count : 4);
printf(" \033[1;34mSecurity:\033[0m Ring 3 Signal Fault Isolation (SIGSEGV)\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[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[40m \033[41m \033[42m \033[43m \033[44m \033[45m \033[46m \033[47m \033[0m\n");
@@ -310,7 +373,7 @@ static void cmd_modules() {
} }
} }
printf("------------------------------------------------------\n"); printf("------------------------------------------------------\n");
puts("To run: type './hello.opc' or 'run hello.opc'\n"); puts("To run: type '<program>', './<program>', or 'run <program>'\n");
} else { } else {
puts("modules: No boot modules detected."); puts("modules: No boot modules detected.");
} }
@@ -402,13 +465,15 @@ static void handle_command(char *cmd) {
puts(" dmesg - Display live microkernel circular log buffer"); puts(" dmesg - Display live microkernel circular log buffer");
puts(" mem / free - Display physical RAM allocator (PFA) metrics"); puts(" mem / free - Display physical RAM allocator (PFA) metrics");
puts(" shm - Demonstrate Zero-Copy Shared Memory"); puts(" shm - Demonstrate Zero-Copy Shared Memory");
puts(" ifconfig / ip - Display network interface (RTL8139) status"); puts(" ifconfig / ip - Display network interface status");
puts(" ping [ip] - Real ICMP Echo ping over virtual network"); puts(" ping [target] - Real ICMP Echo ping over network");
puts(" dhcp - Acquire network lease from DHCP server");
puts(" dns <domain> - Query domain name IP via DNS");
puts(" curl / fetch <u - Fetch webpage via TCP/IPv4 stack"); puts(" curl / fetch <u - Fetch webpage via TCP/IPv4 stack");
puts(" lspci - Enumerate hardware devices on PCI bus"); puts(" lspci - Enumerate hardware devices on PCI bus");
puts(" gpu - Display detected GPU accelerator & VRAM"); puts(" gpu - Display detected GPU accelerator & VRAM");
puts(" modules - List in-memory boot modules available to run"); puts(" modules - List in-memory boot modules available to run");
puts(" run / ./<module> - Execute native .opc or .elf binary (e.g. ./hello.opc)"); puts(" <prog> / ./<prog>- Execute native .opc or .elf binary");
puts(" notify <msg> - Send desktop notification toast to GUI"); puts(" notify <msg> - Send desktop notification toast to GUI");
puts(" gui - Launch Framebuffer graphics & window desktop"); puts(" gui - Launch Framebuffer graphics & window desktop");
puts(" write <str> - Send Rendezvous IPC message to UART driver"); puts(" write <str> - Send Rendezvous IPC message to UART driver");
@@ -444,9 +509,22 @@ static void handle_command(char *cmd) {
puts(cmd + 5); puts(cmd + 5);
} else if (strcmp(cmd, "echo") == 0) { } else if (strcmp(cmd, "echo") == 0) {
puts(""); puts("");
} else if (strcmp(cmd, "ls") == 0 || strcmp(cmd, "dir") == 0) { } else if (strncmp(cmd, "ls", 2) == 0 || strncmp(cmd, "dir", 3) == 0) {
const char *filter = NULL;
if (strncmp(cmd, "ls ", 3) == 0) {
filter = cmd + 3;
while (*filter == ' ') filter++;
} else if (strncmp(cmd, "dir ", 4) == 0) {
filter = cmd + 4;
while (*filter == ' ') filter++;
}
puts("MODE SIZE NAME"); puts("MODE SIZE NAME");
for (size_t i = 0; i < vfs_count; i++) { for (size_t i = 0; i < vfs_count; i++) {
if (filter && *filter) {
if (strncmp(vfs_nodes[i].name, filter, strlen(filter)) != 0) {
continue;
}
}
if (vfs_nodes[i].is_dir) { if (vfs_nodes[i].is_dir) {
printf("drwxr-xr-x 4096 %s\n", vfs_nodes[i].name); printf("drwxr-xr-x 4096 %s\n", vfs_nodes[i].name);
} else { } else {
@@ -721,9 +799,14 @@ static void handle_command(char *cmd) {
} }
} else if (strcmp(cmd, "ifconfig") == 0 || strcmp(cmd, "ip") == 0) { } else if (strcmp(cmd, "ifconfig") == 0 || strcmp(cmd, "ip") == 0) {
net_init(); net_init();
char ip_str[32], mask_str[32], gw_str[32];
format_ip(g_net_cfg.ip, ip_str);
format_ip(g_net_cfg.netmask, mask_str);
format_ip(g_net_cfg.gateway, gw_str);
printf("eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n"); 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(" inet %s netmask %s\n", ip_str, mask_str);
printf(" ether %02x:%02x:%02x:%02x:%02x:%02x txqueuelen 1000 (Ethernet)\n", printf(" gateway %s\n", gw_str);
printf(" ether %02x:%02x:%02x:%02x:%02x:%02x txqueuelen 1000 (PCI Ethernet)\n",
g_rtl8139.mac[0], g_rtl8139.mac[1], g_rtl8139.mac[2], g_rtl8139.mac[0], g_rtl8139.mac[1], g_rtl8139.mac[2],
g_rtl8139.mac[3], g_rtl8139.mac[4], g_rtl8139.mac[5]); 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(" RX packets %lu bytes %lu\n", (unsigned long)g_rtl8139.rx_packets, (unsigned long)g_rtl8139.rx_bytes);
@@ -872,10 +955,36 @@ static void handle_command(char *cmd) {
} else if (strcmp(cmd, "poweroff") == 0 || strcmp(cmd, "exit") == 0) { } else if (strcmp(cmd, "poweroff") == 0 || strcmp(cmd, "exit") == 0) {
puts("Powering off system..."); puts("Powering off system...");
sys_shutdown(); sys_shutdown();
} else {
char prog_name[64];
strncpy(prog_name, cmd, sizeof(prog_name) - 1);
prog_name[sizeof(prog_name) - 1] = '\0';
const char *exec_target = prog_name;
while (*exec_target == '.' || *exec_target == '/') {
exec_target++;
}
int64_t tid = sys_module_exec(exec_target);
if (tid < 0 && !strstr(exec_target, ".")) {
char opc_name[70];
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
tid = sys_module_exec(opc_name);
if (tid < 0) {
char elf_name[70];
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
tid = sys_module_exec(elf_name);
}
}
if (tid >= 0) {
printf("[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
for (int i = 0; i < 6; i++) sys_yield();
} else { } else {
printf("osh: command not found: %s\n", cmd); printf("osh: command not found: %s\n", cmd);
} }
} }
}
extern "C" void _start() { extern "C" void _start() {
// Yield until initial boot modules finish their startup messages // Yield until initial boot modules finish their startup messages
@@ -883,6 +992,9 @@ extern "C" void _start() {
sys_yield(); sys_yield();
} }
// Initialize VFS with any loaded boot modules
vfs_init_modules();
// Clean screen after all boot logs are finished // Clean screen after all boot logs are finished
sys_log_debug("\033[2J\033[H", 7); sys_log_debug("\033[2J\033[H", 7);
print_fastfetch(); print_fastfetch();