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:
+139
-28
@@ -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_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
|
||||
static lv_obj_t *g_start_menu = 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;
|
||||
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),
|
||||
" ___ root@opencoreC\n"
|
||||
" / \\ -----------------\n"
|
||||
@@ -396,17 +430,20 @@ static void execute_console_command(const char *raw_cmd) {
|
||||
" | | / \\ Kernel: v0.1.0-release (Rust #![no_std])\n"
|
||||
" \\ ___ / | (o) | Uptime: %u mins, %u secs\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"
|
||||
" 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"
|
||||
" Network: RTL8139 Fast Ethernet (10.0.2.15)\n"
|
||||
" ACPI: MADT 4 Cores, S5 Power, Hardware Reset\n"
|
||||
" Network: PCI Ethernet (%s)\n"
|
||||
" ACPI: S5 Power, Reset, MADT Active\n"
|
||||
" Security: Ring 3 Fault Isolation (SIGSEGV)\n"
|
||||
" RNG: Hardware RDRAND / RDSEED Active\n",
|
||||
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,
|
||||
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);
|
||||
} 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");
|
||||
@@ -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);
|
||||
lv_textarea_add_text(g_txt_term_output, buf);
|
||||
} 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"
|
||||
" inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255\n"
|
||||
" ether 52:54:00:12:34:56 txqueuelen 1000 (Realtek RTL8139 DMA)\n"
|
||||
" gateway 10.0.2.2 (QEMU Virtual SLIRP NAT)\n");
|
||||
" inet %s netmask %s broadcast 255.255.255.255\n"
|
||||
" ether %02x:%02x:%02x:%02x:%02x:%02x txqueuelen 1000 (PCI Ethernet)\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) {
|
||||
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) {
|
||||
target_ip = parse_ip(raw_cmd + 5);
|
||||
}
|
||||
@@ -579,9 +625,54 @@ static void execute_console_command(const char *raw_cmd) {
|
||||
lv_textarea_add_text(g_txt_term_output, "Powering off opencoreC...\n");
|
||||
register uint64_t rax __asm__("rax") = SYS_SHUTDOWN;
|
||||
__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 {
|
||||
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
|
||||
lv_textarea_add_text(g_txt_term_output, buf);
|
||||
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 {
|
||||
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
|
||||
lv_textarea_add_text(g_txt_term_output, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,15 +698,20 @@ static void start_item_event_cb(lv_event_t *e) {
|
||||
// Ping button inside Network window
|
||||
static void ping_btn_event_cb(lv_event_t *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);
|
||||
|
||||
char ip_str[32];
|
||||
format_ip(target_ip, ip_str);
|
||||
char res_buf[128];
|
||||
if (g_lbl_net_ping_res) {
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -624,7 +720,7 @@ static void ping_btn_event_cb(lv_event_t *e) {
|
||||
static void browser_go_event_cb(lv_event_t *e) {
|
||||
(void)e;
|
||||
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];
|
||||
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_t *lbl_net_info = lv_label_create(net_content);
|
||||
lv_label_set_text(lbl_net_info,
|
||||
"Adapter: Realtek RTL8139 Fast Ethernet PCI\n"
|
||||
"Mode: PCI Bus Master DMA (CMD: 0x107)\n"
|
||||
"MAC: 52:54:00:12:34:56\n"
|
||||
"IP: 10.0.2.15 / 255.255.255.0\n"
|
||||
"Gateway: 10.0.2.2 (QEMU Virtual NAT)\n"
|
||||
"DMA RX: 0x2176000 | DMA TX: 0x217a000");
|
||||
char net_info[256];
|
||||
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(net_info, sizeof(net_info),
|
||||
"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_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_set_style_bg_color(btn_ping, lv_color_hex(0x0284c7), 0);
|
||||
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_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_align(g_ta_browser_url, LV_ALIGN_LEFT_MID, 2, 0);
|
||||
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_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);
|
||||
@@ -932,7 +1039,7 @@ static void create_desktop_environment() {
|
||||
|
||||
// Status / HTTP Header Bar
|
||||
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_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>Stack: TCP/IPv4, ARP, ICMP, HTTP/1.1</p>\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"
|
||||
"</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_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);
|
||||
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_pad_hor(g_lbl_tray_net, 8, 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user