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:
+137
-26
@@ -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, ®s[1], 4);
|
||||||
|
memcpy(brand + 4, ®s[3], 4);
|
||||||
|
memcpy(brand + 8, ®s[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
@@ -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, ®s[1], 4);
|
||||||
|
memcpy(brand + 4, ®s[3], 4);
|
||||||
|
memcpy(brand + 8, ®s[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();
|
||||||
|
|||||||
Reference in New Issue
Block a user